blob: 4fc5862b1ee549ccf8878aa8acbb7ec7fe7f1a33 [file] [log] [blame]
Romain Guy694b5192010-07-21 21:33:20 -07001/*
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
Romain Guy5b3b3522010-10-27 18:57:51 -070017#ifndef ANDROID_HWUI_FONT_RENDERER_H
18#define ANDROID_HWUI_FONT_RENDERER_H
Romain Guy694b5192010-07-21 21:33:20 -070019
20#include <utils/String8.h>
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -070021#include <utils/String16.h>
Romain Guy694b5192010-07-21 21:33:20 -070022#include <utils/Vector.h>
23#include <utils/KeyedVector.h>
24
25#include <SkScalerContext.h>
26#include <SkPaint.h>
Romain Guy97771732012-02-28 18:17:02 -080027#include <SkPathMeasure.h>
28#include <SkPoint.h>
Romain Guy694b5192010-07-21 21:33:20 -070029
30#include <GLES2/gl2.h>
31
Romain Guy09147fb2010-07-22 13:08:20 -070032#include "Rect.h"
Romain Guy51769a62010-07-23 00:28:00 -070033#include "Properties.h"
Romain Guy09147fb2010-07-22 13:08:20 -070034
Romain Guy694b5192010-07-21 21:33:20 -070035namespace android {
36namespace uirenderer {
37
Romain Guy726aeba2011-06-01 14:52:00 -070038///////////////////////////////////////////////////////////////////////////////
39// Defines
40///////////////////////////////////////////////////////////////////////////////
41
42#if RENDER_TEXT_AS_GLYPHS
43 typedef uint16_t glyph_t;
44 #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph)
45 #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
46 #define IS_END_OF_STRING(glyph) false
47#else
48 typedef SkUnichar glyph_t;
49 #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph)
50 #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
51 #define IS_END_OF_STRING(glyph) glyph < 0
52#endif
53
54///////////////////////////////////////////////////////////////////////////////
55// Declarations
56///////////////////////////////////////////////////////////////////////////////
57
Romain Guy694b5192010-07-21 21:33:20 -070058class FontRenderer;
59
Chet Haase7de0cb12011-12-05 16:35:38 -080060class CacheTexture {
61public:
62 CacheTexture(){}
63 CacheTexture(uint8_t* texture, GLuint textureId, uint16_t width, uint16_t height) :
Chet Haase2a47c142011-12-14 15:22:56 -080064 mTexture(texture), mTextureId(textureId), mWidth(width), mHeight(height),
65 mLinearFiltering(false) {}
Chet Haase7de0cb12011-12-05 16:35:38 -080066 ~CacheTexture() {
67 if (mTexture != NULL) {
68 delete[] mTexture;
69 }
70 if (mTextureId != 0) {
71 glDeleteTextures(1, &mTextureId);
72 }
73 }
74
75 uint8_t* mTexture;
76 GLuint mTextureId;
77 uint16_t mWidth;
78 uint16_t mHeight;
Chet Haase2a47c142011-12-14 15:22:56 -080079 bool mLinearFiltering;
Chet Haase7de0cb12011-12-05 16:35:38 -080080};
81
82class CacheTextureLine {
83public:
84 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
85 uint32_t currentCol, CacheTexture* cacheTexture):
86 mMaxHeight(maxHeight),
87 mMaxWidth(maxWidth),
88 mCurrentRow(currentRow),
89 mCurrentCol(currentCol),
90 mDirty(false),
91 mCacheTexture(cacheTexture){
92 }
93
94 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
95
96 uint16_t mMaxHeight;
97 uint16_t mMaxWidth;
98 uint32_t mCurrentRow;
99 uint32_t mCurrentCol;
100 bool mDirty;
101 CacheTexture *mCacheTexture;
102};
103
104struct 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 CacheTextureLine* mCachedTextureLine;
130};
131
132
Romain Guy726aeba2011-06-01 14:52:00 -0700133///////////////////////////////////////////////////////////////////////////////
134// Font
135///////////////////////////////////////////////////////////////////////////////
136
Romain Guy51769a62010-07-23 00:28:00 -0700137/**
138 * Represents a font, defined by a Skia font id and a font size. A font is used
139 * to generate glyphs and cache them in the FontState.
140 */
Romain Guy694b5192010-07-21 21:33:20 -0700141class Font {
142public:
Romain Guy325a0f92011-01-05 15:26:55 -0800143 enum Style {
Romain Guyc7b25be2011-03-23 14:59:20 -0700144 kFakeBold = 1
Romain Guy325a0f92011-01-05 15:26:55 -0800145 };
146
Romain Guy694b5192010-07-21 21:33:20 -0700147 ~Font();
148
Romain Guy51769a62010-07-23 00:28:00 -0700149 /**
150 * Renders the specified string of text.
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700151 * If bitmap is specified, it will be used as the render target
Romain Guy51769a62010-07-23 00:28:00 -0700152 */
Romain Guy726aeba2011-06-01 14:52:00 -0700153 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
154 int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
155 uint32_t bitmapW = 0, uint32_t bitmapH = 0);
Romain Guy671d6cf2012-01-18 12:39:17 -0800156
157 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
158 int numGlyphs, int x, int y, const float* positions);
159
Romain Guy97771732012-02-28 18:17:02 -0800160 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
161 int numGlyphs, SkPath* path, float hOffset, float vOffset);
162
Romain Guy51769a62010-07-23 00:28:00 -0700163 /**
164 * Creates a new font associated with the specified font state.
165 */
Romain Guy2577db12011-01-18 13:02:38 -0800166 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
Romain Guybd496bc2011-08-02 17:32:41 -0700167 int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
168 uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700169
170protected:
Romain Guy694b5192010-07-21 21:33:20 -0700171 friend class FontRenderer;
Romain Guy671d6cf2012-01-18 12:39:17 -0800172 typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*,
173 uint32_t, uint32_t, Rect*, const float*);
Romain Guy694b5192010-07-21 21:33:20 -0700174
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700175 enum RenderMode {
176 FRAMEBUFFER,
177 BITMAP,
178 MEASURE,
179 };
180
Romain Guy726aeba2011-06-01 14:52:00 -0700181 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
182 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
Romain Guy671d6cf2012-01-18 12:39:17 -0800183 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700184
Romain Guy726aeba2011-06-01 14:52:00 -0700185 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
186 int numGlyphs, Rect *bounds);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700187
Chet Haase8668f8a2011-03-02 13:51:36 -0800188 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
Romain Guybd496bc2011-08-02 17:32:41 -0700189 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700190
Romain Guy726aeba2011-06-01 14:52:00 -0700191 // Cache of glyphs
192 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
Romain Guy694b5192010-07-21 21:33:20 -0700193
Chet Haase9a824562011-12-16 15:44:59 -0800194 void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700195
Romain Guy726aeba2011-06-01 14:52:00 -0700196 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
Romain Guy671d6cf2012-01-18 12:39:17 -0800197 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
198
199 void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
200 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
201 Rect* bounds, const float* pos);
202 void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
203 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
204 Rect* bounds, const float* pos);
205 void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
206 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
207 Rect* bounds, const float* pos);
Romain Guy97771732012-02-28 18:17:02 -0800208 void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
209 SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700210
Romain Guy726aeba2011-06-01 14:52:00 -0700211 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
212
213 static glyph_t nextGlyph(const uint16_t** srcPtr) {
214 const uint16_t* src = *srcPtr;
215 glyph_t g = *src++;
216 *srcPtr = src;
217 return g;
218 }
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700219
Romain Guybd0e6aa2010-07-22 18:50:12 -0700220 FontRenderer* mState;
221 uint32_t mFontId;
222 float mFontSize;
Romain Guy325a0f92011-01-05 15:26:55 -0800223 int mFlags;
Romain Guy2577db12011-01-18 13:02:38 -0800224 uint32_t mItalicStyle;
Chet Haase8668f8a2011-03-02 13:51:36 -0800225 uint32_t mScaleX;
Romain Guybd496bc2011-08-02 17:32:41 -0700226 SkPaint::Style mStyle;
227 uint32_t mStrokeWidth;
Romain Guy694b5192010-07-21 21:33:20 -0700228};
229
Romain Guy726aeba2011-06-01 14:52:00 -0700230///////////////////////////////////////////////////////////////////////////////
231// Renderer
232///////////////////////////////////////////////////////////////////////////////
233
Romain Guy694b5192010-07-21 21:33:20 -0700234class FontRenderer {
235public:
236 FontRenderer();
237 ~FontRenderer();
238
239 void init();
240 void deinit();
Chet Haase9a824562011-12-16 15:44:59 -0800241 void flushLargeCaches();
Romain Guy694b5192010-07-21 21:33:20 -0700242
Romain Guyb45c0c92010-08-26 20:35:23 -0700243 void setGammaTable(const uint8_t* gammaTable) {
244 mGammaTable = gammaTable;
245 }
246
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700247 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy671d6cf2012-01-18 12:39:17 -0800248 // bounds is an out parameter
Romain Guy5b3b3522010-10-27 18:57:51 -0700249 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);
Romain Guy671d6cf2012-01-18 12:39:17 -0800251 // 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);
Romain Guy97771732012-02-28 18:17:02 -0800254 // 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);
Romain Guy694b5192010-07-21 21:33:20 -0700257
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700258 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700259 DropShadow() { };
260
261 DropShadow(const DropShadow& dropShadow):
262 width(dropShadow.width), height(dropShadow.height),
263 image(dropShadow.image), penX(dropShadow.penX),
264 penY(dropShadow.penY) {
265 }
266
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700267 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,
Romain Guy1e45aae2010-08-13 19:39:53 -0700277 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700278
Romain Guye8cb9c142010-10-04 14:14:11 -0700279 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700280 checkInit();
Chet Haase2a47c142011-12-14 15:22:56 -0800281 if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
282 mCurrentCacheTexture->mLinearFiltering = linearFiltering;
Romain Guye8cb9c142010-10-04 14:14:11 -0700283 mLinearFiltering = linearFiltering;
284 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
285
Chet Haase7de0cb12011-12-05 16:35:38 -0800286 glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
Romain Guye8cb9c142010-10-04 14:14:11 -0700287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
288 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
289 }
Chet Haase7de0cb12011-12-05 16:35:38 -0800290 return mCurrentCacheTexture->mTextureId;
Romain Guy694b5192010-07-21 21:33:20 -0700291 }
292
Chet Haase7de0cb12011-12-05 16:35:38 -0800293 uint32_t getCacheSize() const {
294 uint32_t size = 0;
295 if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
296 size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
297 }
298 if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
299 size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
300 }
301 if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
302 size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
303 }
304 if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
305 size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
306 }
307 return size;
Romain Guyc15008e2010-11-10 11:59:15 -0800308 }
309
Romain Guy694b5192010-07-21 21:33:20 -0700310protected:
311 friend class Font;
312
Romain Guyb45c0c92010-08-26 20:35:23 -0700313 const uint8_t* mGammaTable;
314
Chet Haase2a47c142011-12-14 15:22:56 -0800315 void allocateTextureMemory(CacheTexture* cacheTexture);
Chet Haase9a824562011-12-16 15:44:59 -0800316 void deallocateTextureMemory(CacheTexture* cacheTexture);
Chet Haase7de0cb12011-12-05 16:35:38 -0800317 void initTextTexture();
Romain Guy97771732012-02-28 18:17:02 -0800318 CacheTexture* createCacheTexture(int width, int height, bool allocate);
Chet Haase7de0cb12011-12-05 16:35:38 -0800319 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
320 uint32_t *retOriginX, uint32_t *retOriginY);
Romain Guy694b5192010-07-21 21:33:20 -0700321
322 void flushAllAndInvalidate();
323 void initVertexArrayBuffers();
324
325 void checkInit();
Romain Guy671d6cf2012-01-18 12:39:17 -0800326 void initRender(const Rect* clip, Rect* bounds);
327 void finishRender();
Romain Guy694b5192010-07-21 21:33:20 -0700328
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700329 String16 mLatinPrecache;
330 void precacheLatin(SkPaint* paint);
331
Romain Guy694b5192010-07-21 21:33:20 -0700332 void issueDrawCommand();
Romain Guy97771732012-02-28 18:17:02 -0800333 void appendMeshQuadNoClip(float x1, float y1, float u1, float v1,
334 float x2, float y2, float u2, float v2,
335 float x3, float y3, float u3, float v3,
336 float x4, float y4, float u4, float v4, CacheTexture* texture);
Romain Guyd71dd362011-12-12 19:03:35 -0800337 void appendMeshQuad(float x1, float y1, float u1, float v1,
338 float x2, float y2, float u2, float v2,
339 float x3, float y3, float u3, float v3,
Chet Haase7de0cb12011-12-05 16:35:38 -0800340 float x4, float y4, float u4, float v4, CacheTexture* texture);
Romain Guy97771732012-02-28 18:17:02 -0800341 void appendRotatedMeshQuad(float x1, float y1, float u1, float v1,
342 float x2, float y2, float u2, float v2,
343 float x3, float y3, float u3, float v3,
344 float x4, float y4, float u4, float v4, CacheTexture* texture);
Romain Guy694b5192010-07-21 21:33:20 -0700345
Chet Haase7de0cb12011-12-05 16:35:38 -0800346 uint32_t mSmallCacheWidth;
347 uint32_t mSmallCacheHeight;
Romain Guy694b5192010-07-21 21:33:20 -0700348
Romain Guy694b5192010-07-21 21:33:20 -0700349 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700350 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700351
Romain Guy09147fb2010-07-22 13:08:20 -0700352 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700353 Vector<Font*> mActiveFonts;
354
Chet Haase7de0cb12011-12-05 16:35:38 -0800355 CacheTexture* mCurrentCacheTexture;
356 CacheTexture* mLastCacheTexture;
357 CacheTexture* mCacheTextureSmall;
358 CacheTexture* mCacheTexture128;
359 CacheTexture* mCacheTexture256;
360 CacheTexture* mCacheTexture512;
361
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700362 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700363 bool mUploadTexture;
364
365 // Pointer to vertex data to speed up frame to frame work
366 float *mTextMeshPtr;
367 uint32_t mCurrentQuadIndex;
368 uint32_t mMaxNumberOfQuads;
369
370 uint32_t mIndexBufferID;
371
Romain Guy09147fb2010-07-22 13:08:20 -0700372 const Rect* mClip;
Romain Guy5b3b3522010-10-27 18:57:51 -0700373 Rect* mBounds;
374 bool mDrawn;
Romain Guy09147fb2010-07-22 13:08:20 -0700375
Romain Guy694b5192010-07-21 21:33:20 -0700376 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700377
Romain Guye8cb9c142010-10-04 14:14:11 -0700378 bool mLinearFiltering;
379
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700380 void computeGaussianWeights(float* weights, int32_t radius);
381 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700382 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700383 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700384 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700385 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700386};
387
388}; // namespace uirenderer
389}; // namespace android
390
Romain Guy5b3b3522010-10-27 18:57:51 -0700391#endif // ANDROID_HWUI_FONT_RENDERER_H