• 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 #include <SkPathMeasure.h>
28 #include <SkPoint.h>
29 
30 #include <GLES2/gl2.h>
31 
32 #include "Rect.h"
33 #include "Properties.h"
34 
35 namespace android {
36 namespace uirenderer {
37 
38 ///////////////////////////////////////////////////////////////////////////////
39 // Defines
40 ///////////////////////////////////////////////////////////////////////////////
41 
42 #if RENDER_TEXT_AS_GLYPHS
43     typedef uint16_t glyph_t;
44     #define TO_GLYPH(g) g
45     #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph)
46     #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
47     #define IS_END_OF_STRING(glyph) false
48 #else
49     typedef SkUnichar glyph_t;
50     #define TO_GLYPH(g) ((SkUnichar) g)
51     #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph)
52     #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
53     #define IS_END_OF_STRING(glyph) glyph < 0
54 #endif
55 
56 ///////////////////////////////////////////////////////////////////////////////
57 // Declarations
58 ///////////////////////////////////////////////////////////////////////////////
59 
60 class FontRenderer;
61 
62 class CacheTexture {
63 public:
CacheTexture()64     CacheTexture() { }
CacheTexture(uint8_t * texture,uint16_t width,uint16_t height)65     CacheTexture(uint8_t* texture, uint16_t width, uint16_t height) :
66             mTexture(texture), mTextureId(0), mWidth(width), mHeight(height),
67             mLinearFiltering(false) { }
~CacheTexture()68     ~CacheTexture() {
69         if (mTexture) {
70             delete[] mTexture;
71         }
72         if (mTextureId) {
73             glDeleteTextures(1, &mTextureId);
74         }
75     }
76 
77     uint8_t* mTexture;
78     GLuint mTextureId;
79     uint16_t mWidth;
80     uint16_t mHeight;
81     bool mLinearFiltering;
82 };
83 
84 class CacheTextureLine {
85 public:
CacheTextureLine(uint16_t maxWidth,uint16_t maxHeight,uint32_t currentRow,uint32_t currentCol,CacheTexture * cacheTexture)86     CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
87             uint32_t currentCol, CacheTexture* cacheTexture):
88                 mMaxHeight(maxHeight),
89                 mMaxWidth(maxWidth),
90                 mCurrentRow(currentRow),
91                 mCurrentCol(currentCol),
92                 mDirty(false),
93                 mCacheTexture(cacheTexture) {
94     }
95 
96     bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
97 
98     uint16_t mMaxHeight;
99     uint16_t mMaxWidth;
100     uint32_t mCurrentRow;
101     uint32_t mCurrentCol;
102     bool mDirty;
103     CacheTexture* mCacheTexture;
104 };
105 
106 struct CachedGlyphInfo {
107     // Has the cache been invalidated?
108     bool mIsValid;
109     // Location of the cached glyph in the bitmap
110     // in case we need to resize the texture or
111     // render to bitmap
112     uint32_t mStartX;
113     uint32_t mStartY;
114     uint32_t mBitmapWidth;
115     uint32_t mBitmapHeight;
116     // Also cache texture coords for the quad
117     float mBitmapMinU;
118     float mBitmapMinV;
119     float mBitmapMaxU;
120     float mBitmapMaxV;
121     // Minimize how much we call freetype
122     uint32_t mGlyphIndex;
123     uint32_t mAdvanceX;
124     uint32_t mAdvanceY;
125     // Values below contain a glyph's origin in the bitmap
126     int32_t mBitmapLeft;
127     int32_t mBitmapTop;
128     // Auto-kerning
129     SkFixed mLsbDelta;
130     SkFixed mRsbDelta;
131     CacheTextureLine* mCachedTextureLine;
132 };
133 
134 
135 ///////////////////////////////////////////////////////////////////////////////
136 // Font
137 ///////////////////////////////////////////////////////////////////////////////
138 
139 /**
140  * Represents a font, defined by a Skia font id and a font size. A font is used
141  * to generate glyphs and cache them in the FontState.
142  */
143 class Font {
144 public:
145     enum Style {
146         kFakeBold = 1
147     };
148 
149     ~Font();
150 
151     /**
152      * Renders the specified string of text.
153      * If bitmap is specified, it will be used as the render target
154      */
155     void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
156             int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
157             uint32_t bitmapW = 0, uint32_t bitmapH = 0);
158 
159     void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
160             int numGlyphs, int x, int y, const float* positions);
161 
162     void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
163             int numGlyphs, SkPath* path, float hOffset, float vOffset);
164 
165     /**
166      * Creates a new font associated with the specified font state.
167      */
168     static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
169             int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
170             uint32_t strokeWidth);
171 
172 protected:
173     friend class FontRenderer;
174     typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*,
175             uint32_t, uint32_t, Rect*, const float*);
176 
177     enum RenderMode {
178         FRAMEBUFFER,
179         BITMAP,
180         MEASURE,
181     };
182 
183     void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
184             int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
185             uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
186 
187     void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
188             int numGlyphs, Rect *bounds);
189 
190     Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
191             uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
192 
193     // Cache of glyphs
194     DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
195 
196     void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
197 
198     CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
199     void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
200 
201     void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
202             uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
203             Rect* bounds, const float* pos);
204     void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
205             uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
206             Rect* bounds, const float* pos);
207     void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
208             uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
209             Rect* bounds, const float* pos);
210     void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
211             SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
212 
213     CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
214 
nextGlyph(const uint16_t ** srcPtr)215     static glyph_t nextGlyph(const uint16_t** srcPtr) {
216         const uint16_t* src = *srcPtr;
217         glyph_t g = *src++;
218         *srcPtr = src;
219         return g;
220     }
221 
222     FontRenderer* mState;
223     uint32_t mFontId;
224     float mFontSize;
225     int mFlags;
226     uint32_t mItalicStyle;
227     uint32_t mScaleX;
228     SkPaint::Style mStyle;
229     uint32_t mStrokeWidth;
230 };
231 
232 ///////////////////////////////////////////////////////////////////////////////
233 // Renderer
234 ///////////////////////////////////////////////////////////////////////////////
235 
236 class FontRenderer {
237 public:
238     FontRenderer();
239     ~FontRenderer();
240 
241     void flushLargeCaches();
242 
setGammaTable(const uint8_t * gammaTable)243     void setGammaTable(const uint8_t* gammaTable) {
244         mGammaTable = gammaTable;
245     }
246 
247     void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
248     // bounds is an out parameter
249     bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
250             uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
251     // bounds is an out parameter
252     bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
253             uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds);
254     // bounds is an out parameter
255     bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
256             uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds);
257 
258     struct DropShadow {
DropShadowDropShadow259         DropShadow() { };
260 
DropShadowDropShadow261         DropShadow(const DropShadow& dropShadow):
262             width(dropShadow.width), height(dropShadow.height),
263             image(dropShadow.image), penX(dropShadow.penX),
264             penY(dropShadow.penY) {
265         }
266 
267         uint32_t width;
268         uint32_t height;
269         uint8_t* image;
270         int32_t penX;
271         int32_t penY;
272     };
273 
274     // After renderDropShadow returns, the called owns the memory in DropShadow.image
275     // and is responsible for releasing it when it's done with it
276     DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
277             uint32_t len, int numGlyphs, uint32_t radius);
278 
279     GLuint getTexture(bool linearFiltering = false) {
280         checkInit();
281 
282         if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
283             mCurrentCacheTexture->mLinearFiltering = linearFiltering;
284             mLinearFiltering = linearFiltering;
285             const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
286 
287             glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
288             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
289             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
290         }
291 
292         return mCurrentCacheTexture->mTextureId;
293     }
294 
getCacheSize()295     uint32_t getCacheSize() const {
296         uint32_t size = 0;
297         if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
298             size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
299         }
300         if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
301             size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
302         }
303         if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
304             size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
305         }
306         if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
307             size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
308         }
309         return size;
310     }
311 
312 protected:
313     friend class Font;
314 
315     const uint8_t* mGammaTable;
316 
317     void allocateTextureMemory(CacheTexture* cacheTexture);
318     void deallocateTextureMemory(CacheTexture* cacheTexture);
319     void initTextTexture();
320     CacheTexture* createCacheTexture(int width, int height, bool allocate);
321     void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
322             uint32_t *retOriginX, uint32_t *retOriginY);
323 
324     void flushAllAndInvalidate();
325     void initVertexArrayBuffers();
326 
327     void checkInit();
328     void initRender(const Rect* clip, Rect* bounds);
329     void finishRender();
330 
331     void precacheLatin(SkPaint* paint);
332 
333     void issueDrawCommand();
334     void appendMeshQuadNoClip(float x1, float y1, float u1, float v1,
335             float x2, float y2, float u2, float v2,
336             float x3, float y3, float u3, float v3,
337             float x4, float y4, float u4, float v4, CacheTexture* texture);
338     void appendMeshQuad(float x1, float y1, float u1, float v1,
339             float x2, float y2, float u2, float v2,
340             float x3, float y3, float u3, float v3,
341             float x4, float y4, float u4, float v4, CacheTexture* texture);
342     void appendRotatedMeshQuad(float x1, float y1, float u1, float v1,
343             float x2, float y2, float u2, float v2,
344             float x3, float y3, float u3, float v3,
345             float x4, float y4, float u4, float v4, CacheTexture* texture);
346 
347     uint32_t mSmallCacheWidth;
348     uint32_t mSmallCacheHeight;
349 
350     Vector<CacheTextureLine*> mCacheLines;
351     uint32_t getRemainingCacheCapacity();
352 
353     Font* mCurrentFont;
354     Vector<Font*> mActiveFonts;
355 
356     CacheTexture* mCurrentCacheTexture;
357     CacheTexture* mLastCacheTexture;
358     CacheTexture* mCacheTextureSmall;
359     CacheTexture* mCacheTexture128;
360     CacheTexture* mCacheTexture256;
361     CacheTexture* mCacheTexture512;
362 
363     void checkTextureUpdate();
364     bool mUploadTexture;
365 
366     // Pointer to vertex data to speed up frame to frame work
367     float *mTextMeshPtr;
368     uint32_t mCurrentQuadIndex;
369     uint32_t mMaxNumberOfQuads;
370 
371     uint32_t mIndexBufferID;
372 
373     const Rect* mClip;
374     Rect* mBounds;
375     bool mDrawn;
376 
377     bool mInitialized;
378 
379     bool mLinearFiltering;
380 
381     void computeGaussianWeights(float* weights, int32_t radius);
382     void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
383             int32_t width, int32_t height);
384     void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
385             int32_t width, int32_t height);
386     void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
387 };
388 
389 }; // namespace uirenderer
390 }; // namespace android
391 
392 #endif // ANDROID_HWUI_FONT_RENDERER_H
393