FontRenderer.h revision 00755fed35e4a91291c42a8a47bed8b957e9f8e1
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/////////////////////////////////////////////////////////////////////////////// 57// Declarations 58/////////////////////////////////////////////////////////////////////////////// 59 60class FontRenderer; 61 62class CacheTexture { 63public: 64 CacheTexture(uint16_t width, uint16_t height) : 65 mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height), 66 mLinearFiltering(false) { } 67 ~CacheTexture() { 68 if (mTexture) { 69 delete[] mTexture; 70 } 71 if (mTextureId) { 72 glDeleteTextures(1, &mTextureId); 73 } 74 } 75 76 uint8_t* mTexture; 77 GLuint mTextureId; 78 uint16_t mWidth; 79 uint16_t mHeight; 80 bool mLinearFiltering; 81}; 82 83class CacheTextureLine { 84public: 85 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow, 86 uint32_t currentCol, CacheTexture* cacheTexture): 87 mMaxHeight(maxHeight), 88 mMaxWidth(maxWidth), 89 mCurrentRow(currentRow), 90 mCurrentCol(currentCol), 91 mDirty(false), 92 mCacheTexture(cacheTexture) { 93 } 94 95 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY); 96 97 uint16_t mMaxHeight; 98 uint16_t mMaxWidth; 99 uint32_t mCurrentRow; 100 uint32_t mCurrentCol; 101 bool mDirty; 102 CacheTexture* mCacheTexture; 103}; 104 105struct CachedGlyphInfo { 106 // Has the cache been invalidated? 107 bool mIsValid; 108 // Location of the cached glyph in the bitmap 109 // in case we need to resize the texture or 110 // render to bitmap 111 uint32_t mStartX; 112 uint32_t mStartY; 113 uint32_t mBitmapWidth; 114 uint32_t mBitmapHeight; 115 // Also cache texture coords for the quad 116 float mBitmapMinU; 117 float mBitmapMinV; 118 float mBitmapMaxU; 119 float mBitmapMaxV; 120 // Minimize how much we call freetype 121 uint32_t mGlyphIndex; 122 uint32_t mAdvanceX; 123 uint32_t mAdvanceY; 124 // Values below contain a glyph's origin in the bitmap 125 int32_t mBitmapLeft; 126 int32_t mBitmapTop; 127 // Auto-kerning 128 SkFixed mLsbDelta; 129 SkFixed mRsbDelta; 130 CacheTextureLine* mCachedTextureLine; 131}; 132 133 134/////////////////////////////////////////////////////////////////////////////// 135// Font 136/////////////////////////////////////////////////////////////////////////////// 137 138/** 139 * Represents a font, defined by a Skia font id and a font size. A font is used 140 * to generate glyphs and cache them in the FontState. 141 */ 142class Font { 143public: 144 enum Style { 145 kFakeBold = 1 146 }; 147 148 ~Font(); 149 150 /** 151 * Renders the specified string of text. 152 * If bitmap is specified, it will be used as the render target 153 */ 154 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 155 int numGlyphs, int x, int y, uint8_t *bitmap = NULL, 156 uint32_t bitmapW = 0, uint32_t bitmapH = 0); 157 158 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 159 int numGlyphs, int x, int y, const float* positions); 160 161 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 162 int numGlyphs, SkPath* path, float hOffset, float vOffset); 163 164 /** 165 * Creates a new font associated with the specified font state. 166 */ 167 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize, 168 int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style, 169 uint32_t strokeWidth); 170 171protected: 172 friend class FontRenderer; 173 typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*, 174 uint32_t, uint32_t, Rect*, const float*); 175 176 enum RenderMode { 177 FRAMEBUFFER, 178 BITMAP, 179 MEASURE, 180 }; 181 182 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 183 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap, 184 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions); 185 186 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, 187 int numGlyphs, Rect *bounds, const float* positions); 188 189 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle, 190 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth); 191 192 // Cache of glyphs 193 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; 194 195 void invalidateTextureCache(CacheTextureLine *cacheLine = NULL); 196 197 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph); 198 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph); 199 200 void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, 201 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 202 Rect* bounds, const float* pos); 203 void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, 204 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 205 Rect* bounds, const float* pos); 206 void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, 207 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 208 Rect* bounds, const float* pos); 209 void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset, 210 SkPathMeasure& measure, SkPoint* position, SkVector* tangent); 211 212 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit); 213 214 static glyph_t nextGlyph(const uint16_t** srcPtr) { 215 const uint16_t* src = *srcPtr; 216 glyph_t g = *src++; 217 *srcPtr = src; 218 return g; 219 } 220 221 FontRenderer* mState; 222 uint32_t mFontId; 223 float mFontSize; 224 int mFlags; 225 uint32_t mItalicStyle; 226 uint32_t mScaleX; 227 SkPaint::Style mStyle; 228 uint32_t mStrokeWidth; 229}; 230 231/////////////////////////////////////////////////////////////////////////////// 232// Renderer 233/////////////////////////////////////////////////////////////////////////////// 234 235class FontRenderer { 236public: 237 FontRenderer(); 238 ~FontRenderer(); 239 240 void flushLargeCaches(); 241 242 void setGammaTable(const uint8_t* gammaTable) { 243 mGammaTable = gammaTable; 244 } 245 246 void setFont(SkPaint* paint, uint32_t fontId, float fontSize); 247 // bounds is an out parameter 248 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 249 uint32_t len, int numGlyphs, int x, int y, Rect* bounds); 250 // bounds is an out parameter 251 bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 252 uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds); 253 // bounds is an out parameter 254 bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 255 uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds); 256 257 struct DropShadow { 258 DropShadow() { }; 259 260 DropShadow(const DropShadow& dropShadow): 261 width(dropShadow.width), height(dropShadow.height), 262 image(dropShadow.image), penX(dropShadow.penX), 263 penY(dropShadow.penY) { 264 } 265 266 uint32_t width; 267 uint32_t height; 268 uint8_t* image; 269 int32_t penX; 270 int32_t penY; 271 }; 272 273 // After renderDropShadow returns, the called owns the memory in DropShadow.image 274 // and is responsible for releasing it when it's done with it 275 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, 276 uint32_t len, int numGlyphs, uint32_t radius, const float* positions); 277 278 GLuint getTexture(bool linearFiltering = false) { 279 checkInit(); 280 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 291 return mCurrentCacheTexture->mTextureId; 292 } 293 294 uint32_t getCacheSize() const { 295 uint32_t size = 0; 296 if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) { 297 size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight; 298 } 299 if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) { 300 size += mCacheTexture128->mWidth * mCacheTexture128->mHeight; 301 } 302 if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) { 303 size += mCacheTexture256->mWidth * mCacheTexture256->mHeight; 304 } 305 if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) { 306 size += mCacheTexture512->mWidth * mCacheTexture512->mHeight; 307 } 308 return size; 309 } 310 311protected: 312 friend class Font; 313 314 const uint8_t* mGammaTable; 315 316 void allocateTextureMemory(CacheTexture* cacheTexture); 317 void deallocateTextureMemory(CacheTexture* cacheTexture); 318 void initTextTexture(); 319 CacheTexture* createCacheTexture(int width, int height, bool allocate); 320 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, 321 uint32_t *retOriginX, uint32_t *retOriginY); 322 323 void flushAllAndInvalidate(); 324 void initVertexArrayBuffers(); 325 326 void checkInit(); 327 void initRender(const Rect* clip, Rect* bounds); 328 void finishRender(); 329 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