blob: 1922812b387e11a5e53ec293f408bb7a5ef0fef8 [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,
Romain Guybd496bc2011-08-02 17:32:41 -070085 int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
86 uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -070087
88protected:
Romain Guy694b5192010-07-21 21:33:20 -070089 friend class FontRenderer;
90
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -070091 enum RenderMode {
92 FRAMEBUFFER,
93 BITMAP,
94 MEASURE,
95 };
96
Romain Guy726aeba2011-06-01 14:52:00 -070097 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
98 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
99 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700100
Romain Guy726aeba2011-06-01 14:52:00 -0700101 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
102 int numGlyphs, Rect *bounds);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700103
Romain Guy694b5192010-07-21 21:33:20 -0700104 struct CachedGlyphInfo {
105 // Has the cache been invalidated?
106 bool mIsValid;
107 // Location of the cached glyph in the bitmap
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700108 // in case we need to resize the texture or
109 // render to bitmap
110 uint32_t mStartX;
111 uint32_t mStartY;
Romain Guy694b5192010-07-21 21:33:20 -0700112 uint32_t mBitmapWidth;
113 uint32_t mBitmapHeight;
114 // Also cache texture coords for the quad
115 float mBitmapMinU;
116 float mBitmapMinV;
117 float mBitmapMaxU;
118 float mBitmapMaxV;
119 // Minimize how much we call freetype
120 uint32_t mGlyphIndex;
121 uint32_t mAdvanceX;
122 uint32_t mAdvanceY;
123 // Values below contain a glyph's origin in the bitmap
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700124 int32_t mBitmapLeft;
125 int32_t mBitmapTop;
Romain Guy2bffd262010-09-12 17:40:02 -0700126 // Auto-kerning
127 SkFixed mLsbDelta;
128 SkFixed mRsbDelta;
Romain Guy694b5192010-07-21 21:33:20 -0700129 };
130
Chet Haase8668f8a2011-03-02 13:51:36 -0800131 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
Romain Guybd496bc2011-08-02 17:32:41 -0700132 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
Romain Guy694b5192010-07-21 21:33:20 -0700133
Romain Guy726aeba2011-06-01 14:52:00 -0700134 // Cache of glyphs
135 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
Romain Guy694b5192010-07-21 21:33:20 -0700136
Romain Guybd0e6aa2010-07-22 18:50:12 -0700137 void invalidateTextureCache();
138
Romain Guy726aeba2011-06-01 14:52:00 -0700139 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
Romain Guy694b5192010-07-21 21:33:20 -0700140 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700141 void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700142 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700143 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
Romain Guy726aeba2011-06-01 14:52:00 -0700144 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700145
Romain Guy726aeba2011-06-01 14:52:00 -0700146 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
147
148 static glyph_t nextGlyph(const uint16_t** srcPtr) {
149 const uint16_t* src = *srcPtr;
150 glyph_t g = *src++;
151 *srcPtr = src;
152 return g;
153 }
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700154
Romain Guybd0e6aa2010-07-22 18:50:12 -0700155 FontRenderer* mState;
156 uint32_t mFontId;
157 float mFontSize;
Romain Guy325a0f92011-01-05 15:26:55 -0800158 int mFlags;
Romain Guy2577db12011-01-18 13:02:38 -0800159 uint32_t mItalicStyle;
Chet Haase8668f8a2011-03-02 13:51:36 -0800160 uint32_t mScaleX;
Romain Guybd496bc2011-08-02 17:32:41 -0700161 SkPaint::Style mStyle;
162 uint32_t mStrokeWidth;
Romain Guy694b5192010-07-21 21:33:20 -0700163};
164
Romain Guy726aeba2011-06-01 14:52:00 -0700165///////////////////////////////////////////////////////////////////////////////
166// Renderer
167///////////////////////////////////////////////////////////////////////////////
168
Romain Guy694b5192010-07-21 21:33:20 -0700169class FontRenderer {
170public:
171 FontRenderer();
172 ~FontRenderer();
173
174 void init();
175 void deinit();
176
Romain Guyb45c0c92010-08-26 20:35:23 -0700177 void setGammaTable(const uint8_t* gammaTable) {
178 mGammaTable = gammaTable;
179 }
180
Alex Sakhartchouk894df172011-02-17 16:45:37 -0800181 void setAttributeBindingSlots(int positionSlot, int texCoordSlot) {
182 mPositionAttrSlot = positionSlot;
183 mTexcoordAttrSlot = texCoordSlot;
184 }
185
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700186 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy5b3b3522010-10-27 18:57:51 -0700187 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
188 uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700189
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700190 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700191 DropShadow() { };
192
193 DropShadow(const DropShadow& dropShadow):
194 width(dropShadow.width), height(dropShadow.height),
195 image(dropShadow.image), penX(dropShadow.penX),
196 penY(dropShadow.penY) {
197 }
198
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700199 uint32_t width;
200 uint32_t height;
201 uint8_t* image;
202 int32_t penX;
203 int32_t penY;
204 };
205
206 // After renderDropShadow returns, the called owns the memory in DropShadow.image
207 // and is responsible for releasing it when it's done with it
208 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Romain Guy1e45aae2010-08-13 19:39:53 -0700209 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700210
Romain Guye8cb9c142010-10-04 14:14:11 -0700211 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700212 checkInit();
Romain Guye8cb9c142010-10-04 14:14:11 -0700213 if (linearFiltering != mLinearFiltering) {
214 mLinearFiltering = linearFiltering;
215 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
216
217 glBindTexture(GL_TEXTURE_2D, mTextureId);
218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
220 }
Romain Guy694b5192010-07-21 21:33:20 -0700221 return mTextureId;
222 }
223
Romain Guyc15008e2010-11-10 11:59:15 -0800224 uint32_t getCacheWidth() const {
225 return mCacheWidth;
226 }
227
228 uint32_t getCacheHeight() const {
229 return mCacheHeight;
230 }
231
Romain Guy694b5192010-07-21 21:33:20 -0700232protected:
233 friend class Font;
234
Romain Guyb45c0c92010-08-26 20:35:23 -0700235 const uint8_t* mGammaTable;
236
Romain Guy694b5192010-07-21 21:33:20 -0700237 struct CacheTextureLine {
238 uint16_t mMaxHeight;
239 uint16_t mMaxWidth;
240 uint32_t mCurrentRow;
241 uint32_t mCurrentCol;
Romain Guy1e45aae2010-08-13 19:39:53 -0700242 bool mDirty;
Romain Guy694b5192010-07-21 21:33:20 -0700243
Romain Guy51769a62010-07-23 00:28:00 -0700244 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
Romain Guy694b5192010-07-21 21:33:20 -0700245 uint32_t currentCol):
Romain Guy51769a62010-07-23 00:28:00 -0700246 mMaxHeight(maxHeight),
247 mMaxWidth(maxWidth),
248 mCurrentRow(currentRow),
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700249 mCurrentCol(currentCol),
250 mDirty(false) {
Romain Guy694b5192010-07-21 21:33:20 -0700251 }
252
253 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
Romain Guy7975fb62010-10-01 16:36:14 -0700254 if (glyph.fHeight + 2 > mMaxHeight) {
Romain Guy694b5192010-07-21 21:33:20 -0700255 return false;
256 }
257
Romain Guy7975fb62010-10-01 16:36:14 -0700258 if (mCurrentCol + glyph.fWidth + 2 < mMaxWidth) {
259 *retOriginX = mCurrentCol + 1;
260 *retOriginY = mCurrentRow + 1;
261 mCurrentCol += glyph.fWidth + 2;
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700262 mDirty = true;
Romain Guy694b5192010-07-21 21:33:20 -0700263 return true;
264 }
265
266 return false;
267 }
268 };
269
Chet Haase44984ea2011-05-19 13:50:47 -0700270 void initTextTexture(bool largeFonts = false);
Romain Guy694b5192010-07-21 21:33:20 -0700271 bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
272
273 void flushAllAndInvalidate();
274 void initVertexArrayBuffers();
275
276 void checkInit();
277
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700278 String16 mLatinPrecache;
279 void precacheLatin(SkPaint* paint);
280
Romain Guy694b5192010-07-21 21:33:20 -0700281 void issueDrawCommand();
Romain Guy694b5192010-07-21 21:33:20 -0700282 void appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2,
283 float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3,
284 float x4, float y4, float z4, float u4, float v4);
285
286 uint32_t mCacheWidth;
287 uint32_t mCacheHeight;
288
Romain Guy694b5192010-07-21 21:33:20 -0700289 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700290 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700291
Romain Guy09147fb2010-07-22 13:08:20 -0700292 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700293 Vector<Font*> mActiveFonts;
294
295 // Texture to cache glyph bitmaps
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700296 uint8_t* mTextTexture;
297 const uint8_t* getTextTextureData() const {
298 return mTextTexture;
299 }
Romain Guy694b5192010-07-21 21:33:20 -0700300 GLuint mTextureId;
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700301 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700302 bool mUploadTexture;
303
304 // Pointer to vertex data to speed up frame to frame work
305 float *mTextMeshPtr;
306 uint32_t mCurrentQuadIndex;
307 uint32_t mMaxNumberOfQuads;
308
309 uint32_t mIndexBufferID;
310
Alex Sakhartchouk894df172011-02-17 16:45:37 -0800311 int32_t mPositionAttrSlot;
312 int32_t mTexcoordAttrSlot;
313
Romain Guy09147fb2010-07-22 13:08:20 -0700314 const Rect* mClip;
Romain Guy5b3b3522010-10-27 18:57:51 -0700315 Rect* mBounds;
316 bool mDrawn;
Romain Guy09147fb2010-07-22 13:08:20 -0700317
Romain Guy694b5192010-07-21 21:33:20 -0700318 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700319
Romain Guye8cb9c142010-10-04 14:14:11 -0700320 bool mLinearFiltering;
321
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700322 void computeGaussianWeights(float* weights, int32_t radius);
323 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700324 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700325 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700326 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700327 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700328};
329
330}; // namespace uirenderer
331}; // namespace android
332
Romain Guy5b3b3522010-10-27 18:57:51 -0700333#endif // ANDROID_HWUI_FONT_RENDERER_H