blob: 9ed69325c914103740cea9e888091ab5a3b6c7d4 [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;
Romain Guyae91c4c2012-05-14 14:00:27 -070044 #define TO_GLYPH(g) g
Romain Guy726aeba2011-06-01 14:52:00 -070045 #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;
Romain Guyae91c4c2012-05-14 14:00:27 -070050 #define TO_GLYPH(g) ((SkUnichar) g)
Romain Guy726aeba2011-06-01 14:52:00 -070051 #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
Romain Guy694b5192010-07-21 21:33:20 -070060class FontRenderer;
61
Chet Haase7de0cb12011-12-05 16:35:38 -080062class CacheTexture {
63public:
Romain Guy0aa87bb2012-07-20 11:14:32 -070064 CacheTexture(uint16_t width, uint16_t height) :
65 mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height),
Romain Guy9d9758a2012-05-14 15:19:58 -070066 mLinearFiltering(false) { }
Chet Haase7de0cb12011-12-05 16:35:38 -080067 ~CacheTexture() {
Romain Guy9d9758a2012-05-14 15:19:58 -070068 if (mTexture) {
Chet Haase7de0cb12011-12-05 16:35:38 -080069 delete[] mTexture;
70 }
Romain Guy9d9758a2012-05-14 15:19:58 -070071 if (mTextureId) {
Chet Haase7de0cb12011-12-05 16:35:38 -080072 glDeleteTextures(1, &mTextureId);
73 }
74 }
75
76 uint8_t* mTexture;
77 GLuint mTextureId;
78 uint16_t mWidth;
79 uint16_t mHeight;
Chet Haase2a47c142011-12-14 15:22:56 -080080 bool mLinearFiltering;
Chet Haase7de0cb12011-12-05 16:35:38 -080081};
82
83class CacheTextureLine {
84public:
85 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
86 uint32_t currentCol, CacheTexture* cacheTexture):
87 mMaxHeight(maxHeight),
88 mMaxWidth(maxWidth),
89 mCurrentRow(currentRow),
90 mCurrentCol(currentCol),
91 mDirty(false),
Romain Guy9d9758a2012-05-14 15:19:58 -070092 mCacheTexture(cacheTexture) {
Chet Haase7de0cb12011-12-05 16:35:38 -080093 }
94
95 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
96
97 uint16_t mMaxHeight;
98 uint16_t mMaxWidth;
99 uint32_t mCurrentRow;
100 uint32_t mCurrentCol;
101 bool mDirty;
Romain Guyae91c4c2012-05-14 14:00:27 -0700102 CacheTexture* mCacheTexture;
Chet Haase7de0cb12011-12-05 16:35:38 -0800103};
104
105struct CachedGlyphInfo {
106 // Has the cache been invalidated?
107 bool mIsValid;
108 // Location of the cached glyph in the bitmap
109 // in case we need to resize the texture or
110 // render to bitmap
111 uint32_t mStartX;
112 uint32_t mStartY;
113 uint32_t mBitmapWidth;
114 uint32_t mBitmapHeight;
115 // Also cache texture coords for the quad
116 float mBitmapMinU;
117 float mBitmapMinV;
118 float mBitmapMaxU;
119 float mBitmapMaxV;
120 // Minimize how much we call freetype
121 uint32_t mGlyphIndex;
122 uint32_t mAdvanceX;
123 uint32_t mAdvanceY;
124 // Values below contain a glyph's origin in the bitmap
125 int32_t mBitmapLeft;
126 int32_t mBitmapTop;
127 // Auto-kerning
128 SkFixed mLsbDelta;
129 SkFixed mRsbDelta;
130 CacheTextureLine* mCachedTextureLine;
131};
132
133
Romain Guy726aeba2011-06-01 14:52:00 -0700134///////////////////////////////////////////////////////////////////////////////
135// Font
136///////////////////////////////////////////////////////////////////////////////
137
Romain Guy51769a62010-07-23 00:28:00 -0700138/**
139 * Represents a font, defined by a Skia font id and a font size. A font is used
140 * to generate glyphs and cache them in the FontState.
141 */
Romain Guy694b5192010-07-21 21:33:20 -0700142class Font {
143public:
Romain Guy325a0f92011-01-05 15:26:55 -0800144 enum Style {
Romain Guyc7b25be2011-03-23 14:59:20 -0700145 kFakeBold = 1
Romain Guy325a0f92011-01-05 15:26:55 -0800146 };
147
Romain Guy694b5192010-07-21 21:33:20 -0700148 ~Font();
149
Romain Guy51769a62010-07-23 00:28:00 -0700150 /**
151 * Renders the specified string of text.
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700152 * If bitmap is specified, it will be used as the render target
Romain Guy51769a62010-07-23 00:28:00 -0700153 */
Romain Guy726aeba2011-06-01 14:52:00 -0700154 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
155 int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
156 uint32_t bitmapW = 0, uint32_t bitmapH = 0);
Romain Guy671d6cf2012-01-18 12:39:17 -0800157
158 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
159 int numGlyphs, int x, int y, const float* positions);
160
Romain Guy97771732012-02-28 18:17:02 -0800161 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
162 int numGlyphs, SkPath* path, float hOffset, float vOffset);
163
Romain Guy51769a62010-07-23 00:28:00 -0700164 /**
165 * Creates a new font associated with the specified font state.
166 */
Romain Guy2577db12011-01-18 13:02:38 -0800167 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
Romain Guybd496bc2011-08-02 17:32:41 -0700168 int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
169 uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700170
171protected:
Romain Guy694b5192010-07-21 21:33:20 -0700172 friend class FontRenderer;
Romain Guy671d6cf2012-01-18 12:39:17 -0800173 typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*,
174 uint32_t, uint32_t, Rect*, const float*);
Romain Guy694b5192010-07-21 21:33:20 -0700175
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700176 enum RenderMode {
177 FRAMEBUFFER,
178 BITMAP,
179 MEASURE,
180 };
181
Romain Guy726aeba2011-06-01 14:52:00 -0700182 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
183 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
Romain Guy671d6cf2012-01-18 12:39:17 -0800184 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700185
Romain Guy726aeba2011-06-01 14:52:00 -0700186 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
Raph Levien416a8472012-07-19 22:48:17 -0700187 int numGlyphs, Rect *bounds, const float* positions);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700188
Chet Haase8668f8a2011-03-02 13:51:36 -0800189 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
Romain Guybd496bc2011-08-02 17:32:41 -0700190 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700191
Romain Guy726aeba2011-06-01 14:52:00 -0700192 // Cache of glyphs
193 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
Romain Guy694b5192010-07-21 21:33:20 -0700194
Chet Haase9a824562011-12-16 15:44:59 -0800195 void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700196
Romain Guy726aeba2011-06-01 14:52:00 -0700197 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
Romain Guy671d6cf2012-01-18 12:39:17 -0800198 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
199
200 void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
201 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
202 Rect* bounds, const float* pos);
203 void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
204 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
205 Rect* bounds, const float* pos);
206 void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
207 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
208 Rect* bounds, const float* pos);
Romain Guy97771732012-02-28 18:17:02 -0800209 void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
210 SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700211
Romain Guy726aeba2011-06-01 14:52:00 -0700212 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
213
214 static glyph_t nextGlyph(const uint16_t** srcPtr) {
215 const uint16_t* src = *srcPtr;
216 glyph_t g = *src++;
217 *srcPtr = src;
218 return g;
219 }
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700220
Romain Guybd0e6aa2010-07-22 18:50:12 -0700221 FontRenderer* mState;
222 uint32_t mFontId;
223 float mFontSize;
Romain Guy325a0f92011-01-05 15:26:55 -0800224 int mFlags;
Romain Guy2577db12011-01-18 13:02:38 -0800225 uint32_t mItalicStyle;
Chet Haase8668f8a2011-03-02 13:51:36 -0800226 uint32_t mScaleX;
Romain Guybd496bc2011-08-02 17:32:41 -0700227 SkPaint::Style mStyle;
228 uint32_t mStrokeWidth;
Romain Guy694b5192010-07-21 21:33:20 -0700229};
230
Romain Guy726aeba2011-06-01 14:52:00 -0700231///////////////////////////////////////////////////////////////////////////////
232// Renderer
233///////////////////////////////////////////////////////////////////////////////
234
Romain Guy694b5192010-07-21 21:33:20 -0700235class FontRenderer {
236public:
237 FontRenderer();
238 ~FontRenderer();
239
Chet Haase9a824562011-12-16 15:44:59 -0800240 void flushLargeCaches();
Romain Guy694b5192010-07-21 21:33:20 -0700241
Romain Guyb45c0c92010-08-26 20:35:23 -0700242 void setGammaTable(const uint8_t* gammaTable) {
243 mGammaTable = gammaTable;
244 }
245
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700246 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy671d6cf2012-01-18 12:39:17 -0800247 // bounds is an out parameter
Romain Guy5b3b3522010-10-27 18:57:51 -0700248 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
249 uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
Romain Guy671d6cf2012-01-18 12:39:17 -0800250 // bounds is an out parameter
251 bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
252 uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds);
Romain Guy97771732012-02-28 18:17:02 -0800253 // bounds is an out parameter
254 bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
255 uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700256
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700257 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700258 DropShadow() { };
259
260 DropShadow(const DropShadow& dropShadow):
261 width(dropShadow.width), height(dropShadow.height),
262 image(dropShadow.image), penX(dropShadow.penX),
263 penY(dropShadow.penY) {
264 }
265
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700266 uint32_t width;
267 uint32_t height;
268 uint8_t* image;
269 int32_t penX;
270 int32_t penY;
271 };
272
273 // After renderDropShadow returns, the called owns the memory in DropShadow.image
274 // and is responsible for releasing it when it's done with it
275 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Raph Levien416a8472012-07-19 22:48:17 -0700276 uint32_t len, int numGlyphs, uint32_t radius, const float* positions);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700277
Romain Guye8cb9c142010-10-04 14:14:11 -0700278 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700279 checkInit();
Romain Guyae91c4c2012-05-14 14:00:27 -0700280
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 }
Romain Guyae91c4c2012-05-14 14:00:27 -0700290
Chet Haase7de0cb12011-12-05 16:35:38 -0800291 return mCurrentCacheTexture->mTextureId;
Romain Guy694b5192010-07-21 21:33:20 -0700292 }
293
Chet Haase7de0cb12011-12-05 16:35:38 -0800294 uint32_t getCacheSize() const {
295 uint32_t size = 0;
296 if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
297 size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
298 }
299 if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
300 size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
301 }
302 if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
303 size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
304 }
305 if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
306 size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
307 }
308 return size;
Romain Guyc15008e2010-11-10 11:59:15 -0800309 }
310
Romain Guy694b5192010-07-21 21:33:20 -0700311protected:
312 friend class Font;
313
Romain Guyb45c0c92010-08-26 20:35:23 -0700314 const uint8_t* mGammaTable;
315
Chet Haase2a47c142011-12-14 15:22:56 -0800316 void allocateTextureMemory(CacheTexture* cacheTexture);
Chet Haase9a824562011-12-16 15:44:59 -0800317 void deallocateTextureMemory(CacheTexture* cacheTexture);
Chet Haase7de0cb12011-12-05 16:35:38 -0800318 void initTextTexture();
Romain Guy97771732012-02-28 18:17:02 -0800319 CacheTexture* createCacheTexture(int width, int height, bool allocate);
Chet Haase7de0cb12011-12-05 16:35:38 -0800320 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
321 uint32_t *retOriginX, uint32_t *retOriginY);
Romain Guy694b5192010-07-21 21:33:20 -0700322
323 void flushAllAndInvalidate();
324 void initVertexArrayBuffers();
325
326 void checkInit();
Romain Guy671d6cf2012-01-18 12:39:17 -0800327 void initRender(const Rect* clip, Rect* bounds);
328 void finishRender();
Romain Guy694b5192010-07-21 21:33:20 -0700329
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700330 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