rsFont.cpp revision 9fc9f0375a92fe22fecb3782b18a5c6060a07290
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"
26d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include FT_BITMAP_H
27d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
28d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/gl.h>
29d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/glext.h>
30d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2.h>
31d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2ext.h>
32d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
33d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android;
34d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android::renderscript;
35d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
36d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL)
37d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
38a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mAllocFile = __FILE__;
39a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mAllocLine = __LINE__;
40d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = false;
41d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mHasKerning = false;
423659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    mFace = NULL;
43d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
44d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool Font::init(const char *name, uint32_t fontSize, uint32_t dpi)
46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mInitialized) {
48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Reinitialization of fonts not supported");
49d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
50d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
51d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
52d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 fontsDir("/fonts/");
53d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 fullPath(getenv("ANDROID_ROOT"));
54d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    fullPath += fontsDir;
55d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    fullPath += name;
56d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
57a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace);
58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(error) {
59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Unable to initialize font %s", fullPath.string());
60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontName = name;
64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontSize = fontSize;
65d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mDpi = dpi;
66d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0);
68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(error) {
69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Unable to set font size on %s", fullPath.string());
70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mHasKerning = FT_HAS_KERNING(mFace);
74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = true;
76d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return true;
77d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
78d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
79d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::invalidateTextureCache()
80d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
81d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
82d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCachedGlyphs.valueAt(i)->mIsValid = false;
83d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
84d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
85d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
86d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y)
87d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
88d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
89d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
90d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    int nPenX = x + glyph->mBitmapLeft;
91d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    int nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
92d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
93d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    state->appendMeshQuad(nPenX, nPenY, 0,
94d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                            glyph->mBitmapMinU, glyph->mBitmapMaxV,
95d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
96d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                            nPenX + (int)glyph->mBitmapWidth, nPenY, 0,
97d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                            glyph->mBitmapMaxU, glyph->mBitmapMaxV,
98d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
99d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                            nPenX + (int)glyph->mBitmapWidth, nPenY - (int)glyph->mBitmapHeight, 0,
100d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                            glyph->mBitmapMaxU, glyph->mBitmapMinV,
101d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
102d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                            nPenX, nPenY - (int)glyph->mBitmapHeight, 0,
103d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                            glyph->mBitmapMinU, glyph->mBitmapMinV);
104d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
105d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
106d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyphs, int x, int y)
107d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
108d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) {
109d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
110d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
111d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
112d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    int penX = x, penY = y;
113d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    int glyphsLeft = 1;
114d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(numGlyphs > 0) {
115d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        glyphsLeft = numGlyphs;
116d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
117d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
118d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t index = start;
119d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t nextIndex = 0;
120d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
121d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    while (glyphsLeft > 0) {
122d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
123d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        int32_t utfChar = utf32_at(text, len, index, &nextIndex);
124d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
125d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Reached the end of the string or encountered
126d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(utfChar < 0) {
127d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
128d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
129d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
130d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Move to the next character in the array
131d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        index = nextIndex;
132d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
133d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar);
134d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
135d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(cachedGlyph == NULL) {
136d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            cachedGlyph = cacheGlyph((uint32_t)utfChar);
137d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
138d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Is the glyph still in texture cache?
139d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(!cachedGlyph->mIsValid) {
140d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            updateGlyphCache(cachedGlyph);
141d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
142d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
143d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
144d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(cachedGlyph->mIsValid) {
145d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            drawCachedGlyph(cachedGlyph, penX, penY);
146d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
147d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
148d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        penX += (cachedGlyph->mAdvance.x >> 6);
149d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
150d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // If we were given a specific number of glyphs, decrement
151d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(numGlyphs > 0) {
152d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            glyphsLeft --;
153d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
154d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
155d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
156d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
157d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph)
158d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
159a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER );
160a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(error) {
161a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        LOGE("Couldn't load glyph.");
162a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        return;
163a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
164d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
165a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mAdvance = mFace->glyph->advance;
166a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapLeft = mFace->glyph->bitmap_left;
167a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapTop = mFace->glyph->bitmap_top;
168d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
169a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    FT_Bitmap *bitmap = &mFace->glyph->bitmap;
170d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
171d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now copy the bitmap into the cache texture
172d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startX = 0;
173d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startY = 0;
174d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
175d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Let the font state figure out where to put the bitmap
176d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
177a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY);
178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
179d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!glyph->mIsValid) {
180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
183a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    uint32_t endX = startX + bitmap->width;
184a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinX = startX;
187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinY = startY;
188a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapWidth = bitmap->width;
189a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    glyph->mBitmapHeight = bitmap->rows;
190d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
192d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheHeight = state->getCacheTextureType()->getDimY();
193d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
194d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinU = (float)startX / (float)cacheWidth;
195d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMinV = (float)startY / (float)cacheHeight;
196d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMaxU = (float)endX / (float)cacheWidth;
197d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glyph->mBitmapMaxV = (float)endY / (float)cacheHeight;
198d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
199d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
200d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph)
201d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
202d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    CachedGlyphInfo *newGlyph = new CachedGlyphInfo();
203d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCachedGlyphs.add(glyph, newGlyph);
204d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
205d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph);
206d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    newGlyph->mIsValid = false;
207d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
208d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    updateGlyphCache(newGlyph);
209d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
210d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return newGlyph;
211d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
213d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi)
214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
215d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts;
216d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
217d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < activeFonts.size(); i ++) {
218d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        Font *ithFont = activeFonts[i];
219d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) {
220d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            return ithFont;
221d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
222d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
223d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
224d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Font *newFont = new Font(rsc);
225d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    bool isInitialized = newFont->init(name, fontSize, dpi);
226d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(isInitialized) {
227d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        activeFonts.push(newFont);
228d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return newFont;
229d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
230d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
231d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    delete newFont;
232d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return NULL;
233d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
234d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
235d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
236d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::~Font()
237d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
238d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mFace) {
239d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        FT_Done_Face(mFace);
240d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
241d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
242d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) {
243d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if (mRSC->mStateFont.mActiveFonts[ct] == this) {
244d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            mRSC->mStateFont.mActiveFonts.removeAt(ct);
245d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
246d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
247d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
248d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
249d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i);
251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        delete glyph;
252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
253d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
255d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::FontState()
256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = false;
258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mMaxNumberOfQuads = 1024;
259d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCurrentQuadIndex = 0;
260d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC = NULL;
2613659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    mLibrary = NULL;
2629fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk    setFontColor(0.0f, 0.0f, 0.0f, 1.0f);
263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
264d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::~FontState()
266d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        delete mCacheLines[i];
269d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
271d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    rsAssert(!mActiveFonts.size());
272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
274a1ccecd965c07c2739f1258989526051a010bdabAlex SakhartchoukFT_Library FontState::getLib()
275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!mLibrary) {
277a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        FT_Error error = FT_Init_FreeType(&mLibrary);
278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(error) {
279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            LOGE("Unable to initialize freetype");
280a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk            return NULL;
281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
2833659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
284a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    return mLibrary;
285a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk}
286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
287a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchoukvoid FontState::init(Context *rsc)
288a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk{
289a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mRSC = rsc;
290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
291d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::flushAllAndInvalidate()
293d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex != 0) {
295d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
296d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
297d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mActiveFonts.size(); i ++) {
299d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mActiveFonts[i]->invalidateTextureCache();
300d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCacheLines[i]->mCurrentCol = 0;
303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
305d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY)
307d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
308d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // If the glyph is too tall, don't cache it
309d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) {
310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return false;
312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now copy the bitmap into the cache texture
315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startX = 0;
316d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t startY = 0;
317d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    bool bitmapFit = false;
319d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(bitmapFit) {
322d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break;
323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
325d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // If the new glyph didn't fit, flush the state so far and invalidate everything
327d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!bitmapFit) {
328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        flushAllAndInvalidate();
329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
330d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // Try to fit it again
331d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
332d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
333d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            if(bitmapFit) {
334d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                break;
335d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            }
336d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
337d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
338d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        // if we still don't fit, something is wrong and we shouldn't draw
339d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        if(!bitmapFit) {
340d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
341d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            return false;
342d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
343d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
344d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
345d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    *retOriginX = startX;
346d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    *retOriginY = startY;
347d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
348d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t endX = startX + bitmap->width;
349d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
350d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
351d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheWidth = getCacheTextureType()->getDimX();
352d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
353d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    unsigned char *cacheBuffer = (unsigned char*)mTextTexture->getPtr();
354d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    unsigned char *bitmapBuffer = bitmap->buffer;
355d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
356d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
357d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) {
358d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) {
359d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            unsigned char tempCol = bitmapBuffer[bY * bitmap->width + bX];
360d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol;
361d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        }
362d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
363d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
364d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // This will dirty the texture and the shader so next time
365d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // we draw it will upload the data
366d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
367d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontShaderF->bindTexture(0, mTextTexture.get());
368d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
369d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Some debug code
370d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    /*for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
371d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        LOGE("Cache Line: H: %u Empty Space: %f",
372d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk             mCacheLines[i]->mMaxHeight,
373d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk              (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f);
374d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
375d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }*/
376d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
377d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    return true;
378d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
379d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
380d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initRenderState()
381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t tmp[5] = {
383d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        RS_TEX_ENV_MODE_REPLACE, 1,
384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        RS_TEX_ENV_MODE_NONE, 0,
385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        0
386d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    };
387d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ProgramFragment *pf = new ProgramFragment(mRSC, tmp, 5);
388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontShaderF.set(pf);
389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontShaderF->init(mRSC);
390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
391d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST,
392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                      RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP);
393d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontSampler.set(sampler);
394d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontShaderF->bindSampler(0, sampler);
395d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ProgramStore *fontStore = new ProgramStore(mRSC);
397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore.set(fontStore);
398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS);
399d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA);
400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDitherEnable(false);
401d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mFontProgramStore->setDepthMask(false);
402d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
403d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initTextTexture()
405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
406d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
407d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // We will allocate a texture to initially hold 32 character bitmaps
409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *texType = new Type(mRSC);
410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setElement(alphaElem);
411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setDimX(1024);
412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->setDimY(256);
413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    texType->compute();
414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *cacheAlloc = new Allocation(mRSC, texType);
416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture.set(cacheAlloc);
417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Split up our cache texture into lines of certain widths
420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    int nextLine = 0;
421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0));
422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0));
430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0));
432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad
435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initVertexArrayBuffers()
436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Now lets write index data
438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *indexType = new Type(mRSC);
440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint32_t numIndicies = mMaxNumberOfQuads * 6;
441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->setDimX(numIndicies);
442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->setElement(indexElem);
443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexType->compute();
444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *indexAlloc = new Allocation(mRSC, indexType);
446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr();
447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Four verts, two triangles , six indices per quad
449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) {
450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        int i6 = i * 6;
451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        int i4 = i * 4;
452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 0] = i4 + 0;
454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 1] = i4 + 1;
455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 2] = i4 + 2;
456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 3] = i4 + 0;
458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 4] = i4 + 2;
459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        indexPtr[i6 + 5] = i4 + 3;
460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    indexAlloc->deferedUploadToBufferObject(mRSC);
463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mIndexBuffer.set(indexAlloc);
464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *elemArray[2];
469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    elemArray[0] = posElem;
470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    elemArray[1] = texElem;
471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
472d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 posName("position");
473d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    String8 texName("texture0");
474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
475d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const char *nameArray[2];
476d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nameArray[0] = posName.string();
477d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    nameArray[1] = texName.string();
478d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t lengths[2];
479d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    lengths[0] = posName.size();
480d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    lengths[1] = texName.size();
481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
482d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const Element *vertexDataElem = Element::create(mRSC, 2, elemArray, nameArray, lengths);
483d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
484d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Type *vertexDataType = new Type(mRSC);
485d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->setDimX(mMaxNumberOfQuads * 4);
486d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->setElement(vertexDataElem);
487d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    vertexDataType->compute();
488d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
489d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType);
490d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mTextMeshPtr = (float*)vertexAlloc->getPtr();
491d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
492d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mVertexArray.set(vertexAlloc);
493d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
494d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
495d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text
496d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::checkInit()
497d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
498d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mInitialized) {
499d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
500d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
501d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
502d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initTextTexture();
503d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initRenderState();
504d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
505d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    initVertexArrayBuffers();
506d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
507d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mInitialized = true;
508d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
509d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
510d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() {
511d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
512d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex());
513d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setVertex(mRSC->getDefaultProgramVertex());
514d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
515d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster());
516d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    mRSC->setRaster(mRSC->getDefaultProgramRaster());
517d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk
518d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment());
519d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragment(mFontShaderF.get());
520d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
521d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore());
522d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragmentStore(mFontProgramStore.get());
523d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
524d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if (!mRSC->setupCheck()) {
525d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setVertex((ProgramVertex *)tmpV.get());
526d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk        mRSC->setRaster((ProgramRaster *)tmpR.get());
527d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setFragment((ProgramFragment *)tmpF.get());
528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *vtx = (float*)mVertexArray->getPtr();
533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *tex = vtx + 3;
534d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    VertexArray va;
536d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    va.add(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "position");
537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    va.add(GL_FLOAT, 2, 20, false, (uint32_t)tex, "texture0");
538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache);
539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mIndexBuffer->uploadCheck(mRSC);
541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0));
543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Reset the state
545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setVertex((ProgramVertex *)tmpV.get());
546d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk    mRSC->setRaster((ProgramRaster *)tmpR.get());
547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragment((ProgramFragment *)tmpF.get());
548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1,
552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u1, float v1,
553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x2, float y2, float z2,
554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u2, float v2,
555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x3, float y3, float z3,
556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u3, float v3,
557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float x4, float y4, float z4,
558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk                                  float u4, float v4)
559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const uint32_t vertsPerQuad = 4;
561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const uint32_t floatsPerVert = 5;
562d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Cull things that are off the screen
565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float width = (float)mRSC->getWidth();
566d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    float height = (float)mRSC->getHeight();
567d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
568d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) {
569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1);
573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V1 x: %f y: %f z: %f", x2, y2, z2);
574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V2 x: %f y: %f z: %f", x3, y3, z3);
575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/
576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x1;
578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y1;
579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z1;
580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u1;
581d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v1;
582d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x2;
584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y2;
585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z2;
586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u2;
587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v2;
588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x3;
590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y3;
591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z3;
592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u3;
593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v3;
594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = x4;
596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = y4;
597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = z4;
598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = u4;
599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    (*currentPos++) = v4;
600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
601d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mCurrentQuadIndex ++;
602d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
603d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex == mMaxNumberOfQuads) {
604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
606d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
609d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, int numGlyphs, int x, int y)
610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
611d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    checkInit();
612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
613a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    //String8 text8(text);
614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    // Render code here
616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    Font *currentFont = mRSC->getFont();
617a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(!currentFont) {
618a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        if(!mDefault.get()) {
619a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk            mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96));
620a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        }
621a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        currentFont = mDefault.get();
622a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
6233659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    if(!currentFont) {
6243659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        LOGE("Unable to initialize any fonts");
6253659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        return;
6263659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    }
6273659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    currentFont->renderUTF(text, len, startIndex, numGlyphs, x, y);
629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
630d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(mCurrentQuadIndex != 0) {
631d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        issueDrawCommand();
632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        mCurrentQuadIndex = 0;
633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::renderText(const char *text, int x, int y)
637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t textLen = strlen(text);
639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    renderText(text, textLen, 0, -1, x, y);
640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
642d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::renderText(Allocation *alloc, int x, int y)
643d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!alloc) {
645d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
646d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
647d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
648d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const char *text = (const char *)alloc->getPtr();
649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t allocSize = alloc->getType()->getSizeBytes();
650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    renderText(text, allocSize, 0, -1, x, y);
651d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
652d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
653d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::renderText(Allocation *alloc, uint32_t start, int len, int x, int y)
654d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
655d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if(!alloc) {
656d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        return;
657d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    const char *text = (const char *)alloc->getPtr();
660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    size_t allocSize = alloc->getType()->getSizeBytes();
661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    renderText(text, allocSize, start, len, x, y);
662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
6649fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) {
6659fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk    mFontColor[0] = r;
6669fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk    mFontColor[1] = g;
6679fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk    mFontColor[2] = b;
6689fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk    mFontColor[3] = a;
6699fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk    mFontColorDirty = true;
6709fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk}
6719fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk
672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::deinit(Context *rsc)
673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
674a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mInitialized = false;
675a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
676a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mIndexBuffer.clear();
677a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mVertexArray.clear();
678a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
679a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontShaderF.clear();
680a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontSampler.clear();
681a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mFontProgramStore.clear();
682a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
683a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mTextTexture.clear();
684a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
685a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        delete mCacheLines[i];
686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    }
687a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    mCacheLines.clear();
688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    mDefault.clear();
690a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk
6913659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    Vector<Font*> fontsToDereference = mActiveFonts;
6923659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    for(uint32_t i = 0; i < fontsToDereference.size(); i ++) {
6933659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        fontsToDereference[i]->zeroUserRef();
6943659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk    }
6953659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk
696a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(mLibrary) {
697a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        FT_Done_FreeType( mLibrary );
6983659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk        mLibrary = NULL;
699a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
701d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
702d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android {
703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript {
704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi)
706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
707a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    Font *newFont = Font::create(rsc, name, fontSize, dpi);
708a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    if(newFont) {
709a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk        newFont->incUserRef();
710a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    }
711a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk    return newFont;
712d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk}
713d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
714d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript
715d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android
716