FontRenderer.h revision 9777173eb6c9eb97c7921c8288ebc65e3ab3ce6f
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 GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph)
45    #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
46    #define IS_END_OF_STRING(glyph) false
47#else
48    typedef SkUnichar glyph_t;
49    #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph)
50    #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
51    #define IS_END_OF_STRING(glyph) glyph < 0
52#endif
53
54///////////////////////////////////////////////////////////////////////////////
55// Declarations
56///////////////////////////////////////////////////////////////////////////////
57
58class FontRenderer;
59
60class CacheTexture {
61public:
62    CacheTexture(){}
63    CacheTexture(uint8_t* texture, GLuint textureId, uint16_t width, uint16_t height) :
64        mTexture(texture), mTextureId(textureId), mWidth(width), mHeight(height),
65        mLinearFiltering(false) {}
66    ~CacheTexture() {
67        if (mTexture != NULL) {
68            delete[] mTexture;
69        }
70        if (mTextureId != 0) {
71            glDeleteTextures(1, &mTextureId);
72        }
73    }
74
75    uint8_t* mTexture;
76    GLuint mTextureId;
77    uint16_t mWidth;
78    uint16_t mHeight;
79    bool mLinearFiltering;
80};
81
82class CacheTextureLine {
83public:
84    CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
85            uint32_t currentCol, CacheTexture* cacheTexture):
86                mMaxHeight(maxHeight),
87                mMaxWidth(maxWidth),
88                mCurrentRow(currentRow),
89                mCurrentCol(currentCol),
90                mDirty(false),
91                mCacheTexture(cacheTexture){
92    }
93
94    bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
95
96    uint16_t mMaxHeight;
97    uint16_t mMaxWidth;
98    uint32_t mCurrentRow;
99    uint32_t mCurrentCol;
100    bool mDirty;
101    CacheTexture *mCacheTexture;
102};
103
104struct CachedGlyphInfo {
105    // Has the cache been invalidated?
106    bool mIsValid;
107    // Location of the cached glyph in the bitmap
108    // in case we need to resize the texture or
109    // render to bitmap
110    uint32_t mStartX;
111    uint32_t mStartY;
112    uint32_t mBitmapWidth;
113    uint32_t mBitmapHeight;
114    // Also cache texture coords for the quad
115    float mBitmapMinU;
116    float mBitmapMinV;
117    float mBitmapMaxU;
118    float mBitmapMaxV;
119    // Minimize how much we call freetype
120    uint32_t mGlyphIndex;
121    uint32_t mAdvanceX;
122    uint32_t mAdvanceY;
123    // Values below contain a glyph's origin in the bitmap
124    int32_t mBitmapLeft;
125    int32_t mBitmapTop;
126    // Auto-kerning
127    SkFixed mLsbDelta;
128    SkFixed mRsbDelta;
129    CacheTextureLine* mCachedTextureLine;
130};
131
132
133///////////////////////////////////////////////////////////////////////////////
134// Font
135///////////////////////////////////////////////////////////////////////////////
136
137/**
138 * Represents a font, defined by a Skia font id and a font size. A font is used
139 * to generate glyphs and cache them in the FontState.
140 */
141class Font {
142public:
143    enum Style {
144        kFakeBold = 1
145    };
146
147    ~Font();
148
149    /**
150     * Renders the specified string of text.
151     * If bitmap is specified, it will be used as the render target
152     */
153    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
154            int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
155            uint32_t bitmapW = 0, uint32_t bitmapH = 0);
156
157    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
158            int numGlyphs, int x, int y, const float* positions);
159
160    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
161            int numGlyphs, SkPath* path, float hOffset, float vOffset);
162
163    /**
164     * Creates a new font associated with the specified font state.
165     */
166    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
167            int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
168            uint32_t strokeWidth);
169
170protected:
171    friend class FontRenderer;
172    typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*,
173            uint32_t, uint32_t, Rect*, const float*);
174
175    enum RenderMode {
176        FRAMEBUFFER,
177        BITMAP,
178        MEASURE,
179    };
180
181    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
182            int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
183            uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
184
185    void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
186            int numGlyphs, Rect *bounds);
187
188    Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
189            uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
190
191    // Cache of glyphs
192    DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
193
194    void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
195
196    CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
197    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
198
199    void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
200            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
201            Rect* bounds, const float* pos);
202    void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
203            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
204            Rect* bounds, const float* pos);
205    void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
206            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
207            Rect* bounds, const float* pos);
208    void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
209            SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
210
211    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
212
213    static glyph_t nextGlyph(const uint16_t** srcPtr) {
214        const uint16_t* src = *srcPtr;
215        glyph_t g = *src++;
216        *srcPtr = src;
217        return g;
218    }
219
220    FontRenderer* mState;
221    uint32_t mFontId;
222    float mFontSize;
223    int mFlags;
224    uint32_t mItalicStyle;
225    uint32_t mScaleX;
226    SkPaint::Style mStyle;
227    uint32_t mStrokeWidth;
228};
229
230///////////////////////////////////////////////////////////////////////////////
231// Renderer
232///////////////////////////////////////////////////////////////////////////////
233
234class FontRenderer {
235public:
236    FontRenderer();
237    ~FontRenderer();
238
239    void init();
240    void deinit();
241    void flushLargeCaches();
242
243    void setGammaTable(const uint8_t* gammaTable) {
244        mGammaTable = gammaTable;
245    }
246
247    void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
248    // bounds is an out parameter
249    bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
250            uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
251    // bounds is an out parameter
252    bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
253            uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds);
254    // bounds is an out parameter
255    bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
256            uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds);
257
258    struct DropShadow {
259        DropShadow() { };
260
261        DropShadow(const DropShadow& dropShadow):
262            width(dropShadow.width), height(dropShadow.height),
263            image(dropShadow.image), penX(dropShadow.penX),
264            penY(dropShadow.penY) {
265        }
266
267        uint32_t width;
268        uint32_t height;
269        uint8_t* image;
270        int32_t penX;
271        int32_t penY;
272    };
273
274    // After renderDropShadow returns, the called owns the memory in DropShadow.image
275    // and is responsible for releasing it when it's done with it
276    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
277            uint32_t len, int numGlyphs, uint32_t radius);
278
279    GLuint getTexture(bool linearFiltering = false) {
280        checkInit();
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        return mCurrentCacheTexture->mTextureId;
291    }
292
293    uint32_t getCacheSize() const {
294        uint32_t size = 0;
295        if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
296            size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
297        }
298        if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
299            size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
300        }
301        if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
302            size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
303        }
304        if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
305            size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
306        }
307        return size;
308    }
309
310protected:
311    friend class Font;
312
313    const uint8_t* mGammaTable;
314
315    void allocateTextureMemory(CacheTexture* cacheTexture);
316    void deallocateTextureMemory(CacheTexture* cacheTexture);
317    void initTextTexture();
318    CacheTexture* createCacheTexture(int width, int height, bool allocate);
319    void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
320            uint32_t *retOriginX, uint32_t *retOriginY);
321
322    void flushAllAndInvalidate();
323    void initVertexArrayBuffers();
324
325    void checkInit();
326    void initRender(const Rect* clip, Rect* bounds);
327    void finishRender();
328
329    String16 mLatinPrecache;
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