• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
33 namespace android {
34 namespace 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 
56 class 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  */
66 class Font {
67 public:
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 
88 protected:
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 
nextGlyph(const uint16_t ** srcPtr)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 
169 class FontRenderer {
170 public:
171     FontRenderer();
172     ~FontRenderer();
173 
174     void init();
175     void deinit();
176 
setGammaTable(const uint8_t * gammaTable)177     void setGammaTable(const uint8_t* gammaTable) {
178         mGammaTable = gammaTable;
179     }
180 
setAttributeBindingSlots(int positionSlot,int texCoordSlot)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 {
DropShadowDropShadow191         DropShadow() { };
192 
DropShadowDropShadow193         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 
getCacheWidth()224     uint32_t getCacheWidth() const {
225         return mCacheWidth;
226     }
227 
getCacheHeight()228     uint32_t getCacheHeight() const {
229         return mCacheHeight;
230     }
231 
232 protected:
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 
CacheTextureLineCacheTextureLine244         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 
fitBitmapCacheTextureLine253         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;
getTextTextureData()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