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