rsFont.cpp revision 5224a27798f89093b13722b41143551a057ce550
1d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
2d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk/*
3d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Copyright (C) 2009 The Android Open Source Project
4d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *
5d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License");
6d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * you may not use this file except in compliance with the License.
7d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * You may obtain a copy of the License at
8d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *
9d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *      http://www.apache.org/licenses/LICENSE-2.0
10d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *
11d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Unless required by applicable law or agreed to in writing, software
12d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS,
13d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * See the License for the specific language governing permissions and
15d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * limitations under the License.
16d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk */
17d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
18d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#ifndef ANDROID_RS_BUILD_FOR_HOST
19d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsContext.h"
20d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#else
21d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsContextHostStub.h"
22d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#endif
23d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
24d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsFont.h"
25d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsProgramFragment.h"
26c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk#include <cutils/properties.h>
27d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include FT_BITMAP_H
28d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
29d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/gl.h>
30d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/glext.h>
31d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2.h>
32d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2ext.h>
33d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
34d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android;
35d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android::renderscript;
36d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
37afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) {
38d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = false;
39d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mHasKerning = false;
403659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    mFace = NULL;
41d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
42d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
435224a27798f89093b13722b41143551a057ce550Alex Sakhartchoukbool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) {
44afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (mInitialized) {
45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Reinitialization of fonts not supported");
46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
495224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    FT_Error error = 0;
505224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    if (data != NULL && dataLen > 0) {
515224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk        error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace);
525224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    } else {
535224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk        error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace);
545224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    }
555224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk
56afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (error) {
57c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk        LOGE("Unable to initialize font %s", name);
58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontName = name;
62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontSize = fontSize;
63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mDpi = dpi;
64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
65c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk    error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0);
66afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (error) {
67c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk        LOGE("Unable to set font size on %s", name);
68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mHasKerning = FT_HAS_KERNING(mFace);
72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = true;
74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return true;
75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
76d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
77afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::invalidateTextureCache() {
78afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
79d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCachedGlyphs.valueAt(i)->mIsValid = false;
80d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
81d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
82d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
83afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) {
84d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
85d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
8609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenX = x + glyph->mBitmapLeft;
8709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
88d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
8909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float u1 = glyph->mBitmapMinU;
9009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float u2 = glyph->mBitmapMaxU;
9109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float v1 = glyph->mBitmapMinV;
9209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float v2 = glyph->mBitmapMaxV;
93d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
9409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t width = (int32_t) glyph->mBitmapWidth;
9509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t height = (int32_t) glyph->mBitmapHeight;
96d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    state->appendMeshQuad(nPenX, nPenY, 0, u1, v2,
9809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                          nPenX + width, nPenY, 0, u2, v2,
9909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                          nPenX + width, nPenY - height, 0, u2, v1,
10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                          nPenX, nPenY - height, 0, u1, v1);
10109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk}
10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
10309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y,
10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) {
10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenX = x + glyph->mBitmapLeft;
10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenY = y + glyph->mBitmapTop;
10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth;
10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight;
11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    const uint8_t* cacheBuffer = state->getTextTextureData();
11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t cacheX = 0, cacheY = 0;
11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t bX = 0, bY = 0;
11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) {
11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) {
11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) {
12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                LOGE("Skipping invalid index");
12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                continue;
12209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            }
12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX];
12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            bitmap[bY * bitmapW + bX] = tempCol;
12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        }
12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
127d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
128d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) {
13009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenX = x + glyph->mBitmapLeft;
13109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
13209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
13309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t width = (int32_t) glyph->mBitmapWidth;
13409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t height = (int32_t) glyph->mBitmapHeight;
13509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
1365224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    // 0, 0 is top left, so bottom is a positive number
1375224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    if (bounds->bottom < nPenY) {
13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->bottom = nPenY;
13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if (bounds->left > nPenX) {
14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->left = nPenX;
14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if (bounds->right < nPenX + width) {
14409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->right = nPenX + width;
14509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
1465224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    if (bounds->top > nPenY - height) {
1475224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk        bounds->top = nPenY - height;
14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk}
15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y,
15209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                     uint32_t start, int32_t numGlyphs,
15309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                     RenderMode mode, Rect *bounds,
154afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                     uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
155afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (!mInitialized || numGlyphs == 0 || text == NULL || len == 0) {
156d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
157d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
158d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
159afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (mode == Font::MEASURE) {
16009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        if (bounds == NULL) {
16109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            LOGE("No return rectangle provided to measure text");
16209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            return;
16309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        }
16409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        // Reset min and max of the bounding box to something large
1655224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk        bounds->set(1e6, -1e6, 1e6, -1e6);
16609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
16709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
16809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t penX = x, penY = y;
16909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t glyphsLeft = 1;
170afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (numGlyphs > 0) {
171d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        glyphsLeft = numGlyphs;
172d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
173d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
174d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t index = start;
175d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t nextIndex = 0;
176d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
177d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    while (glyphsLeft > 0) {
178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
179c9c38dd8508a2f805213abee1f9f44f103ac0a0dKenny Root        int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex);
180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Reached the end of the string or encountered
182afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        if (utfChar < 0) {
183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Move to the next character in the array
187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        index = nextIndex;
188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
18901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar);
190d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
192afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        if (cachedGlyph->mIsValid) {
193afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk            switch (mode) {
19409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            case FRAMEBUFFER:
19509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                drawCachedGlyph(cachedGlyph, penX, penY);
19609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                break;
19709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            case BITMAP:
19809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH);
19909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                break;
20009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            case MEASURE:
20109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                measureCachedGlyph(cachedGlyph, penX, penY, bounds);
20209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                break;
20309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            }
204d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
205d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
206d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        penX += (cachedGlyph->mAdvance.x >> 6);
207d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
208d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // If we were given a specific number of glyphs, decrement
209afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        if (numGlyphs > 0) {
210d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            glyphsLeft --;
211d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
213d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
21501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) {
21601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
21701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar);
218afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (cachedGlyph == NULL) {
21901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        cachedGlyph = cacheGlyph((uint32_t)utfChar);
22001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
22101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    // Is the glyph still in texture cache?
222afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (!cachedGlyph->mIsValid) {
22301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        updateGlyphCache(cachedGlyph);
22401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
22501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
22601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    return cachedGlyph;
22701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
22801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
229afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) {
230a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER );
231afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (error) {
232a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        LOGE("Couldn't load glyph.");
233a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        return;
234a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
235d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
236a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mAdvance = mFace->glyph->advance;
237a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapLeft = mFace->glyph->bitmap_left;
238a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapTop = mFace->glyph->bitmap_top;
239d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
240a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Bitmap *bitmap = &mFace->glyph->bitmap;
241d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
242d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now copy the bitmap into the cache texture
243d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startX = 0;
244d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startY = 0;
245d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
246d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Let the font state figure out where to put the bitmap
247d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
248a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY);
249d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
250afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (!glyph->mIsValid) {
251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
253d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
254a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    uint32_t endX = startX + bitmap->width;
255a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinX = startX;
258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinY = startY;
259a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapWidth = bitmap->width;
260a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapHeight = bitmap->rows;
261d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
262d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheHeight = state->getCacheTextureType()->getDimY();
264d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinU = (float)startX / (float)cacheWidth;
266d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinV = (float)startY / (float)cacheHeight;
267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMaxU = (float)endX / (float)cacheWidth;
268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMaxV = (float)endY / (float)cacheHeight;
269d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
271afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) {
272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    CachedGlyphInfo *newGlyph = new CachedGlyphInfo();
273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCachedGlyphs.add(glyph, newGlyph);
274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph);
276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    newGlyph->mIsValid = false;
277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    updateGlyphCache(newGlyph);
279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
280d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return newGlyph;
281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
2835224a27798f89093b13722b41143551a057ce550Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi,
2845224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk                    const void *data, uint32_t dataLen) {
28535b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    rsc->mStateFont.checkInit();
286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts;
287d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
288afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < activeFonts.size(); i ++) {
289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        Font *ithFont = activeFonts[i];
290afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) {
291d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            return ithFont;
292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
293d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
295d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Font *newFont = new Font(rsc);
2965224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen);
297afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (isInitialized) {
298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        activeFonts.push(newFont);
29901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        rsc->mStateFont.precacheLatin(newFont);
300d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return newFont;
301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
303225afd317e101a7be5fe02c0a86361146ea89f05Jason Sams    ObjectBase::checkDelete(newFont);
304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return NULL;
305d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
307afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::~Font() {
308afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (mFace) {
309d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        FT_Done_Face(mFace);
310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) {
313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if (mRSC->mStateFont.mActiveFonts[ct] == this) {
314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            mRSC->mStateFont.mActiveFonts.removeAt(ct);
315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
316d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
317d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
319afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i);
321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        delete glyph;
322d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
325afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::FontState() {
326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = false;
327d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mMaxNumberOfQuads = 1024;
328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCurrentQuadIndex = 0;
329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC = NULL;
3303659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    mLibrary = NULL;
331c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
332c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the renderer properties
333c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    char property[PROPERTY_VALUE_MAX];
334c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
335c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the gamma
336c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    float gamma = DEFAULT_TEXT_GAMMA;
337c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) {
338c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        gamma = atof(property);
339c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
340c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
341c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the black gamma threshold
34209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) {
344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        blackThreshold = atoi(property);
345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mBlackThreshold = (float)(blackThreshold) / 255.0f;
347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the white gamma threshold
34909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) {
351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        whiteThreshold = atoi(property);
352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mWhiteThreshold = (float)(whiteThreshold) / 255.0f;
354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Compute the gamma tables
356c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mBlackGamma = gamma;
357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mWhiteGamma = 1.0f / gamma;
3584f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk
3594f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk    setFontColor(0.1f, 0.1f, 0.1f, 1.0f);
360d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
361d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
362afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::~FontState() {
363afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
364d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        delete mCacheLines[i];
365d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
366d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
367d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    rsAssert(!mActiveFonts.size());
368d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
369d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
370afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFT_Library FontState::getLib() {
371afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (!mLibrary) {
372a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        FT_Error error = FT_Init_FreeType(&mLibrary);
373afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        if (error) {
374d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            LOGE("Unable to initialize freetype");
375a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk            return NULL;
376d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
377d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
3783659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
379a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    return mLibrary;
380a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk}
381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
382afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::init(Context *rsc) {
383a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mRSC = rsc;
384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
386afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::flushAllAndInvalidate() {
387afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (mCurrentQuadIndex != 0) {
388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
391afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < mActiveFonts.size(); i ++) {
392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mActiveFonts[i]->invalidateTextureCache();
393d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
394afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
395d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCacheLines[i]->mCurrentCol = 0;
396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
399afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) {
400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // If the glyph is too tall, don't cache it
401afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) {
402d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
403d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
406d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now copy the bitmap into the cache texture
407d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startX = 0;
408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startY = 0;
409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    bool bitmapFit = false;
411afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
413afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        if (bitmapFit) {
414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // If the new glyph didn't fit, flush the state so far and invalidate everything
419afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (!bitmapFit) {
420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        flushAllAndInvalidate();
421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Try to fit it again
423afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
425afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk            if (bitmapFit) {
426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                break;
427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            }
428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // if we still don't fit, something is wrong and we shouldn't draw
431afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        if (!bitmapFit) {
432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            return false;
434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    *retOriginX = startX;
438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    *retOriginY = startY;
439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t endX = startX + bitmap->width;
441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheWidth = getCacheTextureType()->getDimX();
444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
44509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr();
44609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint8_t *bitmapBuffer = bitmap->buffer;
447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
449afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) {
450afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) {
45109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX];
452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol;
453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // This will dirty the texture and the shader so next time
457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // we draw it will upload the data
458b7e83bda41e66c966b98935b44140692bfe0c4caJason Sams    mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT);
459383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get());
460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Some debug code
462afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Cache Line: H: %u Empty Space: %f",
464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk             mCacheLines[i]->mMaxHeight,
465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk              (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f);
466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }*/
468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return true;
470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
472afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initRenderState() {
4737ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk    String8 shaderString("varying vec2 varTex0;\n");
474e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("void main() {\n");
475e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  lowp vec4 col = UNI_Color;\n");
476e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n");
477c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    shaderString.append("  col.a = pow(col.a, UNI_Gamma);\n");
478e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  gl_FragColor = col;\n");
479e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("}\n");
480e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
481e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
482c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
483e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mRSC->mStateElement.elementBuilderBegin();
484e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1);
485c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1);
486e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC);
487e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
488f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams    Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false);
489e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
490e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    uint32_t tmp[4];
491e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
492e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[1] = (uint32_t)inputType;
49384e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk    tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE;
49484e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk    tmp[3] = RS_TEXTURE_2D;
495e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
496366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams    mFontShaderFConstant.set(new Allocation(mRSC, inputType,
497366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams                                            RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS));
498e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(),
499e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk                                              shaderString.length(), tmp, 4);
500d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontShaderF.set(pf);
501383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0);
502d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
503d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST,
504d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                      RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP);
505d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontSampler.set(sampler);
506383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindSampler(mRSC, 0, sampler);
507d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
508d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ProgramStore *fontStore = new ProgramStore(mRSC);
509d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore.set(fontStore);
510d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS);
511d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA);
512d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDitherEnable(false);
513d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDepthMask(false);
514d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
515d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
516afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initTextTexture() {
517d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
518d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
519d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // We will allocate a texture to initially hold 32 character bitmaps
520f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams    Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false);
521d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
522366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams    Allocation *cacheAlloc = new Allocation(mRSC, texType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE);
523d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture.set(cacheAlloc);
524b7e83bda41e66c966b98935b44140692bfe0c4caJason Sams    mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT);
525d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
526d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Split up our cache texture into lines of certain widths
52709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nextLine = 0;
528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0));
529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
53201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
53301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
534d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
536d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0));
539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0));
541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad
544afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initVertexArrayBuffers() {
545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now lets write index data
546d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t numIndicies = mMaxNumberOfQuads * 6;
548f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams    Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false);
549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
550366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams    Allocation *indexAlloc = new Allocation(mRSC, indexType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX);
551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr();
552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Four verts, two triangles , six indices per quad
554afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) {
55509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        int32_t i6 = i * 6;
55609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        int32_t i4 = i * 4;
557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 0] = i4 + 0;
559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 1] = i4 + 1;
560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 2] = i4 + 2;
561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
562d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 3] = i4 + 0;
563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 4] = i4 + 2;
564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 5] = i4 + 3;
565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
566d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
567d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexAlloc->deferedUploadToBufferObject(mRSC);
568d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mIndexBuffer.set(indexAlloc);
569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
57364cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk    mRSC->mStateElement.elementBuilderBegin();
57464cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1);
57564cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1);
57664cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk    const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC);
577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
578f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams    Type *vertexDataType = Type::getType(mRSC, vertexDataElem,
579f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams                                         mMaxNumberOfQuads * 4,
580f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams                                         0, 0, false, false);
581d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
582366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams    Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX);
583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextMeshPtr = (float*)vertexAlloc->getPtr();
584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mVertexArray.set(vertexAlloc);
586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text
589afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::checkInit() {
590afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (mInitialized) {
591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initTextTexture();
595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initRenderState();
596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initVertexArrayBuffers();
598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
59935b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    // We store a string with letters in a rough frequency of occurrence
60035b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq");
60135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ");
60235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8(",.?!()-+@;:`'");
60335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8("0123456789");
60435b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk
605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = true;
606d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() {
60960709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams    Context::PushState ps(mRSC);
610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
61160709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams    mRSC->setProgramVertex(mRSC->getDefaultProgramVertex());
61260709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams    mRSC->setProgramRaster(mRSC->getDefaultProgramRaster());
61360709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams    mRSC->setProgramFragment(mFontShaderF.get());
61460709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams    mRSC->setProgramStore(mFontProgramStore.get());
615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
616afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (mConstantsDirty) {
6174b45b8998e0d7038efaea80c70d23c086640b4e3Jason Sams        mFontShaderFConstant->data(mRSC, 0, 0, 1, &mConstants, sizeof(mConstants));
618c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstantsDirty = false;
619ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk    }
620ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk
621d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if (!mRSC->setupCheck()) {
622d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *vtx = (float*)mVertexArray->getPtr();
626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *tex = vtx + 3;
627d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
62854929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk    VertexArray::Attrib attribs[2];
62954929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk    attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position");
63054929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk    attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0");
63154929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk    VertexArray va(attribs, 2);
632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache);
633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mIndexBuffer->uploadCheck(mRSC);
635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0));
637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1,
640afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                               float u1, float v1,
641afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                               float x2, float y2, float z2,
642afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                               float u2, float v2,
643afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                               float x3, float y3, float z3,
644afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                               float u3, float v3,
645afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                               float x4, float y4, float z4,
646afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                               float u4, float v4) {
647d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const uint32_t vertsPerQuad = 4;
648d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const uint32_t floatsPerVert = 5;
649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
651d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Cull things that are off the screen
652d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float width = (float)mRSC->getWidth();
653d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float height = (float)mRSC->getHeight();
654d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
655afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) {
656d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
657d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1);
660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V1 x: %f y: %f z: %f", x2, y2, z2);
661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V2 x: %f y: %f z: %f", x3, y3, z3);
662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/
663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x1;
665d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y1;
666d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z1;
667d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u1;
668d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v1;
669d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x2;
671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y2;
672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z2;
673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u2;
674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v2;
675d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
676d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x3;
677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y3;
678d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z3;
679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u3;
680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v3;
681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
682d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x4;
683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y4;
684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z4;
685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u4;
686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v4;
687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCurrentQuadIndex ++;
689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
690afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (mCurrentQuadIndex == mMaxNumberOfQuads) {
691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
692d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
69601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() {
69701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t remainingCapacity = 0;
69835b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    uint32_t totalPixels = 0;
699afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
70001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk         remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol);
70101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk         totalPixels += mCacheLines[i]->mMaxWidth;
70201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
70301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    remainingCapacity = (remainingCapacity * 100) / totalPixels;
70401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    return remainingCapacity;
70501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
70601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
70701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) {
70801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    // Remaining capacity is measured in %
70901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t remainingCapacity = getRemainingCacheCapacity();
71001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t precacheIdx = 0;
711afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) {
71201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]);
71301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        remainingCapacity = getRemainingCacheCapacity();
71401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        precacheIdx ++;
71501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
71601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
71701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
71801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
71909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y,
72009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           uint32_t startIndex, int32_t numGlyphs,
72109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           Font::RenderMode mode,
72209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           Font::Rect *bounds,
723afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                           uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
724d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    checkInit();
725d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
726d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Render code here
727d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Font *currentFont = mRSC->getFont();
728afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (!currentFont) {
729afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        if (!mDefault.get()) {
730c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk            String8 fontsDir("/fonts/DroidSans.ttf");
731c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk            String8 fullPath(getenv("ANDROID_ROOT"));
732c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk            fullPath += fontsDir;
733c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk
734c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk            mDefault.set(Font::create(mRSC, fullPath.string(), 16, 96));
735a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        }
736a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        currentFont = mDefault.get();
737a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
738afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (!currentFont) {
7393659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        LOGE("Unable to initialize any fonts");
7403659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        return;
7413659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    }
7423659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
74309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs,
74409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           mode, bounds, bitmap, bitmapW, bitmapH);
745d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
746afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (mCurrentQuadIndex != 0) {
747d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
748d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
749d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
75209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) {
75309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds);
7545224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    bounds->bottom = - bounds->bottom;
7555224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    bounds->top = - bounds->top;
756d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
757d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
7589fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) {
759c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[0] = r;
760c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[1] = g;
761c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[2] = b;
762c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[3] = a;
763c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
764c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mGamma = 1.0f;
765c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f;
766c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (luminance <= mBlackThreshold) {
767c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstants.mGamma = mBlackGamma;
768c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else if (luminance >= mWhiteThreshold) {
769c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstants.mGamma = mWhiteGamma;
770c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
7714f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk
772c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstantsDirty = true;
7739fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk}
7749fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk
775ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const {
776c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *r = mConstants.mFontColor[0];
777c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *g = mConstants.mFontColor[1];
778c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *b = mConstants.mFontColor[2];
779c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *a = mConstants.mFontColor[3];
780ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk}
781ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk
782afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::deinit(Context *rsc) {
783a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mInitialized = false;
784a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
78501b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines    mFontShaderFConstant.clear();
78601b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines
787a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mIndexBuffer.clear();
788a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mVertexArray.clear();
789a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
790a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontShaderF.clear();
791a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontSampler.clear();
792a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontProgramStore.clear();
793a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
794a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mTextTexture.clear();
795afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < mCacheLines.size(); i ++) {
796a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        delete mCacheLines[i];
797d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
798a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mCacheLines.clear();
799d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
800d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mDefault.clear();
801a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
8023659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    Vector<Font*> fontsToDereference = mActiveFonts;
803afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    for (uint32_t i = 0; i < fontsToDereference.size(); i ++) {
8043659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        fontsToDereference[i]->zeroUserRef();
8053659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    }
8063659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
807afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (mLibrary) {
808a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        FT_Done_FreeType( mLibrary );
8093659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        mLibrary = NULL;
810a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
811d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
812d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
813d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android {
814d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript {
815d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
816c17ace2391783dcabc6c1482edf0362654fd83e5Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, float fontSize, uint32_t dpi) {
817a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    Font *newFont = Font::create(rsc, name, fontSize, dpi);
818afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (newFont) {
819a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        newFont->incUserRef();
820a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
821a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    return newFont;
822d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
823d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
8245224a27798f89093b13722b41143551a057ce550Alex SakhartchoukRsFont rsi_FontCreateFromMemory(Context *rsc, char const *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) {
8255224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    Font *newFont = Font::create(rsc, name, fontSize, dpi, data, dataLen);
8265224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    if (newFont) {
8275224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk        newFont->incUserRef();
8285224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    }
8295224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk    return newFont;
8305224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk}
8315224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk
832d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript
833d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android
834