FontRenderer.h revision 671d6cf460531825a321edb200523d0faa7792c9
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
28#include <GLES2/gl2.h>
29
30#include "Rect.h"
31#include "Properties.h"
32
33namespace android {
34namespace uirenderer {
35
36///////////////////////////////////////////////////////////////////////////////
37// Defines
38///////////////////////////////////////////////////////////////////////////////
39
40#if RENDER_TEXT_AS_GLYPHS
41    typedef uint16_t glyph_t;
42    #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph)
43    #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
44    #define IS_END_OF_STRING(glyph) false
45#else
46    typedef SkUnichar glyph_t;
47    #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph)
48    #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
49    #define IS_END_OF_STRING(glyph) glyph < 0
50#endif
51
52///////////////////////////////////////////////////////////////////////////////
53// Declarations
54///////////////////////////////////////////////////////////////////////////////
55
56class FontRenderer;
57
58class CacheTexture {
59public:
60    CacheTexture(){}
61    CacheTexture(uint8_t* texture, GLuint textureId, uint16_t width, uint16_t height) :
62        mTexture(texture), mTextureId(textureId), mWidth(width), mHeight(height),
63        mLinearFiltering(false) {}
64    ~CacheTexture() {
65        if (mTexture != NULL) {
66            delete[] mTexture;
67        }
68        if (mTextureId != 0) {
69            glDeleteTextures(1, &mTextureId);
70        }
71    }
72
73    uint8_t* mTexture;
74    GLuint mTextureId;
75    uint16_t mWidth;
76    uint16_t mHeight;
77    bool mLinearFiltering;
78};
79
80class CacheTextureLine {
81public:
82    CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
83            uint32_t currentCol, CacheTexture* cacheTexture):
84                mMaxHeight(maxHeight),
85                mMaxWidth(maxWidth),
86                mCurrentRow(currentRow),
87                mCurrentCol(currentCol),
88                mDirty(false),
89                mCacheTexture(cacheTexture){
90    }
91
92    bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
93
94    uint16_t mMaxHeight;
95    uint16_t mMaxWidth;
96    uint32_t mCurrentRow;
97    uint32_t mCurrentCol;
98    bool mDirty;
99    CacheTexture *mCacheTexture;
100};
101
102struct CachedGlyphInfo {
103    // Has the cache been invalidated?
104    bool mIsValid;
105    // Location of the cached glyph in the bitmap
106    // in case we need to resize the texture or
107    // render to bitmap
108    uint32_t mStartX;
109    uint32_t mStartY;
110    uint32_t mBitmapWidth;
111    uint32_t mBitmapHeight;
112    // Also cache texture coords for the quad
113    float mBitmapMinU;
114    float mBitmapMinV;
115    float mBitmapMaxU;
116    float mBitmapMaxV;
117    // Minimize how much we call freetype
118    uint32_t mGlyphIndex;
119    uint32_t mAdvanceX;
120    uint32_t mAdvanceY;
121    // Values below contain a glyph's origin in the bitmap
122    int32_t mBitmapLeft;
123    int32_t mBitmapTop;
124    // Auto-kerning
125    SkFixed mLsbDelta;
126    SkFixed mRsbDelta;
127    CacheTextureLine* mCachedTextureLine;
128};
129
130
131///////////////////////////////////////////////////////////////////////////////
132// Font
133///////////////////////////////////////////////////////////////////////////////
134
135/**
136 * Represents a font, defined by a Skia font id and a font size. A font is used
137 * to generate glyphs and cache them in the FontState.
138 */
139class Font {
140public:
141    enum Style {
142        kFakeBold = 1
143    };
144
145    ~Font();
146
147    /**
148     * Renders the specified string of text.
149     * If bitmap is specified, it will be used as the render target
150     */
151    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
152            int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
153            uint32_t bitmapW = 0, uint32_t bitmapH = 0);
154
155    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
156            int numGlyphs, int x, int y, const float* positions);
157
158    /**
159     * Creates a new font associated with the specified font state.
160     */
161    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
162            int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
163            uint32_t strokeWidth);
164
165protected:
166    friend class FontRenderer;
167    typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*,
168            uint32_t, uint32_t, Rect*, const float*);
169
170    enum RenderMode {
171        FRAMEBUFFER,
172        BITMAP,
173        MEASURE,
174    };
175
176    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
177            int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
178            uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
179
180    void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
181            int numGlyphs, Rect *bounds);
182
183    Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
184            uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
185
186    // Cache of glyphs
187    DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
188
189    void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
190
191    CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
192    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
193
194    void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
195            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
196            Rect* bounds, const float* pos);
197    void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
198            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
199            Rect* bounds, const float* pos);
200    void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
201            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
202            Rect* bounds, const float* pos);
203
204    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
205
206    static glyph_t nextGlyph(const uint16_t** srcPtr) {
207        const uint16_t* src = *srcPtr;
208        glyph_t g = *src++;
209        *srcPtr = src;
210        return g;
211    }
212
213    FontRenderer* mState;
214    uint32_t mFontId;
215    float mFontSize;
216    int mFlags;
217    uint32_t mItalicStyle;
218    uint32_t mScaleX;
219    SkPaint::Style mStyle;
220    uint32_t mStrokeWidth;
221};
222
223///////////////////////////////////////////////////////////////////////////////
224// Renderer
225///////////////////////////////////////////////////////////////////////////////
226
227class FontRenderer {
228public:
229    FontRenderer();
230    ~FontRenderer();
231
232    void init();
233    void deinit();
234    void flushLargeCaches();
235
236    void setGammaTable(const uint8_t* gammaTable) {
237        mGammaTable = gammaTable;
238    }
239
240    void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
241    // bounds is an out parameter
242    bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
243            uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
244    // bounds is an out parameter
245    bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
246            uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds);
247
248    struct DropShadow {
249        DropShadow() { };
250
251        DropShadow(const DropShadow& dropShadow):
252            width(dropShadow.width), height(dropShadow.height),
253            image(dropShadow.image), penX(dropShadow.penX),
254            penY(dropShadow.penY) {
255        }
256
257        uint32_t width;
258        uint32_t height;
259        uint8_t* image;
260        int32_t penX;
261        int32_t penY;
262    };
263
264    // After renderDropShadow returns, the called owns the memory in DropShadow.image
265    // and is responsible for releasing it when it's done with it
266    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
267            uint32_t len, int numGlyphs, uint32_t radius);
268
269    GLuint getTexture(bool linearFiltering = false) {
270        checkInit();
271        if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
272            mCurrentCacheTexture->mLinearFiltering = linearFiltering;
273            mLinearFiltering = linearFiltering;
274            const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
275
276            glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
277            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
278            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
279        }
280        return mCurrentCacheTexture->mTextureId;
281    }
282
283    uint32_t getCacheSize() const {
284        uint32_t size = 0;
285        if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
286            size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
287        }
288        if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
289            size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
290        }
291        if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
292            size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
293        }
294        if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
295            size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
296        }
297        return size;
298    }
299
300protected:
301    friend class Font;
302
303    const uint8_t* mGammaTable;
304
305    void allocateTextureMemory(CacheTexture* cacheTexture);
306    void deallocateTextureMemory(CacheTexture* cacheTexture);
307    void initTextTexture();
308    CacheTexture *createCacheTexture(int width, int height, bool allocate);
309    void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
310            uint32_t *retOriginX, uint32_t *retOriginY);
311
312    void flushAllAndInvalidate();
313    void initVertexArrayBuffers();
314
315    void checkInit();
316    void initRender(const Rect* clip, Rect* bounds);
317    void finishRender();
318
319    String16 mLatinPrecache;
320    void precacheLatin(SkPaint* paint);
321
322    void issueDrawCommand();
323    void appendMeshQuad(float x1, float y1, float u1, float v1,
324            float x2, float y2, float u2, float v2,
325            float x3, float y3, float u3, float v3,
326            float x4, float y4, float u4, float v4, CacheTexture* texture);
327
328    uint32_t mSmallCacheWidth;
329    uint32_t mSmallCacheHeight;
330
331    Vector<CacheTextureLine*> mCacheLines;
332    uint32_t getRemainingCacheCapacity();
333
334    Font* mCurrentFont;
335    Vector<Font*> mActiveFonts;
336
337    CacheTexture* mCurrentCacheTexture;
338    CacheTexture* mLastCacheTexture;
339    CacheTexture* mCacheTextureSmall;
340    CacheTexture* mCacheTexture128;
341    CacheTexture* mCacheTexture256;
342    CacheTexture* mCacheTexture512;
343
344    void checkTextureUpdate();
345    bool mUploadTexture;
346
347    // Pointer to vertex data to speed up frame to frame work
348    float *mTextMeshPtr;
349    uint32_t mCurrentQuadIndex;
350    uint32_t mMaxNumberOfQuads;
351
352    uint32_t mIndexBufferID;
353
354    const Rect* mClip;
355    Rect* mBounds;
356    bool mDrawn;
357
358    bool mInitialized;
359
360    bool mLinearFiltering;
361
362    void computeGaussianWeights(float* weights, int32_t radius);
363    void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
364            int32_t width, int32_t height);
365    void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
366            int32_t width, int32_t height);
367    void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
368};
369
370}; // namespace uirenderer
371}; // namespace android
372
373#endif // ANDROID_HWUI_FONT_RENDERER_H
374