rsFont.cpp revision 4f230b31d59b5f17100686bc1416b3b07a4a618d
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{
39a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mAllocFile = __FILE__;
40a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mAllocLine = __LINE__;
41d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = false;
42d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mHasKerning = false;
433659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    mFace = NULL;
44d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool Font::init(const char *name, uint32_t fontSize, uint32_t dpi)
47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mInitialized) {
49d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Reinitialization of fonts not supported");
50d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
51d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
52d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
53d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 fontsDir("/fonts/");
54d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 fullPath(getenv("ANDROID_ROOT"));
55d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    fullPath += fontsDir;
56d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    fullPath += name;
57d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
58a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace);
59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(error) {
60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Unable to initialize font %s", fullPath.string());
61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontName = name;
65d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontSize = fontSize;
66d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mDpi = dpi;
67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0);
69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(error) {
70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Unable to set font size on %s", fullPath.string());
71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mHasKerning = FT_HAS_KERNING(mFace);
75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
76d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = true;
77d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return true;
78d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
79d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
80d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::invalidateTextureCache()
81d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
82d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
83d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCachedGlyphs.valueAt(i)->mIsValid = false;
84d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
85d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
86d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
8709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y)
88d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
89d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
90d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
9109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenX = x + glyph->mBitmapLeft;
9209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
93d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
9409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float u1 = glyph->mBitmapMinU;
9509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float u2 = glyph->mBitmapMaxU;
9609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float v1 = glyph->mBitmapMinV;
9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    float v2 = glyph->mBitmapMaxV;
98d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
9909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t width = (int32_t) glyph->mBitmapWidth;
10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t height = (int32_t) glyph->mBitmapHeight;
101d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    state->appendMeshQuad(nPenX, nPenY, 0, u1, v2,
10309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                          nPenX + width, nPenY, 0, u2, v2,
10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                          nPenX + width, nPenY - height, 0, u2, v1,
10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                          nPenX, nPenY - height, 0, u1, v1);
10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk}
10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y,
10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) {
11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenX = x + glyph->mBitmapLeft;
11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenY = y + glyph->mBitmapTop;
11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth;
11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight;
11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    const uint8_t* cacheBuffer = state->getTextTextureData();
11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint32_t cacheX = 0, cacheY = 0;
12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t bX = 0, bY = 0;
12209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) {
12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) {
12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) {
12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                LOGE("Skipping invalid index");
12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                continue;
12709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            }
12809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX];
12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            bitmap[bY * bitmapW + bX] = tempCol;
13009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        }
13109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
132d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
133d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
134d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
13509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) {
13609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenX = x + glyph->mBitmapLeft;
13709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t width = (int32_t) glyph->mBitmapWidth;
14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t height = (int32_t) glyph->mBitmapHeight;
14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if (bounds->bottom > nPenY) {
14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->bottom = nPenY;
14409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
14509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if (bounds->left > nPenX) {
14609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->left = nPenX;
14709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if (bounds->right < nPenX + width) {
14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->right = nPenX + width;
15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if (bounds->top < nPenY + height) {
15209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->top = nPenY + height;
15309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
15409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk}
15509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
15609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y,
15709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                     uint32_t start, int32_t numGlyphs,
15809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                     RenderMode mode, Rect *bounds,
15909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                     uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH)
160d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
161d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) {
162d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
163d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
164d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
16509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    if(mode == Font::MEASURE) {
16609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        if (bounds == NULL) {
16709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            LOGE("No return rectangle provided to measure text");
16809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            return;
16909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        }
17009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        // Reset min and max of the bounding box to something large
17109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        bounds->set(1e6, -1e6, -1e6, 1e6);
17209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    }
17309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
17409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t penX = x, penY = y;
17509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t glyphsLeft = 1;
176d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(numGlyphs > 0) {
177d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        glyphsLeft = numGlyphs;
178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
179d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t index = start;
181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t nextIndex = 0;
182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    while (glyphsLeft > 0) {
184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        int32_t utfChar = utf32_at(text, len, index, &nextIndex);
186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Reached the end of the string or encountered
188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(utfChar < 0) {
189d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
190d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
192d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Move to the next character in the array
193d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        index = nextIndex;
194d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
19501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar);
196d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
197d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
198d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(cachedGlyph->mIsValid) {
19909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            switch(mode) {
20009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            case FRAMEBUFFER:
20109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                drawCachedGlyph(cachedGlyph, penX, penY);
20209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                break;
20309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            case BITMAP:
20409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH);
20509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                break;
20609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            case MEASURE:
20709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                measureCachedGlyph(cachedGlyph, penX, penY, bounds);
20809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                break;
20909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            }
210d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
211d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        penX += (cachedGlyph->mAdvance.x >> 6);
213d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // If we were given a specific number of glyphs, decrement
215d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(numGlyphs > 0) {
216d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            glyphsLeft --;
217d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
218d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
219d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
220d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
22101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) {
22201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
22301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar);
22401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    if(cachedGlyph == NULL) {
22501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        cachedGlyph = cacheGlyph((uint32_t)utfChar);
22601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
22701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    // Is the glyph still in texture cache?
22801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    if(!cachedGlyph->mIsValid) {
22901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        updateGlyphCache(cachedGlyph);
23001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
23101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
23201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    return cachedGlyph;
23301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
23401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
235d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph)
236d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
237a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER );
238a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(error) {
239a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        LOGE("Couldn't load glyph.");
240a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        return;
241a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
242d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
243a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mAdvance = mFace->glyph->advance;
244a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapLeft = mFace->glyph->bitmap_left;
245a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapTop = mFace->glyph->bitmap_top;
246d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
247a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Bitmap *bitmap = &mFace->glyph->bitmap;
248d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
249d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now copy the bitmap into the cache texture
250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startX = 0;
251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startY = 0;
252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
253d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Let the font state figure out where to put the bitmap
254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
255a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY);
256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!glyph->mIsValid) {
258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
259d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
260d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
261a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    uint32_t endX = startX + bitmap->width;
262a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
264d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinX = startX;
265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinY = startY;
266a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapWidth = bitmap->width;
267a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapHeight = bitmap->rows;
268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
269d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheHeight = state->getCacheTextureType()->getDimY();
271d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinU = (float)startX / (float)cacheWidth;
273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinV = (float)startY / (float)cacheHeight;
274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMaxU = (float)endX / (float)cacheWidth;
275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMaxV = (float)endY / (float)cacheHeight;
276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph)
279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
280d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    CachedGlyphInfo *newGlyph = new CachedGlyphInfo();
281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCachedGlyphs.add(glyph, newGlyph);
282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
283d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph);
284d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    newGlyph->mIsValid = false;
285d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    updateGlyphCache(newGlyph);
287d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
288d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return newGlyph;
289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
291d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi)
292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
29335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    rsc->mStateFont.checkInit();
294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts;
295d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
296d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < activeFonts.size(); i ++) {
297d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        Font *ithFont = activeFonts[i];
298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) {
299d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            return ithFont;
300d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Font *newFont = new Font(rsc);
304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    bool isInitialized = newFont->init(name, fontSize, dpi);
305d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(isInitialized) {
306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        activeFonts.push(newFont);
30701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        rsc->mStateFont.precacheLatin(newFont);
308d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return newFont;
309d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    delete newFont;
312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return NULL;
313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
316d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::~Font()
317d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mFace) {
319d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        FT_Done_Face(mFace);
320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
322d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) {
323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if (mRSC->mStateFont.mActiveFonts[ct] == this) {
324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            mRSC->mStateFont.mActiveFonts.removeAt(ct);
325d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
327d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
330d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i);
331d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        delete glyph;
332d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
333d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
334d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
335d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::FontState()
336d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
337d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = false;
338d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mMaxNumberOfQuads = 1024;
339d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCurrentQuadIndex = 0;
340d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC = NULL;
3413659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    mLibrary = NULL;
342c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the renderer properties
344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    char property[PROPERTY_VALUE_MAX];
345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the gamma
347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    float gamma = DEFAULT_TEXT_GAMMA;
348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) {
349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Setting text gamma to %s", property);
350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        gamma = atof(property);
351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else {
352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA);
353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the black gamma threshold
35609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) {
358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Setting text black gamma threshold to %s", property);
359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        blackThreshold = atoi(property);
360c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else {
361c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Using default text black gamma threshold of %d",
362c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk                DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD);
363c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
364c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mBlackThreshold = (float)(blackThreshold) / 255.0f;
365c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
366c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the white gamma threshold
36709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
368c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) {
369c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Setting text white gamma threshold to %s", property);
370c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        whiteThreshold = atoi(property);
371c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else {
372c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Using default white black gamma threshold of %d",
373c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk                DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD);
374c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
375c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mWhiteThreshold = (float)(whiteThreshold) / 255.0f;
376c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
377c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Compute the gamma tables
378c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mBlackGamma = gamma;
379c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mWhiteGamma = 1.0f / gamma;
3804f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk
3814f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk    setFontColor(0.1f, 0.1f, 0.1f, 1.0f);
382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
383d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::~FontState()
385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
386d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
387d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        delete mCacheLines[i];
388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    rsAssert(!mActiveFonts.size());
391d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
393a1ccecd965c07c2739f1258989526051a010bdabAlex SakhartchoukFT_Library FontState::getLib()
394d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
395d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!mLibrary) {
396a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        FT_Error error = FT_Init_FreeType(&mLibrary);
397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(error) {
398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            LOGE("Unable to initialize freetype");
399a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk            return NULL;
400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
401d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
4023659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
403a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    return mLibrary;
404a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk}
405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
406a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchoukvoid FontState::init(Context *rsc)
407a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk{
408a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mRSC = rsc;
409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::flushAllAndInvalidate()
412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex != 0) {
414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mActiveFonts.size(); i ++) {
418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mActiveFonts[i]->invalidateTextureCache();
419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCacheLines[i]->mCurrentCol = 0;
422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY)
426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // If the glyph is too tall, don't cache it
428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) {
429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now copy the bitmap into the cache texture
434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startX = 0;
435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startY = 0;
436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    bool bitmapFit = false;
438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(bitmapFit) {
441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // If the new glyph didn't fit, flush the state so far and invalidate everything
446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!bitmapFit) {
447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        flushAllAndInvalidate();
448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Try to fit it again
450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            if(bitmapFit) {
453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                break;
454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            }
455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // if we still don't fit, something is wrong and we shouldn't draw
458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(!bitmapFit) {
459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            return false;
461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    *retOriginX = startX;
465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    *retOriginY = startY;
466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t endX = startX + bitmap->width;
468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheWidth = getCacheTextureType()->getDimX();
471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
47209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr();
47309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint8_t *bitmapBuffer = bitmap->buffer;
474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
475d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
476d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) {
477d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) {
47809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX];
479d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol;
480d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
482d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
483d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // This will dirty the texture and the shader so next time
484d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // we draw it will upload the data
485d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
486383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get());
487d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
488d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Some debug code
489d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    /*for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
490d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Cache Line: H: %u Empty Space: %f",
491d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk             mCacheLines[i]->mMaxHeight,
492d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk              (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f);
493d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
494d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }*/
495d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
496d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return true;
497d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
498d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
499d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initRenderState()
500d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
5017ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk    String8 shaderString("varying vec2 varTex0;\n");
502e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("void main() {\n");
503e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  lowp vec4 col = UNI_Color;\n");
504e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n");
505c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    shaderString.append("  col.a = pow(col.a, UNI_Gamma);\n");
506e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  gl_FragColor = col;\n");
507e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("}\n");
508e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
509e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
510c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
511e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mRSC->mStateElement.elementBuilderBegin();
512e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1);
513c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1);
514e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC);
515e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
516e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    Type *inputType = new Type(mRSC);
517e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    inputType->setElement(constInput);
518e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    inputType->setDimX(1);
519e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    inputType->compute();
520e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
521e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    uint32_t tmp[4];
522e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
523e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[1] = (uint32_t)inputType;
524e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT;
525e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[3] = 1;
526e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
527e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mFontShaderFConstant.set(new Allocation(mRSC, inputType));
528e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(),
529e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk                                              shaderString.length(), tmp, 4);
530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontShaderF.set(pf);
531383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0);
532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST,
534d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                      RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP);
535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontSampler.set(sampler);
536383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindSampler(mRSC, 0, sampler);
537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ProgramStore *fontStore = new ProgramStore(mRSC);
539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore.set(fontStore);
540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS);
541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA);
542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDitherEnable(false);
543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDepthMask(false);
544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
546d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initTextTexture()
547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // We will allocate a texture to initially hold 32 character bitmaps
551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *texType = new Type(mRSC);
552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setElement(alphaElem);
553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setDimX(1024);
554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setDimY(256);
555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->compute();
556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *cacheAlloc = new Allocation(mRSC, texType);
558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture.set(cacheAlloc);
559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Split up our cache texture into lines of certain widths
56209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nextLine = 0;
563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0));
564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
566d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
56701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
56801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex 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(32, texType->getDimX(), nextLine, 0));
572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0));
574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0));
576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad
579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initVertexArrayBuffers()
580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
581d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now lets write index data
582d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *indexType = new Type(mRSC);
584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t numIndicies = mMaxNumberOfQuads * 6;
585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->setDimX(numIndicies);
586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->setElement(indexElem);
587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->compute();
588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *indexAlloc = new Allocation(mRSC, indexType);
590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr();
591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Four verts, two triangles , six indices per quad
593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) {
59409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        int32_t i6 = i * 6;
59509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        int32_t i4 = i * 4;
596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 0] = i4 + 0;
598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 1] = i4 + 1;
599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 2] = i4 + 2;
600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
601d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 3] = i4 + 0;
602d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 4] = i4 + 2;
603d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 5] = i4 + 3;
604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
606d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexAlloc->deferedUploadToBufferObject(mRSC);
607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mIndexBuffer.set(indexAlloc);
608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
609d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
611d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *elemArray[2];
613d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    elemArray[0] = posElem;
614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    elemArray[1] = texElem;
615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 posName("position");
617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 texName("texture0");
618d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
619d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const char *nameArray[2];
620d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nameArray[0] = posName.string();
621d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nameArray[1] = texName.string();
622d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t lengths[2];
623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    lengths[0] = posName.size();
624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    lengths[1] = texName.size();
62546e45548dc80e801139c9ccc2f2aa927e7f35027Jason Sams    uint32_t arraySizes[2] = {1, 1};
626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
62746e45548dc80e801139c9ccc2f2aa927e7f35027Jason Sams    const Element *vertexDataElem = Element::create(mRSC, 2, elemArray, nameArray, lengths, arraySizes);
628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *vertexDataType = new Type(mRSC);
630d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->setDimX(mMaxNumberOfQuads * 4);
631d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->setElement(vertexDataElem);
632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->compute();
633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType);
635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextMeshPtr = (float*)vertexAlloc->getPtr();
636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mVertexArray.set(vertexAlloc);
638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text
641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::checkInit()
642d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
643d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mInitialized) {
644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
645d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
646d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
647d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initTextTexture();
648d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initRenderState();
649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initVertexArrayBuffers();
651d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
65235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    // We store a string with letters in a rough frequency of occurrence
65335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq");
65435b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ");
65535b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8(",.?!()-+@;:`'");
65635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8("0123456789");
65735b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk
658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = true;
659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() {
662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex());
664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setVertex(mRSC->getDefaultProgramVertex());
665d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
666d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster());
667d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    mRSC->setRaster(mRSC->getDefaultProgramRaster());
668d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk
669d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment());
670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragment(mFontShaderF.get());
671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore());
673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragmentStore(mFontProgramStore.get());
674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
675c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if(mConstantsDirty) {
676c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants));
677c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstantsDirty = false;
678ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk    }
679ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk
680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if (!mRSC->setupCheck()) {
681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setVertex((ProgramVertex *)tmpV.get());
682d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk        mRSC->setRaster((ProgramRaster *)tmpR.get());
683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setFragment((ProgramFragment *)tmpF.get());
684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *vtx = (float*)mVertexArray->getPtr();
689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *tex = vtx + 3;
690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    VertexArray va;
692886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk    va.add(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position");
693886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk    va.add(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0");
694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache);
695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mIndexBuffer->uploadCheck(mRSC);
697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
698d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0));
699d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Reset the state
701d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setVertex((ProgramVertex *)tmpV.get());
702d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    mRSC->setRaster((ProgramRaster *)tmpR.get());
703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragment((ProgramFragment *)tmpF.get());
704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
707d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1,
708d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u1, float v1,
709d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x2, float y2, float z2,
710d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u2, float v2,
711d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x3, float y3, float z3,
712d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u3, float v3,
713d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x4, float y4, float z4,
714d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u4, float v4)
715d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
716d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const uint32_t vertsPerQuad = 4;
717d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const uint32_t floatsPerVert = 5;
718d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
719d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
720d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Cull things that are off the screen
721d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float width = (float)mRSC->getWidth();
722d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float height = (float)mRSC->getHeight();
723d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
724d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) {
725d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
726d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
727d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
728d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1);
729d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V1 x: %f y: %f z: %f", x2, y2, z2);
730d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V2 x: %f y: %f z: %f", x3, y3, z3);
731d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/
732d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
733d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x1;
734d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y1;
735d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z1;
736d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u1;
737d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v1;
738d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
739d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x2;
740d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y2;
741d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z2;
742d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u2;
743d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v2;
744d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
745d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x3;
746d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y3;
747d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z3;
748d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u3;
749d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v3;
750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x4;
752d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y4;
753d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z4;
754d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u4;
755d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v4;
756d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
757d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCurrentQuadIndex ++;
758d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
759d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex == mMaxNumberOfQuads) {
760d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
761d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
762d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
763d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
764d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
76501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() {
76601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t remainingCapacity = 0;
76735b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    uint32_t totalPixels = 0;
76801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
76901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk         remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol);
77001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk         totalPixels += mCacheLines[i]->mMaxWidth;
77101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
77201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    remainingCapacity = (remainingCapacity * 100) / totalPixels;
77301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    return remainingCapacity;
77401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
77501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
77601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) {
77701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    // Remaining capacity is measured in %
77801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t remainingCapacity = getRemainingCacheCapacity();
77901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t precacheIdx = 0;
78001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    while(remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) {
78101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]);
78201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        remainingCapacity = getRemainingCacheCapacity();
78301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        precacheIdx ++;
78401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
78501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
78601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
78701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
78809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y,
78909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           uint32_t startIndex, int32_t numGlyphs,
79009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           Font::RenderMode mode,
79109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           Font::Rect *bounds,
79209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH)
793d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
794d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    checkInit();
795d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
796d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Render code here
797d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Font *currentFont = mRSC->getFont();
798a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(!currentFont) {
799a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        if(!mDefault.get()) {
800a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk            mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96));
801a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        }
802a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        currentFont = mDefault.get();
803a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
8043659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    if(!currentFont) {
8053659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        LOGE("Unable to initialize any fonts");
8063659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        return;
8073659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    }
8083659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
80909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs,
81009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           mode, bounds, bitmap, bitmapW, bitmapH);
811d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
812d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex != 0) {
813d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
814d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
815d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
816d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
817d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
81809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) {
81909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds);
820d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
821d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
8229fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) {
823c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[0] = r;
824c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[1] = g;
825c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[2] = b;
826c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[3] = a;
827c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
828c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mGamma = 1.0f;
829c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f;
830c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (luminance <= mBlackThreshold) {
831c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstants.mGamma = mBlackGamma;
832c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else if (luminance >= mWhiteThreshold) {
833c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstants.mGamma = mWhiteGamma;
834c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
8354f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk
836c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstantsDirty = true;
8379fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk}
8389fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk
839ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const {
840c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *r = mConstants.mFontColor[0];
841c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *g = mConstants.mFontColor[1];
842c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *b = mConstants.mFontColor[2];
843c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *a = mConstants.mFontColor[3];
844ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk}
845ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk
846d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::deinit(Context *rsc)
847d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
848a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mInitialized = false;
849a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
85001b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines    mFontShaderFConstant.clear();
85101b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines
852a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mIndexBuffer.clear();
853a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mVertexArray.clear();
854a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
855a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontShaderF.clear();
856a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontSampler.clear();
857a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontProgramStore.clear();
858a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
859a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mTextTexture.clear();
860a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
861a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        delete mCacheLines[i];
862d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
863a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mCacheLines.clear();
864d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
865d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mDefault.clear();
866a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
8673659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    Vector<Font*> fontsToDereference = mActiveFonts;
8683659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    for(uint32_t i = 0; i < fontsToDereference.size(); i ++) {
8693659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        fontsToDereference[i]->zeroUserRef();
8703659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    }
8713659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
872a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(mLibrary) {
873a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        FT_Done_FreeType( mLibrary );
8743659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        mLibrary = NULL;
875a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
876d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
877d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
878d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android {
879d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript {
880d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
881d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi)
882d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
883a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    Font *newFont = Font::create(rsc, name, fontSize, dpi);
884a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(newFont) {
885a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        newFont->incUserRef();
886a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
887a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    return newFont;
888d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
889d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
890d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript
891d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android
892