rsFont.cpp revision 225afd317e101a7be5fe02c0a86361146ea89f05
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
37d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL)
38d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
39d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = false;
40d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mHasKerning = false;
413659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    mFace = NULL;
42d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
43d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
44d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool Font::init(const char *name, uint32_t fontSize, uint32_t dpi)
45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mInitialized) {
47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Reinitialization of fonts not supported");
48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
49d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
50d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
51d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 fontsDir("/fonts/");
52d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 fullPath(getenv("ANDROID_ROOT"));
53d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    fullPath += fontsDir;
54d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    fullPath += name;
55d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
56a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace);
57d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(error) {
58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Unable to initialize font %s", fullPath.string());
59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontName = name;
63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontSize = fontSize;
64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mDpi = dpi;
65d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
66d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0);
67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(error) {
68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Unable to set font size on %s", fullPath.string());
69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mHasKerning = FT_HAS_KERNING(mFace);
73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = true;
75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return true;
76d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
77d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
78d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::invalidateTextureCache()
79d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
80d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
81d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCachedGlyphs.valueAt(i)->mIsValid = false;
82d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
83d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
84d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
8509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y)
86d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
87d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
88d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
8909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenX = x + glyph->mBitmapLeft;
9009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
91d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
9209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float u1 = glyph->mBitmapMinU;
9309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float u2 = glyph->mBitmapMaxU;
9409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float v1 = glyph->mBitmapMinV;
9509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float v2 = glyph->mBitmapMaxV;
96d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t width = (int32_t) glyph->mBitmapWidth;
9809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t height = (int32_t) glyph->mBitmapHeight;
99d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    state->appendMeshQuad(nPenX, nPenY, 0, u1, v2,
10109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                          nPenX + width, nPenY, 0, u2, v2,
10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                          nPenX + width, nPenY - height, 0, u2, v1,
10309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                          nPenX, nPenY - height, 0, u1, v1);
10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk}
10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y,
10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) {
10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenX = x + glyph->mBitmapLeft;
10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenY = y + glyph->mBitmapTop;
11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth;
11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight;
11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    const uint8_t* cacheBuffer = state->getTextTextureData();
11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t cacheX = 0, cacheY = 0;
11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t bX = 0, bY = 0;
12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) {
12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) {
12209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) {
12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                LOGE("Skipping invalid index");
12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                continue;
12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            }
12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX];
12709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            bitmap[bY * bitmapW + bX] = tempCol;
12809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        }
12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
130d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
131d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
132d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
13309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) {
13409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenX = x + glyph->mBitmapLeft;
13509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
13609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
13709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t width = (int32_t) glyph->mBitmapWidth;
13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t height = (int32_t) glyph->mBitmapHeight;
13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if (bounds->bottom > nPenY) {
14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->bottom = nPenY;
14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if (bounds->left > nPenX) {
14409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->left = nPenX;
14509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
14609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if (bounds->right < nPenX + width) {
14709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->right = nPenX + width;
14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if (bounds->top < nPenY + height) {
15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->top = nPenY + height;
15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
15209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk}
15309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
15409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y,
15509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                     uint32_t start, int32_t numGlyphs,
15609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                     RenderMode mode, Rect *bounds,
15709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                     uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH)
158d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
159d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) {
160d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
161d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
162d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
16309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if(mode == Font::MEASURE) {
16409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        if (bounds == NULL) {
16509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            LOGE("No return rectangle provided to measure text");
16609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            return;
16709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        }
16809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        // Reset min and max of the bounding box to something large
16909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->set(1e6, -1e6, -1e6, 1e6);
17009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
17109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
17209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t penX = x, penY = y;
17309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t glyphsLeft = 1;
174d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(numGlyphs > 0) {
175d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        glyphsLeft = numGlyphs;
176d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
177d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t index = start;
179d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t nextIndex = 0;
180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    while (glyphsLeft > 0) {
182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        int32_t utfChar = utf32_at(text, len, index, &nextIndex);
184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Reached the end of the string or encountered
186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(utfChar < 0) {
187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
189d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
190d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Move to the next character in the array
191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        index = nextIndex;
192d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
19301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar);
194d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
195d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
196d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(cachedGlyph->mIsValid) {
19709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            switch(mode) {
19809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            case FRAMEBUFFER:
19909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                drawCachedGlyph(cachedGlyph, penX, penY);
20009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                break;
20109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            case BITMAP:
20209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH);
20309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                break;
20409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            case MEASURE:
20509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                measureCachedGlyph(cachedGlyph, penX, penY, bounds);
20609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                break;
20709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            }
208d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
209d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
210d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        penX += (cachedGlyph->mAdvance.x >> 6);
211d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // If we were given a specific number of glyphs, decrement
213d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(numGlyphs > 0) {
214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            glyphsLeft --;
215d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
216d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
217d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
218d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
21901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) {
22001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
22101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar);
22201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    if(cachedGlyph == NULL) {
22301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        cachedGlyph = cacheGlyph((uint32_t)utfChar);
22401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
22501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    // Is the glyph still in texture cache?
22601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    if(!cachedGlyph->mIsValid) {
22701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        updateGlyphCache(cachedGlyph);
22801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
22901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
23001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    return cachedGlyph;
23101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
23201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
233d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph)
234d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
235a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER );
236a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(error) {
237a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        LOGE("Couldn't load glyph.");
238a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        return;
239a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
240d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
241a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mAdvance = mFace->glyph->advance;
242a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapLeft = mFace->glyph->bitmap_left;
243a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapTop = mFace->glyph->bitmap_top;
244d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
245a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Bitmap *bitmap = &mFace->glyph->bitmap;
246d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
247d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now copy the bitmap into the cache texture
248d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startX = 0;
249d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startY = 0;
250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Let the font state figure out where to put the bitmap
252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
253a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY);
254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
255d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!glyph->mIsValid) {
256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
259a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    uint32_t endX = startX + bitmap->width;
260a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
261d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
262d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinX = startX;
263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinY = startY;
264a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapWidth = bitmap->width;
265a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapHeight = bitmap->rows;
266d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheHeight = state->getCacheTextureType()->getDimY();
269d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinU = (float)startX / (float)cacheWidth;
271d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinV = (float)startY / (float)cacheHeight;
272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMaxU = (float)endX / (float)cacheWidth;
273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMaxV = (float)endY / (float)cacheHeight;
274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph)
277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    CachedGlyphInfo *newGlyph = new CachedGlyphInfo();
279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCachedGlyphs.add(glyph, newGlyph);
280d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph);
282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    newGlyph->mIsValid = false;
283d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
284d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    updateGlyphCache(newGlyph);
285d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return newGlyph;
287d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
288d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi)
290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
29135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    rsc->mStateFont.checkInit();
292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts;
293d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < activeFonts.size(); i ++) {
295d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        Font *ithFont = activeFonts[i];
296d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) {
297d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            return ithFont;
298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
299d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
300d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Font *newFont = new Font(rsc);
302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    bool isInitialized = newFont->init(name, fontSize, dpi);
303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(isInitialized) {
304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        activeFonts.push(newFont);
30501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        rsc->mStateFont.precacheLatin(newFont);
306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return newFont;
307d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
308d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
309225afd317e101a7be5fe02c0a86361146ea89f05Jason Sams    ObjectBase::checkDelete(newFont);
310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return NULL;
311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::~Font()
315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
316d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mFace) {
317d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        FT_Done_Face(mFace);
318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
319d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) {
321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if (mRSC->mStateFont.mActiveFonts[ct] == this) {
322d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            mRSC->mStateFont.mActiveFonts.removeAt(ct);
323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
325d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
327d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i);
329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        delete glyph;
330d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
331d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
332d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
333d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::FontState()
334d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
335d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = false;
336d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mMaxNumberOfQuads = 1024;
337d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCurrentQuadIndex = 0;
338d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC = NULL;
3393659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    mLibrary = NULL;
340c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
341c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the renderer properties
342c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    char property[PROPERTY_VALUE_MAX];
343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the gamma
345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    float gamma = DEFAULT_TEXT_GAMMA;
346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) {
347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Setting text gamma to %s", property);
348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        gamma = atof(property);
349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else {
350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA);
351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the black gamma threshold
35409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) {
356c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Setting text black gamma threshold to %s", property);
357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        blackThreshold = atoi(property);
358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else {
359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Using default text black gamma threshold of %d",
360c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk                DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD);
361c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
362c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mBlackThreshold = (float)(blackThreshold) / 255.0f;
363c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
364c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the white gamma threshold
36509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
366c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) {
367c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Setting text white gamma threshold to %s", property);
368c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        whiteThreshold = atoi(property);
369c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else {
370c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Using default white black gamma threshold of %d",
371c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk                DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD);
372c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
373c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mWhiteThreshold = (float)(whiteThreshold) / 255.0f;
374c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
375c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Compute the gamma tables
376c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mBlackGamma = gamma;
377c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mWhiteGamma = 1.0f / gamma;
3784f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk
3794f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk    setFontColor(0.1f, 0.1f, 0.1f, 1.0f);
380d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::~FontState()
383d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        delete mCacheLines[i];
386d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
387d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    rsAssert(!mActiveFonts.size());
389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
391a1ccecd965c07c2739f1258989526051a010bdabAlex SakhartchoukFT_Library FontState::getLib()
392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
393d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!mLibrary) {
394a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        FT_Error error = FT_Init_FreeType(&mLibrary);
395d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(error) {
396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            LOGE("Unable to initialize freetype");
397a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk            return NULL;
398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
399d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
4003659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
401a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    return mLibrary;
402a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk}
403d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
404a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchoukvoid FontState::init(Context *rsc)
405a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk{
406a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mRSC = rsc;
407d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::flushAllAndInvalidate()
410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex != 0) {
412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mActiveFonts.size(); i ++) {
416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mActiveFonts[i]->invalidateTextureCache();
417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCacheLines[i]->mCurrentCol = 0;
420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY)
424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // If the glyph is too tall, don't cache it
426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) {
427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now copy the bitmap into the cache texture
432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startX = 0;
433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startY = 0;
434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    bool bitmapFit = false;
436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(bitmapFit) {
439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // If the new glyph didn't fit, flush the state so far and invalidate everything
444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!bitmapFit) {
445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        flushAllAndInvalidate();
446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Try to fit it again
448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            if(bitmapFit) {
451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                break;
452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            }
453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // if we still don't fit, something is wrong and we shouldn't draw
456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(!bitmapFit) {
457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            return false;
459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    *retOriginX = startX;
463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    *retOriginY = startY;
464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t endX = startX + bitmap->width;
466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheWidth = getCacheTextureType()->getDimX();
469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
47009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr();
47109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint8_t *bitmapBuffer = bitmap->buffer;
472d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
473d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) {
475d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) {
47609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX];
477d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol;
478d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
479d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
480d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // This will dirty the texture and the shader so next time
482d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // we draw it will upload the data
483d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
484383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get());
485d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
486d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Some debug code
487d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    /*for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
488d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Cache Line: H: %u Empty Space: %f",
489d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk             mCacheLines[i]->mMaxHeight,
490d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk              (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f);
491d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
492d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }*/
493d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
494d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return true;
495d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
496d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
497d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initRenderState()
498d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
4997ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk    String8 shaderString("varying vec2 varTex0;\n");
500e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("void main() {\n");
501e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  lowp vec4 col = UNI_Color;\n");
502e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n");
503c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    shaderString.append("  col.a = pow(col.a, UNI_Gamma);\n");
504e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  gl_FragColor = col;\n");
505e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("}\n");
506e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
507e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
508c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
509e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mRSC->mStateElement.elementBuilderBegin();
510e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1);
511c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1);
512e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC);
513e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
514e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    Type *inputType = new Type(mRSC);
515e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    inputType->setElement(constInput);
516e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    inputType->setDimX(1);
517e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    inputType->compute();
518e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
519e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    uint32_t tmp[4];
520e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
521e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[1] = (uint32_t)inputType;
522e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT;
523e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[3] = 1;
524e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
525e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mFontShaderFConstant.set(new Allocation(mRSC, inputType));
526e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(),
527e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk                                              shaderString.length(), tmp, 4);
528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontShaderF.set(pf);
529383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0);
530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST,
532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                      RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP);
533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontSampler.set(sampler);
534383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindSampler(mRSC, 0, sampler);
535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
536d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ProgramStore *fontStore = new ProgramStore(mRSC);
537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore.set(fontStore);
538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS);
539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA);
540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDitherEnable(false);
541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDepthMask(false);
542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initTextTexture()
545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
546d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // We will allocate a texture to initially hold 32 character bitmaps
549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *texType = new Type(mRSC);
550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setElement(alphaElem);
551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setDimX(1024);
552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setDimY(256);
553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->compute();
554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *cacheAlloc = new Allocation(mRSC, texType);
556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture.set(cacheAlloc);
557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Split up our cache texture into lines of certain widths
56009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nextLine = 0;
561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0));
562d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
56501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
56601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
567d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
568d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0));
572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0));
574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad
577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initVertexArrayBuffers()
578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now lets write index data
580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
581d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *indexType = new Type(mRSC);
582d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t numIndicies = mMaxNumberOfQuads * 6;
583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->setDimX(numIndicies);
584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->setElement(indexElem);
585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->compute();
586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *indexAlloc = new Allocation(mRSC, indexType);
588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr();
589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Four verts, two triangles , six indices per quad
591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) {
59209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        int32_t i6 = i * 6;
59309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        int32_t i4 = i * 4;
594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 0] = i4 + 0;
596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 1] = i4 + 1;
597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 2] = i4 + 2;
598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 3] = i4 + 0;
600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 4] = i4 + 2;
601d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 5] = i4 + 3;
602d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
603d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexAlloc->deferedUploadToBufferObject(mRSC);
605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mIndexBuffer.set(indexAlloc);
606d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
609d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
61064cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk    mRSC->mStateElement.elementBuilderBegin();
61164cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1);
61264cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1);
61364cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk    const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC);
614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *vertexDataType = new Type(mRSC);
616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->setDimX(mMaxNumberOfQuads * 4);
617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->setElement(vertexDataElem);
618d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->compute();
619d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
620d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType);
621d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextMeshPtr = (float*)vertexAlloc->getPtr();
622d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mVertexArray.set(vertexAlloc);
624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text
627d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::checkInit()
628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mInitialized) {
630d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
631d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initTextTexture();
634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initRenderState();
635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initVertexArrayBuffers();
637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
63835b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    // We store a string with letters in a rough frequency of occurrence
63935b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq");
64035b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ");
64135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8(",.?!()-+@;:`'");
64235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8("0123456789");
64335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk
644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = true;
645d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
646d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
647d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() {
648d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex());
650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setVertex(mRSC->getDefaultProgramVertex());
651d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
652d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster());
653d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    mRSC->setRaster(mRSC->getDefaultProgramRaster());
654d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk
655d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment());
656d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragment(mFontShaderF.get());
657d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore());
659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragmentStore(mFontProgramStore.get());
660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
661c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if(mConstantsDirty) {
662c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants));
663c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstantsDirty = false;
664ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk    }
665ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk
666d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if (!mRSC->setupCheck()) {
667d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setVertex((ProgramVertex *)tmpV.get());
668d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk        mRSC->setRaster((ProgramRaster *)tmpR.get());
669d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setFragment((ProgramFragment *)tmpF.get());
670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *vtx = (float*)mVertexArray->getPtr();
675d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *tex = vtx + 3;
676d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    VertexArray va;
678886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk    va.add(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position");
679886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk    va.add(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0");
680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache);
681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
682d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mIndexBuffer->uploadCheck(mRSC);
683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0));
685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Reset the state
687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setVertex((ProgramVertex *)tmpV.get());
688d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    mRSC->setRaster((ProgramRaster *)tmpR.get());
689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragment((ProgramFragment *)tmpF.get());
690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
692d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1,
694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u1, float v1,
695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x2, float y2, float z2,
696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u2, float v2,
697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x3, float y3, float z3,
698d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u3, float v3,
699d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x4, float y4, float z4,
700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u4, float v4)
701d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
702d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const uint32_t vertsPerQuad = 4;
703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const uint32_t floatsPerVert = 5;
704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Cull things that are off the screen
707d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float width = (float)mRSC->getWidth();
708d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float height = (float)mRSC->getHeight();
709d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
710d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) {
711d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
712d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
713d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
714d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1);
715d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V1 x: %f y: %f z: %f", x2, y2, z2);
716d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V2 x: %f y: %f z: %f", x3, y3, z3);
717d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/
718d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
719d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x1;
720d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y1;
721d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z1;
722d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u1;
723d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v1;
724d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
725d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x2;
726d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y2;
727d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z2;
728d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u2;
729d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v2;
730d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
731d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x3;
732d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y3;
733d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z3;
734d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u3;
735d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v3;
736d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
737d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x4;
738d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y4;
739d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z4;
740d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u4;
741d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v4;
742d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
743d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCurrentQuadIndex ++;
744d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
745d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex == mMaxNumberOfQuads) {
746d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
747d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
748d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
749d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
75101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() {
75201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t remainingCapacity = 0;
75335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    uint32_t totalPixels = 0;
75401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
75501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk         remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol);
75601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk         totalPixels += mCacheLines[i]->mMaxWidth;
75701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
75801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    remainingCapacity = (remainingCapacity * 100) / totalPixels;
75901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    return remainingCapacity;
76001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
76101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
76201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) {
76301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    // Remaining capacity is measured in %
76401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t remainingCapacity = getRemainingCacheCapacity();
76501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t precacheIdx = 0;
76601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    while(remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) {
76701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]);
76801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        remainingCapacity = getRemainingCacheCapacity();
76901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        precacheIdx ++;
77001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
77101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
77201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
77301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
77409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y,
77509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           uint32_t startIndex, int32_t numGlyphs,
77609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           Font::RenderMode mode,
77709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           Font::Rect *bounds,
77809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH)
779d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
780d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    checkInit();
781d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
782d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Render code here
783d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Font *currentFont = mRSC->getFont();
784a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(!currentFont) {
785a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        if(!mDefault.get()) {
786a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk            mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96));
787a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        }
788a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        currentFont = mDefault.get();
789a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
7903659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    if(!currentFont) {
7913659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        LOGE("Unable to initialize any fonts");
7923659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        return;
7933659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    }
7943659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
79509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs,
79609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           mode, bounds, bitmap, bitmapW, bitmapH);
797d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
798d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex != 0) {
799d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
800d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
801d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
802d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
803d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
80409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) {
80509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds);
806d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
807d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
8089fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) {
809c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[0] = r;
810c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[1] = g;
811c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[2] = b;
812c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[3] = a;
813c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
814c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mGamma = 1.0f;
815c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f;
816c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (luminance <= mBlackThreshold) {
817c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstants.mGamma = mBlackGamma;
818c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else if (luminance >= mWhiteThreshold) {
819c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstants.mGamma = mWhiteGamma;
820c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
8214f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk
822c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstantsDirty = true;
8239fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk}
8249fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk
825ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const {
826c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *r = mConstants.mFontColor[0];
827c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *g = mConstants.mFontColor[1];
828c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *b = mConstants.mFontColor[2];
829c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *a = mConstants.mFontColor[3];
830ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk}
831ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk
832d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::deinit(Context *rsc)
833d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
834a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mInitialized = false;
835a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
83601b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines    mFontShaderFConstant.clear();
83701b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines
838a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mIndexBuffer.clear();
839a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mVertexArray.clear();
840a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
841a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontShaderF.clear();
842a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontSampler.clear();
843a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontProgramStore.clear();
844a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
845a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mTextTexture.clear();
846a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
847a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        delete mCacheLines[i];
848d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
849a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mCacheLines.clear();
850d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
851d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mDefault.clear();
852a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
8533659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    Vector<Font*> fontsToDereference = mActiveFonts;
8543659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    for(uint32_t i = 0; i < fontsToDereference.size(); i ++) {
8553659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        fontsToDereference[i]->zeroUserRef();
8563659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    }
8573659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
858a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(mLibrary) {
859a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        FT_Done_FreeType( mLibrary );
8603659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        mLibrary = NULL;
861a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
862d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
863d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
864d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android {
865d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript {
866d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
867d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi)
868d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
869a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    Font *newFont = Font::create(rsc, name, fontSize, dpi);
870a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(newFont) {
871a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        newFont->incUserRef();
872a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
873a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    return newFont;
874d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
875d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
876d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript
877d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android
878