blob: f10efad8945722a4bf4fa966e5ad5ca51a79d437 [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
17#ifndef ANDROID_UI_FONT_RENDERER_H
18#define ANDROID_UI_FONT_RENDERER_H
19
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:
44 ~Font();
45
Romain Guy51769a62010-07-23 00:28:00 -070046 /**
47 * Renders the specified string of text.
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -070048 * If bitmap is specified, it will be used as the render target
Romain Guy51769a62010-07-23 00:28:00 -070049 */
50 void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -070051 int numGlyphs, int x, int y,
52 uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0);
Romain Guy51769a62010-07-23 00:28:00 -070053 /**
54 * Creates a new font associated with the specified font state.
55 */
Romain Guy694b5192010-07-21 21:33:20 -070056 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize);
57
58protected:
Romain Guy694b5192010-07-21 21:33:20 -070059 friend class FontRenderer;
60
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -070061 enum RenderMode {
62 FRAMEBUFFER,
63 BITMAP,
64 MEASURE,
65 };
66
67 void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
68 int numGlyphs, int x, int y, RenderMode mode,
69 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
70 Rect *bounds);
71
72 void measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
73 int numGlyphs, Rect *bounds);
74
Romain Guy694b5192010-07-21 21:33:20 -070075 struct CachedGlyphInfo {
76 // Has the cache been invalidated?
77 bool mIsValid;
78 // Location of the cached glyph in the bitmap
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -070079 // in case we need to resize the texture or
80 // render to bitmap
81 uint32_t mStartX;
82 uint32_t mStartY;
Romain Guy694b5192010-07-21 21:33:20 -070083 uint32_t mBitmapWidth;
84 uint32_t mBitmapHeight;
85 // Also cache texture coords for the quad
86 float mBitmapMinU;
87 float mBitmapMinV;
88 float mBitmapMaxU;
89 float mBitmapMaxV;
90 // Minimize how much we call freetype
91 uint32_t mGlyphIndex;
92 uint32_t mAdvanceX;
93 uint32_t mAdvanceY;
94 // Values below contain a glyph's origin in the bitmap
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -070095 int32_t mBitmapLeft;
96 int32_t mBitmapTop;
Romain Guy2bffd262010-09-12 17:40:02 -070097 // Auto-kerning
98 SkFixed mLsbDelta;
99 SkFixed mRsbDelta;
Romain Guy694b5192010-07-21 21:33:20 -0700100 };
101
Romain Guy694b5192010-07-21 21:33:20 -0700102 Font(FontRenderer* state, uint32_t fontId, float fontSize);
103
104 DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs;
105
Romain Guybd0e6aa2010-07-22 18:50:12 -0700106 void invalidateTextureCache();
107
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700108 CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_t glyph);
Romain Guy694b5192010-07-21 21:33:20 -0700109 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700110 void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
Romain Guy694b5192010-07-21 21:33:20 -0700111 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700112 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
113 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
Romain Guybd0e6aa2010-07-22 18:50:12 -0700114
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700115 CachedGlyphInfo* getCachedUTFChar(SkPaint* paint, int32_t utfChar);
116
Romain Guybd0e6aa2010-07-22 18:50:12 -0700117 FontRenderer* mState;
118 uint32_t mFontId;
119 float mFontSize;
Romain Guy694b5192010-07-21 21:33:20 -0700120};
121
122class FontRenderer {
123public:
124 FontRenderer();
125 ~FontRenderer();
126
127 void init();
128 void deinit();
129
Romain Guyb45c0c92010-08-26 20:35:23 -0700130 void setGammaTable(const uint8_t* gammaTable) {
131 mGammaTable = gammaTable;
132 }
133
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700134 void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
Romain Guy51769a62010-07-23 00:28:00 -0700135 void renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
136 uint32_t len, int numGlyphs, int x, int y);
Romain Guy694b5192010-07-21 21:33:20 -0700137
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700138 struct DropShadow {
Romain Guy1e45aae2010-08-13 19:39:53 -0700139 DropShadow() { };
140
141 DropShadow(const DropShadow& dropShadow):
142 width(dropShadow.width), height(dropShadow.height),
143 image(dropShadow.image), penX(dropShadow.penX),
144 penY(dropShadow.penY) {
145 }
146
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700147 uint32_t width;
148 uint32_t height;
149 uint8_t* image;
150 int32_t penX;
151 int32_t penY;
152 };
153
154 // After renderDropShadow returns, the called owns the memory in DropShadow.image
155 // and is responsible for releasing it when it's done with it
156 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
Romain Guy1e45aae2010-08-13 19:39:53 -0700157 uint32_t len, int numGlyphs, uint32_t radius);
Alex Sakhartchoukf18136c2010-08-06 14:49:04 -0700158
Romain Guye8cb9c142010-10-04 14:14:11 -0700159 GLuint getTexture(bool linearFiltering = false) {
Romain Guy694b5192010-07-21 21:33:20 -0700160 checkInit();
Romain Guye8cb9c142010-10-04 14:14:11 -0700161 if (linearFiltering != mLinearFiltering) {
162 mLinearFiltering = linearFiltering;
163 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
164
165 glBindTexture(GL_TEXTURE_2D, mTextureId);
166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
168 }
Romain Guy694b5192010-07-21 21:33:20 -0700169 return mTextureId;
170 }
171
172protected:
173 friend class Font;
174
Romain Guyb45c0c92010-08-26 20:35:23 -0700175 const uint8_t* mGammaTable;
176
Romain Guy694b5192010-07-21 21:33:20 -0700177 struct CacheTextureLine {
178 uint16_t mMaxHeight;
179 uint16_t mMaxWidth;
180 uint32_t mCurrentRow;
181 uint32_t mCurrentCol;
Romain Guy1e45aae2010-08-13 19:39:53 -0700182 bool mDirty;
Romain Guy694b5192010-07-21 21:33:20 -0700183
Romain Guy51769a62010-07-23 00:28:00 -0700184 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
Romain Guy694b5192010-07-21 21:33:20 -0700185 uint32_t currentCol):
Romain Guy51769a62010-07-23 00:28:00 -0700186 mMaxHeight(maxHeight),
187 mMaxWidth(maxWidth),
188 mCurrentRow(currentRow),
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700189 mCurrentCol(currentCol),
190 mDirty(false) {
Romain Guy694b5192010-07-21 21:33:20 -0700191 }
192
193 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
Romain Guy7975fb62010-10-01 16:36:14 -0700194 if (glyph.fHeight + 2 > mMaxHeight) {
Romain Guy694b5192010-07-21 21:33:20 -0700195 return false;
196 }
197
Romain Guy7975fb62010-10-01 16:36:14 -0700198 if (mCurrentCol + glyph.fWidth + 2 < mMaxWidth) {
199 *retOriginX = mCurrentCol + 1;
200 *retOriginY = mCurrentRow + 1;
201 mCurrentCol += glyph.fWidth + 2;
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700202 mDirty = true;
Romain Guy694b5192010-07-21 21:33:20 -0700203 return true;
204 }
205
206 return false;
207 }
208 };
209
210 uint32_t getCacheWidth() const {
211 return mCacheWidth;
212 }
213
214 uint32_t getCacheHeight() const {
215 return mCacheHeight;
216 }
217
218 void initTextTexture();
Romain Guy694b5192010-07-21 21:33:20 -0700219 bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
220
221 void flushAllAndInvalidate();
222 void initVertexArrayBuffers();
223
224 void checkInit();
225
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700226 String16 mLatinPrecache;
227 void precacheLatin(SkPaint* paint);
228
Romain Guy694b5192010-07-21 21:33:20 -0700229 void issueDrawCommand();
Romain Guy694b5192010-07-21 21:33:20 -0700230 void appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2,
231 float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3,
232 float x4, float y4, float z4, float u4, float v4);
233
234 uint32_t mCacheWidth;
235 uint32_t mCacheHeight;
236
Romain Guy694b5192010-07-21 21:33:20 -0700237 Vector<CacheTextureLine*> mCacheLines;
Alex Sakhartchouk65ef9092010-07-26 11:09:33 -0700238 uint32_t getRemainingCacheCapacity();
Romain Guy694b5192010-07-21 21:33:20 -0700239
Romain Guy09147fb2010-07-22 13:08:20 -0700240 Font* mCurrentFont;
Romain Guy694b5192010-07-21 21:33:20 -0700241 Vector<Font*> mActiveFonts;
242
243 // Texture to cache glyph bitmaps
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700244 uint8_t* mTextTexture;
245 const uint8_t* getTextTextureData() const {
246 return mTextTexture;
247 }
Romain Guy694b5192010-07-21 21:33:20 -0700248 GLuint mTextureId;
Alex Sakhartchouk9b9902d2010-07-23 14:45:49 -0700249 void checkTextureUpdate();
Romain Guy694b5192010-07-21 21:33:20 -0700250 bool mUploadTexture;
251
252 // Pointer to vertex data to speed up frame to frame work
253 float *mTextMeshPtr;
254 uint32_t mCurrentQuadIndex;
255 uint32_t mMaxNumberOfQuads;
256
257 uint32_t mIndexBufferID;
258
Romain Guy09147fb2010-07-22 13:08:20 -0700259 const Rect* mClip;
260
Romain Guy694b5192010-07-21 21:33:20 -0700261 bool mInitialized;
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700262
Romain Guye8cb9c142010-10-04 14:14:11 -0700263 bool mLinearFiltering;
264
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700265 void computeGaussianWeights(float* weights, int32_t radius);
266 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700267 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700268 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest,
Romain Guy1e45aae2010-08-13 19:39:53 -0700269 int32_t width, int32_t height);
Alex Sakhartchouk89a524a2010-08-02 17:52:30 -0700270 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius);
Romain Guy694b5192010-07-21 21:33:20 -0700271};
272
273}; // namespace uirenderer
274}; // namespace android
275
276#endif // ANDROID_UI_FONT_RENDERER_H