rsFont.cpp revision 7ffcaf20cbb115326f3d72a983835d6c314a4cef
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;
342ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk    setFontColor(0.1f, 0.1f, 0.1f, 1.0f);
343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the renderer properties
345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    char property[PROPERTY_VALUE_MAX];
346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the gamma
348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    float gamma = DEFAULT_TEXT_GAMMA;
349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) {
350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Setting text gamma to %s", property);
351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        gamma = atof(property);
352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else {
353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA);
354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
356c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the black gamma threshold
35709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) {
359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Setting text black gamma threshold to %s", property);
360c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        blackThreshold = atoi(property);
361c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else {
362c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Using default text black gamma threshold of %d",
363c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk                DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD);
364c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
365c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mBlackThreshold = (float)(blackThreshold) / 255.0f;
366c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
367c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Get the white gamma threshold
36809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
369c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) {
370c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Setting text white gamma threshold to %s", property);
371c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        whiteThreshold = atoi(property);
372c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else {
373c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        LOGD("  Using default white black gamma threshold of %d",
374c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk                DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD);
375c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
376c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mWhiteThreshold = (float)(whiteThreshold) / 255.0f;
377c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
378c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    // Compute the gamma tables
379c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mBlackGamma = gamma;
380c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mWhiteGamma = 1.0f / gamma;
381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
383d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::~FontState()
384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
386d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        delete mCacheLines[i];
387d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    rsAssert(!mActiveFonts.size());
390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
391d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
392a1ccecd965c07c2739f1258989526051a010bdabAlex SakhartchoukFT_Library FontState::getLib()
393d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
394d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!mLibrary) {
395a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        FT_Error error = FT_Init_FreeType(&mLibrary);
396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(error) {
397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            LOGE("Unable to initialize freetype");
398a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk            return NULL;
399d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
4013659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
402a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    return mLibrary;
403a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk}
404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
405a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchoukvoid FontState::init(Context *rsc)
406a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk{
407a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mRSC = rsc;
408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::flushAllAndInvalidate()
411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex != 0) {
413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mActiveFonts.size(); i ++) {
417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mActiveFonts[i]->invalidateTextureCache();
418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCacheLines[i]->mCurrentCol = 0;
421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY)
425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // If the glyph is too tall, don't cache it
427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) {
428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now copy the bitmap into the cache texture
433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startX = 0;
434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startY = 0;
435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    bool bitmapFit = false;
437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(bitmapFit) {
440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // If the new glyph didn't fit, flush the state so far and invalidate everything
445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!bitmapFit) {
446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        flushAllAndInvalidate();
447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Try to fit it again
449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            if(bitmapFit) {
452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                break;
453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            }
454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // if we still don't fit, something is wrong and we shouldn't draw
457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(!bitmapFit) {
458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            return false;
460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    *retOriginX = startX;
464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    *retOriginY = startY;
465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t endX = startX + bitmap->width;
467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheWidth = getCacheTextureType()->getDimX();
470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
47109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr();
47209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    uint8_t *bitmapBuffer = bitmap->buffer;
473d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
475d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) {
476d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) {
47709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk            uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX];
478d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol;
479d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
480d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
482d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // This will dirty the texture and the shader so next time
483d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // we draw it will upload the data
484d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
485383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get());
486d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
487d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Some debug code
488d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    /*for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
489d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Cache Line: H: %u Empty Space: %f",
490d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk             mCacheLines[i]->mMaxHeight,
491d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk              (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f);
492d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
493d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }*/
494d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
495d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return true;
496d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
497d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
498d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initRenderState()
499d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
5007ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk    String8 shaderString("varying vec2 varTex0;\n");
501e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("void main() {\n");
502e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  lowp vec4 col = UNI_Color;\n");
503e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n");
504c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    shaderString.append("  col.a = pow(col.a, UNI_Gamma);\n");
505e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("  gl_FragColor = col;\n");
506e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    shaderString.append("}\n");
507e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
508e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
509c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
510e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mRSC->mStateElement.elementBuilderBegin();
511e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1);
512c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1);
513e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC);
514e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
515e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    Type *inputType = new Type(mRSC);
516e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    inputType->setElement(constInput);
517e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    inputType->setDimX(1);
518e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    inputType->compute();
519e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
520e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    uint32_t tmp[4];
521e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
522e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[1] = (uint32_t)inputType;
523e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT;
524e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    tmp[3] = 1;
525e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk
526e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    mFontShaderFConstant.set(new Allocation(mRSC, inputType));
527e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk    ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(),
528e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk                                              shaderString.length(), tmp, 4);
529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontShaderF.set(pf);
530383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0);
531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST,
533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                      RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP);
534d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontSampler.set(sampler);
535383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk    mFontShaderF->bindSampler(mRSC, 0, sampler);
536d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ProgramStore *fontStore = new ProgramStore(mRSC);
538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore.set(fontStore);
539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS);
540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA);
541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDitherEnable(false);
542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDepthMask(false);
543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initTextTexture()
546d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // We will allocate a texture to initially hold 32 character bitmaps
550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *texType = new Type(mRSC);
551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setElement(alphaElem);
552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setDimX(1024);
553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setDimY(256);
554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->compute();
555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *cacheAlloc = new Allocation(mRSC, texType);
557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture.set(cacheAlloc);
558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Split up our cache texture into lines of certain widths
56109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    int32_t nextLine = 0;
562d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0));
563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
56601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
56701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
568d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0));
573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0));
575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad
578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initVertexArrayBuffers()
579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now lets write index data
581d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
582d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *indexType = new Type(mRSC);
583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t numIndicies = mMaxNumberOfQuads * 6;
584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->setDimX(numIndicies);
585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->setElement(indexElem);
586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->compute();
587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *indexAlloc = new Allocation(mRSC, indexType);
589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr();
590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Four verts, two triangles , six indices per quad
592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) {
59309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        int32_t i6 = i * 6;
59409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk        int32_t i4 = i * 4;
595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 0] = i4 + 0;
597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 1] = i4 + 1;
598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 2] = i4 + 2;
599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 3] = i4 + 0;
601d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 4] = i4 + 2;
602d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 5] = i4 + 3;
603d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexAlloc->deferedUploadToBufferObject(mRSC);
606d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mIndexBuffer.set(indexAlloc);
607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
609d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
611d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *elemArray[2];
612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    elemArray[0] = posElem;
613d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    elemArray[1] = texElem;
614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 posName("position");
616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 texName("texture0");
617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
618d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const char *nameArray[2];
619d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nameArray[0] = posName.string();
620d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nameArray[1] = texName.string();
621d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t lengths[2];
622d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    lengths[0] = posName.size();
623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    lengths[1] = texName.size();
62446e45548dc80e801139c9ccc2f2aa927e7f35027Jason Sams    uint32_t arraySizes[2] = {1, 1};
625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
62646e45548dc80e801139c9ccc2f2aa927e7f35027Jason Sams    const Element *vertexDataElem = Element::create(mRSC, 2, elemArray, nameArray, lengths, arraySizes);
627d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *vertexDataType = new Type(mRSC);
629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->setDimX(mMaxNumberOfQuads * 4);
630d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->setElement(vertexDataElem);
631d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->compute();
632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType);
634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextMeshPtr = (float*)vertexAlloc->getPtr();
635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mVertexArray.set(vertexAlloc);
637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text
640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::checkInit()
641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
642d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mInitialized) {
643d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
645d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
646d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initTextTexture();
647d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initRenderState();
648d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initVertexArrayBuffers();
650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
65135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    // We store a string with letters in a rough frequency of occurrence
65235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq");
65335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ");
65435b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8(",.?!()-+@;:`'");
65535b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    mLatinPrecache += String8("0123456789");
65635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk
657d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = true;
658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() {
661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex());
663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setVertex(mRSC->getDefaultProgramVertex());
664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
665d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster());
666d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    mRSC->setRaster(mRSC->getDefaultProgramRaster());
667d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk
668d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment());
669d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragment(mFontShaderF.get());
670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore());
672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragmentStore(mFontProgramStore.get());
673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
674c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if(mConstantsDirty) {
675c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants));
676c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstantsDirty = false;
677ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk    }
678ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk
679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if (!mRSC->setupCheck()) {
680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setVertex((ProgramVertex *)tmpV.get());
681d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk        mRSC->setRaster((ProgramRaster *)tmpR.get());
682d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setFragment((ProgramFragment *)tmpF.get());
683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *vtx = (float*)mVertexArray->getPtr();
688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *tex = vtx + 3;
689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    VertexArray va;
691886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk    va.add(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position");
692886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk    va.add(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0");
693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache);
694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mIndexBuffer->uploadCheck(mRSC);
696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0));
698d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
699d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Reset the state
700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setVertex((ProgramVertex *)tmpV.get());
701d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    mRSC->setRaster((ProgramRaster *)tmpR.get());
702d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragment((ProgramFragment *)tmpF.get());
703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1,
707d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u1, float v1,
708d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x2, float y2, float z2,
709d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u2, float v2,
710d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x3, float y3, float z3,
711d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u3, float v3,
712d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x4, float y4, float z4,
713d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u4, float v4)
714d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
715d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const uint32_t vertsPerQuad = 4;
716d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const uint32_t floatsPerVert = 5;
717d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
718d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
719d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Cull things that are off the screen
720d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float width = (float)mRSC->getWidth();
721d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float height = (float)mRSC->getHeight();
722d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
723d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) {
724d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
725d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
726d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
727d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1);
728d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V1 x: %f y: %f z: %f", x2, y2, z2);
729d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V2 x: %f y: %f z: %f", x3, y3, z3);
730d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/
731d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
732d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x1;
733d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y1;
734d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z1;
735d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u1;
736d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v1;
737d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
738d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x2;
739d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y2;
740d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z2;
741d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u2;
742d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v2;
743d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
744d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x3;
745d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y3;
746d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z3;
747d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u3;
748d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v3;
749d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x4;
751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y4;
752d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z4;
753d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u4;
754d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v4;
755d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
756d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCurrentQuadIndex ++;
757d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
758d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex == mMaxNumberOfQuads) {
759d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
760d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
761d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
762d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
763d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
76401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() {
76501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t remainingCapacity = 0;
76635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk    uint32_t totalPixels = 0;
76701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
76801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk         remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol);
76901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk         totalPixels += mCacheLines[i]->mMaxWidth;
77001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
77101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    remainingCapacity = (remainingCapacity * 100) / totalPixels;
77201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    return remainingCapacity;
77301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
77401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
77501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) {
77601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    // Remaining capacity is measured in %
77701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t remainingCapacity = getRemainingCacheCapacity();
77801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    uint32_t precacheIdx = 0;
77901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    while(remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) {
78001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]);
78101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        remainingCapacity = getRemainingCacheCapacity();
78201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk        precacheIdx ++;
78301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk    }
78401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk}
78501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
78601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk
78709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y,
78809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           uint32_t startIndex, int32_t numGlyphs,
78909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           Font::RenderMode mode,
79009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           Font::Rect *bounds,
79109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH)
792d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
793d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    checkInit();
794d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
795d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Render code here
796d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Font *currentFont = mRSC->getFont();
797a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(!currentFont) {
798a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        if(!mDefault.get()) {
799a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk            mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96));
800a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        }
801a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        currentFont = mDefault.get();
802a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
8033659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    if(!currentFont) {
8043659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        LOGE("Unable to initialize any fonts");
8053659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        return;
8063659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    }
8073659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
80809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs,
80909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk                           mode, bounds, bitmap, bitmapW, bitmapH);
810d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
811d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex != 0) {
812d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
813d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
814d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
815d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
816d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
81709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) {
81809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk    renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds);
819d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
820d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
8219fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) {
822c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[0] = r;
823c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[1] = g;
824c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[2] = b;
825c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mFontColor[3] = a;
826c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk
827c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstants.mGamma = 1.0f;
828c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f;
829c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    if (luminance <= mBlackThreshold) {
830c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstants.mGamma = mBlackGamma;
831c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    } else if (luminance >= mWhiteThreshold) {
832c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk        mConstants.mGamma = mWhiteGamma;
833c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    }
834c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    mConstantsDirty = true;
8359fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk}
8369fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk
837ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const {
838c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *r = mConstants.mFontColor[0];
839c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *g = mConstants.mFontColor[1];
840c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *b = mConstants.mFontColor[2];
841c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk    *a = mConstants.mFontColor[3];
842ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk}
843ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk
844d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::deinit(Context *rsc)
845d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
846a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mInitialized = false;
847a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
84801b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines    mFontShaderFConstant.clear();
84901b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines
850a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mIndexBuffer.clear();
851a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mVertexArray.clear();
852a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
853a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontShaderF.clear();
854a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontSampler.clear();
855a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontProgramStore.clear();
856a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
857a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mTextTexture.clear();
858a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
859a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        delete mCacheLines[i];
860d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
861a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mCacheLines.clear();
862d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
863d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mDefault.clear();
864a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
8653659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    Vector<Font*> fontsToDereference = mActiveFonts;
8663659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    for(uint32_t i = 0; i < fontsToDereference.size(); i ++) {
8673659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        fontsToDereference[i]->zeroUserRef();
8683659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    }
8693659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
870a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(mLibrary) {
871a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        FT_Done_FreeType( mLibrary );
8723659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        mLibrary = NULL;
873a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
874d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
875d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
876d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android {
877d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript {
878d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
879d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi)
880d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
881a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    Font *newFont = Font::create(rsc, name, fontSize, dpi);
882a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(newFont) {
883a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        newFont->incUserRef();
884a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
885a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    return newFont;
886d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
887d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
888d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript
889d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android
890