blob: b34fdfafd02fb899ec3f1b0557dcba82a8d50ede [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
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700225 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy5b3b3522010-10-27 18:57:51 -0700226 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
227 uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700228
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700229 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700230 DropShadow() { };
231
232 DropShadow(const DropShadow& dropShadow):
233 width(dropShadow.width), height(dropShadow.height),
234 image(dropShadow.image), penX(dropShadow.penX),
235 penY(dropShadow.penY) {
236 }
237
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700238 uint32_t width;
239 uint32_t height;
240 uint8_t* image;
241 int32_t penX;
242 int32_t penY;
243 };
244
245 // After renderDropShadow returns, the called owns the memory in DropShadow.image
246 // and is responsible for releasing it when it's done with it
247 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Romain Guy1e45aae2010-08-13 19:39:53 -0700248 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700249
Romain Guye8cb9c142010-10-04 14:14:11 -0700250 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700251 checkInit();
Romain Guye8cb9c142010-10-04 14:14:11 -0700252 if (linearFiltering != mLinearFiltering) {
253 mLinearFiltering = linearFiltering;
254 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
255
Chet Haase7de0cb12011-12-05 16:35:38 -0800256 glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
Romain Guye8cb9c142010-10-04 14:14:11 -0700257 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
258 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
259 }
Chet Haase7de0cb12011-12-05 16:35:38 -0800260 return mCurrentCacheTexture->mTextureId;
Romain Guy694b5192010-07-21 21:33:20 -0700261 }
262
Chet Haase7de0cb12011-12-05 16:35:38 -0800263 uint32_t getCacheSize() const {
264 uint32_t size = 0;
265 if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
266 size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
267 }
268 if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
269 size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
270 }
271 if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
272 size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
273 }
274 if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
275 size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
276 }
277 return size;
Romain Guyc15008e2010-11-10 11:59:15 -0800278 }
279
Romain Guy694b5192010-07-21 21:33:20 -0700280protected:
281 friend class Font;
282
Romain Guyb45c0c92010-08-26 20:35:23 -0700283 const uint8_t* mGammaTable;
284
Chet Haase7de0cb12011-12-05 16:35:38 -0800285 uint8_t* allocateTextureMemory(int width, int height);
286 void initTextTexture();
287 CacheTexture *createCacheTexture(int width, int height, bool allocate);
288 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
289 uint32_t *retOriginX, uint32_t *retOriginY);
Romain Guy694b5192010-07-21 21:33:20 -0700290
291 void flushAllAndInvalidate();
292 void initVertexArrayBuffers();
293
294 void checkInit();
295
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700296 String16 mLatinPrecache;
297 void precacheLatin(SkPaint* paint);
298
Romain Guy694b5192010-07-21 21:33:20 -0700299 void issueDrawCommand();
Romain Guyd71dd362011-12-12 19:03:35 -0800300 void appendMeshQuad(float x1, float y1, float u1, float v1,
301 float x2, float y2, float u2, float v2,
302 float x3, float y3, float u3, float v3,
Chet Haase7de0cb12011-12-05 16:35:38 -0800303 float x4, float y4, float u4, float v4, CacheTexture* texture);
Romain Guy694b5192010-07-21 21:33:20 -0700304
Chet Haase7de0cb12011-12-05 16:35:38 -0800305 uint32_t mSmallCacheWidth;
306 uint32_t mSmallCacheHeight;
Romain Guy694b5192010-07-21 21:33:20 -0700307
Romain Guy694b5192010-07-21 21:33:20 -0700308 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700309 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700310
Romain Guy09147fb2010-07-22 13:08:20 -0700311 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700312 Vector<Font*> mActiveFonts;
313
Chet Haase7de0cb12011-12-05 16:35:38 -0800314 CacheTexture* mCurrentCacheTexture;
315 CacheTexture* mLastCacheTexture;
316 CacheTexture* mCacheTextureSmall;
317 CacheTexture* mCacheTexture128;
318 CacheTexture* mCacheTexture256;
319 CacheTexture* mCacheTexture512;
320
321
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700322 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700323 bool mUploadTexture;
324
325 // Pointer to vertex data to speed up frame to frame work
326 float *mTextMeshPtr;
327 uint32_t mCurrentQuadIndex;
328 uint32_t mMaxNumberOfQuads;
329
330 uint32_t mIndexBufferID;
331
Romain Guy09147fb2010-07-22 13:08:20 -0700332 const Rect* mClip;
Romain Guy5b3b3522010-10-27 18:57:51 -0700333 Rect* mBounds;
334 bool mDrawn;
Romain Guy09147fb2010-07-22 13:08:20 -0700335
Romain Guy694b5192010-07-21 21:33:20 -0700336 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700337
Romain Guye8cb9c142010-10-04 14:14:11 -0700338 bool mLinearFiltering;
339
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700340 void computeGaussianWeights(float* weights, int32_t radius);
341 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700342 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700343 void verticalBlur(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 blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700346};
347
348}; // namespace uirenderer
349}; // namespace android
350
Romain Guy5b3b3522010-10-27 18:57:51 -0700351#endif // ANDROID_HWUI_FONT_RENDERER_H