FontRenderer.h revision 7de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86
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
36///////////////////////////////////////////////////////////////////////////////
37// Defines
38///////////////////////////////////////////////////////////////////////////////
39
40#if RENDER_TEXT_AS_GLYPHS
41    typedef uint16_t glyph_t;
42    #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph)
43    #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
44    #define IS_END_OF_STRING(glyph) false
45#else
46    typedef SkUnichar glyph_t;
47    #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph)
48    #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
49    #define IS_END_OF_STRING(glyph) glyph < 0
50#endif
51
52///////////////////////////////////////////////////////////////////////////////
53// Declarations
54///////////////////////////////////////////////////////////////////////////////
55
56class FontRenderer;
57
58class CacheTexture {
59public:
60    CacheTexture(){}
61    CacheTexture(uint8_t* texture, GLuint textureId, uint16_t width, uint16_t height) :
62        mTexture(texture), mTextureId(textureId), mWidth(width), mHeight(height) {}
63    ~CacheTexture() {
64        if (mTexture != NULL) {
65            delete[] mTexture;
66        }
67        if (mTextureId != 0) {
68            glDeleteTextures(1, &mTextureId);
69        }
70    }
71
72    uint8_t* mTexture;
73    GLuint mTextureId;
74    uint16_t mWidth;
75    uint16_t mHeight;
76};
77
78class CacheTextureLine {
79public:
80    CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
81            uint32_t currentCol, CacheTexture* cacheTexture):
82                mMaxHeight(maxHeight),
83                mMaxWidth(maxWidth),
84                mCurrentRow(currentRow),
85                mCurrentCol(currentCol),
86                mDirty(false),
87                mCacheTexture(cacheTexture){
88    }
89
90    bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
91
92    uint16_t mMaxHeight;
93    uint16_t mMaxWidth;
94    uint32_t mCurrentRow;
95    uint32_t mCurrentCol;
96    bool mDirty;
97    CacheTexture *mCacheTexture;
98};
99
100struct CachedGlyphInfo {
101    // Has the cache been invalidated?
102    bool mIsValid;
103    // Location of the cached glyph in the bitmap
104    // in case we need to resize the texture or
105    // render to bitmap
106    uint32_t mStartX;
107    uint32_t mStartY;
108    uint32_t mBitmapWidth;
109    uint32_t mBitmapHeight;
110    // Also cache texture coords for the quad
111    float mBitmapMinU;
112    float mBitmapMinV;
113    float mBitmapMaxU;
114    float mBitmapMaxV;
115    // Minimize how much we call freetype
116    uint32_t mGlyphIndex;
117    uint32_t mAdvanceX;
118    uint32_t mAdvanceY;
119    // Values below contain a glyph's origin in the bitmap
120    int32_t mBitmapLeft;
121    int32_t mBitmapTop;
122    // Auto-kerning
123    SkFixed mLsbDelta;
124    SkFixed mRsbDelta;
125    CacheTextureLine* mCachedTextureLine;
126};
127
128
129///////////////////////////////////////////////////////////////////////////////
130// Font
131///////////////////////////////////////////////////////////////////////////////
132
133/**
134 * Represents a font, defined by a Skia font id and a font size. A font is used
135 * to generate glyphs and cache them in the FontState.
136 */
137class Font {
138public:
139    enum Style {
140        kFakeBold = 1
141    };
142
143    ~Font();
144
145    /**
146     * Renders the specified string of text.
147     * If bitmap is specified, it will be used as the render target
148     */
149    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
150            int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
151            uint32_t bitmapW = 0, uint32_t bitmapH = 0);
152    /**
153     * Creates a new font associated with the specified font state.
154     */
155    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
156            int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
157            uint32_t strokeWidth);
158
159protected:
160    friend class FontRenderer;
161
162    enum RenderMode {
163        FRAMEBUFFER,
164        BITMAP,
165        MEASURE,
166    };
167
168    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
169            int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
170            uint32_t bitmapW, uint32_t bitmapH, Rect *bounds);
171
172    void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
173            int numGlyphs, Rect *bounds);
174
175    Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
176            uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
177
178    // Cache of glyphs
179    DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
180
181    void invalidateTextureCache();
182
183    CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
184    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
185    void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
186    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
187    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
188            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
189
190    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
191
192    static glyph_t nextGlyph(const uint16_t** srcPtr) {
193        const uint16_t* src = *srcPtr;
194        glyph_t g = *src++;
195        *srcPtr = src;
196        return g;
197    }
198
199    FontRenderer* mState;
200    uint32_t mFontId;
201    float mFontSize;
202    int mFlags;
203    uint32_t mItalicStyle;
204    uint32_t mScaleX;
205    SkPaint::Style mStyle;
206    uint32_t mStrokeWidth;
207};
208
209///////////////////////////////////////////////////////////////////////////////
210// Renderer
211///////////////////////////////////////////////////////////////////////////////
212
213class FontRenderer {
214public:
215    FontRenderer();
216    ~FontRenderer();
217
218    void init();
219    void deinit();
220
221    void setGammaTable(const uint8_t* gammaTable) {
222        mGammaTable = gammaTable;
223    }
224
225    inline float* getMeshBuffer() {
226        checkInit();
227        return mTextMeshPtr;
228    }
229
230    inline int getMeshTexCoordsOffset() const {
231        return 2;
232    }
233
234    void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
235    bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
236            uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
237
238    struct DropShadow {
239        DropShadow() { };
240
241        DropShadow(const DropShadow& dropShadow):
242            width(dropShadow.width), height(dropShadow.height),
243            image(dropShadow.image), penX(dropShadow.penX),
244            penY(dropShadow.penY) {
245        }
246
247        uint32_t width;
248        uint32_t height;
249        uint8_t* image;
250        int32_t penX;
251        int32_t penY;
252    };
253
254    // After renderDropShadow returns, the called owns the memory in DropShadow.image
255    // and is responsible for releasing it when it's done with it
256    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
257            uint32_t len, int numGlyphs, uint32_t radius);
258
259    GLuint getTexture(bool linearFiltering = false) {
260        checkInit();
261        if (linearFiltering != mLinearFiltering) {
262            mLinearFiltering = linearFiltering;
263            const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
264
265            glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
266            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
267            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
268        }
269        return mCurrentCacheTexture->mTextureId;
270    }
271
272    uint32_t getCacheSize() const {
273        uint32_t size = 0;
274        if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
275            size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
276        }
277        if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
278            size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
279        }
280        if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
281            size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
282        }
283        if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
284            size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
285        }
286        return size;
287    }
288
289protected:
290    friend class Font;
291
292    const uint8_t* mGammaTable;
293
294    uint8_t* allocateTextureMemory(int width, int height);
295    void initTextTexture();
296    CacheTexture *createCacheTexture(int width, int height, bool allocate);
297    void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
298            uint32_t *retOriginX, uint32_t *retOriginY);
299
300    void flushAllAndInvalidate();
301    void initVertexArrayBuffers();
302
303    void checkInit();
304
305    String16 mLatinPrecache;
306    void precacheLatin(SkPaint* paint);
307
308    void issueDrawCommand();
309    void appendMeshQuad(float x1, float y1, float u1, float v1,
310            float x2, float y2, float u2, float v2,
311            float x3, float y3, float u3, float v3,
312            float x4, float y4, float u4, float v4, CacheTexture* texture);
313
314    uint32_t mSmallCacheWidth;
315    uint32_t mSmallCacheHeight;
316
317    Vector<CacheTextureLine*> mCacheLines;
318    uint32_t getRemainingCacheCapacity();
319
320    Font* mCurrentFont;
321    Vector<Font*> mActiveFonts;
322
323    CacheTexture* mCurrentCacheTexture;
324    CacheTexture* mLastCacheTexture;
325    CacheTexture* mCacheTextureSmall;
326    CacheTexture* mCacheTexture128;
327    CacheTexture* mCacheTexture256;
328    CacheTexture* mCacheTexture512;
329
330
331    void checkTextureUpdate();
332    bool mUploadTexture;
333
334    // Pointer to vertex data to speed up frame to frame work
335    float *mTextMeshPtr;
336    uint32_t mCurrentQuadIndex;
337    uint32_t mMaxNumberOfQuads;
338
339    uint32_t mIndexBufferID;
340
341    const Rect* mClip;
342    Rect* mBounds;
343    bool mDrawn;
344
345    bool mInitialized;
346
347    bool mLinearFiltering;
348
349    void computeGaussianWeights(float* weights, int32_t radius);
350    void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
351            int32_t width, int32_t height);
352    void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
353            int32_t width, int32_t height);
354    void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
355};
356
357}; // namespace uirenderer
358}; // namespace android
359
360#endif // ANDROID_HWUI_FONT_RENDERER_H
361