blob: 24ed6fa4756f4434c46240e193c79e7c9492635c [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
Romain Guy726aeba2011-06-01 14:52:00 -070058///////////////////////////////////////////////////////////////////////////////
59// Font
60///////////////////////////////////////////////////////////////////////////////
61
Romain Guy51769a62010-07-23 00:28:00 -070062/**
63 * Represents a font, defined by a Skia font id and a font size. A font is used
64 * to generate glyphs and cache them in the FontState.
65 */
Romain Guy694b5192010-07-21 21:33:20 -070066class Font {
67public:
Romain Guy325a0f92011-01-05 15:26:55 -080068 enum Style {
Romain Guyc7b25be2011-03-23 14:59:20 -070069 kFakeBold = 1
Romain Guy325a0f92011-01-05 15:26:55 -080070 };
71
Romain Guy694b5192010-07-21 21:33:20 -070072 ~Font();
73
Romain Guy51769a62010-07-23 00:28:00 -070074 /**
75 * Renders the specified string of text.
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -070076 * If bitmap is specified, it will be used as the render target
Romain Guy51769a62010-07-23 00:28:00 -070077 */
Romain Guy726aeba2011-06-01 14:52:00 -070078 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
79 int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
80 uint32_t bitmapW = 0, uint32_t bitmapH = 0);
Romain Guy51769a62010-07-23 00:28:00 -070081 /**
82 * Creates a new font associated with the specified font state.
83 */
Romain Guy2577db12011-01-18 13:02:38 -080084 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
Chet Haase8668f8a2011-03-02 13:51:36 -080085 int flags, uint32_t italicStyle, uint32_t scaleX);
Romain Guy694b5192010-07-21 21:33:20 -070086
87protected:
Romain Guy694b5192010-07-21 21:33:20 -070088 friend class FontRenderer;
89
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -070090 enum RenderMode {
91 FRAMEBUFFER,
92 BITMAP,
93 MEASURE,
94 };
95
Romain Guy726aeba2011-06-01 14:52:00 -070096 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
97 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
98 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -070099
Romain Guy726aeba2011-06-01 14:52:00 -0700100 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
101 int numGlyphs, Rect *bounds);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700102
Romain Guy694b5192010-07-21 21:33:20 -0700103 struct CachedGlyphInfo {
104 // Has the cache been invalidated?
105 bool mIsValid;
106 // Location of the cached glyph in the bitmap
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700107 // in case we need to resize the texture or
108 // render to bitmap
109 uint32_t mStartX;
110 uint32_t mStartY;
Romain Guy694b5192010-07-21 21:33:20 -0700111 uint32_t mBitmapWidth;
112 uint32_t mBitmapHeight;
113 // Also cache texture coords for the quad
114 float mBitmapMinU;
115 float mBitmapMinV;
116 float mBitmapMaxU;
117 float mBitmapMaxV;
118 // Minimize how much we call freetype
119 uint32_t mGlyphIndex;
120 uint32_t mAdvanceX;
121 uint32_t mAdvanceY;
122 // Values below contain a glyph's origin in the bitmap
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700123 int32_t mBitmapLeft;
124 int32_t mBitmapTop;
Romain Guy2bffd262010-09-12 17:40:02 -0700125 // Auto-kerning
126 SkFixed mLsbDelta;
127 SkFixed mRsbDelta;
Romain Guy694b5192010-07-21 21:33:20 -0700128 };
129
Chet Haase8668f8a2011-03-02 13:51:36 -0800130 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
131 uint32_t scaleX);
Romain Guy694b5192010-07-21 21:33:20 -0700132
Romain Guy726aeba2011-06-01 14:52:00 -0700133 // Cache of glyphs
134 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
Romain Guy694b5192010-07-21 21:33:20 -0700135
Romain Guybd0e6aa2010-07-22 18:50:12 -0700136 void invalidateTextureCache();
137
Romain Guy726aeba2011-06-01 14:52:00 -0700138 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
Romain Guy694b5192010-07-21 21:33:20 -0700139 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700140 void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700141 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700142 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
Romain Guy726aeba2011-06-01 14:52:00 -0700143 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700144
Romain Guy726aeba2011-06-01 14:52:00 -0700145 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
146
147 static glyph_t nextGlyph(const uint16_t** srcPtr) {
148 const uint16_t* src = *srcPtr;
149 glyph_t g = *src++;
150 *srcPtr = src;
151 return g;
152 }
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700153
Romain Guybd0e6aa2010-07-22 18:50:12 -0700154 FontRenderer* mState;
155 uint32_t mFontId;
156 float mFontSize;
Romain Guy325a0f92011-01-05 15:26:55 -0800157 int mFlags;
Romain Guy2577db12011-01-18 13:02:38 -0800158 uint32_t mItalicStyle;
Chet Haase8668f8a2011-03-02 13:51:36 -0800159 uint32_t mScaleX;
Romain Guy694b5192010-07-21 21:33:20 -0700160};
161
Romain Guy726aeba2011-06-01 14:52:00 -0700162///////////////////////////////////////////////////////////////////////////////
163// Renderer
164///////////////////////////////////////////////////////////////////////////////
165
Romain Guy694b5192010-07-21 21:33:20 -0700166class FontRenderer {
167public:
168 FontRenderer();
169 ~FontRenderer();
170
171 void init();
172 void deinit();
173
Romain Guyb45c0c92010-08-26 20:35:23 -0700174 void setGammaTable(const uint8_t* gammaTable) {
175 mGammaTable = gammaTable;
176 }
177
Alex Sakhartchouk894df172011-02-17 16:45:37 -0800178 void setAttributeBindingSlots(int positionSlot, int texCoordSlot) {
179 mPositionAttrSlot = positionSlot;
180 mTexcoordAttrSlot = texCoordSlot;
181 }
182
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700183 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy5b3b3522010-10-27 18:57:51 -0700184 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
185 uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700186
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700187 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700188 DropShadow() { };
189
190 DropShadow(const DropShadow& dropShadow):
191 width(dropShadow.width), height(dropShadow.height),
192 image(dropShadow.image), penX(dropShadow.penX),
193 penY(dropShadow.penY) {
194 }
195
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700196 uint32_t width;
197 uint32_t height;
198 uint8_t* image;
199 int32_t penX;
200 int32_t penY;
201 };
202
203 // After renderDropShadow returns, the called owns the memory in DropShadow.image
204 // and is responsible for releasing it when it's done with it
205 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Romain Guy1e45aae2010-08-13 19:39:53 -0700206 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700207
Romain Guye8cb9c142010-10-04 14:14:11 -0700208 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700209 checkInit();
Romain Guye8cb9c142010-10-04 14:14:11 -0700210 if (linearFiltering != mLinearFiltering) {
211 mLinearFiltering = linearFiltering;
212 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
213
214 glBindTexture(GL_TEXTURE_2D, mTextureId);
215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
217 }
Romain Guy694b5192010-07-21 21:33:20 -0700218 return mTextureId;
219 }
220
Romain Guyc15008e2010-11-10 11:59:15 -0800221 uint32_t getCacheWidth() const {
222 return mCacheWidth;
223 }
224
225 uint32_t getCacheHeight() const {
226 return mCacheHeight;
227 }
228
Romain Guy694b5192010-07-21 21:33:20 -0700229protected:
230 friend class Font;
231
Romain Guyb45c0c92010-08-26 20:35:23 -0700232 const uint8_t* mGammaTable;
233
Romain Guy694b5192010-07-21 21:33:20 -0700234 struct CacheTextureLine {
235 uint16_t mMaxHeight;
236 uint16_t mMaxWidth;
237 uint32_t mCurrentRow;
238 uint32_t mCurrentCol;
Romain Guy1e45aae2010-08-13 19:39:53 -0700239 bool mDirty;
Romain Guy694b5192010-07-21 21:33:20 -0700240
Romain Guy51769a62010-07-23 00:28:00 -0700241 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
Romain Guy694b5192010-07-21 21:33:20 -0700242 uint32_t currentCol):
Romain Guy51769a62010-07-23 00:28:00 -0700243 mMaxHeight(maxHeight),
244 mMaxWidth(maxWidth),
245 mCurrentRow(currentRow),
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700246 mCurrentCol(currentCol),
247 mDirty(false) {
Romain Guy694b5192010-07-21 21:33:20 -0700248 }
249
250 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
Romain Guy7975fb62010-10-01 16:36:14 -0700251 if (glyph.fHeight + 2 > mMaxHeight) {
Romain Guy694b5192010-07-21 21:33:20 -0700252 return false;
253 }
254
Romain Guy7975fb62010-10-01 16:36:14 -0700255 if (mCurrentCol + glyph.fWidth + 2 < mMaxWidth) {
256 *retOriginX = mCurrentCol + 1;
257 *retOriginY = mCurrentRow + 1;
258 mCurrentCol += glyph.fWidth + 2;
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700259 mDirty = true;
Romain Guy694b5192010-07-21 21:33:20 -0700260 return true;
261 }
262
263 return false;
264 }
265 };
266
Chet Haase44984ea2011-05-19 13:50:47 -0700267 void initTextTexture(bool largeFonts = false);
Romain Guy694b5192010-07-21 21:33:20 -0700268 bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
269
270 void flushAllAndInvalidate();
271 void initVertexArrayBuffers();
272
273 void checkInit();
274
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700275 String16 mLatinPrecache;
276 void precacheLatin(SkPaint* paint);
277
Romain Guy694b5192010-07-21 21:33:20 -0700278 void issueDrawCommand();
Romain Guy694b5192010-07-21 21:33:20 -0700279 void appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2,
280 float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3,
281 float x4, float y4, float z4, float u4, float v4);
282
283 uint32_t mCacheWidth;
284 uint32_t mCacheHeight;
285
Romain Guy694b5192010-07-21 21:33:20 -0700286 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700287 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700288
Romain Guy09147fb2010-07-22 13:08:20 -0700289 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700290 Vector<Font*> mActiveFonts;
291
292 // Texture to cache glyph bitmaps
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700293 uint8_t* mTextTexture;
294 const uint8_t* getTextTextureData() const {
295 return mTextTexture;
296 }
Romain Guy694b5192010-07-21 21:33:20 -0700297 GLuint mTextureId;
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700298 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700299 bool mUploadTexture;
300
301 // Pointer to vertex data to speed up frame to frame work
302 float *mTextMeshPtr;
303 uint32_t mCurrentQuadIndex;
304 uint32_t mMaxNumberOfQuads;
305
306 uint32_t mIndexBufferID;
307
Alex Sakhartchouk894df172011-02-17 16:45:37 -0800308 int32_t mPositionAttrSlot;
309 int32_t mTexcoordAttrSlot;
310
Romain Guy09147fb2010-07-22 13:08:20 -0700311 const Rect* mClip;
Romain Guy5b3b3522010-10-27 18:57:51 -0700312 Rect* mBounds;
313 bool mDrawn;
Romain Guy09147fb2010-07-22 13:08:20 -0700314
Romain Guy694b5192010-07-21 21:33:20 -0700315 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700316
Romain Guye8cb9c142010-10-04 14:14:11 -0700317 bool mLinearFiltering;
318
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700319 void computeGaussianWeights(float* weights, int32_t radius);
320 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700321 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700322 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700323 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700324 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700325};
326
327}; // namespace uirenderer
328}; // namespace android
329
Romain Guy5b3b3522010-10-27 18:57:51 -0700330#endif // ANDROID_HWUI_FONT_RENDERER_H