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