FontRenderer.h revision c15008e72ec00ca20a271c3006dac649fd07533b
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
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    bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
136            uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
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(bool linearFiltering = false) {
160        checkInit();
161        if (linearFiltering != mLinearFiltering) {
162            mLinearFiltering = linearFiltering;
163            const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
164
165            glBindTexture(GL_TEXTURE_2D, mTextureId);
166            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
167            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
168        }
169        return mTextureId;
170    }
171
172    uint32_t getCacheWidth() const {
173        return mCacheWidth;
174    }
175
176    uint32_t getCacheHeight() const {
177        return mCacheHeight;
178    }
179
180protected:
181    friend class Font;
182
183    const uint8_t* mGammaTable;
184
185    struct CacheTextureLine {
186        uint16_t mMaxHeight;
187        uint16_t mMaxWidth;
188        uint32_t mCurrentRow;
189        uint32_t mCurrentCol;
190        bool mDirty;
191
192        CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
193                uint32_t currentCol):
194                    mMaxHeight(maxHeight),
195                    mMaxWidth(maxWidth),
196                    mCurrentRow(currentRow),
197                    mCurrentCol(currentCol),
198                    mDirty(false) {
199        }
200
201        bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
202            if (glyph.fHeight + 2 > mMaxHeight) {
203                return false;
204            }
205
206            if (mCurrentCol + glyph.fWidth + 2 < mMaxWidth) {
207                *retOriginX = mCurrentCol + 1;
208                *retOriginY = mCurrentRow + 1;
209                mCurrentCol += glyph.fWidth + 2;
210                mDirty = true;
211                return true;
212            }
213
214            return false;
215        }
216    };
217
218    void initTextTexture();
219    bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
220
221    void flushAllAndInvalidate();
222    void initVertexArrayBuffers();
223
224    void checkInit();
225
226    String16 mLatinPrecache;
227    void precacheLatin(SkPaint* paint);
228
229    void issueDrawCommand();
230    void appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2,
231            float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3,
232            float x4, float y4, float z4, float u4, float v4);
233
234    uint32_t mCacheWidth;
235    uint32_t mCacheHeight;
236
237    Vector<CacheTextureLine*> mCacheLines;
238    uint32_t getRemainingCacheCapacity();
239
240    Font* mCurrentFont;
241    Vector<Font*> mActiveFonts;
242
243    // Texture to cache glyph bitmaps
244    uint8_t* mTextTexture;
245    const uint8_t* getTextTextureData() const {
246        return mTextTexture;
247    }
248    GLuint mTextureId;
249    void checkTextureUpdate();
250    bool mUploadTexture;
251
252    // Pointer to vertex data to speed up frame to frame work
253    float *mTextMeshPtr;
254    uint32_t mCurrentQuadIndex;
255    uint32_t mMaxNumberOfQuads;
256
257    uint32_t mIndexBufferID;
258
259    const Rect* mClip;
260    Rect* mBounds;
261    bool mDrawn;
262
263    bool mInitialized;
264
265    bool mLinearFiltering;
266
267    void computeGaussianWeights(float* weights, int32_t radius);
268    void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
269            int32_t width, int32_t height);
270    void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
271            int32_t width, int32_t height);
272    void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
273};
274
275}; // namespace uirenderer
276}; // namespace android
277
278#endif // ANDROID_HWUI_FONT_RENDERER_H
279