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