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