rsFont.cpp revision 071508d9f3d1c004cd9ef8d5329949e7a8a949c8
19b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
29b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk/*
39b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * Copyright (C) 2009 The Android Open Source Project
49b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *
59b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License");
69b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * you may not use this file except in compliance with the License.
79b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * You may obtain a copy of the License at
89b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *
99b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *      http://www.apache.org/licenses/LICENSE-2.0
109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *
119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * Unless required by applicable law or agreed to in writing, software
129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS,
139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * See the License for the specific language governing permissions and
159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * limitations under the License.
169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk */
179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#ifndef ANDROID_RS_BUILD_FOR_HOST
199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include "rsContext.h"
209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#else
219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include "rsContextHostStub.h"
229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#endif
239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include "rsFont.h"
259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include "rsProgramFragment.h"
269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include FT_BITMAP_H
279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include <GLES/gl.h>
299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include <GLES/glext.h>
309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include <GLES2/gl2.h>
319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include <GLES2/gl2ext.h>
329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukusing namespace android;
349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukusing namespace android::renderscript;
359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
369b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL)
379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
38071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mAllocFile = __FILE__;
39071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mAllocLine = __LINE__;
409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mInitialized = false;
419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mHasKerning = false;
429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukbool Font::init(const char *name, uint32_t fontSize, uint32_t dpi)
459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(mInitialized) {
479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        LOGE("Reinitialization of fonts not supported");
489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return false;
499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    String8 fontsDir("/fonts/");
529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    String8 fullPath(getenv("ANDROID_ROOT"));
539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    fullPath += fontsDir;
549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    fullPath += name;
559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
56071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace);
579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(error) {
589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        LOGE("Unable to initialize font %s", fullPath.string());
599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return false;
609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontName = name;
639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontSize = fontSize;
649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mDpi = dpi;
659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    //LOGE("Font initialized: %s", fullPath.string());
679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0);
699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(error) {
709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        LOGE("Unable to set font size on %s", fullPath.string());
719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return false;
729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mHasKerning = FT_HAS_KERNING(mFace);
759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mInitialized = true;
779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    return true;
789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid Font::invalidateTextureCache()
819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        mCachedGlyphs.valueAt(i)->mIsValid = false;
849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y)
889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    int nPenX = x + glyph->mBitmapLeft;
929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    int nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight;
939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    state->appendMeshQuad(nPenX, nPenY, 0,
959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                            glyph->mBitmapMinU, glyph->mBitmapMaxV,
969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                            nPenX + (int)glyph->mBitmapWidth, nPenY, 0,
989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                            glyph->mBitmapMaxU, glyph->mBitmapMaxV,
999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                            nPenX + (int)glyph->mBitmapWidth, nPenY - (int)glyph->mBitmapHeight, 0,
1019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                            glyph->mBitmapMaxU, glyph->mBitmapMinV,
1029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                            nPenX, nPenY - (int)glyph->mBitmapHeight, 0,
1049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                            glyph->mBitmapMinU, glyph->mBitmapMinV);
1059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
1069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyphs, int x, int y)
1089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
1099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) {
1109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return;
1119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
1129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    int penX = x, penY = y;
1149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    int glyphsLeft = 1;
1159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(numGlyphs > 0) {
1169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        glyphsLeft = numGlyphs;
1179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
1189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    size_t index = start;
1209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    size_t nextIndex = 0;
1219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    while (glyphsLeft > 0) {
1239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        int32_t utfChar = utf32_at(text, len, index, &nextIndex);
1259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        // Reached the end of the string or encountered
1279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        if(utfChar < 0) {
1289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            break;
1299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
1309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        // Move to the next character in the array
1329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        index = nextIndex;
1339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar);
1359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        if(cachedGlyph == NULL) {
1379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            cachedGlyph = cacheGlyph((uint32_t)utfChar);
1389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
1399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        // Is the glyph still in texture cache?
1409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        if(!cachedGlyph->mIsValid) {
1419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            updateGlyphCache(cachedGlyph);
1429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
1439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
1459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        if(cachedGlyph->mIsValid) {
1469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            drawCachedGlyph(cachedGlyph, penX, penY);
1479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
1489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        penX += (cachedGlyph->mAdvance.x >> 6);
1509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        // If we were given a specific number of glyphs, decrement
1529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        if(numGlyphs > 0) {
1539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            glyphsLeft --;
1549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
1559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
1569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
1579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph)
1599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
160071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER );
161071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    if(error) {
162071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk        LOGE("Couldn't load glyph.");
163071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk        return;
164071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    }
1659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
166071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    glyph->mAdvance = mFace->glyph->advance;
167071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    glyph->mBitmapLeft = mFace->glyph->bitmap_left;
168071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    glyph->mBitmapTop = mFace->glyph->bitmap_top;
1699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
170071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    FT_Bitmap *bitmap = &mFace->glyph->bitmap;
1719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // Now copy the bitmap into the cache texture
1739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t startX = 0;
1749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t startY = 0;
1759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // Let the font state figure out where to put the bitmap
1779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    FontState *state = &mRSC->mStateFont;
178071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY);
1799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(!glyph->mIsValid) {
1819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return;
1829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
1839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
184071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    uint32_t endX = startX + bitmap->width;
185071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
1869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    glyph->mBitmapMinX = startX;
1889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    glyph->mBitmapMinY = startY;
189071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    glyph->mBitmapWidth = bitmap->width;
190071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    glyph->mBitmapHeight = bitmap->rows;
1919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t cacheWidth = state->getCacheTextureType()->getDimX();
1939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t cacheHeight = state->getCacheTextureType()->getDimY();
1949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
1959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    glyph->mBitmapMinU = (float)startX / (float)cacheWidth;
1969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    glyph->mBitmapMinV = (float)startY / (float)cacheHeight;
1979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    glyph->mBitmapMaxU = (float)endX / (float)cacheWidth;
1989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    glyph->mBitmapMaxV = (float)endY / (float)cacheHeight;
1999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
2009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2019b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph)
2029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
2039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    CachedGlyphInfo *newGlyph = new CachedGlyphInfo();
2049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mCachedGlyphs.add(glyph, newGlyph);
2059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph);
2079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    newGlyph->mIsValid = false;
2089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    //LOGE("Glyph = %c, face index: %u", (unsigned char)glyph, newGlyph->mGlyphIndex);
2109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    updateGlyphCache(newGlyph);
2129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    return newGlyph;
2149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
2159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2169b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi)
2179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
2189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts;
2199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for(uint32_t i = 0; i < activeFonts.size(); i ++) {
2219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        Font *ithFont = activeFonts[i];
2229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        if(ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) {
2239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            return ithFont;
2249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
2259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
2269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    Font *newFont = new Font(rsc);
2289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    bool isInitialized = newFont->init(name, fontSize, dpi);
2299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(isInitialized) {
2309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        activeFonts.push(newFont);
2319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return newFont;
2329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
2339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    delete newFont;
2359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    return NULL;
2369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
2389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2399b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFont::~Font()
2409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
2419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(mFace) {
2429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        FT_Done_Face(mFace);
2439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
2449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) {
2469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        if (mRSC->mStateFont.mActiveFonts[ct] == this) {
2479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            mRSC->mStateFont.mActiveFonts.removeAt(ct);
2489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            break;
2499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
2509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
2519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) {
2539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i);
2549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        delete glyph;
2559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
2569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
2579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2589b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFontState::FontState()
2599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
2609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mInitialized = false;
2619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mMaxNumberOfQuads = 1024;
2629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mCurrentQuadIndex = 0;
2639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mRSC = NULL;
2649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
2659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2669b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFontState::~FontState()
2679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
2689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
2699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        delete mCacheLines[i];
2709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
2719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    rsAssert(!mActiveFonts.size());
2739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
2749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
275071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex SakhartchoukFT_Library FontState::getLib()
2769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
2779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(!mLibrary) {
278071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk        FT_Error error = FT_Init_FreeType(&mLibrary);
2799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        if(error) {
2809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            LOGE("Unable to initialize freetype");
281071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk            return NULL;
2829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
2839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
284071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    return mLibrary;
285071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk}
2869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
287071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchoukvoid FontState::init(Context *rsc)
288071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk{
289071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    //getLib();
2909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
291071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mRSC = rsc;
2929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
2939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
2949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::flushAllAndInvalidate()
2959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
2969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(mCurrentQuadIndex != 0) {
2979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        issueDrawCommand();
2989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        mCurrentQuadIndex = 0;
2999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
3009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for(uint32_t i = 0; i < mActiveFonts.size(); i ++) {
3019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        mActiveFonts[i]->invalidateTextureCache();
3029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
3039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
3049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        mCacheLines[i]->mCurrentCol = 0;
3059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
3069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
3079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY)
3099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
3109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // If the glyph is too tall, don't cache it
3119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) {
3129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
3139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return false;
3149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
3159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // Now copy the bitmap into the cache texture
3179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t startX = 0;
3189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t startY = 0;
3199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    bool bitmapFit = false;
3219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
3229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
3239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        if(bitmapFit) {
3249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            break;
3259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
3269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
3279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // If the new glyph didn't fit, flush the state so far and invalidate everything
3299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(!bitmapFit) {
3309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        flushAllAndInvalidate();
3319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        // Try to fit it again
3339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
3349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY);
3359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            if(bitmapFit) {
3369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                break;
3379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            }
3389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
3399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        // if we still don't fit, something is wrong and we shouldn't draw
3419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        if(!bitmapFit) {
3429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
3439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            return false;
3449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
3459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
3469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    *retOriginX = startX;
3489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    *retOriginY = startY;
3499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t endX = startX + bitmap->width;
3519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t endY = startY + bitmap->rows;
3529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    //LOGE("Bitmap width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows);
3549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t cacheWidth = getCacheTextureType()->getDimX();
3569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    unsigned char *cacheBuffer = (unsigned char*)mTextTexture->getPtr();
3589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    unsigned char *bitmapBuffer = bitmap->buffer;
3599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
3619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) {
3629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) {
3639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            unsigned char tempCol = bitmapBuffer[bY * bitmap->width + bX];
3649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk            cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol;
3659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        }
3669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
3679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // This will dirty the texture and the shader so next time
3699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // we draw it will upload the data
3709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
3719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontShaderF->bindTexture(0, mTextTexture.get());
3729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // Some debug code
3749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    /*for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
3759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        LOGE("Cache Line: H: %u Empty Space: %f",
3769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk             mCacheLines[i]->mMaxHeight,
3779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk              (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f);
3789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }*/
3809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    return true;
3829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
3839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::initRenderState()
3859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
3869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t tmp[5] = {
3879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        RS_TEX_ENV_MODE_REPLACE, 1,
3889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        RS_TEX_ENV_MODE_NONE, 0,
3899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        0
3909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    };
3919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    ProgramFragment *pf = new ProgramFragment(mRSC, tmp, 5);
3929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontShaderF.set(pf);
3939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontShaderF->init(mRSC);
3949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
3959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST,
3969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                                      RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP);
3979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontSampler.set(sampler);
3989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontShaderF->bindSampler(0, sampler);
3999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    ProgramStore *fontStore = new ProgramStore(mRSC);
4019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontProgramStore.set(fontStore);
4029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS);
4039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA);
4049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontProgramStore->setDitherEnable(false);
4059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mFontProgramStore->setDepthMask(false);
4069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
4079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::initTextTexture()
4099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
4109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
4119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // We will allocate a texture to initially hold 32 character bitmaps
4139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    Type *texType = new Type(mRSC);
4149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    texType->setElement(alphaElem);
4159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    texType->setDimX(1024);
4169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    texType->setDimY(256);
4179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    texType->compute();
4189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    Allocation *cacheAlloc = new Allocation(mRSC, texType);
4209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mTextTexture.set(cacheAlloc);
4219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mTextTexture->deferedUploadToTexture(mRSC, false, 0);
4229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // Split up our cache texture into lines of certain widths
4249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    int nextLine = 0;
4259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0));
4269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
4279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0));
4289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
4299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
4309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
4319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0));
4329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
4339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0));
4349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    nextLine += mCacheLines.top()->mMaxHeight;
4359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0));
4369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
4379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad
4399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::initVertexArrayBuffers()
4409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
4419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // Now lets write index data
4429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
4439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    Type *indexType = new Type(mRSC);
4449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint32_t numIndicies = mMaxNumberOfQuads * 6;
4459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    indexType->setDimX(numIndicies);
4469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    indexType->setElement(indexElem);
4479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    indexType->compute();
4489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    Allocation *indexAlloc = new Allocation(mRSC, indexType);
4509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr();
4519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // Four verts, two triangles , six indices per quad
4539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) {
4549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        int i6 = i * 6;
4559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        int i4 = i * 4;
4569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        indexPtr[i6 + 0] = i4 + 0;
4589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        indexPtr[i6 + 1] = i4 + 1;
4599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        indexPtr[i6 + 2] = i4 + 2;
4609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        indexPtr[i6 + 3] = i4 + 0;
4629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        indexPtr[i6 + 4] = i4 + 2;
4639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        indexPtr[i6 + 5] = i4 + 3;
4649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
4659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    indexAlloc->deferedUploadToBufferObject(mRSC);
4679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mIndexBuffer.set(indexAlloc);
4689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
4709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
4719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const Element *elemArray[2];
4739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    elemArray[0] = posElem;
4749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    elemArray[1] = texElem;
4759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    String8 posName("position");
4779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    String8 texName("texture0");
4789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const char *nameArray[2];
4809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    nameArray[0] = posName.string();
4819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    nameArray[1] = texName.string();
4829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    size_t lengths[2];
4839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    lengths[0] = posName.size();
4849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    lengths[1] = texName.size();
4859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const Element *vertexDataElem = Element::create(mRSC, 2, elemArray, nameArray, lengths);
4879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    Type *vertexDataType = new Type(mRSC);
4899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    vertexDataType->setDimX(mMaxNumberOfQuads * 4);
4909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    vertexDataType->setElement(vertexDataElem);
4919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    vertexDataType->compute();
4929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType);
4949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mTextMeshPtr = (float*)vertexAlloc->getPtr();
4959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mVertexArray.set(vertexAlloc);
4979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
4989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
4999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text
5009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::checkInit()
5019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
5029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(mInitialized) {
5039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return;
5049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
5059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    initTextTexture();
5079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    initRenderState();
5089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    initVertexArrayBuffers();
5109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    /*mTextMeshRefs = new ObjectBaseRef<SimpleMesh>[mNumMeshes];
5129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    for(uint32_t i = 0; i < mNumMeshes; i ++){
5149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        SimpleMesh *textMesh = createTextMesh();
5159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        mTextMeshRefs[i].set(textMesh);
5169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }*/
5179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mInitialized = true;
5199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
5209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::issueDrawCommand() {
5229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex());
5249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mRSC->setVertex(mRSC->getDefaultProgramVertex());
5259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment());
5279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mRSC->setFragment(mFontShaderF.get());
5289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore());
5309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mRSC->setFragmentStore(mFontProgramStore.get());
5319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if (!mRSC->setupCheck()) {
5339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        mRSC->setVertex((ProgramVertex *)tmpV.get());
5349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        mRSC->setFragment((ProgramFragment *)tmpF.get());
5359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
5369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return;
5379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
5389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    float *vtx = (float*)mVertexArray->getPtr();
5409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    float *tex = vtx + 3;
5419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    VertexArray va;
5439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    va.add(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "position");
5449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    va.add(GL_FLOAT, 2, 20, false, (uint32_t)tex, "texture0");
5459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache);
5469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mIndexBuffer->uploadCheck(mRSC);
5489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
5499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0));
5509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // Reset the state
5529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mRSC->setVertex((ProgramVertex *)tmpV.get());
5539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mRSC->setFragment((ProgramFragment *)tmpF.get());
5549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mRSC->setFragmentStore((ProgramStore *)tmpPS.get());
5559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
5569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1,
5589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                                  float u1, float v1,
5599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                                  float x2, float y2, float z2,
5609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                                  float u2, float v2,
5619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                                  float x3, float y3, float z3,
5629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                                  float u3, float v3,
5639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                                  float x4, float y4, float z4,
5649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk                                  float u4, float v4)
5659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
5669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const uint32_t vertsPerQuad = 4;
5679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const uint32_t floatsPerVert = 5;
5689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
5699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // Cull things that are off the screen
5719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    float width = (float)mRSC->getWidth();
5729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    float height = (float)mRSC->getHeight();
5739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) {
5759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return;
5769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
5779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1);
5799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    LOGE("V1 x: %f y: %f z: %f", x2, y2, z2);
5809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    LOGE("V2 x: %f y: %f z: %f", x3, y3, z3);
5819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/
5829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = x1;
5849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = y1;
5859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = z1;
5869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = u1;
5879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = v1;
5889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = x2;
5909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = y2;
5919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = z2;
5929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = u2;
5939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = v2;
5949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
5959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = x3;
5969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = y3;
5979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = z3;
5989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = u3;
5999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = v3;
6009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = x4;
6029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = y4;
6039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = z4;
6049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = u4;
6059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    (*currentPos++) = v4;
6069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mCurrentQuadIndex ++;
6089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(mCurrentQuadIndex == mMaxNumberOfQuads) {
6109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        issueDrawCommand();
6119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        mCurrentQuadIndex = 0;
6129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
6139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
6149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, int numGlyphs, int x, int y)
6169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
6179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    checkInit();
6189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
619071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    //String8 text8(text);
6209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    // Render code here
6229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    Font *currentFont = mRSC->getFont();
623071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    if(!currentFont) {
624071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk        if(!mDefault.get()) {
625071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk            mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96));
626071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk        }
627071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk        currentFont = mDefault.get();
628071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    }
6299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    currentFont->renderUTF(text, len, startIndex, numGlyphs, x, y);
6309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(mCurrentQuadIndex != 0) {
6329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        issueDrawCommand();
6339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        mCurrentQuadIndex = 0;
6349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
6359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
6369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::renderText(const char *text, int x, int y)
6389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
6399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    size_t textLen = strlen(text);
6409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    renderText(text, textLen, 0, -1, x, y);
6419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
6429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::renderText(Allocation *alloc, int x, int y)
6449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
6459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(!alloc) {
6469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return;
6479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
6489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const char *text = (const char *)alloc->getPtr();
6509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    size_t allocSize = alloc->getType()->getSizeBytes();
6519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    renderText(text, allocSize, 0, -1, x, y);
6529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
6539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::renderText(Allocation *alloc, uint32_t start, int len, int x, int y)
6559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
6569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    if(!alloc) {
6579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk        return;
6589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
6599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    const char *text = (const char *)alloc->getPtr();
6619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    size_t allocSize = alloc->getType()->getSizeBytes();
6629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    renderText(text, allocSize, start, len, x, y);
6639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
6649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::deinit(Context *rsc)
6669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
667071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mInitialized = false;
668071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk
669071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mIndexBuffer.clear();
670071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mVertexArray.clear();
671071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk
672071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mFontShaderF.clear();
673071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mFontSampler.clear();
674071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mFontProgramStore.clear();
675071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk
676071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mTextTexture.clear();
677071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
678071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk        delete mCacheLines[i];
6799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    }
680071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    mCacheLines.clear();
6819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk    mDefault.clear();
683071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk
684071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    if(mLibrary) {
685071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk        FT_Done_FreeType( mLibrary );
686071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    }
6879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
6889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouknamespace android {
6909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouknamespace renderscript {
6919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
6929b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi)
6939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{
694071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    Font *newFont = Font::create(rsc, name, fontSize, dpi);
695071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    if(newFont) {
696071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk        newFont->incUserRef();
697071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    }
698071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk    return newFont;
6999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk}
7009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk
7019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} // renderscript
7029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} // android
703