blob: 005cddeebe7ae0d8a814a64fef7eb9633043d1de [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
Chet Haase9a824562011-12-16 15:44:59 -0800183 void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700184
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();
Chet Haase9a824562011-12-16 15:44:59 -0800222 void flushLargeCaches();
Romain Guy694b5192010-07-21 21:33:20 -0700223
Romain Guyb45c0c92010-08-26 20:35:23 -0700224 void setGammaTable(const uint8_t* gammaTable) {
225 mGammaTable = gammaTable;
226 }
227
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700228 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy5b3b3522010-10-27 18:57:51 -0700229 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
230 uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700231
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700232 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700233 DropShadow() { };
234
235 DropShadow(const DropShadow& dropShadow):
236 width(dropShadow.width), height(dropShadow.height),
237 image(dropShadow.image), penX(dropShadow.penX),
238 penY(dropShadow.penY) {
239 }
240
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700241 uint32_t width;
242 uint32_t height;
243 uint8_t* image;
244 int32_t penX;
245 int32_t penY;
246 };
247
248 // After renderDropShadow returns, the called owns the memory in DropShadow.image
249 // and is responsible for releasing it when it's done with it
250 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Romain Guy1e45aae2010-08-13 19:39:53 -0700251 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700252
Romain Guye8cb9c142010-10-04 14:14:11 -0700253 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700254 checkInit();
Chet Haase2a47c142011-12-14 15:22:56 -0800255 if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
256 mCurrentCacheTexture->mLinearFiltering = linearFiltering;
Romain Guye8cb9c142010-10-04 14:14:11 -0700257 mLinearFiltering = linearFiltering;
258 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
259
Chet Haase7de0cb12011-12-05 16:35:38 -0800260 glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
Romain Guye8cb9c142010-10-04 14:14:11 -0700261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
263 }
Chet Haase7de0cb12011-12-05 16:35:38 -0800264 return mCurrentCacheTexture->mTextureId;
Romain Guy694b5192010-07-21 21:33:20 -0700265 }
266
Chet Haase7de0cb12011-12-05 16:35:38 -0800267 uint32_t getCacheSize() const {
268 uint32_t size = 0;
269 if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
270 size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
271 }
272 if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
273 size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
274 }
275 if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
276 size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
277 }
278 if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
279 size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
280 }
281 return size;
Romain Guyc15008e2010-11-10 11:59:15 -0800282 }
283
Romain Guy694b5192010-07-21 21:33:20 -0700284protected:
285 friend class Font;
286
Romain Guyb45c0c92010-08-26 20:35:23 -0700287 const uint8_t* mGammaTable;
288
Chet Haase2a47c142011-12-14 15:22:56 -0800289 void allocateTextureMemory(CacheTexture* cacheTexture);
Chet Haase9a824562011-12-16 15:44:59 -0800290 void deallocateTextureMemory(CacheTexture* cacheTexture);
Chet Haase7de0cb12011-12-05 16:35:38 -0800291 void initTextTexture();
292 CacheTexture *createCacheTexture(int width, int height, bool allocate);
293 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
294 uint32_t *retOriginX, uint32_t *retOriginY);
Romain Guy694b5192010-07-21 21:33:20 -0700295
296 void flushAllAndInvalidate();
297 void initVertexArrayBuffers();
298
299 void checkInit();
300
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700301 String16 mLatinPrecache;
302 void precacheLatin(SkPaint* paint);
303
Romain Guy694b5192010-07-21 21:33:20 -0700304 void issueDrawCommand();
Romain Guyd71dd362011-12-12 19:03:35 -0800305 void appendMeshQuad(float x1, float y1, float u1, float v1,
306 float x2, float y2, float u2, float v2,
307 float x3, float y3, float u3, float v3,
Chet Haase7de0cb12011-12-05 16:35:38 -0800308 float x4, float y4, float u4, float v4, CacheTexture* texture);
Romain Guy694b5192010-07-21 21:33:20 -0700309
Chet Haase7de0cb12011-12-05 16:35:38 -0800310 uint32_t mSmallCacheWidth;
311 uint32_t mSmallCacheHeight;
Romain Guy694b5192010-07-21 21:33:20 -0700312
Romain Guy694b5192010-07-21 21:33:20 -0700313 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700314 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700315
Romain Guy09147fb2010-07-22 13:08:20 -0700316 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700317 Vector<Font*> mActiveFonts;
318
Chet Haase7de0cb12011-12-05 16:35:38 -0800319 CacheTexture* mCurrentCacheTexture;
320 CacheTexture* mLastCacheTexture;
321 CacheTexture* mCacheTextureSmall;
322 CacheTexture* mCacheTexture128;
323 CacheTexture* mCacheTexture256;
324 CacheTexture* mCacheTexture512;
325
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700326 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700327 bool mUploadTexture;
328
329 // Pointer to vertex data to speed up frame to frame work
330 float *mTextMeshPtr;
331 uint32_t mCurrentQuadIndex;
332 uint32_t mMaxNumberOfQuads;
333
334 uint32_t mIndexBufferID;
335
Romain Guy09147fb2010-07-22 13:08:20 -0700336 const Rect* mClip;
Romain Guy5b3b3522010-10-27 18:57:51 -0700337 Rect* mBounds;
338 bool mDrawn;
Romain Guy09147fb2010-07-22 13:08:20 -0700339
Romain Guy694b5192010-07-21 21:33:20 -0700340 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700341
Romain Guye8cb9c142010-10-04 14:14:11 -0700342 bool mLinearFiltering;
343
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700344 void computeGaussianWeights(float* weights, int32_t radius);
345 void horizontalBlur(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 verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700348 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700349 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700350};
351
352}; // namespace uirenderer
353}; // namespace android
354
Romain Guy5b3b3522010-10-27 18:57:51 -0700355#endif // ANDROID_HWUI_FONT_RENDERER_H