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 35 namespace android { 36 namespace 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 /////////////////////////////////////////////////////////////////////////////// 57 // Declarations 58 /////////////////////////////////////////////////////////////////////////////// 59 60 class FontRenderer; 61 62 class CacheTexture { 63 public: CacheTexture()64 CacheTexture() { } CacheTexture(uint8_t * texture,uint16_t width,uint16_t height)65 CacheTexture(uint8_t* texture, uint16_t width, uint16_t height) : 66 mTexture(texture), mTextureId(0), mWidth(width), mHeight(height), 67 mLinearFiltering(false) { } ~CacheTexture()68 ~CacheTexture() { 69 if (mTexture) { 70 delete[] mTexture; 71 } 72 if (mTextureId) { 73 glDeleteTextures(1, &mTextureId); 74 } 75 } 76 77 uint8_t* mTexture; 78 GLuint mTextureId; 79 uint16_t mWidth; 80 uint16_t mHeight; 81 bool mLinearFiltering; 82 }; 83 84 class CacheTextureLine { 85 public: CacheTextureLine(uint16_t maxWidth,uint16_t maxHeight,uint32_t currentRow,uint32_t currentCol,CacheTexture * cacheTexture)86 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow, 87 uint32_t currentCol, CacheTexture* cacheTexture): 88 mMaxHeight(maxHeight), 89 mMaxWidth(maxWidth), 90 mCurrentRow(currentRow), 91 mCurrentCol(currentCol), 92 mDirty(false), 93 mCacheTexture(cacheTexture) { 94 } 95 96 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY); 97 98 uint16_t mMaxHeight; 99 uint16_t mMaxWidth; 100 uint32_t mCurrentRow; 101 uint32_t mCurrentCol; 102 bool mDirty; 103 CacheTexture* mCacheTexture; 104 }; 105 106 struct CachedGlyphInfo { 107 // Has the cache been invalidated? 108 bool mIsValid; 109 // Location of the cached glyph in the bitmap 110 // in case we need to resize the texture or 111 // render to bitmap 112 uint32_t mStartX; 113 uint32_t mStartY; 114 uint32_t mBitmapWidth; 115 uint32_t mBitmapHeight; 116 // Also cache texture coords for the quad 117 float mBitmapMinU; 118 float mBitmapMinV; 119 float mBitmapMaxU; 120 float mBitmapMaxV; 121 // Minimize how much we call freetype 122 uint32_t mGlyphIndex; 123 uint32_t mAdvanceX; 124 uint32_t mAdvanceY; 125 // Values below contain a glyph's origin in the bitmap 126 int32_t mBitmapLeft; 127 int32_t mBitmapTop; 128 // Auto-kerning 129 SkFixed mLsbDelta; 130 SkFixed mRsbDelta; 131 CacheTextureLine* mCachedTextureLine; 132 }; 133 134 135 /////////////////////////////////////////////////////////////////////////////// 136 // Font 137 /////////////////////////////////////////////////////////////////////////////// 138 139 /** 140 * Represents a font, defined by a Skia font id and a font size. A font is used 141 * to generate glyphs and cache them in the FontState. 142 */ 143 class Font { 144 public: 145 enum Style { 146 kFakeBold = 1 147 }; 148 149 ~Font(); 150 151 /** 152 * Renders the specified string of text. 153 * If bitmap is specified, it will be used as the render target 154 */ 155 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 156 int numGlyphs, int x, int y, uint8_t *bitmap = NULL, 157 uint32_t bitmapW = 0, uint32_t bitmapH = 0); 158 159 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 160 int numGlyphs, int x, int y, const float* positions); 161 162 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 163 int numGlyphs, SkPath* path, float hOffset, float vOffset); 164 165 /** 166 * Creates a new font associated with the specified font state. 167 */ 168 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize, 169 int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style, 170 uint32_t strokeWidth); 171 172 protected: 173 friend class FontRenderer; 174 typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*, 175 uint32_t, uint32_t, Rect*, const float*); 176 177 enum RenderMode { 178 FRAMEBUFFER, 179 BITMAP, 180 MEASURE, 181 }; 182 183 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 184 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap, 185 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions); 186 187 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, 188 int numGlyphs, Rect *bounds); 189 190 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle, 191 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth); 192 193 // Cache of glyphs 194 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; 195 196 void invalidateTextureCache(CacheTextureLine *cacheLine = NULL); 197 198 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph); 199 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph); 200 201 void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, 202 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 203 Rect* bounds, const float* pos); 204 void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, 205 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 206 Rect* bounds, const float* pos); 207 void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, 208 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 209 Rect* bounds, const float* pos); 210 void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset, 211 SkPathMeasure& measure, SkPoint* position, SkVector* tangent); 212 213 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit); 214 nextGlyph(const uint16_t ** srcPtr)215 static glyph_t nextGlyph(const uint16_t** srcPtr) { 216 const uint16_t* src = *srcPtr; 217 glyph_t g = *src++; 218 *srcPtr = src; 219 return g; 220 } 221 222 FontRenderer* mState; 223 uint32_t mFontId; 224 float mFontSize; 225 int mFlags; 226 uint32_t mItalicStyle; 227 uint32_t mScaleX; 228 SkPaint::Style mStyle; 229 uint32_t mStrokeWidth; 230 }; 231 232 /////////////////////////////////////////////////////////////////////////////// 233 // Renderer 234 /////////////////////////////////////////////////////////////////////////////// 235 236 class FontRenderer { 237 public: 238 FontRenderer(); 239 ~FontRenderer(); 240 241 void flushLargeCaches(); 242 setGammaTable(const uint8_t * gammaTable)243 void setGammaTable(const uint8_t* gammaTable) { 244 mGammaTable = gammaTable; 245 } 246 247 void setFont(SkPaint* paint, uint32_t fontId, float fontSize); 248 // bounds is an out parameter 249 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 250 uint32_t len, int numGlyphs, int x, int y, Rect* bounds); 251 // bounds is an out parameter 252 bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 253 uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds); 254 // bounds is an out parameter 255 bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 256 uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds); 257 258 struct DropShadow { DropShadowDropShadow259 DropShadow() { }; 260 DropShadowDropShadow261 DropShadow(const DropShadow& dropShadow): 262 width(dropShadow.width), height(dropShadow.height), 263 image(dropShadow.image), penX(dropShadow.penX), 264 penY(dropShadow.penY) { 265 } 266 267 uint32_t width; 268 uint32_t height; 269 uint8_t* image; 270 int32_t penX; 271 int32_t penY; 272 }; 273 274 // After renderDropShadow returns, the called owns the memory in DropShadow.image 275 // and is responsible for releasing it when it's done with it 276 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, 277 uint32_t len, int numGlyphs, uint32_t radius); 278 279 GLuint getTexture(bool linearFiltering = false) { 280 checkInit(); 281 282 if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) { 283 mCurrentCacheTexture->mLinearFiltering = linearFiltering; 284 mLinearFiltering = linearFiltering; 285 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; 286 287 glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId); 288 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 289 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 290 } 291 292 return mCurrentCacheTexture->mTextureId; 293 } 294 getCacheSize()295 uint32_t getCacheSize() const { 296 uint32_t size = 0; 297 if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) { 298 size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight; 299 } 300 if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) { 301 size += mCacheTexture128->mWidth * mCacheTexture128->mHeight; 302 } 303 if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) { 304 size += mCacheTexture256->mWidth * mCacheTexture256->mHeight; 305 } 306 if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) { 307 size += mCacheTexture512->mWidth * mCacheTexture512->mHeight; 308 } 309 return size; 310 } 311 312 protected: 313 friend class Font; 314 315 const uint8_t* mGammaTable; 316 317 void allocateTextureMemory(CacheTexture* cacheTexture); 318 void deallocateTextureMemory(CacheTexture* cacheTexture); 319 void initTextTexture(); 320 CacheTexture* createCacheTexture(int width, int height, bool allocate); 321 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, 322 uint32_t *retOriginX, uint32_t *retOriginY); 323 324 void flushAllAndInvalidate(); 325 void initVertexArrayBuffers(); 326 327 void checkInit(); 328 void initRender(const Rect* clip, Rect* bounds); 329 void finishRender(); 330 331 void precacheLatin(SkPaint* paint); 332 333 void issueDrawCommand(); 334 void appendMeshQuadNoClip(float x1, float y1, float u1, float v1, 335 float x2, float y2, float u2, float v2, 336 float x3, float y3, float u3, float v3, 337 float x4, float y4, float u4, float v4, CacheTexture* texture); 338 void appendMeshQuad(float x1, float y1, float u1, float v1, 339 float x2, float y2, float u2, float v2, 340 float x3, float y3, float u3, float v3, 341 float x4, float y4, float u4, float v4, CacheTexture* texture); 342 void appendRotatedMeshQuad(float x1, float y1, float u1, float v1, 343 float x2, float y2, float u2, float v2, 344 float x3, float y3, float u3, float v3, 345 float x4, float y4, float u4, float v4, CacheTexture* texture); 346 347 uint32_t mSmallCacheWidth; 348 uint32_t mSmallCacheHeight; 349 350 Vector<CacheTextureLine*> mCacheLines; 351 uint32_t getRemainingCacheCapacity(); 352 353 Font* mCurrentFont; 354 Vector<Font*> mActiveFonts; 355 356 CacheTexture* mCurrentCacheTexture; 357 CacheTexture* mLastCacheTexture; 358 CacheTexture* mCacheTextureSmall; 359 CacheTexture* mCacheTexture128; 360 CacheTexture* mCacheTexture256; 361 CacheTexture* mCacheTexture512; 362 363 void checkTextureUpdate(); 364 bool mUploadTexture; 365 366 // Pointer to vertex data to speed up frame to frame work 367 float *mTextMeshPtr; 368 uint32_t mCurrentQuadIndex; 369 uint32_t mMaxNumberOfQuads; 370 371 uint32_t mIndexBufferID; 372 373 const Rect* mClip; 374 Rect* mBounds; 375 bool mDrawn; 376 377 bool mInitialized; 378 379 bool mLinearFiltering; 380 381 void computeGaussianWeights(float* weights, int32_t radius); 382 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest, 383 int32_t width, int32_t height); 384 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest, 385 int32_t width, int32_t height); 386 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius); 387 }; 388 389 }; // namespace uirenderer 390 }; // namespace android 391 392 #endif // ANDROID_HWUI_FONT_RENDERER_H 393