FontRenderer.h revision eb32a499194119b3783b86c925172df02e5d2685
1ce0537b80087a6225273040a987414b1dd081aa0Romain Guy/* 2ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * Copyright (C) 2010 The Android Open Source Project 3ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * 4ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * you may not use this file except in compliance with the License. 6ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * You may obtain a copy of the License at 7ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * 8ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 9ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * 10ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * Unless required by applicable law or agreed to in writing, software 11ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * See the License for the specific language governing permissions and 14ce0537b80087a6225273040a987414b1dd081aa0Romain Guy * limitations under the License. 15ce0537b80087a6225273040a987414b1dd081aa0Romain Guy */ 16ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 17ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#ifndef ANDROID_HWUI_FONT_RENDERER_H 18ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#define ANDROID_HWUI_FONT_RENDERER_H 19ca89e2a68703bd428e8b66547d033a6ed35b3595Romain Guy 209aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy#include <utils/String8.h> 21ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck#include <utils/String16.h> 22713e1bb9df6bdfc21bd5c40d1a6ecf6c822a4be5Romain Guy#include <utils/Vector.h> 232dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include <utils/KeyedVector.h> 24ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 25fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#include <SkScalerContext.h> 2670850ea258cbf91477efa57a1f1a23cc0044cc93Chris Craik#include <SkPaint.h> 27ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include <SkPathMeasure.h> 28ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include <SkPoint.h> 29ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 30ce0537b80087a6225273040a987414b1dd081aa0Romain Guy#include <GLES2/gl2.h> 31121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 32121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy#include "Rect.h" 33121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy#include "Properties.h" 34121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 35117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craiknamespace android { 36117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craiknamespace uirenderer { 37117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik 3848a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik/////////////////////////////////////////////////////////////////////////////// 3948a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik// Defines 40117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik/////////////////////////////////////////////////////////////////////////////// 41fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 42fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#if RENDER_TEXT_AS_GLYPHS 43fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy typedef uint16_t glyph_t; 44f6834478b379856d3e5de92ddce7de0e6ba9fa4aRomain Guy #define TO_GLYPH(g) g 45e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph) 462507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text) 47fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy #define IS_END_OF_STRING(glyph) false 48fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#else 49117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik typedef SkUnichar glyph_t; 50117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik #define TO_GLYPH(g) ((SkUnichar) g) 51117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph) 52117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text) 53121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy #define IS_END_OF_STRING(glyph) glyph < 0 54121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy#endif 55121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 56121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy#define TEXTURE_BORDER_SIZE 1 577d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guy 58121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 59121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy// Declarations 60121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/////////////////////////////////////////////////////////////////////////////// 617d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guy 62121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guyclass FontRenderer; 63121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 64121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy/** 65121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy * CacheBlock is a node in a linked list of current free space areas in a CacheTexture. 66121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy * Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right. 67121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy * When we add a glyph to the cache, we see if it fits within one of the existing columns that 68121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy * have already been started (this is the case if the glyph fits vertically as well as 6971d08a07189c2b433080203895d9d5e936b16b9eJohn Reck * horizontally, and if its width is sufficiently close to the column width to avoid 709aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy * sub-optimal packing of small glyphs into wide columns). If there is no column in which the 71121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy * glyph fits, we check the final node, which is the remaining space in the cache, creating 729aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy * a new column as appropriate. 739e10841c27d973b930e1b49a099c69d866659505Romain Guy * 749e10841c27d973b930e1b49a099c69d866659505Romain Guy * As columns fill up, we remove their CacheBlock from the list to avoid having to check 75e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy * small blocks in the future. 765baa3a62a97544669fba6d65a11c07f252e654ddSteve Block */ 77e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guystruct CacheBlock { 78be1b127c7bec252e0c6ab0e06ed6babed07d496fRomain Guy uint16_t mX; 79121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy uint16_t mY; 80ce0537b80087a6225273040a987414b1dd081aa0Romain Guy uint16_t mWidth; 81ce0537b80087a6225273040a987414b1dd081aa0Romain Guy uint16_t mHeight; 82ce0537b80087a6225273040a987414b1dd081aa0Romain Guy CacheBlock* mNext; 83121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy CacheBlock* mPrev; 84121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 85121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool empty = false): 86121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL) 87ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck { 88ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck } 89ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck 90ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck static CacheBlock* insertBlock(CacheBlock* head, CacheBlock *newBlock); 9100e79c9947b741194ff6c0d08ede9b3befbf9c9dJohn Reck 9271d08a07189c2b433080203895d9d5e936b16b9eJohn Reck static CacheBlock* removeBlock(CacheBlock* head, CacheBlock *blockToRemove); 93860d155f866cc15a725e7ce03763280987f24901John Reck 9400e79c9947b741194ff6c0d08ede9b3befbf9c9dJohn Reck void output() { 9500e79c9947b741194ff6c0d08ede9b3befbf9c9dJohn Reck CacheBlock *currBlock = this; 9600e79c9947b741194ff6c0d08ede9b3befbf9c9dJohn Reck while (currBlock) { 97860d155f866cc15a725e7ce03763280987f24901John Reck ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d", 98860d155f866cc15a725e7ce03763280987f24901John Reck currBlock, currBlock->mX, currBlock->mY, currBlock->mWidth, currBlock->mHeight); 99860d155f866cc15a725e7ce03763280987f24901John Reck currBlock = currBlock->mNext; 100860d155f866cc15a725e7ce03763280987f24901John Reck } 101860d155f866cc15a725e7ce03763280987f24901John Reck } 102860d155f866cc15a725e7ce03763280987f24901John Reck}; 103860d155f866cc15a725e7ce03763280987f24901John Reck 104860d155f866cc15a725e7ce03763280987f24901John Reckclass CacheTexture { 105860d155f866cc15a725e7ce03763280987f24901John Reckpublic: 106860d155f866cc15a725e7ce03763280987f24901John Reck CacheTexture(uint16_t width, uint16_t height) : 107860d155f866cc15a725e7ce03763280987f24901John Reck mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height), 108860d155f866cc15a725e7ce03763280987f24901John Reck mLinearFiltering(false), mDirty(false), mNumGlyphs(0) { 109860d155f866cc15a725e7ce03763280987f24901John Reck mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 110860d155f866cc15a725e7ce03763280987f24901John Reck mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true); 1116ad690e16f8e139bfd29a035b52ab616d813a74bChris Craik } 1126ad690e16f8e139bfd29a035b52ab616d813a74bChris Craik 11315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ~CacheTexture() { 114ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck if (mTexture) { 115ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck delete[] mTexture; 116ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck } 117ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck if (mTextureId) { 118ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck glDeleteTextures(1, &mTextureId); 11971d08a07189c2b433080203895d9d5e936b16b9eJohn Reck } 120a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy reset(); 121ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 122860d155f866cc15a725e7ce03763280987f24901John Reck 123d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik void reset() { 1249cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy // Delete existing cache blocks 1259cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy while (mCacheBlocks != NULL) { 1267d139ba2c331f11e9b485753cc727a0ff202f2a4Romain Guy CacheBlock* tmpBlock = mCacheBlocks; 127860d155f866cc15a725e7ce03763280987f24901John Reck mCacheBlocks = mCacheBlocks->mNext; 128121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy delete tmpBlock; 129860d155f866cc15a725e7ce03763280987f24901John Reck } 130860d155f866cc15a725e7ce03763280987f24901John Reck mNumGlyphs = 0; 131860d155f866cc15a725e7ce03763280987f24901John Reck } 132121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 133860d155f866cc15a725e7ce03763280987f24901John Reck void init() { 134860d155f866cc15a725e7ce03763280987f24901John Reck // reset, then create a new remainder space to start again 135121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy reset(); 136121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 137121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true); 138860d155f866cc15a725e7ce03763280987f24901John Reck } 1398e93a7c9377b4ae43ecfb408f4906a09f6c83c03Chris Craik 140860d155f866cc15a725e7ce03763280987f24901John Reck bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY); 14138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 14238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck uint8_t* mTexture; 143121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy GLuint mTextureId; 144121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy uint16_t mWidth; 1459e10841c27d973b930e1b49a099c69d866659505Romain Guy uint16_t mHeight; 1469e10841c27d973b930e1b49a099c69d866659505Romain Guy bool mLinearFiltering; 147e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy bool mDirty; 1485baa3a62a97544669fba6d65a11c07f252e654ddSteve Block uint16_t mNumGlyphs; 149e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy CacheBlock* mCacheBlocks; 15071d08a07189c2b433080203895d9d5e936b16b9eJohn Reck}; 151121e2242565d5f09ad83a2d33ecd2225838802c5Romain Guy 152860d155f866cc15a725e7ce03763280987f24901John Reckstruct CachedGlyphInfo { 153860d155f866cc15a725e7ce03763280987f24901John Reck // Has the cache been invalidated? 154860d155f866cc15a725e7ce03763280987f24901John Reck bool mIsValid; 15538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck // Location of the cached glyph in the bitmap 15638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck // in case we need to resize the texture or 157ce0537b80087a6225273040a987414b1dd081aa0Romain Guy // render to bitmap 15822158e139a3d6c6a9787ca0de224e9368f643284Romain Guy uint32_t mStartX; 159ce0537b80087a6225273040a987414b1dd081aa0Romain Guy uint32_t mStartY; 160ce0537b80087a6225273040a987414b1dd081aa0Romain Guy uint32_t mBitmapWidth; 161ce0537b80087a6225273040a987414b1dd081aa0Romain Guy uint32_t mBitmapHeight; 16200e79c9947b741194ff6c0d08ede9b3befbf9c9dJohn Reck // Also cache texture coords for the quad 1636ad690e16f8e139bfd29a035b52ab616d813a74bChris Craik float mBitmapMinU; 164860d155f866cc15a725e7ce03763280987f24901John Reck float mBitmapMinV; 16500e79c9947b741194ff6c0d08ede9b3befbf9c9dJohn Reck float mBitmapMaxU; 166860d155f866cc15a725e7ce03763280987f24901John Reck float mBitmapMaxV; 167860d155f866cc15a725e7ce03763280987f24901John Reck // Minimize how much we call freetype 168860d155f866cc15a725e7ce03763280987f24901John Reck uint32_t mGlyphIndex; 169860d155f866cc15a725e7ce03763280987f24901John Reck uint32_t mAdvanceX; 1706ad690e16f8e139bfd29a035b52ab616d813a74bChris Craik uint32_t mAdvanceY; 1716ad690e16f8e139bfd29a035b52ab616d813a74bChris Craik // Values below contain a glyph's origin in the bitmap 172860d155f866cc15a725e7ce03763280987f24901John Reck int32_t mBitmapLeft; 173860d155f866cc15a725e7ce03763280987f24901John Reck int32_t mBitmapTop; 174860d155f866cc15a725e7ce03763280987f24901John Reck // Auto-kerning 175d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik SkFixed mLsbDelta; 176860d155f866cc15a725e7ce03763280987f24901John Reck SkFixed mRsbDelta; 177860d155f866cc15a725e7ce03763280987f24901John Reck CacheTexture* mCacheTexture; 178860d155f866cc15a725e7ce03763280987f24901John Reck}; 1798e93a7c9377b4ae43ecfb408f4906a09f6c83c03Chris Craik 180860d155f866cc15a725e7ce03763280987f24901John Reck 18138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck/////////////////////////////////////////////////////////////////////////////// 18238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck// Font 183860d155f866cc15a725e7ce03763280987f24901John Reck/////////////////////////////////////////////////////////////////////////////// 184860d155f866cc15a725e7ce03763280987f24901John Reck 185860d155f866cc15a725e7ce03763280987f24901John Reck/** 186860d155f866cc15a725e7ce03763280987f24901John Reck * Represents a font, defined by a Skia font id and a font size. A font is used 187860d155f866cc15a725e7ce03763280987f24901John Reck * to generate glyphs and cache them in the FontState. 188860d155f866cc15a725e7ce03763280987f24901John Reck */ 1893d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenbergerclass Font { 1909aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guypublic: 191272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck enum Style { 192fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy kFakeBold = 1 193fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy }; 194fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 195fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy ~Font(); 196fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 197fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy /** 198272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck * Renders the specified string of text. 19971d08a07189c2b433080203895d9d5e936b16b9eJohn Reck * If bitmap is specified, it will be used as the render target 200fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy */ 201fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 202fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy int numGlyphs, int x, int y, uint8_t *bitmap = NULL, 203fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy uint32_t bitmapW = 0, uint32_t bitmapH = 0); 204fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy 205ce0537b80087a6225273040a987414b1dd081aa0Romain Guy void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 206912a7b32d0c59ba38265c5dd6ff84ce93f909a7fRomain Guy int numGlyphs, int x, int y, const float* positions); 207ce0537b80087a6225273040a987414b1dd081aa0Romain Guy 208ce0537b80087a6225273040a987414b1dd081aa0Romain Guy void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 209eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy int numGlyphs, SkPath* path, float hOffset, float vOffset); 210eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 211eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy /** 212eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy * Creates a new font associated with the specified font state. 213eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy */ 214eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy static Font* create(FontRenderer* state, uint32_t fontId, float fontSize, 215eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style, 216eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy uint32_t strokeWidth); 217eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 218eca0ca2424afc1e98912405906edfc32f7733e16Romain Guyprotected: 219eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy friend class FontRenderer; 220eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*, 221eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy uint32_t, uint32_t, Rect*, const float*); 222eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy 223eca0ca2424afc1e98912405906edfc32f7733e16Romain Guy enum RenderMode { 224ce0537b80087a6225273040a987414b1dd081aa0Romain Guy FRAMEBUFFER, 225ce0537b80087a6225273040a987414b1dd081aa0Romain Guy BITMAP, 226 MEASURE, 227 }; 228 229 void precache(SkPaint* paint, const char* text, int numGlyphs); 230 231 void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len, 232 int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap, 233 uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions); 234 235 void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len, 236 int numGlyphs, Rect *bounds, const float* positions); 237 238 Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle, 239 uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth); 240 241 // Cache of glyphs 242 DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; 243 244 void invalidateTextureCache(CacheTexture *cacheTexture = NULL); 245 246 CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching); 247 void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph, 248 bool precaching); 249 250 void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, 251 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 252 Rect* bounds, const float* pos); 253 void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, 254 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 255 Rect* bounds, const float* pos); 256 void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, 257 uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH, 258 Rect* bounds, const float* pos); 259 void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset, 260 SkPathMeasure& measure, SkPoint* position, SkVector* tangent); 261 262 CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching = false); 263 264 static glyph_t nextGlyph(const uint16_t** srcPtr) { 265 const uint16_t* src = *srcPtr; 266 glyph_t g = *src++; 267 *srcPtr = src; 268 return g; 269 } 270 271 FontRenderer* mState; 272 uint32_t mFontId; 273 float mFontSize; 274 int mFlags; 275 uint32_t mItalicStyle; 276 uint32_t mScaleX; 277 SkPaint::Style mStyle; 278 uint32_t mStrokeWidth; 279}; 280 281/////////////////////////////////////////////////////////////////////////////// 282// Renderer 283/////////////////////////////////////////////////////////////////////////////// 284 285class FontRenderer { 286public: 287 FontRenderer(); 288 ~FontRenderer(); 289 290 void flushLargeCaches(); 291 292 void setGammaTable(const uint8_t* gammaTable) { 293 mGammaTable = gammaTable; 294 } 295 296 void setFont(SkPaint* paint, uint32_t fontId, float fontSize); 297 298 void precache(SkPaint* paint, const char* text, int numGlyphs); 299 300 // bounds is an out parameter 301 bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 302 uint32_t len, int numGlyphs, int x, int y, Rect* bounds); 303 // bounds is an out parameter 304 bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 305 uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds); 306 // bounds is an out parameter 307 bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, 308 uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds); 309 310 struct DropShadow { 311 DropShadow() { }; 312 313 DropShadow(const DropShadow& dropShadow): 314 width(dropShadow.width), height(dropShadow.height), 315 image(dropShadow.image), penX(dropShadow.penX), 316 penY(dropShadow.penY) { 317 } 318 319 uint32_t width; 320 uint32_t height; 321 uint8_t* image; 322 int32_t penX; 323 int32_t penY; 324 }; 325 326 // After renderDropShadow returns, the called owns the memory in DropShadow.image 327 // and is responsible for releasing it when it's done with it 328 DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex, 329 uint32_t len, int numGlyphs, uint32_t radius, const float* positions); 330 331 GLuint getTexture(bool linearFiltering = false) { 332 checkInit(); 333 334 if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) { 335 mCurrentCacheTexture->mLinearFiltering = linearFiltering; 336 mLinearFiltering = linearFiltering; 337 const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST; 338 339 glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId); 340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); 341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); 342 } 343 344 return mCurrentCacheTexture->mTextureId; 345 } 346 347 uint32_t getCacheSize() const { 348 uint32_t size = 0; 349 for (uint32_t i = 0; i < mCacheTextures.size(); i++) { 350 CacheTexture* cacheTexture = mCacheTextures[i]; 351 if (cacheTexture != NULL && cacheTexture->mTexture != NULL) { 352 size += cacheTexture->mWidth * cacheTexture->mHeight; 353 } 354 } 355 return size; 356 } 357 358protected: 359 friend class Font; 360 361 const uint8_t* mGammaTable; 362 363 void allocateTextureMemory(CacheTexture* cacheTexture); 364 void deallocateTextureMemory(CacheTexture* cacheTexture); 365 void initTextTexture(); 366 CacheTexture* createCacheTexture(int width, int height, bool allocate); 367 void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, 368 uint32_t *retOriginX, uint32_t *retOriginY, bool precaching); 369 CacheTexture* cacheBitmapInTexture(const SkGlyph& glyph, uint32_t* startX, uint32_t* startY); 370 371 void flushAllAndInvalidate(); 372 void initVertexArrayBuffers(); 373 374 void checkInit(); 375 void initRender(const Rect* clip, Rect* bounds); 376 void finishRender(); 377 378 void issueDrawCommand(); 379 void appendMeshQuadNoClip(float x1, float y1, float u1, float v1, 380 float x2, float y2, float u2, float v2, 381 float x3, float y3, float u3, float v3, 382 float x4, float y4, float u4, float v4, CacheTexture* texture); 383 void appendMeshQuad(float x1, float y1, float u1, float v1, 384 float x2, float y2, float u2, float v2, 385 float x3, float y3, float u3, float v3, 386 float x4, float y4, float u4, float v4, CacheTexture* texture); 387 void appendRotatedMeshQuad(float x1, float y1, float u1, float v1, 388 float x2, float y2, float u2, float v2, 389 float x3, float y3, float u3, float v3, 390 float x4, float y4, float u4, float v4, CacheTexture* texture); 391 392 uint32_t mSmallCacheWidth; 393 uint32_t mSmallCacheHeight; 394 uint32_t mLargeCacheWidth; 395 uint32_t mLargeCacheHeight; 396 397 Vector<CacheTexture*> mCacheTextures; 398 399 Font* mCurrentFont; 400 Vector<Font*> mActiveFonts; 401 402 CacheTexture* mCurrentCacheTexture; 403 CacheTexture* mLastCacheTexture; 404 405 void checkTextureUpdate(); 406 bool mUploadTexture; 407 408 // Pointer to vertex data to speed up frame to frame work 409 float *mTextMeshPtr; 410 uint32_t mCurrentQuadIndex; 411 uint32_t mMaxNumberOfQuads; 412 413 uint32_t mIndexBufferID; 414 415 const Rect* mClip; 416 Rect* mBounds; 417 bool mDrawn; 418 419 bool mInitialized; 420 421 bool mLinearFiltering; 422 423 void computeGaussianWeights(float* weights, int32_t radius); 424 void horizontalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest, 425 int32_t width, int32_t height); 426 void verticalBlur(float* weights, int32_t radius, const uint8_t *source, uint8_t *dest, 427 int32_t width, int32_t height); 428 void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius); 429}; 430 431}; // namespace uirenderer 432}; // namespace android 433 434#endif // ANDROID_HWUI_FONT_RENDERER_H 435