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