blob: f685d5f98ad22a7bf973e14e9aaa0e021487e2bb [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
36class FontRenderer;
37
Romain Guy51769a62010-07-23 00:28:00 -070038/**
39 * Represents a font, defined by a Skia font id and a font size. A font is used
40 * to generate glyphs and cache them in the FontState.
41 */
Romain Guy694b5192010-07-21 21:33:20 -070042class Font {
43public:
Romain Guy325a0f92011-01-05 15:26:55 -080044 enum Style {
Romain Guyb5fa4902011-03-23 14:59:20 -070045 kFakeBold = 1
Romain Guy325a0f92011-01-05 15:26:55 -080046 };
47
Romain Guy694b5192010-07-21 21:33:20 -070048 ~Font();
49
Romain Guy51769a62010-07-23 00:28:00 -070050 /**
51 * Renders the specified string of text.
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -070052 * If bitmap is specified, it will be used as the render target
Romain Guy51769a62010-07-23 00:28:00 -070053 */
54 void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -070055 int numGlyphs, int x, int y,
56 uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0);
Romain Guy51769a62010-07-23 00:28:00 -070057 /**
58 * Creates a new font associated with the specified font state.
59 */
Romain Guy2577db12011-01-18 13:02:38 -080060 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
Chet Haase8668f8a2011-03-02 13:51:36 -080061 int flags, uint32_t italicStyle, uint32_t scaleX);
Romain Guy694b5192010-07-21 21:33:20 -070062
63protected:
Romain Guy694b5192010-07-21 21:33:20 -070064 friend class FontRenderer;
65
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -070066 enum RenderMode {
67 FRAMEBUFFER,
68 BITMAP,
69 MEASURE,
70 };
71
72 void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
73 int numGlyphs, int x, int y, RenderMode mode,
74 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
75 Rect *bounds);
76
77 void measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
78 int numGlyphs, Rect *bounds);
79
Romain Guy694b5192010-07-21 21:33:20 -070080 struct CachedGlyphInfo {
81 // Has the cache been invalidated?
82 bool mIsValid;
83 // Location of the cached glyph in the bitmap
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -070084 // in case we need to resize the texture or
85 // render to bitmap
86 uint32_t mStartX;
87 uint32_t mStartY;
Romain Guy694b5192010-07-21 21:33:20 -070088 uint32_t mBitmapWidth;
89 uint32_t mBitmapHeight;
90 // Also cache texture coords for the quad
91 float mBitmapMinU;
92 float mBitmapMinV;
93 float mBitmapMaxU;
94 float mBitmapMaxV;
95 // Minimize how much we call freetype
96 uint32_t mGlyphIndex;
97 uint32_t mAdvanceX;
98 uint32_t mAdvanceY;
99 // Values below contain a glyph's origin in the bitmap
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700100 int32_t mBitmapLeft;
101 int32_t mBitmapTop;
Romain Guy2bffd262010-09-12 17:40:02 -0700102 // Auto-kerning
103 SkFixed mLsbDelta;
104 SkFixed mRsbDelta;
Romain Guy694b5192010-07-21 21:33:20 -0700105 };
106
Chet Haase8668f8a2011-03-02 13:51:36 -0800107 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
108 uint32_t scaleX);
Romain Guy694b5192010-07-21 21:33:20 -0700109
110 DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs;
111
Romain Guybd0e6aa2010-07-22 18:50:12 -0700112 void invalidateTextureCache();
113
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700114 CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_t glyph);
Romain Guy694b5192010-07-21 21:33:20 -0700115 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700116 void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700117 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700118 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
119 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700120
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700121 CachedGlyphInfo* getCachedUTFChar(SkPaint* paint, int32_t utfChar);
122
Romain Guybd0e6aa2010-07-22 18:50:12 -0700123 FontRenderer* mState;
124 uint32_t mFontId;
125 float mFontSize;
Romain Guy325a0f92011-01-05 15:26:55 -0800126 int mFlags;
Romain Guy2577db12011-01-18 13:02:38 -0800127 uint32_t mItalicStyle;
Chet Haase8668f8a2011-03-02 13:51:36 -0800128 uint32_t mScaleX;
Romain Guy694b5192010-07-21 21:33:20 -0700129};
130
131class FontRenderer {
132public:
133 FontRenderer();
134 ~FontRenderer();
135
136 void init();
137 void deinit();
138
Romain Guyb45c0c92010-08-26 20:35:23 -0700139 void setGammaTable(const uint8_t* gammaTable) {
140 mGammaTable = gammaTable;
141 }
142
Alex Sakhartchouk894df172011-02-17 16:45:37 -0800143 void setAttributeBindingSlots(int positionSlot, int texCoordSlot) {
144 mPositionAttrSlot = positionSlot;
145 mTexcoordAttrSlot = texCoordSlot;
146 }
147
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700148 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy5b3b3522010-10-27 18:57:51 -0700149 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
150 uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700151
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700152 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700153 DropShadow() { };
154
155 DropShadow(const DropShadow& dropShadow):
156 width(dropShadow.width), height(dropShadow.height),
157 image(dropShadow.image), penX(dropShadow.penX),
158 penY(dropShadow.penY) {
159 }
160
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700161 uint32_t width;
162 uint32_t height;
163 uint8_t* image;
164 int32_t penX;
165 int32_t penY;
166 };
167
168 // After renderDropShadow returns, the called owns the memory in DropShadow.image
169 // and is responsible for releasing it when it's done with it
170 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Romain Guy1e45aae2010-08-13 19:39:53 -0700171 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700172
Romain Guye8cb9c142010-10-04 14:14:11 -0700173 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700174 checkInit();
Romain Guye8cb9c142010-10-04 14:14:11 -0700175 if (linearFiltering != mLinearFiltering) {
176 mLinearFiltering = linearFiltering;
177 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
178
179 glBindTexture(GL_TEXTURE_2D, mTextureId);
180 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
181 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
182 }
Romain Guy694b5192010-07-21 21:33:20 -0700183 return mTextureId;
184 }
185
Romain Guyc15008e2010-11-10 11:59:15 -0800186 uint32_t getCacheWidth() const {
187 return mCacheWidth;
188 }
189
190 uint32_t getCacheHeight() const {
191 return mCacheHeight;
192 }
193
Romain Guy694b5192010-07-21 21:33:20 -0700194protected:
195 friend class Font;
196
Romain Guyb45c0c92010-08-26 20:35:23 -0700197 const uint8_t* mGammaTable;
198
Romain Guy694b5192010-07-21 21:33:20 -0700199 struct CacheTextureLine {
200 uint16_t mMaxHeight;
201 uint16_t mMaxWidth;
202 uint32_t mCurrentRow;
203 uint32_t mCurrentCol;
Romain Guy1e45aae2010-08-13 19:39:53 -0700204 bool mDirty;
Romain Guy694b5192010-07-21 21:33:20 -0700205
Romain Guy51769a62010-07-23 00:28:00 -0700206 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
Romain Guy694b5192010-07-21 21:33:20 -0700207 uint32_t currentCol):
Romain Guy51769a62010-07-23 00:28:00 -0700208 mMaxHeight(maxHeight),
209 mMaxWidth(maxWidth),
210 mCurrentRow(currentRow),
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700211 mCurrentCol(currentCol),
212 mDirty(false) {
Romain Guy694b5192010-07-21 21:33:20 -0700213 }
214
215 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
Romain Guy7975fb62010-10-01 16:36:14 -0700216 if (glyph.fHeight + 2 > mMaxHeight) {
Romain Guy694b5192010-07-21 21:33:20 -0700217 return false;
218 }
219
Romain Guy7975fb62010-10-01 16:36:14 -0700220 if (mCurrentCol + glyph.fWidth + 2 < mMaxWidth) {
221 *retOriginX = mCurrentCol + 1;
222 *retOriginY = mCurrentRow + 1;
223 mCurrentCol += glyph.fWidth + 2;
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700224 mDirty = true;
Romain Guy694b5192010-07-21 21:33:20 -0700225 return true;
226 }
227
228 return false;
229 }
230 };
231
Romain Guy694b5192010-07-21 21:33:20 -0700232 void initTextTexture();
Romain Guy694b5192010-07-21 21:33:20 -0700233 bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
234
235 void flushAllAndInvalidate();
236 void initVertexArrayBuffers();
237
238 void checkInit();
239
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700240 String16 mLatinPrecache;
241 void precacheLatin(SkPaint* paint);
242
Romain Guy694b5192010-07-21 21:33:20 -0700243 void issueDrawCommand();
Romain Guy694b5192010-07-21 21:33:20 -0700244 void appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2,
245 float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3,
246 float x4, float y4, float z4, float u4, float v4);
247
248 uint32_t mCacheWidth;
249 uint32_t mCacheHeight;
250
Romain Guy694b5192010-07-21 21:33:20 -0700251 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700252 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700253
Romain Guy09147fb2010-07-22 13:08:20 -0700254 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700255 Vector<Font*> mActiveFonts;
256
257 // Texture to cache glyph bitmaps
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700258 uint8_t* mTextTexture;
259 const uint8_t* getTextTextureData() const {
260 return mTextTexture;
261 }
Romain Guy694b5192010-07-21 21:33:20 -0700262 GLuint mTextureId;
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700263 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700264 bool mUploadTexture;
265
266 // Pointer to vertex data to speed up frame to frame work
267 float *mTextMeshPtr;
268 uint32_t mCurrentQuadIndex;
269 uint32_t mMaxNumberOfQuads;
270
271 uint32_t mIndexBufferID;
272
Alex Sakhartchouk894df172011-02-17 16:45:37 -0800273 int32_t mPositionAttrSlot;
274 int32_t mTexcoordAttrSlot;
275
Romain Guy09147fb2010-07-22 13:08:20 -0700276 const Rect* mClip;
Romain Guy5b3b3522010-10-27 18:57:51 -0700277 Rect* mBounds;
278 bool mDrawn;
Romain Guy09147fb2010-07-22 13:08:20 -0700279
Romain Guy694b5192010-07-21 21:33:20 -0700280 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700281
Romain Guye8cb9c142010-10-04 14:14:11 -0700282 bool mLinearFiltering;
283
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700284 void computeGaussianWeights(float* weights, int32_t radius);
285 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700286 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700287 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700288 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700289 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700290};
291
292}; // namespace uirenderer
293}; // namespace android
294
Romain Guy5b3b3522010-10-27 18:57:51 -0700295#endif // ANDROID_HWUI_FONT_RENDERER_H