FontRenderer.h revision f18136cb3c881a9d16c1a4f0f341732c276936bf
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_UI_FONT_RENDERER_H
18#define ANDROID_UI_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
36class FontRenderer;
37
38/**
39 * Represents a font, defined by a Skia font id and a font size. A font is used
40 * to generate glyphs and cache them in the FontState.
41 */
42class Font {
43public:
44    ~Font();
45
46    /**
47     * Renders the specified string of text.
48     * If bitmap is specified, it will be used as the render target
49     */
50    void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
51                     int numGlyphs, int x, int y,
52                     uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0);
53    /**
54     * Creates a new font associated with the specified font state.
55     */
56    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize);
57
58protected:
59    friend class FontRenderer;
60
61    enum RenderMode {
62        FRAMEBUFFER,
63        BITMAP,
64        MEASURE,
65    };
66
67    void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
68                     int numGlyphs, int x, int y, RenderMode mode,
69                     uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
70                     Rect *bounds);
71
72    void measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
73                      int numGlyphs, Rect *bounds);
74
75    struct CachedGlyphInfo {
76        // Has the cache been invalidated?
77        bool mIsValid;
78        // Location of the cached glyph in the bitmap
79        // in case we need to resize the texture or
80        // render to bitmap
81        uint32_t mStartX;
82        uint32_t mStartY;
83        uint32_t mBitmapWidth;
84        uint32_t mBitmapHeight;
85        // Also cache texture coords for the quad
86        float mBitmapMinU;
87        float mBitmapMinV;
88        float mBitmapMaxU;
89        float mBitmapMaxV;
90        // Minimize how much we call freetype
91        uint32_t mGlyphIndex;
92        uint32_t mAdvanceX;
93        uint32_t mAdvanceY;
94        // Values below contain a glyph's origin in the bitmap
95        int32_t mBitmapLeft;
96        int32_t mBitmapTop;
97    };
98
99    Font(FontRenderer* state, uint32_t fontId, float fontSize);
100
101    DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs;
102
103    void invalidateTextureCache();
104
105    CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_t glyph);
106    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
107    void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
108    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
109    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
110                          uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
111
112    CachedGlyphInfo* getCachedUTFChar(SkPaint* paint, int32_t utfChar);
113
114    FontRenderer* mState;
115    uint32_t mFontId;
116    float mFontSize;
117};
118
119class FontRenderer {
120public:
121    FontRenderer();
122    ~FontRenderer();
123
124    void init();
125    void deinit();
126
127    void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
128    void renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
129            uint32_t len, int numGlyphs, int x, int y);
130
131    struct DropShadow {
132        uint32_t width;
133        uint32_t height;
134        uint8_t* image;
135        int32_t penX;
136        int32_t penY;
137    };
138
139    // After renderDropShadow returns, the called owns the memory in DropShadow.image
140    // and is responsible for releasing it when it's done with it
141    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
142                                   uint32_t len, int numGlyphs, uint32_t radius);
143
144    GLuint getTexture() {
145        checkInit();
146        return mTextureId;
147    }
148
149protected:
150    friend class Font;
151
152    struct CacheTextureLine {
153        uint16_t mMaxHeight;
154        uint16_t mMaxWidth;
155        uint32_t mCurrentRow;
156        uint32_t mCurrentCol;
157        bool     mDirty;
158
159        CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
160                uint32_t currentCol):
161                    mMaxHeight(maxHeight),
162                    mMaxWidth(maxWidth),
163                    mCurrentRow(currentRow),
164                    mCurrentCol(currentCol),
165                    mDirty(false) {
166        }
167
168        bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
169            if (glyph.fHeight > mMaxHeight) {
170                return false;
171            }
172
173            if (mCurrentCol + glyph.fWidth < mMaxWidth) {
174                *retOriginX = mCurrentCol;
175                *retOriginY = mCurrentRow;
176                mCurrentCol += glyph.fWidth;
177                mDirty = true;
178                return true;
179            }
180
181            return false;
182        }
183    };
184
185    uint32_t getCacheWidth() const {
186        return mCacheWidth;
187    }
188
189    uint32_t getCacheHeight() const {
190        return mCacheHeight;
191    }
192
193    void initTextTexture();
194    bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
195
196    void flushAllAndInvalidate();
197    void initVertexArrayBuffers();
198
199    void checkInit();
200
201    String16 mLatinPrecache;
202    void precacheLatin(SkPaint* paint);
203
204    void issueDrawCommand();
205    void appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2,
206            float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3,
207            float x4, float y4, float z4, float u4, float v4);
208
209    uint32_t mCacheWidth;
210    uint32_t mCacheHeight;
211
212    Vector<CacheTextureLine*> mCacheLines;
213    uint32_t getRemainingCacheCapacity();
214
215    Font* mCurrentFont;
216    Vector<Font*> mActiveFonts;
217
218    // Texture to cache glyph bitmaps
219    uint8_t* mTextTexture;
220    const uint8_t* getTextTextureData() const {
221        return mTextTexture;
222    }
223    GLuint mTextureId;
224    void checkTextureUpdate();
225    bool mUploadTexture;
226
227    // Pointer to vertex data to speed up frame to frame work
228    float *mTextMeshPtr;
229    uint32_t mCurrentQuadIndex;
230    uint32_t mMaxNumberOfQuads;
231
232    uint32_t mIndexBufferID;
233
234    const Rect* mClip;
235
236    bool mInitialized;
237
238    void computeGaussianWeights(float* weights, int32_t radius);
239    void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
240                         int32_t width, int32_t height);
241    void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
242                         int32_t width, int32_t height);
243    void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
244};
245
246}; // namespace uirenderer
247}; // namespace android
248
249#endif // ANDROID_UI_FONT_RENDERER_H
250