blob: 10058125a8e136aae0ddb67395c5f7bf367ff05a [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 {
45 kFakeBold
46 };
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,
61 int flags, uint32_t italicStyle);
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
Romain Guy2577db12011-01-18 13:02:38 -0800107 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle);
Romain Guy694b5192010-07-21 21:33:20 -0700108
109 DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs;
110
Romain Guybd0e6aa2010-07-22 18:50:12 -0700111 void invalidateTextureCache();
112
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700113 CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_t glyph);
Romain Guy694b5192010-07-21 21:33:20 -0700114 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700115 void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700116 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700117 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
118 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700119
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700120 CachedGlyphInfo* getCachedUTFChar(SkPaint* paint, int32_t utfChar);
121
Romain Guybd0e6aa2010-07-22 18:50:12 -0700122 FontRenderer* mState;
123 uint32_t mFontId;
124 float mFontSize;
Romain Guy325a0f92011-01-05 15:26:55 -0800125 int mFlags;
Romain Guy2577db12011-01-18 13:02:38 -0800126 uint32_t mItalicStyle;
Romain Guy694b5192010-07-21 21:33:20 -0700127};
128
129class FontRenderer {
130public:
131 FontRenderer();
132 ~FontRenderer();
133
134 void init();
135 void deinit();
136
Romain Guyb45c0c92010-08-26 20:35:23 -0700137 void setGammaTable(const uint8_t* gammaTable) {
138 mGammaTable = gammaTable;
139 }
140
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700141 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy5b3b3522010-10-27 18:57:51 -0700142 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
143 uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700144
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700145 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700146 DropShadow() { };
147
148 DropShadow(const DropShadow& dropShadow):
149 width(dropShadow.width), height(dropShadow.height),
150 image(dropShadow.image), penX(dropShadow.penX),
151 penY(dropShadow.penY) {
152 }
153
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700154 uint32_t width;
155 uint32_t height;
156 uint8_t* image;
157 int32_t penX;
158 int32_t penY;
159 };
160
161 // After renderDropShadow returns, the called owns the memory in DropShadow.image
162 // and is responsible for releasing it when it's done with it
163 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Romain Guy1e45aae2010-08-13 19:39:53 -0700164 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700165
Romain Guye8cb9c142010-10-04 14:14:11 -0700166 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700167 checkInit();
Romain Guye8cb9c142010-10-04 14:14:11 -0700168 if (linearFiltering != mLinearFiltering) {
169 mLinearFiltering = linearFiltering;
170 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
171
172 glBindTexture(GL_TEXTURE_2D, mTextureId);
173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
175 }
Romain Guy694b5192010-07-21 21:33:20 -0700176 return mTextureId;
177 }
178
Romain Guyc15008e2010-11-10 11:59:15 -0800179 uint32_t getCacheWidth() const {
180 return mCacheWidth;
181 }
182
183 uint32_t getCacheHeight() const {
184 return mCacheHeight;
185 }
186
Romain Guy694b5192010-07-21 21:33:20 -0700187protected:
188 friend class Font;
189
Romain Guyb45c0c92010-08-26 20:35:23 -0700190 const uint8_t* mGammaTable;
191
Romain Guy694b5192010-07-21 21:33:20 -0700192 struct CacheTextureLine {
193 uint16_t mMaxHeight;
194 uint16_t mMaxWidth;
195 uint32_t mCurrentRow;
196 uint32_t mCurrentCol;
Romain Guy1e45aae2010-08-13 19:39:53 -0700197 bool mDirty;
Romain Guy694b5192010-07-21 21:33:20 -0700198
Romain Guy51769a62010-07-23 00:28:00 -0700199 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
Romain Guy694b5192010-07-21 21:33:20 -0700200 uint32_t currentCol):
Romain Guy51769a62010-07-23 00:28:00 -0700201 mMaxHeight(maxHeight),
202 mMaxWidth(maxWidth),
203 mCurrentRow(currentRow),
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700204 mCurrentCol(currentCol),
205 mDirty(false) {
Romain Guy694b5192010-07-21 21:33:20 -0700206 }
207
208 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
Romain Guy7975fb62010-10-01 16:36:14 -0700209 if (glyph.fHeight + 2 > mMaxHeight) {
Romain Guy694b5192010-07-21 21:33:20 -0700210 return false;
211 }
212
Romain Guy7975fb62010-10-01 16:36:14 -0700213 if (mCurrentCol + glyph.fWidth + 2 < mMaxWidth) {
214 *retOriginX = mCurrentCol + 1;
215 *retOriginY = mCurrentRow + 1;
216 mCurrentCol += glyph.fWidth + 2;
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700217 mDirty = true;
Romain Guy694b5192010-07-21 21:33:20 -0700218 return true;
219 }
220
221 return false;
222 }
223 };
224
Romain Guy694b5192010-07-21 21:33:20 -0700225 void initTextTexture();
Romain Guy694b5192010-07-21 21:33:20 -0700226 bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
227
228 void flushAllAndInvalidate();
229 void initVertexArrayBuffers();
230
231 void checkInit();
232
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700233 String16 mLatinPrecache;
234 void precacheLatin(SkPaint* paint);
235
Romain Guy694b5192010-07-21 21:33:20 -0700236 void issueDrawCommand();
Romain Guy694b5192010-07-21 21:33:20 -0700237 void appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2,
238 float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3,
239 float x4, float y4, float z4, float u4, float v4);
240
241 uint32_t mCacheWidth;
242 uint32_t mCacheHeight;
243
Romain Guy694b5192010-07-21 21:33:20 -0700244 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700245 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700246
Romain Guy09147fb2010-07-22 13:08:20 -0700247 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700248 Vector<Font*> mActiveFonts;
249
250 // Texture to cache glyph bitmaps
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700251 uint8_t* mTextTexture;
252 const uint8_t* getTextTextureData() const {
253 return mTextTexture;
254 }
Romain Guy694b5192010-07-21 21:33:20 -0700255 GLuint mTextureId;
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700256 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700257 bool mUploadTexture;
258
259 // Pointer to vertex data to speed up frame to frame work
260 float *mTextMeshPtr;
261 uint32_t mCurrentQuadIndex;
262 uint32_t mMaxNumberOfQuads;
263
264 uint32_t mIndexBufferID;
265
Romain Guy09147fb2010-07-22 13:08:20 -0700266 const Rect* mClip;
Romain Guy5b3b3522010-10-27 18:57:51 -0700267 Rect* mBounds;
268 bool mDrawn;
Romain Guy09147fb2010-07-22 13:08:20 -0700269
Romain Guy694b5192010-07-21 21:33:20 -0700270 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700271
Romain Guye8cb9c142010-10-04 14:14:11 -0700272 bool mLinearFiltering;
273
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700274 void computeGaussianWeights(float* weights, int32_t radius);
275 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700276 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700277 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700278 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700279 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700280};
281
282}; // namespace uirenderer
283}; // namespace android
284
Romain Guy5b3b3522010-10-27 18:57:51 -0700285#endif // ANDROID_HWUI_FONT_RENDERER_H