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 58/////////////////////////////////////////////////////////////////////////////// 59// Font 60/////////////////////////////////////////////////////////////////////////////// 61 62/** 63 * Represents a font, defined by a Skia font id and a font size. A font is used 64 * to generate glyphs and cache them in the FontState. 65 */ 66class Font { 67public: 68 enum Style { 69 kFakeBold = 1 70 }; 71 72 ~Font(); 73 74 /** 75 * Renders the specified string of text. 76 * If bitmap is specified, it will be used as the render target 77 */ 78 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 79 int numGlyphs, int x, int y, uint8_t *bitmap = NULL, 80 uint32_t bitmapW = 0, uint32_t bitmapH = 0); 81 /** 82 * Creates a new font associated with the specified font state. 83 */ 84 static Font* create(FontRenderer* state, uint32_t fontId, float fontSize, 85 int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style, 86 uint32_t strokeWidth); 87 88protected: 89 friend class FontRenderer; 90 91 enum RenderMode { 92 FRAMEBUFFER, 93 BITMAP, 94 MEASURE, 95 }; 96 97 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 98 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap, 99 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds); 100 101 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, 102 int numGlyphs, Rect *bounds); 103 104 struct 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 }; 130 131 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle, 132 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth); 133 134 // Cache of glyphs 135 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; 136 137 void invalidateTextureCache(); 138 139 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph); 140 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph); 141 void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds); 142 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y); 143 void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y, 144 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH); 145 146 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit); 147 148 static glyph_t nextGlyph(const uint16_t** srcPtr) { 149 const uint16_t* src = *srcPtr; 150 glyph_t g = *src++; 151 *srcPtr = src; 152 return g; 153 } 154 155 FontRenderer* mState; 156 uint32_t mFontId; 157 float mFontSize; 158 int mFlags; 159 uint32_t mItalicStyle; 160 uint32_t mScaleX; 161 SkPaint::Style mStyle; 162 uint32_t mStrokeWidth; 163}; 164 165/////////////////////////////////////////////////////////////////////////////// 166// Renderer 167/////////////////////////////////////////////////////////////////////////////// 168 169class FontRenderer { 170public: 171 FontRenderer(); 172 ~FontRenderer(); 173 174 void init(); 175 void deinit(); 176 177 void setGammaTable(const uint8_t* gammaTable) { 178 mGammaTable = gammaTable; 179 } 180 181 void setAttributeBindingSlots(int positionSlot, int texCoordSlot) { 182 mPositionAttrSlot = positionSlot; 183 mTexcoordAttrSlot = texCoordSlot; 184 } 185 186 void setFont(SkPaint* paint, uint32_t fontId, float fontSize); 187 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 188 uint32_t len, int numGlyphs, int x, int y, Rect* bounds); 189 190 struct DropShadow { 191 DropShadow() { }; 192 193 DropShadow(const DropShadow& dropShadow): 194 width(dropShadow.width), height(dropShadow.height), 195 image(dropShadow.image), penX(dropShadow.penX), 196 penY(dropShadow.penY) { 197 } 198 199 uint32_t width; 200 uint32_t height; 201 uint8_t* image; 202 int32_t penX; 203 int32_t penY; 204 }; 205 206 // After renderDropShadow returns, the called owns the memory in DropShadow.image 207 // and is responsible for releasing it when it's done with it 208 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, 209 uint32_t len, int numGlyphs, uint32_t radius); 210 211 GLuint getTexture(bool linearFiltering = false) { 212 checkInit(); 213 if (linearFiltering != mLinearFiltering) { 214 mLinearFiltering = linearFiltering; 215 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; 216 217 glBindTexture(GL_TEXTURE_2D, mTextureId); 218 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 220 } 221 return mTextureId; 222 } 223 224 uint32_t getCacheWidth() const { 225 return mCacheWidth; 226 } 227 228 uint32_t getCacheHeight() const { 229 return mCacheHeight; 230 } 231 232protected: 233 friend class Font; 234 235 const uint8_t* mGammaTable; 236 237 struct CacheTextureLine { 238 uint16_t mMaxHeight; 239 uint16_t mMaxWidth; 240 uint32_t mCurrentRow; 241 uint32_t mCurrentCol; 242 bool mDirty; 243 244 CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow, 245 uint32_t currentCol): 246 mMaxHeight(maxHeight), 247 mMaxWidth(maxWidth), 248 mCurrentRow(currentRow), 249 mCurrentCol(currentCol), 250 mDirty(false) { 251 } 252 253 bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) { 254 if (glyph.fHeight + 2 > mMaxHeight) { 255 return false; 256 } 257 258 if (mCurrentCol + glyph.fWidth + 2 < mMaxWidth) { 259 *retOriginX = mCurrentCol + 1; 260 *retOriginY = mCurrentRow + 1; 261 mCurrentCol += glyph.fWidth + 2; 262 mDirty = true; 263 return true; 264 } 265 266 return false; 267 } 268 }; 269 270 void initTextTexture(bool largeFonts = false); 271 bool cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY); 272 273 void flushAllAndInvalidate(); 274 void initVertexArrayBuffers(); 275 276 void checkInit(); 277 278 String16 mLatinPrecache; 279 void precacheLatin(SkPaint* paint); 280 281 void issueDrawCommand(); 282 void appendMeshQuad(float x1, float y1, float z1, float u1, float v1, float x2, float y2, 283 float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3, 284 float x4, float y4, float z4, float u4, float v4); 285 286 uint32_t mCacheWidth; 287 uint32_t mCacheHeight; 288 289 Vector<CacheTextureLine*> mCacheLines; 290 uint32_t getRemainingCacheCapacity(); 291 292 Font* mCurrentFont; 293 Vector<Font*> mActiveFonts; 294 295 // Texture to cache glyph bitmaps 296 uint8_t* mTextTexture; 297 const uint8_t* getTextTextureData() const { 298 return mTextTexture; 299 } 300 GLuint mTextureId; 301 void checkTextureUpdate(); 302 bool mUploadTexture; 303 304 // Pointer to vertex data to speed up frame to frame work 305 float *mTextMeshPtr; 306 uint32_t mCurrentQuadIndex; 307 uint32_t mMaxNumberOfQuads; 308 309 uint32_t mIndexBufferID; 310 311 int32_t mPositionAttrSlot; 312 int32_t mTexcoordAttrSlot; 313 314 const Rect* mClip; 315 Rect* mBounds; 316 bool mDrawn; 317 318 bool mInitialized; 319 320 bool mLinearFiltering; 321 322 void computeGaussianWeights(float* weights, int32_t radius); 323 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest, 324 int32_t width, int32_t height); 325 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest, 326 int32_t width, int32_t height); 327 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius); 328}; 329 330}; // namespace uirenderer 331}; // namespace android 332 333#endif // ANDROID_HWUI_FONT_RENDERER_H 334