FontRenderer.h revision 378e919ccb75efe24d5a5aa75ac2c6ef255dcb48
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);
247    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
248
249    void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
250            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
251            Rect* bounds, const float* pos);
252    void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
253            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
254            Rect* bounds, const float* pos);
255    void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
256            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
257            Rect* bounds, const float* pos);
258    void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
259            SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
260
261    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
262
263    static glyph_t nextGlyph(const uint16_t** srcPtr) {
264        const uint16_t* src = *srcPtr;
265        glyph_t g = *src++;
266        *srcPtr = src;
267        return g;
268    }
269
270    FontRenderer* mState;
271    uint32_t mFontId;
272    float mFontSize;
273    int mFlags;
274    uint32_t mItalicStyle;
275    uint32_t mScaleX;
276    SkPaint::Style mStyle;
277    uint32_t mStrokeWidth;
278};
279
280///////////////////////////////////////////////////////////////////////////////
281// Renderer
282///////////////////////////////////////////////////////////////////////////////
283
284class FontRenderer {
285public:
286    FontRenderer();
287    ~FontRenderer();
288
289    void flushLargeCaches();
290
291    void setGammaTable(const uint8_t* gammaTable) {
292        mGammaTable = gammaTable;
293    }
294
295    void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
296
297    void precache(SkPaint* paint, const char* text, int numGlyphs);
298
299    // bounds is an out parameter
300    bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
301            uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
302    // bounds is an out parameter
303    bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
304            uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds);
305    // bounds is an out parameter
306    bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
307            uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds);
308
309    struct DropShadow {
310        DropShadow() { };
311
312        DropShadow(const DropShadow& dropShadow):
313            width(dropShadow.width), height(dropShadow.height),
314            image(dropShadow.image), penX(dropShadow.penX),
315            penY(dropShadow.penY) {
316        }
317
318        uint32_t width;
319        uint32_t height;
320        uint8_t* image;
321        int32_t penX;
322        int32_t penY;
323    };
324
325    // After renderDropShadow returns, the called owns the memory in DropShadow.image
326    // and is responsible for releasing it when it's done with it
327    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
328            uint32_t len, int numGlyphs, uint32_t radius, const float* positions);
329
330    GLuint getTexture(bool linearFiltering = false) {
331        checkInit();
332
333        if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
334            mCurrentCacheTexture->mLinearFiltering = linearFiltering;
335            mLinearFiltering = linearFiltering;
336            const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
337
338            glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
339            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
340            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
341        }
342
343        return mCurrentCacheTexture->mTextureId;
344    }
345
346    uint32_t getCacheSize() const {
347        uint32_t size = 0;
348        for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
349            CacheTexture* cacheTexture = mCacheTextures[i];
350            if (cacheTexture != NULL && cacheTexture->mTexture != NULL) {
351                size += cacheTexture->mWidth * cacheTexture->mHeight;
352            }
353        }
354        return size;
355    }
356
357protected:
358    friend class Font;
359
360    const uint8_t* mGammaTable;
361
362    void allocateTextureMemory(CacheTexture* cacheTexture);
363    void deallocateTextureMemory(CacheTexture* cacheTexture);
364    void initTextTexture();
365    CacheTexture* createCacheTexture(int width, int height, bool allocate);
366    void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
367            uint32_t *retOriginX, uint32_t *retOriginY);
368    CacheTexture* cacheBitmapInTexture(const SkGlyph& glyph, uint32_t* startX, uint32_t* startY);
369
370    void flushAllAndInvalidate();
371    void initVertexArrayBuffers();
372
373    void checkInit();
374    void initRender(const Rect* clip, Rect* bounds);
375    void finishRender();
376
377    void issueDrawCommand();
378    void appendMeshQuadNoClip(float x1, float y1, float u1, float v1,
379            float x2, float y2, float u2, float v2,
380            float x3, float y3, float u3, float v3,
381            float x4, float y4, float u4, float v4, CacheTexture* texture);
382    void appendMeshQuad(float x1, float y1, float u1, float v1,
383            float x2, float y2, float u2, float v2,
384            float x3, float y3, float u3, float v3,
385            float x4, float y4, float u4, float v4, CacheTexture* texture);
386    void appendRotatedMeshQuad(float x1, float y1, float u1, float v1,
387            float x2, float y2, float u2, float v2,
388            float x3, float y3, float u3, float v3,
389            float x4, float y4, float u4, float v4, CacheTexture* texture);
390
391    uint32_t mSmallCacheWidth;
392    uint32_t mSmallCacheHeight;
393
394    Vector<CacheTexture*> mCacheTextures;
395
396    Font* mCurrentFont;
397    Vector<Font*> mActiveFonts;
398
399    CacheTexture* mCurrentCacheTexture;
400    CacheTexture* mLastCacheTexture;
401
402    void checkTextureUpdate();
403    bool mUploadTexture;
404
405    // Pointer to vertex data to speed up frame to frame work
406    float *mTextMeshPtr;
407    uint32_t mCurrentQuadIndex;
408    uint32_t mMaxNumberOfQuads;
409
410    uint32_t mIndexBufferID;
411
412    const Rect* mClip;
413    Rect* mBounds;
414    bool mDrawn;
415
416    bool mInitialized;
417
418    bool mLinearFiltering;
419
420    void computeGaussianWeights(float* weights, int32_t radius);
421    void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
422            int32_t width, int32_t height);
423    void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
424            int32_t width, int32_t height);
425    void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
426};
427
428}; // namespace uirenderer
429}; // namespace android
430
431#endif // ANDROID_HWUI_FONT_RENDERER_H
432