blob: b767be57fbf8a6640745aed91291d9e5dfbe21bd [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) :
Chet Haase2a47c142011-12-14 15:22:56 -080062 mTexture(texture), mTextureId(textureId), mWidth(width), mHeight(height),
63 mLinearFiltering(false) {}
Chet Haase7de0cb12011-12-05 16:35:38 -080064 ~CacheTexture() {
65 if (mTexture != NULL) {
66 delete[] mTexture;
67 }
68 if (mTextureId != 0) {
69 glDeleteTextures(1, &mTextureId);
70 }
71 }
72
73 uint8_t* mTexture;
74 GLuint mTextureId;
75 uint16_t mWidth;
76 uint16_t mHeight;
Chet Haase2a47c142011-12-14 15:22:56 -080077 bool mLinearFiltering;
Chet Haase7de0cb12011-12-05 16:35:38 -080078};
79
80class CacheTextureLine {
81public:
82 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
83 uint32_t currentCol, CacheTexture* cacheTexture):
84 mMaxHeight(maxHeight),
85 mMaxWidth(maxWidth),
86 mCurrentRow(currentRow),
87 mCurrentCol(currentCol),
88 mDirty(false),
89 mCacheTexture(cacheTexture){
90 }
91
92 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
93
94 uint16_t mMaxHeight;
95 uint16_t mMaxWidth;
96 uint32_t mCurrentRow;
97 uint32_t mCurrentCol;
98 bool mDirty;
99 CacheTexture *mCacheTexture;
100};
101
102struct CachedGlyphInfo {
103 // Has the cache been invalidated?
104 bool mIsValid;
105 // Location of the cached glyph in the bitmap
106 // in case we need to resize the texture or
107 // render to bitmap
108 uint32_t mStartX;
109 uint32_t mStartY;
110 uint32_t mBitmapWidth;
111 uint32_t mBitmapHeight;
112 // Also cache texture coords for the quad
113 float mBitmapMinU;
114 float mBitmapMinV;
115 float mBitmapMaxU;
116 float mBitmapMaxV;
117 // Minimize how much we call freetype
118 uint32_t mGlyphIndex;
119 uint32_t mAdvanceX;
120 uint32_t mAdvanceY;
121 // Values below contain a glyph's origin in the bitmap
122 int32_t mBitmapLeft;
123 int32_t mBitmapTop;
124 // Auto-kerning
125 SkFixed mLsbDelta;
126 SkFixed mRsbDelta;
127 CacheTextureLine* mCachedTextureLine;
128};
129
130
Romain Guy726aeba2011-06-01 14:52:00 -0700131///////////////////////////////////////////////////////////////////////////////
132// Font
133///////////////////////////////////////////////////////////////////////////////
134
Romain Guy51769a62010-07-23 00:28:00 -0700135/**
136 * Represents a font, defined by a Skia font id and a font size. A font is used
137 * to generate glyphs and cache them in the FontState.
138 */
Romain Guy694b5192010-07-21 21:33:20 -0700139class Font {
140public:
Romain Guy325a0f92011-01-05 15:26:55 -0800141 enum Style {
Romain Guyc7b25be2011-03-23 14:59:20 -0700142 kFakeBold = 1
Romain Guy325a0f92011-01-05 15:26:55 -0800143 };
144
Romain Guy694b5192010-07-21 21:33:20 -0700145 ~Font();
146
Romain Guy51769a62010-07-23 00:28:00 -0700147 /**
148 * Renders the specified string of text.
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700149 * If bitmap is specified, it will be used as the render target
Romain Guy51769a62010-07-23 00:28:00 -0700150 */
Romain Guy726aeba2011-06-01 14:52:00 -0700151 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
152 int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
153 uint32_t bitmapW = 0, uint32_t bitmapH = 0);
Romain Guy671d6cf2012-01-18 12:39:17 -0800154
155 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
156 int numGlyphs, int x, int y, const float* positions);
157
Romain Guy51769a62010-07-23 00:28:00 -0700158 /**
159 * Creates a new font associated with the specified font state.
160 */
Romain Guy2577db12011-01-18 13:02:38 -0800161 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
Romain Guybd496bc2011-08-02 17:32:41 -0700162 int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
163 uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700164
165protected:
Romain Guy694b5192010-07-21 21:33:20 -0700166 friend class FontRenderer;
Romain Guy671d6cf2012-01-18 12:39:17 -0800167 typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*,
168 uint32_t, uint32_t, Rect*, const float*);
Romain Guy694b5192010-07-21 21:33:20 -0700169
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700170 enum RenderMode {
171 FRAMEBUFFER,
172 BITMAP,
173 MEASURE,
174 };
175
Romain Guy726aeba2011-06-01 14:52:00 -0700176 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
177 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
Romain Guy671d6cf2012-01-18 12:39:17 -0800178 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700179
Romain Guy726aeba2011-06-01 14:52:00 -0700180 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
181 int numGlyphs, Rect *bounds);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700182
Chet Haase8668f8a2011-03-02 13:51:36 -0800183 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
Romain Guybd496bc2011-08-02 17:32:41 -0700184 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700185
Romain Guy726aeba2011-06-01 14:52:00 -0700186 // Cache of glyphs
187 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
Romain Guy694b5192010-07-21 21:33:20 -0700188
Chet Haase9a824562011-12-16 15:44:59 -0800189 void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700190
Romain Guy726aeba2011-06-01 14:52:00 -0700191 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
Romain Guy671d6cf2012-01-18 12:39:17 -0800192 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
193
194 void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
195 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
196 Rect* bounds, const float* pos);
197 void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
198 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
199 Rect* bounds, const float* pos);
200 void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
201 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
202 Rect* bounds, const float* pos);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700203
Romain Guy726aeba2011-06-01 14:52:00 -0700204 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
205
206 static glyph_t nextGlyph(const uint16_t** srcPtr) {
207 const uint16_t* src = *srcPtr;
208 glyph_t g = *src++;
209 *srcPtr = src;
210 return g;
211 }
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700212
Romain Guybd0e6aa2010-07-22 18:50:12 -0700213 FontRenderer* mState;
214 uint32_t mFontId;
215 float mFontSize;
Romain Guy325a0f92011-01-05 15:26:55 -0800216 int mFlags;
Romain Guy2577db12011-01-18 13:02:38 -0800217 uint32_t mItalicStyle;
Chet Haase8668f8a2011-03-02 13:51:36 -0800218 uint32_t mScaleX;
Romain Guybd496bc2011-08-02 17:32:41 -0700219 SkPaint::Style mStyle;
220 uint32_t mStrokeWidth;
Romain Guy694b5192010-07-21 21:33:20 -0700221};
222
Romain Guy726aeba2011-06-01 14:52:00 -0700223///////////////////////////////////////////////////////////////////////////////
224// Renderer
225///////////////////////////////////////////////////////////////////////////////
226
Romain Guy694b5192010-07-21 21:33:20 -0700227class FontRenderer {
228public:
229 FontRenderer();
230 ~FontRenderer();
231
232 void init();
233 void deinit();
Chet Haase9a824562011-12-16 15:44:59 -0800234 void flushLargeCaches();
Romain Guy694b5192010-07-21 21:33:20 -0700235
Romain Guyb45c0c92010-08-26 20:35:23 -0700236 void setGammaTable(const uint8_t* gammaTable) {
237 mGammaTable = gammaTable;
238 }
239
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700240 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy671d6cf2012-01-18 12:39:17 -0800241 // bounds is an out parameter
Romain Guy5b3b3522010-10-27 18:57:51 -0700242 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
243 uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
Romain Guy671d6cf2012-01-18 12:39:17 -0800244 // bounds is an out parameter
245 bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
246 uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700247
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700248 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700249 DropShadow() { };
250
251 DropShadow(const DropShadow& dropShadow):
252 width(dropShadow.width), height(dropShadow.height),
253 image(dropShadow.image), penX(dropShadow.penX),
254 penY(dropShadow.penY) {
255 }
256
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700257 uint32_t width;
258 uint32_t height;
259 uint8_t* image;
260 int32_t penX;
261 int32_t penY;
262 };
263
264 // After renderDropShadow returns, the called owns the memory in DropShadow.image
265 // and is responsible for releasing it when it's done with it
266 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Romain Guy1e45aae2010-08-13 19:39:53 -0700267 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700268
Romain Guye8cb9c142010-10-04 14:14:11 -0700269 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700270 checkInit();
Chet Haase2a47c142011-12-14 15:22:56 -0800271 if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
272 mCurrentCacheTexture->mLinearFiltering = linearFiltering;
Romain Guye8cb9c142010-10-04 14:14:11 -0700273 mLinearFiltering = linearFiltering;
274 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
275
Chet Haase7de0cb12011-12-05 16:35:38 -0800276 glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
Romain Guye8cb9c142010-10-04 14:14:11 -0700277 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
279 }
Chet Haase7de0cb12011-12-05 16:35:38 -0800280 return mCurrentCacheTexture->mTextureId;
Romain Guy694b5192010-07-21 21:33:20 -0700281 }
282
Chet Haase7de0cb12011-12-05 16:35:38 -0800283 uint32_t getCacheSize() const {
284 uint32_t size = 0;
285 if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
286 size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
287 }
288 if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
289 size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
290 }
291 if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
292 size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
293 }
294 if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
295 size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
296 }
297 return size;
Romain Guyc15008e2010-11-10 11:59:15 -0800298 }
299
Romain Guy694b5192010-07-21 21:33:20 -0700300protected:
301 friend class Font;
302
Romain Guyb45c0c92010-08-26 20:35:23 -0700303 const uint8_t* mGammaTable;
304
Chet Haase2a47c142011-12-14 15:22:56 -0800305 void allocateTextureMemory(CacheTexture* cacheTexture);
Chet Haase9a824562011-12-16 15:44:59 -0800306 void deallocateTextureMemory(CacheTexture* cacheTexture);
Chet Haase7de0cb12011-12-05 16:35:38 -0800307 void initTextTexture();
308 CacheTexture *createCacheTexture(int width, int height, bool allocate);
309 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
310 uint32_t *retOriginX, uint32_t *retOriginY);
Romain Guy694b5192010-07-21 21:33:20 -0700311
312 void flushAllAndInvalidate();
313 void initVertexArrayBuffers();
314
315 void checkInit();
Romain Guy671d6cf2012-01-18 12:39:17 -0800316 void initRender(const Rect* clip, Rect* bounds);
317 void finishRender();
Romain Guy694b5192010-07-21 21:33:20 -0700318
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700319 String16 mLatinPrecache;
320 void precacheLatin(SkPaint* paint);
321
Romain Guy694b5192010-07-21 21:33:20 -0700322 void issueDrawCommand();
Romain Guyd71dd362011-12-12 19:03:35 -0800323 void appendMeshQuad(float x1, float y1, float u1, float v1,
324 float x2, float y2, float u2, float v2,
325 float x3, float y3, float u3, float v3,
Chet Haase7de0cb12011-12-05 16:35:38 -0800326 float x4, float y4, float u4, float v4, CacheTexture* texture);
Romain Guy694b5192010-07-21 21:33:20 -0700327
Chet Haase7de0cb12011-12-05 16:35:38 -0800328 uint32_t mSmallCacheWidth;
329 uint32_t mSmallCacheHeight;
Romain Guy694b5192010-07-21 21:33:20 -0700330
Romain Guy694b5192010-07-21 21:33:20 -0700331 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700332 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700333
Romain Guy09147fb2010-07-22 13:08:20 -0700334 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700335 Vector<Font*> mActiveFonts;
336
Chet Haase7de0cb12011-12-05 16:35:38 -0800337 CacheTexture* mCurrentCacheTexture;
338 CacheTexture* mLastCacheTexture;
339 CacheTexture* mCacheTextureSmall;
340 CacheTexture* mCacheTexture128;
341 CacheTexture* mCacheTexture256;
342 CacheTexture* mCacheTexture512;
343
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700344 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700345 bool mUploadTexture;
346
347 // Pointer to vertex data to speed up frame to frame work
348 float *mTextMeshPtr;
349 uint32_t mCurrentQuadIndex;
350 uint32_t mMaxNumberOfQuads;
351
352 uint32_t mIndexBufferID;
353
Romain Guy09147fb2010-07-22 13:08:20 -0700354 const Rect* mClip;
Romain Guy5b3b3522010-10-27 18:57:51 -0700355 Rect* mBounds;
356 bool mDrawn;
Romain Guy09147fb2010-07-22 13:08:20 -0700357
Romain Guy694b5192010-07-21 21:33:20 -0700358 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700359
Romain Guye8cb9c142010-10-04 14:14:11 -0700360 bool mLinearFiltering;
361
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700362 void computeGaussianWeights(float* weights, int32_t radius);
363 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700364 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700365 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700366 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700367 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700368};
369
370}; // namespace uirenderer
371}; // namespace android
372
Romain Guy5b3b3522010-10-27 18:57:51 -0700373#endif // ANDROID_HWUI_FONT_RENDERER_H