FontRenderer.h revision e816baea651476aca4407200d4a5e629b9ab8dfa
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#define TEXTURE_BORDER_SIZE 1
57
58///////////////////////////////////////////////////////////////////////////////
59// Declarations
60///////////////////////////////////////////////////////////////////////////////
61
62class FontRenderer;
63
64class CacheTexture {
65public:
66    CacheTexture(uint16_t width, uint16_t height) :
67            mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height),
68            mLinearFiltering(false) { }
69    ~CacheTexture() {
70        if (mTexture) {
71            delete[] mTexture;
72        }
73        if (mTextureId) {
74            glDeleteTextures(1, &mTextureId);
75        }
76    }
77
78    uint8_t* mTexture;
79    GLuint mTextureId;
80    uint16_t mWidth;
81    uint16_t mHeight;
82    bool mLinearFiltering;
83};
84
85/**
86 * CacheBlock is a noce in a linked list of current free space areas in a CacheTextureLine.
87 * Using CacheBlocks enables us to pack the cache line from top to bottom as well as left to right.
88 * When we add a glyph to the cache, we see if it fits within one of the existing columns that
89 * have already been started (this is the case if the glyph fits vertically as well as
90 * horizontally, and if its width is sufficiently close to the column width to avoid
91 * sub-optimal packing of small glyphs into wide columns). If there is no column in which the
92 * glyph fits, we check the final node, which is the remaining space in the cache line, creating
93 * a new column as appropriate.
94 *
95 * As columns fill up, we remove their CacheBlock from the list to avoid having to check
96 * small blocks in the future.
97 */
98struct CacheBlock {
99    uint16_t mX;
100    uint16_t mY;
101    uint16_t mWidth;
102    uint16_t mHeight;
103    CacheBlock* mNext;
104    CacheBlock* mPrev;
105
106    CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool empty = false):
107        mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL)
108    {
109    }
110
111    static CacheBlock* insertBlock(CacheBlock* head, CacheBlock *newBlock);
112
113    static CacheBlock* removeBlock(CacheBlock* head, CacheBlock *blockToRemove);
114
115    void output() {
116        CacheBlock *currBlock = this;
117        while (currBlock) {
118            ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d",
119                    currBlock, currBlock->mX, currBlock->mY, currBlock->mWidth, currBlock->mHeight);
120            currBlock = currBlock->mNext;
121        }
122    }
123};
124
125class CacheTextureLine {
126public:
127    CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
128            CacheTexture* cacheTexture):
129                mMaxHeight(maxHeight),
130                mMaxWidth(maxWidth),
131                mCurrentRow(currentRow),
132                mDirty(false),
133                mNumGlyphs(0),
134                mCacheTexture(cacheTexture) {
135        mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
136                maxWidth - TEXTURE_BORDER_SIZE, maxHeight - TEXTURE_BORDER_SIZE, true);
137    }
138
139    ~CacheTextureLine() {
140        reset();
141    }
142
143    void reset() {
144        // Delete existing cache blocks
145        while (mCacheBlocks != NULL) {
146            CacheBlock* tmpBlock = mCacheBlocks;
147            mCacheBlocks = mCacheBlocks->mNext;
148            delete tmpBlock;
149        }
150        mNumGlyphs = 0;
151    }
152
153    void init() {
154        // reset, then create a new remainder space to start again
155        reset();
156        mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
157                mMaxWidth - TEXTURE_BORDER_SIZE, mMaxHeight - TEXTURE_BORDER_SIZE, true);
158    }
159
160    bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
161
162    uint16_t mMaxHeight;
163    uint16_t mMaxWidth;
164    uint32_t mCurrentRow;
165    bool mDirty;
166    uint16_t mNumGlyphs;
167    CacheTexture* mCacheTexture;
168    CacheBlock* mCacheBlocks;
169};
170
171struct CachedGlyphInfo {
172    // Has the cache been invalidated?
173    bool mIsValid;
174    // Location of the cached glyph in the bitmap
175    // in case we need to resize the texture or
176    // render to bitmap
177    uint32_t mStartX;
178    uint32_t mStartY;
179    uint32_t mBitmapWidth;
180    uint32_t mBitmapHeight;
181    // Also cache texture coords for the quad
182    float mBitmapMinU;
183    float mBitmapMinV;
184    float mBitmapMaxU;
185    float mBitmapMaxV;
186    // Minimize how much we call freetype
187    uint32_t mGlyphIndex;
188    uint32_t mAdvanceX;
189    uint32_t mAdvanceY;
190    // Values below contain a glyph's origin in the bitmap
191    int32_t mBitmapLeft;
192    int32_t mBitmapTop;
193    // Auto-kerning
194    SkFixed mLsbDelta;
195    SkFixed mRsbDelta;
196    CacheTextureLine* mCachedTextureLine;
197};
198
199
200///////////////////////////////////////////////////////////////////////////////
201// Font
202///////////////////////////////////////////////////////////////////////////////
203
204/**
205 * Represents a font, defined by a Skia font id and a font size. A font is used
206 * to generate glyphs and cache them in the FontState.
207 */
208class Font {
209public:
210    enum Style {
211        kFakeBold = 1
212    };
213
214    ~Font();
215
216    /**
217     * Renders the specified string of text.
218     * If bitmap is specified, it will be used as the render target
219     */
220    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
221            int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
222            uint32_t bitmapW = 0, uint32_t bitmapH = 0);
223
224    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
225            int numGlyphs, int x, int y, const float* positions);
226
227    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
228            int numGlyphs, SkPath* path, float hOffset, float vOffset);
229
230    /**
231     * Creates a new font associated with the specified font state.
232     */
233    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
234            int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
235            uint32_t strokeWidth);
236
237protected:
238    friend class FontRenderer;
239    typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*,
240            uint32_t, uint32_t, Rect*, const float*);
241
242    enum RenderMode {
243        FRAMEBUFFER,
244        BITMAP,
245        MEASURE,
246    };
247
248    void precache(SkPaint* paint, const char* text, int numGlyphs);
249
250    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
251            int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
252            uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
253
254    void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
255            int numGlyphs, Rect *bounds, const float* positions);
256
257    Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
258            uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
259
260    // Cache of glyphs
261    DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
262
263    void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
264
265    CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
266    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
267
268    void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
269            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
270            Rect* bounds, const float* pos);
271    void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
272            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
273            Rect* bounds, const float* pos);
274    void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
275            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
276            Rect* bounds, const float* pos);
277    void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
278            SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
279
280    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
281
282    static glyph_t nextGlyph(const uint16_t** srcPtr) {
283        const uint16_t* src = *srcPtr;
284        glyph_t g = *src++;
285        *srcPtr = src;
286        return g;
287    }
288
289    FontRenderer* mState;
290    uint32_t mFontId;
291    float mFontSize;
292    int mFlags;
293    uint32_t mItalicStyle;
294    uint32_t mScaleX;
295    SkPaint::Style mStyle;
296    uint32_t mStrokeWidth;
297};
298
299///////////////////////////////////////////////////////////////////////////////
300// Renderer
301///////////////////////////////////////////////////////////////////////////////
302
303class FontRenderer {
304public:
305    FontRenderer();
306    ~FontRenderer();
307
308    void flushLargeCaches();
309
310    void setGammaTable(const uint8_t* gammaTable) {
311        mGammaTable = gammaTable;
312    }
313
314    void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
315
316    void precache(SkPaint* paint, const char* text, int numGlyphs);
317
318    // bounds is an out parameter
319    bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
320            uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
321    // bounds is an out parameter
322    bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
323            uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds);
324    // bounds is an out parameter
325    bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
326            uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds);
327
328    struct DropShadow {
329        DropShadow() { };
330
331        DropShadow(const DropShadow& dropShadow):
332            width(dropShadow.width), height(dropShadow.height),
333            image(dropShadow.image), penX(dropShadow.penX),
334            penY(dropShadow.penY) {
335        }
336
337        uint32_t width;
338        uint32_t height;
339        uint8_t* image;
340        int32_t penX;
341        int32_t penY;
342    };
343
344    // After renderDropShadow returns, the called owns the memory in DropShadow.image
345    // and is responsible for releasing it when it's done with it
346    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
347            uint32_t len, int numGlyphs, uint32_t radius, const float* positions);
348
349    GLuint getTexture(bool linearFiltering = false) {
350        checkInit();
351
352        if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
353            mCurrentCacheTexture->mLinearFiltering = linearFiltering;
354            mLinearFiltering = linearFiltering;
355            const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
356
357            glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
358            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
359            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
360        }
361
362        return mCurrentCacheTexture->mTextureId;
363    }
364
365    uint32_t getCacheSize() const {
366        uint32_t size = 0;
367        if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
368            size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
369        }
370        if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
371            size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
372        }
373        if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
374            size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
375        }
376        if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
377            size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
378        }
379        return size;
380    }
381
382protected:
383    friend class Font;
384
385    const uint8_t* mGammaTable;
386
387    void allocateTextureMemory(CacheTexture* cacheTexture);
388    void deallocateTextureMemory(CacheTexture* cacheTexture);
389    void initTextTexture();
390    CacheTexture* createCacheTexture(int width, int height, bool allocate);
391    void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
392            uint32_t *retOriginX, uint32_t *retOriginY);
393
394    void flushAllAndInvalidate();
395    void initVertexArrayBuffers();
396
397    void checkInit();
398    void initRender(const Rect* clip, Rect* bounds);
399    void finishRender();
400
401    void issueDrawCommand();
402    void appendMeshQuadNoClip(float x1, float y1, float u1, float v1,
403            float x2, float y2, float u2, float v2,
404            float x3, float y3, float u3, float v3,
405            float x4, float y4, float u4, float v4, CacheTexture* texture);
406    void appendMeshQuad(float x1, float y1, float u1, float v1,
407            float x2, float y2, float u2, float v2,
408            float x3, float y3, float u3, float v3,
409            float x4, float y4, float u4, float v4, CacheTexture* texture);
410    void appendRotatedMeshQuad(float x1, float y1, float u1, float v1,
411            float x2, float y2, float u2, float v2,
412            float x3, float y3, float u3, float v3,
413            float x4, float y4, float u4, float v4, CacheTexture* texture);
414
415    uint32_t mSmallCacheWidth;
416    uint32_t mSmallCacheHeight;
417
418    Vector<CacheTextureLine*> mCacheLines;
419
420    Font* mCurrentFont;
421    Vector<Font*> mActiveFonts;
422
423    CacheTexture* mCurrentCacheTexture;
424    CacheTexture* mLastCacheTexture;
425    CacheTexture* mCacheTextureSmall;
426    CacheTexture* mCacheTexture128;
427    CacheTexture* mCacheTexture256;
428    CacheTexture* mCacheTexture512;
429
430    void checkTextureUpdate();
431    bool mUploadTexture;
432
433    // Pointer to vertex data to speed up frame to frame work
434    float *mTextMeshPtr;
435    uint32_t mCurrentQuadIndex;
436    uint32_t mMaxNumberOfQuads;
437
438    uint32_t mIndexBufferID;
439
440    const Rect* mClip;
441    Rect* mBounds;
442    bool mDrawn;
443
444    bool mInitialized;
445
446    bool mLinearFiltering;
447
448    void computeGaussianWeights(float* weights, int32_t radius);
449    void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
450            int32_t width, int32_t height);
451    void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
452            int32_t width, int32_t height);
453    void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
454};
455
456}; // namespace uirenderer
457}; // namespace android
458
459#endif // ANDROID_HWUI_FONT_RENDERER_H
460