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