FontRenderer.h revision 378e919ccb75efe24d5a5aa75ac2c6ef255dcb48
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); 247 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph); 248 249 void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, 250 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 251 Rect* bounds, const float* pos); 252 void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, 253 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 254 Rect* bounds, const float* pos); 255 void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, 256 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 257 Rect* bounds, const float* pos); 258 void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset, 259 SkPathMeasure& measure, SkPoint* position, SkVector* tangent); 260 261 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit); 262 263 static glyph_t nextGlyph(const uint16_t** srcPtr) { 264 const uint16_t* src = *srcPtr; 265 glyph_t g = *src++; 266 *srcPtr = src; 267 return g; 268 } 269 270 FontRenderer* mState; 271 uint32_t mFontId; 272 float mFontSize; 273 int mFlags; 274 uint32_t mItalicStyle; 275 uint32_t mScaleX; 276 SkPaint::Style mStyle; 277 uint32_t mStrokeWidth; 278}; 279 280/////////////////////////////////////////////////////////////////////////////// 281// Renderer 282/////////////////////////////////////////////////////////////////////////////// 283 284class FontRenderer { 285public: 286 FontRenderer(); 287 ~FontRenderer(); 288 289 void flushLargeCaches(); 290 291 void setGammaTable(const uint8_t* gammaTable) { 292 mGammaTable = gammaTable; 293 } 294 295 void setFont(SkPaint* paint, uint32_t fontId, float fontSize); 296 297 void precache(SkPaint* paint, const char* text, int numGlyphs); 298 299 // bounds is an out parameter 300 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 301 uint32_t len, int numGlyphs, int x, int y, Rect* bounds); 302 // bounds is an out parameter 303 bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 304 uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds); 305 // bounds is an out parameter 306 bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 307 uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds); 308 309 struct DropShadow { 310 DropShadow() { }; 311 312 DropShadow(const DropShadow& dropShadow): 313 width(dropShadow.width), height(dropShadow.height), 314 image(dropShadow.image), penX(dropShadow.penX), 315 penY(dropShadow.penY) { 316 } 317 318 uint32_t width; 319 uint32_t height; 320 uint8_t* image; 321 int32_t penX; 322 int32_t penY; 323 }; 324 325 // After renderDropShadow returns, the called owns the memory in DropShadow.image 326 // and is responsible for releasing it when it's done with it 327 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, 328 uint32_t len, int numGlyphs, uint32_t radius, const float* positions); 329 330 GLuint getTexture(bool linearFiltering = false) { 331 checkInit(); 332 333 if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) { 334 mCurrentCacheTexture->mLinearFiltering = linearFiltering; 335 mLinearFiltering = linearFiltering; 336 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; 337 338 glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId); 339 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 341 } 342 343 return mCurrentCacheTexture->mTextureId; 344 } 345 346 uint32_t getCacheSize() const { 347 uint32_t size = 0; 348 for (uint32_t i = 0; i < mCacheTextures.size(); i++) { 349 CacheTexture* cacheTexture = mCacheTextures[i]; 350 if (cacheTexture != NULL && cacheTexture->mTexture != NULL) { 351 size += cacheTexture->mWidth * cacheTexture->mHeight; 352 } 353 } 354 return size; 355 } 356 357protected: 358 friend class Font; 359 360 const uint8_t* mGammaTable; 361 362 void allocateTextureMemory(CacheTexture* cacheTexture); 363 void deallocateTextureMemory(CacheTexture* cacheTexture); 364 void initTextTexture(); 365 CacheTexture* createCacheTexture(int width, int height, bool allocate); 366 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, 367 uint32_t *retOriginX, uint32_t *retOriginY); 368 CacheTexture* cacheBitmapInTexture(const SkGlyph& glyph, uint32_t* startX, uint32_t* startY); 369 370 void flushAllAndInvalidate(); 371 void initVertexArrayBuffers(); 372 373 void checkInit(); 374 void initRender(const Rect* clip, Rect* bounds); 375 void finishRender(); 376 377 void issueDrawCommand(); 378 void appendMeshQuadNoClip(float x1, float y1, float u1, float v1, 379 float x2, float y2, float u2, float v2, 380 float x3, float y3, float u3, float v3, 381 float x4, float y4, float u4, float v4, CacheTexture* texture); 382 void appendMeshQuad(float x1, float y1, float u1, float v1, 383 float x2, float y2, float u2, float v2, 384 float x3, float y3, float u3, float v3, 385 float x4, float y4, float u4, float v4, CacheTexture* texture); 386 void appendRotatedMeshQuad(float x1, float y1, float u1, float v1, 387 float x2, float y2, float u2, float v2, 388 float x3, float y3, float u3, float v3, 389 float x4, float y4, float u4, float v4, CacheTexture* texture); 390 391 uint32_t mSmallCacheWidth; 392 uint32_t mSmallCacheHeight; 393 394 Vector<CacheTexture*> mCacheTextures; 395 396 Font* mCurrentFont; 397 Vector<Font*> mActiveFonts; 398 399 CacheTexture* mCurrentCacheTexture; 400 CacheTexture* mLastCacheTexture; 401 402 void checkTextureUpdate(); 403 bool mUploadTexture; 404 405 // Pointer to vertex data to speed up frame to frame work 406 float *mTextMeshPtr; 407 uint32_t mCurrentQuadIndex; 408 uint32_t mMaxNumberOfQuads; 409 410 uint32_t mIndexBufferID; 411 412 const Rect* mClip; 413 Rect* mBounds; 414 bool mDrawn; 415 416 bool mInitialized; 417 418 bool mLinearFiltering; 419 420 void computeGaussianWeights(float* weights, int32_t radius); 421 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest, 422 int32_t width, int32_t height); 423 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest, 424 int32_t width, int32_t height); 425 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius); 426}; 427 428}; // namespace uirenderer 429}; // namespace android 430 431#endif // ANDROID_HWUI_FONT_RENDERER_H 432