FontRenderer.h revision 894df17eee708688c8a6e67941add2017239c790
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_HWUI_FONT_RENDERER_H
18#define ANDROID_HWUI_FONT_RENDERER_H
19
20#include <utils/String8.h>
21#include <utils/String16.h>
22#include <utils/Vector.h>
23#include <utils/KeyedVector.h>
24
25#include <SkScalerContext.h>
26#include <SkPaint.h>
27
28#include <GLES2/gl2.h>
29
30#include "Rect.h"
31#include "Properties.h"
32
33namespace android {
34namespace uirenderer {
35
36class FontRenderer;
37
38/**
39 * Represents a font, defined by a Skia font id and a font size. A font is used
40 * to generate glyphs and cache them in the FontState.
41 */
42class Font {
43public:
44    enum Style {
45        kFakeBold
46    };
47
48    ~Font();
49
50    /**
51     * Renders the specified string of text.
52     * If bitmap is specified, it will be used as the render target
53     */
54    void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
55                     int numGlyphs, int x, int y,
56                     uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0);
57    /**
58     * Creates a new font associated with the specified font state.
59     */
60    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
61            int flags, uint32_t italicStyle);
62
63protected:
64    friend class FontRenderer;
65
66    enum RenderMode {
67        FRAMEBUFFER,
68        BITMAP,
69        MEASURE,
70    };
71
72    void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
73                     int numGlyphs, int x, int y, RenderMode mode,
74                     uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
75                     Rect *bounds);
76
77    void measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
78                      int numGlyphs, Rect *bounds);
79
80    struct CachedGlyphInfo {
81        // Has the cache been invalidated?
82        bool mIsValid;
83        // Location of the cached glyph in the bitmap
84        // in case we need to resize the texture or
85        // render to bitmap
86        uint32_t mStartX;
87        uint32_t mStartY;
88        uint32_t mBitmapWidth;
89        uint32_t mBitmapHeight;
90        // Also cache texture coords for the quad
91        float mBitmapMinU;
92        float mBitmapMinV;
93        float mBitmapMaxU;
94        float mBitmapMaxV;
95        // Minimize how much we call freetype
96        uint32_t mGlyphIndex;
97        uint32_t mAdvanceX;
98        uint32_t mAdvanceY;
99        // Values below contain a glyph's origin in the bitmap
100        int32_t mBitmapLeft;
101        int32_t mBitmapTop;
102        // Auto-kerning
103        SkFixed mLsbDelta;
104        SkFixed mRsbDelta;
105    };
106
107    Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle);
108
109    DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs;
110
111    void invalidateTextureCache();
112
113    CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_t glyph);
114    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
115    void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
116    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
117    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
118                          uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
119
120    CachedGlyphInfo* getCachedUTFChar(SkPaint* paint, int32_t utfChar);
121
122    FontRenderer* mState;
123    uint32_t mFontId;
124    float mFontSize;
125    int mFlags;
126    uint32_t mItalicStyle;
127};
128
129class FontRenderer {
130public:
131    FontRenderer();
132    ~FontRenderer();
133
134    void init();
135    void deinit();
136
137    void setGammaTable(const uint8_t* gammaTable) {
138        mGammaTable = gammaTable;
139    }
140
141    void setAttributeBindingSlots(int positionSlot, int texCoordSlot) {
142        mPositionAttrSlot = positionSlot;
143        mTexcoordAttrSlot = texCoordSlot;
144    }
145
146    void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
147    bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
148            uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
149
150    struct DropShadow {
151        DropShadow() { };
152
153        DropShadow(const DropShadow& dropShadow):
154            width(dropShadow.width), height(dropShadow.height),
155            image(dropShadow.image), penX(dropShadow.penX),
156            penY(dropShadow.penY) {
157        }
158
159        uint32_t width;
160        uint32_t height;
161        uint8_t* image;
162        int32_t penX;
163        int32_t penY;
164    };
165
166    // After renderDropShadow returns, the called owns the memory in DropShadow.image
167    // and is responsible for releasing it when it's done with it
168    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
169            uint32_t len, int numGlyphs, uint32_t radius);
170
171    GLuint getTexture(bool linearFiltering = false) {
172        checkInit();
173        if (linearFiltering != mLinearFiltering) {
174            mLinearFiltering = linearFiltering;
175            const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
176
177            glBindTexture(GL_TEXTURE_2D, mTextureId);
178            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
179            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
180        }
181        return mTextureId;
182    }
183
184    uint32_t getCacheWidth() const {
185        return mCacheWidth;
186    }
187
188    uint32_t getCacheHeight() const {
189        return mCacheHeight;
190    }
191
192protected:
193    friend class Font;
194
195    const uint8_t* mGammaTable;
196
197    struct CacheTextureLine {
198        uint16_t mMaxHeight;
199        uint16_t mMaxWidth;
200        uint32_t mCurrentRow;
201        uint32_t mCurrentCol;
202        bool mDirty;
203
204        CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
205                uint32_t currentCol):
206                    mMaxHeight(maxHeight),
207                    mMaxWidth(maxWidth),
208                    mCurrentRow(currentRow),
209                    mCurrentCol(currentCol),
210                    mDirty(false) {
211        }
212
213        bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
214            if (glyph.fHeight + 2 > mMaxHeight) {
215                return false;
216            }
217
218            if (mCurrentCol + glyph.fWidth + 2 < mMaxWidth) {
219                *retOriginX = mCurrentCol + 1;
220                *retOriginY = mCurrentRow + 1;
221                mCurrentCol += glyph.fWidth + 2;
222                mDirty = true;
223                return true;
224            }
225
226            return false;
227        }
228    };
229
230    void initTextTexture();
231    bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
232
233    void flushAllAndInvalidate();
234    void initVertexArrayBuffers();
235
236    void checkInit();
237
238    String16 mLatinPrecache;
239    void precacheLatin(SkPaint* paint);
240
241    void issueDrawCommand();
242    void appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2,
243            float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3,
244            float x4, float y4, float z4, float u4, float v4);
245
246    uint32_t mCacheWidth;
247    uint32_t mCacheHeight;
248
249    Vector<CacheTextureLine*> mCacheLines;
250    uint32_t getRemainingCacheCapacity();
251
252    Font* mCurrentFont;
253    Vector<Font*> mActiveFonts;
254
255    // Texture to cache glyph bitmaps
256    uint8_t* mTextTexture;
257    const uint8_t* getTextTextureData() const {
258        return mTextTexture;
259    }
260    GLuint mTextureId;
261    void checkTextureUpdate();
262    bool mUploadTexture;
263
264    // Pointer to vertex data to speed up frame to frame work
265    float *mTextMeshPtr;
266    uint32_t mCurrentQuadIndex;
267    uint32_t mMaxNumberOfQuads;
268
269    uint32_t mIndexBufferID;
270
271    int32_t mPositionAttrSlot;
272    int32_t mTexcoordAttrSlot;
273
274    const Rect* mClip;
275    Rect* mBounds;
276    bool mDrawn;
277
278    bool mInitialized;
279
280    bool mLinearFiltering;
281
282    void computeGaussianWeights(float* weights, int32_t radius);
283    void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
284            int32_t width, int32_t height);
285    void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
286            int32_t width, int32_t height);
287    void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
288};
289
290}; // namespace uirenderer
291}; // namespace android
292
293#endif // ANDROID_HWUI_FONT_RENDERER_H
294