FontRenderer.h revision f942cf10e04567f6b9456f6258e29c803b8bfb41
1/* 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_HWUI_FONT_RENDERER_H 18#define ANDROID_HWUI_FONT_RENDERER_H 19 20#include <utils/String8.h> 21#include <utils/String16.h> 22#include <utils/Vector.h> 23#include <utils/KeyedVector.h> 24 25#include <SkScalerContext.h> 26#include <SkPaint.h> 27#include <SkPathMeasure.h> 28#include <SkPoint.h> 29 30#include <GLES2/gl2.h> 31 32#include "Rect.h" 33#include "Properties.h" 34 35namespace android { 36namespace uirenderer { 37 38/////////////////////////////////////////////////////////////////////////////// 39// Defines 40/////////////////////////////////////////////////////////////////////////////// 41 42#if RENDER_TEXT_AS_GLYPHS 43 typedef uint16_t glyph_t; 44 #define TO_GLYPH(g) g 45 #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph) 46 #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text) 47 #define IS_END_OF_STRING(glyph) false 48#else 49 typedef SkUnichar glyph_t; 50 #define TO_GLYPH(g) ((SkUnichar) g) 51 #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph) 52 #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text) 53 #define IS_END_OF_STRING(glyph) glyph < 0 54#endif 55 56#define TEXTURE_BORDER_SIZE 1 57 58/////////////////////////////////////////////////////////////////////////////// 59// Declarations 60/////////////////////////////////////////////////////////////////////////////// 61 62class FontRenderer; 63 64/** 65 * CacheBlock is a node in a linked list of current free space areas in a CacheTexture. 66 * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right. 67 * When we add a glyph to the cache, we see if it fits within one of the existing columns that 68 * have already been started (this is the case if the glyph fits vertically as well as 69 * horizontally, and if its width is sufficiently close to the column width to avoid 70 * sub-optimal packing of small glyphs into wide columns). If there is no column in which the 71 * glyph fits, we check the final node, which is the remaining space in the cache, creating 72 * a new column as appropriate. 73 * 74 * As columns fill up, we remove their CacheBlock from the list to avoid having to check 75 * small blocks in the future. 76 */ 77struct CacheBlock { 78 uint16_t mX; 79 uint16_t mY; 80 uint16_t mWidth; 81 uint16_t mHeight; 82 CacheBlock* mNext; 83 CacheBlock* mPrev; 84 85 CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool empty = false): 86 mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL) 87 { 88 } 89 90 static CacheBlock* insertBlock(CacheBlock* head, CacheBlock *newBlock); 91 92 static CacheBlock* removeBlock(CacheBlock* head, CacheBlock *blockToRemove); 93 94 void output() { 95 CacheBlock *currBlock = this; 96 while (currBlock) { 97 ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d", 98 currBlock, currBlock->mX, currBlock->mY, currBlock->mWidth, currBlock->mHeight); 99 currBlock = currBlock->mNext; 100 } 101 } 102}; 103 104class CacheTexture { 105public: 106 CacheTexture(uint16_t width, uint16_t height) : 107 mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height), 108 mLinearFiltering(false), mDirty(false), mNumGlyphs(0) { 109 mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 110 mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true); 111 } 112 113 ~CacheTexture() { 114 if (mTexture) { 115 delete[] mTexture; 116 } 117 if (mTextureId) { 118 glDeleteTextures(1, &mTextureId); 119 } 120 reset(); 121 } 122 123 void reset() { 124 // Delete existing cache blocks 125 while (mCacheBlocks != NULL) { 126 CacheBlock* tmpBlock = mCacheBlocks; 127 mCacheBlocks = mCacheBlocks->mNext; 128 delete tmpBlock; 129 } 130 mNumGlyphs = 0; 131 } 132 133 void init() { 134 // reset, then create a new remainder space to start again 135 reset(); 136 mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 137 mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true); 138 } 139 140 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY); 141 142 uint8_t* mTexture; 143 GLuint mTextureId; 144 uint16_t mWidth; 145 uint16_t mHeight; 146 bool mLinearFiltering; 147 bool mDirty; 148 uint16_t mNumGlyphs; 149 CacheBlock* mCacheBlocks; 150}; 151 152struct CachedGlyphInfo { 153 // Has the cache been invalidated? 154 bool mIsValid; 155 // Location of the cached glyph in the bitmap 156 // in case we need to resize the texture or 157 // render to bitmap 158 uint32_t mStartX; 159 uint32_t mStartY; 160 uint32_t mBitmapWidth; 161 uint32_t mBitmapHeight; 162 // Also cache texture coords for the quad 163 float mBitmapMinU; 164 float mBitmapMinV; 165 float mBitmapMaxU; 166 float mBitmapMaxV; 167 // Minimize how much we call freetype 168 uint32_t mGlyphIndex; 169 uint32_t mAdvanceX; 170 uint32_t mAdvanceY; 171 // Values below contain a glyph's origin in the bitmap 172 int32_t mBitmapLeft; 173 int32_t mBitmapTop; 174 // Auto-kerning 175 SkFixed mLsbDelta; 176 SkFixed mRsbDelta; 177 CacheTexture* mCacheTexture; 178}; 179 180 181/////////////////////////////////////////////////////////////////////////////// 182// Font 183/////////////////////////////////////////////////////////////////////////////// 184 185/** 186 * Represents a font, defined by a Skia font id and a font size. A font is used 187 * to generate glyphs and cache them in the FontState. 188 */ 189class Font { 190public: 191 enum Style { 192 kFakeBold = 1 193 }; 194 195 ~Font(); 196 197 /** 198 * Renders the specified string of text. 199 * If bitmap is specified, it will be used as the render target 200 */ 201 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 202 int numGlyphs, int x, int y, uint8_t *bitmap = NULL, 203 uint32_t bitmapW = 0, uint32_t bitmapH = 0); 204 205 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 206 int numGlyphs, int x, int y, const float* positions); 207 208 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 209 int numGlyphs, SkPath* path, float hOffset, float vOffset); 210 211 /** 212 * Creates a new font associated with the specified font state. 213 */ 214 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize, 215 int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style, 216 uint32_t strokeWidth); 217 218protected: 219 friend class FontRenderer; 220 typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*, 221 uint32_t, uint32_t, Rect*, const float*); 222 223 enum RenderMode { 224 FRAMEBUFFER, 225 BITMAP, 226 MEASURE, 227 }; 228 229 void precache(SkPaint* paint, const char* text, int numGlyphs); 230 231 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 232 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap, 233 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions); 234 235 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, 236 int numGlyphs, Rect *bounds, const float* positions); 237 238 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle, 239 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth); 240 241 // Cache of glyphs 242 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; 243 244 void invalidateTextureCache(CacheTexture *cacheTexture = NULL); 245 246 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching); 247 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph, 248 bool precaching); 249 250 void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, 251 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 252 Rect* bounds, const float* pos); 253 void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, 254 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 255 Rect* bounds, const float* pos); 256 void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, 257 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 258 Rect* bounds, const float* pos); 259 void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset, 260 SkPathMeasure& measure, SkPoint* position, SkVector* tangent); 261 262 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching = false); 263 264 static glyph_t nextGlyph(const uint16_t** srcPtr) { 265 const uint16_t* src = *srcPtr; 266 glyph_t g = *src++; 267 *srcPtr = src; 268 return g; 269 } 270 271 FontRenderer* mState; 272 uint32_t mFontId; 273 float mFontSize; 274 int mFlags; 275 uint32_t mItalicStyle; 276 uint32_t mScaleX; 277 SkPaint::Style mStyle; 278 uint32_t mStrokeWidth; 279}; 280 281/////////////////////////////////////////////////////////////////////////////// 282// Renderer 283/////////////////////////////////////////////////////////////////////////////// 284 285class FontRenderer { 286public: 287 FontRenderer(); 288 ~FontRenderer(); 289 290 void flushLargeCaches(); 291 292 void setGammaTable(const uint8_t* gammaTable) { 293 mGammaTable = gammaTable; 294 } 295 296 void setFont(SkPaint* paint, uint32_t fontId, float fontSize); 297 298 void precache(SkPaint* paint, const char* text, int numGlyphs); 299 300 // bounds is an out parameter 301 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 302 uint32_t len, int numGlyphs, int x, int y, Rect* bounds); 303 // bounds is an out parameter 304 bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 305 uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds); 306 // bounds is an out parameter 307 bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 308 uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds); 309 310 struct DropShadow { 311 DropShadow() { }; 312 313 DropShadow(const DropShadow& dropShadow): 314 width(dropShadow.width), height(dropShadow.height), 315 image(dropShadow.image), penX(dropShadow.penX), 316 penY(dropShadow.penY) { 317 } 318 319 uint32_t width; 320 uint32_t height; 321 uint8_t* image; 322 int32_t penX; 323 int32_t penY; 324 }; 325 326 // After renderDropShadow returns, the called owns the memory in DropShadow.image 327 // and is responsible for releasing it when it's done with it 328 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, 329 uint32_t len, int numGlyphs, uint32_t radius, const float* positions); 330 331 GLuint getTexture(bool linearFiltering = false) { 332 checkInit(); 333 334 if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) { 335 mCurrentCacheTexture->mLinearFiltering = linearFiltering; 336 mLinearFiltering = linearFiltering; 337 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; 338 339 glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId); 340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 342 } 343 344 return mCurrentCacheTexture->mTextureId; 345 } 346 347 uint32_t getCacheSize() const { 348 uint32_t size = 0; 349 for (uint32_t i = 0; i < mCacheTextures.size(); i++) { 350 CacheTexture* cacheTexture = mCacheTextures[i]; 351 if (cacheTexture != NULL && cacheTexture->mTexture != NULL) { 352 size += cacheTexture->mWidth * cacheTexture->mHeight; 353 } 354 } 355 return size; 356 } 357 358protected: 359 friend class Font; 360 361 const uint8_t* mGammaTable; 362 363 void allocateTextureMemory(CacheTexture* cacheTexture); 364 void deallocateTextureMemory(CacheTexture* cacheTexture); 365 void initTextTexture(); 366 CacheTexture* createCacheTexture(int width, int height, bool allocate); 367 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, 368 uint32_t *retOriginX, uint32_t *retOriginY, bool precaching); 369 CacheTexture* cacheBitmapInTexture(const SkGlyph& glyph, uint32_t* startX, uint32_t* startY); 370 371 void flushAllAndInvalidate(); 372 void initVertexArrayBuffers(); 373 374 void checkInit(); 375 void initRender(const Rect* clip, Rect* bounds); 376 void finishRender(); 377 378 void issueDrawCommand(); 379 void appendMeshQuadNoClip(float x1, float y1, float u1, float v1, 380 float x2, float y2, float u2, float v2, 381 float x3, float y3, float u3, float v3, 382 float x4, float y4, float u4, float v4, CacheTexture* texture); 383 void appendMeshQuad(float x1, float y1, float u1, float v1, 384 float x2, float y2, float u2, float v2, 385 float x3, float y3, float u3, float v3, 386 float x4, float y4, float u4, float v4, CacheTexture* texture); 387 void appendRotatedMeshQuad(float x1, float y1, float u1, float v1, 388 float x2, float y2, float u2, float v2, 389 float x3, float y3, float u3, float v3, 390 float x4, float y4, float u4, float v4, CacheTexture* texture); 391 392 uint32_t mSmallCacheWidth; 393 uint32_t mSmallCacheHeight; 394 395 Vector<CacheTexture*> mCacheTextures; 396 397 Font* mCurrentFont; 398 Vector<Font*> mActiveFonts; 399 400 CacheTexture* mCurrentCacheTexture; 401 CacheTexture* mLastCacheTexture; 402 403 void checkTextureUpdate(); 404 bool mUploadTexture; 405 406 // Pointer to vertex data to speed up frame to frame work 407 float *mTextMeshPtr; 408 uint32_t mCurrentQuadIndex; 409 uint32_t mMaxNumberOfQuads; 410 411 uint32_t mIndexBufferID; 412 413 const Rect* mClip; 414 Rect* mBounds; 415 bool mDrawn; 416 417 bool mInitialized; 418 419 bool mLinearFiltering; 420 421 void computeGaussianWeights(float* weights, int32_t radius); 422 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest, 423 int32_t width, int32_t height); 424 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest, 425 int32_t width, int32_t height); 426 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius); 427}; 428 429}; // namespace uirenderer 430}; // namespace android 431 432#endif // ANDROID_HWUI_FONT_RENDERER_H 433