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