blob: cac915d37bfbf5c7cc8be5fe31c966d614482584 [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>
27
28#include <GLES2/gl2.h>
29
Romain Guy09147fb2010-07-22 13:08:20 -070030#include "Rect.h"
Romain Guy51769a62010-07-23 00:28:00 -070031#include "Properties.h"
Romain Guy09147fb2010-07-22 13:08:20 -070032
Romain Guy694b5192010-07-21 21:33:20 -070033namespace android {
34namespace uirenderer {
35
Romain Guy726aeba2011-06-01 14:52:00 -070036///////////////////////////////////////////////////////////////////////////////
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
Romain Guy694b5192010-07-21 21:33:20 -070056class FontRenderer;
57
Chet Haase7de0cb12011-12-05 16:35:38 -080058class CacheTexture {
59public:
60 CacheTexture(){}
61 CacheTexture(uint8_t* texture, GLuint textureId, uint16_t width, uint16_t height) :
62 mTexture(texture), mTextureId(textureId), mWidth(width), mHeight(height) {}
63 ~CacheTexture() {
64 if (mTexture != NULL) {
65 delete[] mTexture;
66 }
67 if (mTextureId != 0) {
68 glDeleteTextures(1, &mTextureId);
69 }
70 }
71
72 uint8_t* mTexture;
73 GLuint mTextureId;
74 uint16_t mWidth;
75 uint16_t mHeight;
76};
77
78class CacheTextureLine {
79public:
80 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
81 uint32_t currentCol, CacheTexture* cacheTexture):
82 mMaxHeight(maxHeight),
83 mMaxWidth(maxWidth),
84 mCurrentRow(currentRow),
85 mCurrentCol(currentCol),
86 mDirty(false),
87 mCacheTexture(cacheTexture){
88 }
89
90 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
91
92 uint16_t mMaxHeight;
93 uint16_t mMaxWidth;
94 uint32_t mCurrentRow;
95 uint32_t mCurrentCol;
96 bool mDirty;
97 CacheTexture *mCacheTexture;
98};
99
100struct CachedGlyphInfo {
101 // Has the cache been invalidated?
102 bool mIsValid;
103 // Location of the cached glyph in the bitmap
104 // in case we need to resize the texture or
105 // render to bitmap
106 uint32_t mStartX;
107 uint32_t mStartY;
108 uint32_t mBitmapWidth;
109 uint32_t mBitmapHeight;
110 // Also cache texture coords for the quad
111 float mBitmapMinU;
112 float mBitmapMinV;
113 float mBitmapMaxU;
114 float mBitmapMaxV;
115 // Minimize how much we call freetype
116 uint32_t mGlyphIndex;
117 uint32_t mAdvanceX;
118 uint32_t mAdvanceY;
119 // Values below contain a glyph's origin in the bitmap
120 int32_t mBitmapLeft;
121 int32_t mBitmapTop;
122 // Auto-kerning
123 SkFixed mLsbDelta;
124 SkFixed mRsbDelta;
125 CacheTextureLine* mCachedTextureLine;
126};
127
128
Romain Guy726aeba2011-06-01 14:52:00 -0700129///////////////////////////////////////////////////////////////////////////////
130// Font
131///////////////////////////////////////////////////////////////////////////////
132
Romain Guy51769a62010-07-23 00:28:00 -0700133/**
134 * Represents a font, defined by a Skia font id and a font size. A font is used
135 * to generate glyphs and cache them in the FontState.
136 */
Romain Guy694b5192010-07-21 21:33:20 -0700137class Font {
138public:
Romain Guy325a0f92011-01-05 15:26:55 -0800139 enum Style {
Romain Guyc7b25be2011-03-23 14:59:20 -0700140 kFakeBold = 1
Romain Guy325a0f92011-01-05 15:26:55 -0800141 };
142
Romain Guy694b5192010-07-21 21:33:20 -0700143 ~Font();
144
Romain Guy51769a62010-07-23 00:28:00 -0700145 /**
146 * Renders the specified string of text.
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700147 * If bitmap is specified, it will be used as the render target
Romain Guy51769a62010-07-23 00:28:00 -0700148 */
Romain Guy726aeba2011-06-01 14:52:00 -0700149 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
150 int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
151 uint32_t bitmapW = 0, uint32_t bitmapH = 0);
Romain Guy51769a62010-07-23 00:28:00 -0700152 /**
153 * Creates a new font associated with the specified font state.
154 */
Romain Guy2577db12011-01-18 13:02:38 -0800155 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
Romain Guybd496bc2011-08-02 17:32:41 -0700156 int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
157 uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700158
159protected:
Romain Guy694b5192010-07-21 21:33:20 -0700160 friend class FontRenderer;
161
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700162 enum RenderMode {
163 FRAMEBUFFER,
164 BITMAP,
165 MEASURE,
166 };
167
Romain Guy726aeba2011-06-01 14:52:00 -0700168 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
169 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
170 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700171
Romain Guy726aeba2011-06-01 14:52:00 -0700172 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
173 int numGlyphs, Rect *bounds);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700174
Chet Haase8668f8a2011-03-02 13:51:36 -0800175 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
Romain Guybd496bc2011-08-02 17:32:41 -0700176 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700177
Romain Guy726aeba2011-06-01 14:52:00 -0700178 // Cache of glyphs
179 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
Romain Guy694b5192010-07-21 21:33:20 -0700180
Romain Guybd0e6aa2010-07-22 18:50:12 -0700181 void invalidateTextureCache();
182
Romain Guy726aeba2011-06-01 14:52:00 -0700183 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
Romain Guy694b5192010-07-21 21:33:20 -0700184 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700185 void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700186 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700187 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
Romain Guy726aeba2011-06-01 14:52:00 -0700188 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700189
Romain Guy726aeba2011-06-01 14:52:00 -0700190 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
191
192 static glyph_t nextGlyph(const uint16_t** srcPtr) {
193 const uint16_t* src = *srcPtr;
194 glyph_t g = *src++;
195 *srcPtr = src;
196 return g;
197 }
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700198
Romain Guybd0e6aa2010-07-22 18:50:12 -0700199 FontRenderer* mState;
200 uint32_t mFontId;
201 float mFontSize;
Romain Guy325a0f92011-01-05 15:26:55 -0800202 int mFlags;
Romain Guy2577db12011-01-18 13:02:38 -0800203 uint32_t mItalicStyle;
Chet Haase8668f8a2011-03-02 13:51:36 -0800204 uint32_t mScaleX;
Romain Guybd496bc2011-08-02 17:32:41 -0700205 SkPaint::Style mStyle;
206 uint32_t mStrokeWidth;
Romain Guy694b5192010-07-21 21:33:20 -0700207};
208
Romain Guy726aeba2011-06-01 14:52:00 -0700209///////////////////////////////////////////////////////////////////////////////
210// Renderer
211///////////////////////////////////////////////////////////////////////////////
212
Romain Guy694b5192010-07-21 21:33:20 -0700213class FontRenderer {
214public:
215 FontRenderer();
216 ~FontRenderer();
217
218 void init();
219 void deinit();
220
Romain Guyb45c0c92010-08-26 20:35:23 -0700221 void setGammaTable(const uint8_t* gammaTable) {
222 mGammaTable = gammaTable;
223 }
224
Romain Guyf3a910b42011-12-12 20:35:21 -0800225 inline float* getMeshBuffer() {
226 checkInit();
227 return mTextMeshPtr;
228 }
229
230 inline int getMeshTexCoordsOffset() const {
231 return 2;
Alex Sakhartchouk894df172011-02-17 16:45:37 -0800232 }
233
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700234 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy5b3b3522010-10-27 18:57:51 -0700235 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
236 uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700237
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700238 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700239 DropShadow() { };
240
241 DropShadow(const DropShadow& dropShadow):
242 width(dropShadow.width), height(dropShadow.height),
243 image(dropShadow.image), penX(dropShadow.penX),
244 penY(dropShadow.penY) {
245 }
246
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700247 uint32_t width;
248 uint32_t height;
249 uint8_t* image;
250 int32_t penX;
251 int32_t penY;
252 };
253
254 // After renderDropShadow returns, the called owns the memory in DropShadow.image
255 // and is responsible for releasing it when it's done with it
256 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Romain Guy1e45aae2010-08-13 19:39:53 -0700257 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700258
Romain Guye8cb9c142010-10-04 14:14:11 -0700259 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700260 checkInit();
Romain Guye8cb9c142010-10-04 14:14:11 -0700261 if (linearFiltering != mLinearFiltering) {
262 mLinearFiltering = linearFiltering;
263 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
264
Chet Haase7de0cb12011-12-05 16:35:38 -0800265 glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
Romain Guye8cb9c142010-10-04 14:14:11 -0700266 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
267 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
268 }
Chet Haase7de0cb12011-12-05 16:35:38 -0800269 return mCurrentCacheTexture->mTextureId;
Romain Guy694b5192010-07-21 21:33:20 -0700270 }
271
Chet Haase7de0cb12011-12-05 16:35:38 -0800272 uint32_t getCacheSize() const {
273 uint32_t size = 0;
274 if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
275 size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
276 }
277 if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
278 size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
279 }
280 if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
281 size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
282 }
283 if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
284 size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
285 }
286 return size;
Romain Guyc15008e2010-11-10 11:59:15 -0800287 }
288
Romain Guy694b5192010-07-21 21:33:20 -0700289protected:
290 friend class Font;
291
Romain Guyb45c0c92010-08-26 20:35:23 -0700292 const uint8_t* mGammaTable;
293
Chet Haase7de0cb12011-12-05 16:35:38 -0800294 uint8_t* allocateTextureMemory(int width, int height);
295 void initTextTexture();
296 CacheTexture *createCacheTexture(int width, int height, bool allocate);
297 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
298 uint32_t *retOriginX, uint32_t *retOriginY);
Romain Guy694b5192010-07-21 21:33:20 -0700299
300 void flushAllAndInvalidate();
301 void initVertexArrayBuffers();
302
303 void checkInit();
304
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700305 String16 mLatinPrecache;
306 void precacheLatin(SkPaint* paint);
307
Romain Guy694b5192010-07-21 21:33:20 -0700308 void issueDrawCommand();
Romain Guyd71dd362011-12-12 19:03:35 -0800309 void appendMeshQuad(float x1, float y1, float u1, float v1,
310 float x2, float y2, float u2, float v2,
311 float x3, float y3, float u3, float v3,
Chet Haase7de0cb12011-12-05 16:35:38 -0800312 float x4, float y4, float u4, float v4, CacheTexture* texture);
Romain Guy694b5192010-07-21 21:33:20 -0700313
Chet Haase7de0cb12011-12-05 16:35:38 -0800314 uint32_t mSmallCacheWidth;
315 uint32_t mSmallCacheHeight;
Romain Guy694b5192010-07-21 21:33:20 -0700316
Romain Guy694b5192010-07-21 21:33:20 -0700317 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700318 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700319
Romain Guy09147fb2010-07-22 13:08:20 -0700320 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700321 Vector<Font*> mActiveFonts;
322
Chet Haase7de0cb12011-12-05 16:35:38 -0800323 CacheTexture* mCurrentCacheTexture;
324 CacheTexture* mLastCacheTexture;
325 CacheTexture* mCacheTextureSmall;
326 CacheTexture* mCacheTexture128;
327 CacheTexture* mCacheTexture256;
328 CacheTexture* mCacheTexture512;
329
330
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700331 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700332 bool mUploadTexture;
333
334 // Pointer to vertex data to speed up frame to frame work
335 float *mTextMeshPtr;
336 uint32_t mCurrentQuadIndex;
337 uint32_t mMaxNumberOfQuads;
338
339 uint32_t mIndexBufferID;
340
Romain Guy09147fb2010-07-22 13:08:20 -0700341 const Rect* mClip;
Romain Guy5b3b3522010-10-27 18:57:51 -0700342 Rect* mBounds;
343 bool mDrawn;
Romain Guy09147fb2010-07-22 13:08:20 -0700344
Romain Guy694b5192010-07-21 21:33:20 -0700345 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700346
Romain Guye8cb9c142010-10-04 14:14:11 -0700347 bool mLinearFiltering;
348
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700349 void computeGaussianWeights(float* weights, int32_t radius);
350 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700351 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700352 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700353 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700354 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700355};
356
357}; // namespace uirenderer
358}; // namespace android
359
Romain Guy5b3b3522010-10-27 18:57:51 -0700360#endif // ANDROID_HWUI_FONT_RENDERER_H