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