FontRenderer.h revision 2a47c14e2a6f152496b43104bc785c488583fd59
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     * Creates a new font associated with the specified font state.
156     */
157    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
158            int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
159            uint32_t strokeWidth);
160
161protected:
162    friend class FontRenderer;
163
164    enum RenderMode {
165        FRAMEBUFFER,
166        BITMAP,
167        MEASURE,
168    };
169
170    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
171            int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
172            uint32_t bitmapW, uint32_t bitmapH, Rect *bounds);
173
174    void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
175            int numGlyphs, Rect *bounds);
176
177    Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
178            uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
179
180    // Cache of glyphs
181    DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
182
183    void invalidateTextureCache();
184
185    CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
186    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
187    void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
188    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
189    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
190            uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
191
192    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
193
194    static glyph_t nextGlyph(const uint16_t** srcPtr) {
195        const uint16_t* src = *srcPtr;
196        glyph_t g = *src++;
197        *srcPtr = src;
198        return g;
199    }
200
201    FontRenderer* mState;
202    uint32_t mFontId;
203    float mFontSize;
204    int mFlags;
205    uint32_t mItalicStyle;
206    uint32_t mScaleX;
207    SkPaint::Style mStyle;
208    uint32_t mStrokeWidth;
209};
210
211///////////////////////////////////////////////////////////////////////////////
212// Renderer
213///////////////////////////////////////////////////////////////////////////////
214
215class FontRenderer {
216public:
217    FontRenderer();
218    ~FontRenderer();
219
220    void init();
221    void deinit();
222
223    void setGammaTable(const uint8_t* gammaTable) {
224        mGammaTable = gammaTable;
225    }
226
227    void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
228    bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
229            uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
230
231    struct DropShadow {
232        DropShadow() { };
233
234        DropShadow(const DropShadow& dropShadow):
235            width(dropShadow.width), height(dropShadow.height),
236            image(dropShadow.image), penX(dropShadow.penX),
237            penY(dropShadow.penY) {
238        }
239
240        uint32_t width;
241        uint32_t height;
242        uint8_t* image;
243        int32_t penX;
244        int32_t penY;
245    };
246
247    // After renderDropShadow returns, the called owns the memory in DropShadow.image
248    // and is responsible for releasing it when it's done with it
249    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
250            uint32_t len, int numGlyphs, uint32_t radius);
251
252    GLuint getTexture(bool linearFiltering = false) {
253        checkInit();
254        if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
255            mCurrentCacheTexture->mLinearFiltering = linearFiltering;
256            mLinearFiltering = linearFiltering;
257            const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
258
259            glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
260            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
261            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
262        }
263        return mCurrentCacheTexture->mTextureId;
264    }
265
266    uint32_t getCacheSize() const {
267        uint32_t size = 0;
268        if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
269            size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
270        }
271        if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
272            size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
273        }
274        if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
275            size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
276        }
277        if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
278            size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
279        }
280        return size;
281    }
282
283protected:
284    friend class Font;
285
286    const uint8_t* mGammaTable;
287
288    void allocateTextureMemory(CacheTexture* cacheTexture);
289    void initTextTexture();
290    CacheTexture *createCacheTexture(int width, int height, bool allocate);
291    void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
292            uint32_t *retOriginX, uint32_t *retOriginY);
293
294    void flushAllAndInvalidate();
295    void initVertexArrayBuffers();
296
297    void checkInit();
298
299    String16 mLatinPrecache;
300    void precacheLatin(SkPaint* paint);
301
302    void issueDrawCommand();
303    void appendMeshQuad(float x1, float y1, float u1, float v1,
304            float x2, float y2, float u2, float v2,
305            float x3, float y3, float u3, float v3,
306            float x4, float y4, float u4, float v4, CacheTexture* texture);
307
308    uint32_t mSmallCacheWidth;
309    uint32_t mSmallCacheHeight;
310
311    Vector<CacheTextureLine*> mCacheLines;
312    uint32_t getRemainingCacheCapacity();
313
314    Font* mCurrentFont;
315    Vector<Font*> mActiveFonts;
316
317    CacheTexture* mCurrentCacheTexture;
318    CacheTexture* mLastCacheTexture;
319    CacheTexture* mCacheTextureSmall;
320    CacheTexture* mCacheTexture128;
321    CacheTexture* mCacheTexture256;
322    CacheTexture* mCacheTexture512;
323
324    void checkTextureUpdate();
325    bool mUploadTexture;
326
327    // Pointer to vertex data to speed up frame to frame work
328    float *mTextMeshPtr;
329    uint32_t mCurrentQuadIndex;
330    uint32_t mMaxNumberOfQuads;
331
332    uint32_t mIndexBufferID;
333
334    const Rect* mClip;
335    Rect* mBounds;
336    bool mDrawn;
337
338    bool mInitialized;
339
340    bool mLinearFiltering;
341
342    void computeGaussianWeights(float* weights, int32_t radius);
343    void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
344            int32_t width, int32_t height);
345    void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
346            int32_t width, int32_t height);
347    void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
348};
349
350}; // namespace uirenderer
351}; // namespace android
352
353#endif // ANDROID_HWUI_FONT_RENDERER_H
354