blob: 9f32747a1cea81a163b89f03f2cd81ce9e36c3da [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 Guy51769a62010-07-23 00:28:00 -0700154 /**
155 * Creates a new font associated with the specified font state.
156 */
Romain Guy2577db12011-01-18 13:02:38 -0800157 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
Romain Guybd496bc2011-08-02 17:32:41 -0700158 int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
159 uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700160
161protected:
Romain Guy694b5192010-07-21 21:33:20 -0700162 friend class FontRenderer;
163
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700164 enum RenderMode {
165 FRAMEBUFFER,
166 BITMAP,
167 MEASURE,
168 };
169
Romain Guy726aeba2011-06-01 14:52:00 -0700170 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
171 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
172 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700173
Romain Guy726aeba2011-06-01 14:52:00 -0700174 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
175 int numGlyphs, Rect *bounds);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700176
Chet Haase8668f8a2011-03-02 13:51:36 -0800177 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
Romain Guybd496bc2011-08-02 17:32:41 -0700178 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700179
Romain Guy726aeba2011-06-01 14:52:00 -0700180 // Cache of glyphs
181 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
Romain Guy694b5192010-07-21 21:33:20 -0700182
Romain Guybd0e6aa2010-07-22 18:50:12 -0700183 void invalidateTextureCache();
184
Romain Guy726aeba2011-06-01 14:52:00 -0700185 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
Romain Guy694b5192010-07-21 21:33:20 -0700186 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700187 void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700188 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700189 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
Romain Guy726aeba2011-06-01 14:52:00 -0700190 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700191
Romain Guy726aeba2011-06-01 14:52:00 -0700192 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
193
194 static glyph_t nextGlyph(const uint16_t** srcPtr) {
195 const uint16_t* src = *srcPtr;
196 glyph_t g = *src++;
197 *srcPtr = src;
198 return g;
199 }
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700200
Romain Guybd0e6aa2010-07-22 18:50:12 -0700201 FontRenderer* mState;
202 uint32_t mFontId;
203 float mFontSize;
Romain Guy325a0f92011-01-05 15:26:55 -0800204 int mFlags;
Romain Guy2577db12011-01-18 13:02:38 -0800205 uint32_t mItalicStyle;
Chet Haase8668f8a2011-03-02 13:51:36 -0800206 uint32_t mScaleX;
Romain Guybd496bc2011-08-02 17:32:41 -0700207 SkPaint::Style mStyle;
208 uint32_t mStrokeWidth;
Romain Guy694b5192010-07-21 21:33:20 -0700209};
210
Romain Guy726aeba2011-06-01 14:52:00 -0700211///////////////////////////////////////////////////////////////////////////////
212// Renderer
213///////////////////////////////////////////////////////////////////////////////
214
Romain Guy694b5192010-07-21 21:33:20 -0700215class FontRenderer {
216public:
217 FontRenderer();
218 ~FontRenderer();
219
220 void init();
221 void deinit();
222
Romain Guyb45c0c92010-08-26 20:35:23 -0700223 void setGammaTable(const uint8_t* gammaTable) {
224 mGammaTable = gammaTable;
225 }
226
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700227 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy5b3b3522010-10-27 18:57:51 -0700228 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
229 uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700230
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700231 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700232 DropShadow() { };
233
234 DropShadow(const DropShadow& dropShadow):
235 width(dropShadow.width), height(dropShadow.height),
236 image(dropShadow.image), penX(dropShadow.penX),
237 penY(dropShadow.penY) {
238 }
239
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700240 uint32_t width;
241 uint32_t height;
242 uint8_t* image;
243 int32_t penX;
244 int32_t penY;
245 };
246
247 // After renderDropShadow returns, the called owns the memory in DropShadow.image
248 // and is responsible for releasing it when it's done with it
249 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Romain Guy1e45aae2010-08-13 19:39:53 -0700250 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700251
Romain Guye8cb9c142010-10-04 14:14:11 -0700252 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700253 checkInit();
Chet Haase2a47c142011-12-14 15:22:56 -0800254 if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
255 mCurrentCacheTexture->mLinearFiltering = linearFiltering;
Romain Guye8cb9c142010-10-04 14:14:11 -0700256 mLinearFiltering = linearFiltering;
257 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
258
Chet Haase7de0cb12011-12-05 16:35:38 -0800259 glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
Romain Guye8cb9c142010-10-04 14:14:11 -0700260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
262 }
Chet Haase7de0cb12011-12-05 16:35:38 -0800263 return mCurrentCacheTexture->mTextureId;
Romain Guy694b5192010-07-21 21:33:20 -0700264 }
265
Chet Haase7de0cb12011-12-05 16:35:38 -0800266 uint32_t getCacheSize() const {
267 uint32_t size = 0;
268 if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
269 size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
270 }
271 if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
272 size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
273 }
274 if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
275 size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
276 }
277 if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
278 size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
279 }
280 return size;
Romain Guyc15008e2010-11-10 11:59:15 -0800281 }
282
Romain Guy694b5192010-07-21 21:33:20 -0700283protected:
284 friend class Font;
285
Romain Guyb45c0c92010-08-26 20:35:23 -0700286 const uint8_t* mGammaTable;
287
Chet Haase2a47c142011-12-14 15:22:56 -0800288 void allocateTextureMemory(CacheTexture* cacheTexture);
Chet Haase7de0cb12011-12-05 16:35:38 -0800289 void initTextTexture();
290 CacheTexture *createCacheTexture(int width, int height, bool allocate);
291 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
292 uint32_t *retOriginX, uint32_t *retOriginY);
Romain Guy694b5192010-07-21 21:33:20 -0700293
294 void flushAllAndInvalidate();
295 void initVertexArrayBuffers();
296
297 void checkInit();
298
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700299 String16 mLatinPrecache;
300 void precacheLatin(SkPaint* paint);
301
Romain Guy694b5192010-07-21 21:33:20 -0700302 void issueDrawCommand();
Romain Guyd71dd362011-12-12 19:03:35 -0800303 void appendMeshQuad(float x1, float y1, float u1, float v1,
304 float x2, float y2, float u2, float v2,
305 float x3, float y3, float u3, float v3,
Chet Haase7de0cb12011-12-05 16:35:38 -0800306 float x4, float y4, float u4, float v4, CacheTexture* texture);
Romain Guy694b5192010-07-21 21:33:20 -0700307
Chet Haase7de0cb12011-12-05 16:35:38 -0800308 uint32_t mSmallCacheWidth;
309 uint32_t mSmallCacheHeight;
Romain Guy694b5192010-07-21 21:33:20 -0700310
Romain Guy694b5192010-07-21 21:33:20 -0700311 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700312 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700313
Romain Guy09147fb2010-07-22 13:08:20 -0700314 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700315 Vector<Font*> mActiveFonts;
316
Chet Haase7de0cb12011-12-05 16:35:38 -0800317 CacheTexture* mCurrentCacheTexture;
318 CacheTexture* mLastCacheTexture;
319 CacheTexture* mCacheTextureSmall;
320 CacheTexture* mCacheTexture128;
321 CacheTexture* mCacheTexture256;
322 CacheTexture* mCacheTexture512;
323
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700324 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700325 bool mUploadTexture;
326
327 // Pointer to vertex data to speed up frame to frame work
328 float *mTextMeshPtr;
329 uint32_t mCurrentQuadIndex;
330 uint32_t mMaxNumberOfQuads;
331
332 uint32_t mIndexBufferID;
333
Romain Guy09147fb2010-07-22 13:08:20 -0700334 const Rect* mClip;
Romain Guy5b3b3522010-10-27 18:57:51 -0700335 Rect* mBounds;
336 bool mDrawn;
Romain Guy09147fb2010-07-22 13:08:20 -0700337
Romain Guy694b5192010-07-21 21:33:20 -0700338 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700339
Romain Guye8cb9c142010-10-04 14:14:11 -0700340 bool mLinearFiltering;
341
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700342 void computeGaussianWeights(float* weights, int32_t radius);
343 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700344 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700345 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700346 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700347 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700348};
349
350}; // namespace uirenderer
351}; // namespace android
352
Romain Guy5b3b3522010-10-27 18:57:51 -0700353#endif // ANDROID_HWUI_FONT_RENDERER_H