FontRenderer.h revision 7975fb6d12cb1eb96b75e3a563627cd4c4081bd6
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        // Auto-kerning
98        SkFixed mLsbDelta;
99        SkFixed mRsbDelta;
100    };
101
102    Font(FontRenderer* state, uint32_t fontId, float fontSize);
103
104    DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs;
105
106    void invalidateTextureCache();
107
108    CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_t glyph);
109    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
110    void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
111    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
112    void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
113                          uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
114
115    CachedGlyphInfo* getCachedUTFChar(SkPaint* paint, int32_t utfChar);
116
117    FontRenderer* mState;
118    uint32_t mFontId;
119    float mFontSize;
120};
121
122class FontRenderer {
123public:
124    FontRenderer();
125    ~FontRenderer();
126
127    void init();
128    void deinit();
129
130    void setGammaTable(const uint8_t* gammaTable) {
131        mGammaTable = gammaTable;
132    }
133
134    void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
135    void renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
136            uint32_t len, int numGlyphs, int x, int y);
137
138    struct DropShadow {
139        DropShadow() { };
140
141        DropShadow(const DropShadow& dropShadow):
142            width(dropShadow.width), height(dropShadow.height),
143            image(dropShadow.image), penX(dropShadow.penX),
144            penY(dropShadow.penY) {
145        }
146
147        uint32_t width;
148        uint32_t height;
149        uint8_t* image;
150        int32_t penX;
151        int32_t penY;
152    };
153
154    // After renderDropShadow returns, the called owns the memory in DropShadow.image
155    // and is responsible for releasing it when it's done with it
156    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
157            uint32_t len, int numGlyphs, uint32_t radius);
158
159    GLuint getTexture() {
160        checkInit();
161        return mTextureId;
162    }
163
164protected:
165    friend class Font;
166
167    const uint8_t* mGammaTable;
168
169    struct CacheTextureLine {
170        uint16_t mMaxHeight;
171        uint16_t mMaxWidth;
172        uint32_t mCurrentRow;
173        uint32_t mCurrentCol;
174        bool mDirty;
175
176        CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
177                uint32_t currentCol):
178                    mMaxHeight(maxHeight),
179                    mMaxWidth(maxWidth),
180                    mCurrentRow(currentRow),
181                    mCurrentCol(currentCol),
182                    mDirty(false) {
183        }
184
185        bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
186            if (glyph.fHeight + 2 > mMaxHeight) {
187                return false;
188            }
189
190            if (mCurrentCol + glyph.fWidth + 2 < mMaxWidth) {
191                *retOriginX = mCurrentCol + 1;
192                *retOriginY = mCurrentRow + 1;
193                mCurrentCol += glyph.fWidth + 2;
194                mDirty = true;
195                return true;
196            }
197
198            return false;
199        }
200    };
201
202    uint32_t getCacheWidth() const {
203        return mCacheWidth;
204    }
205
206    uint32_t getCacheHeight() const {
207        return mCacheHeight;
208    }
209
210    void initTextTexture();
211    bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
212
213    void flushAllAndInvalidate();
214    void initVertexArrayBuffers();
215
216    void checkInit();
217
218    String16 mLatinPrecache;
219    void precacheLatin(SkPaint* paint);
220
221    void issueDrawCommand();
222    void appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2,
223            float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3,
224            float x4, float y4, float z4, float u4, float v4);
225
226    uint32_t mCacheWidth;
227    uint32_t mCacheHeight;
228
229    Vector<CacheTextureLine*> mCacheLines;
230    uint32_t getRemainingCacheCapacity();
231
232    Font* mCurrentFont;
233    Vector<Font*> mActiveFonts;
234
235    // Texture to cache glyph bitmaps
236    uint8_t* mTextTexture;
237    const uint8_t* getTextTextureData() const {
238        return mTextTexture;
239    }
240    GLuint mTextureId;
241    void checkTextureUpdate();
242    bool mUploadTexture;
243
244    // Pointer to vertex data to speed up frame to frame work
245    float *mTextMeshPtr;
246    uint32_t mCurrentQuadIndex;
247    uint32_t mMaxNumberOfQuads;
248
249    uint32_t mIndexBufferID;
250
251    const Rect* mClip;
252
253    bool mInitialized;
254
255    void computeGaussianWeights(float* weights, int32_t radius);
256    void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
257            int32_t width, int32_t height);
258    void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
259            int32_t width, int32_t height);
260    void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
261};
262
263}; // namespace uirenderer
264}; // namespace android
265
266#endif // ANDROID_UI_FONT_RENDERER_H
267