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