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