rsFont.cpp revision 46e45548dc80e801139c9ccc2f2aa927e7f35027
1d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 2d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk/* 3d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Copyright (C) 2009 The Android Open Source Project 4d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * 5d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License"); 6d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * you may not use this file except in compliance with the License. 7d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * You may obtain a copy of the License at 8d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * 9d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * http://www.apache.org/licenses/LICENSE-2.0 10d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * 11d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Unless required by applicable law or agreed to in writing, software 12d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS, 13d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * See the License for the specific language governing permissions and 15d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * limitations under the License. 16d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk */ 17d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 18d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#ifndef ANDROID_RS_BUILD_FOR_HOST 19d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsContext.h" 20d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#else 21d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsContextHostStub.h" 22d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#endif 23d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 24d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsFont.h" 25d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsProgramFragment.h" 26d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include FT_BITMAP_H 27d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 28d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/gl.h> 29d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/glext.h> 30d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2.h> 31d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2ext.h> 32d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 33d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android; 34d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android::renderscript; 35d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 36d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) 37d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 38a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mAllocFile = __FILE__; 39a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mAllocLine = __LINE__; 40d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 41d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = false; 423659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mFace = NULL; 43d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 44d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool Font::init(const char *name, uint32_t fontSize, uint32_t dpi) 46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mInitialized) { 48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 49d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 50d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 51d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 52d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 fontsDir("/fonts/"); 53d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 54d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk fullPath += fontsDir; 55d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk fullPath += name; 56d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 57a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace); 58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(error) { 59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize font %s", fullPath.string()); 60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontName = name; 64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSize = fontSize; 65d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDpi = dpi; 66d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0); 68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(error) { 69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to set font size on %s", fullPath.string()); 70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 76d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 77d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 78d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 79d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::invalidateTextureCache() 80d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 81d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 82d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 83d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 84d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 85d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 86d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y) 87d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 88d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 89d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 90d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk int nPenX = x + glyph->mBitmapLeft; 91d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk int nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 92d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 93d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, 94d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU, glyph->mBitmapMaxV, 95d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 96d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nPenX + (int)glyph->mBitmapWidth, nPenY, 0, 97d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU, glyph->mBitmapMaxV, 98d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 99d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nPenX + (int)glyph->mBitmapWidth, nPenY - (int)glyph->mBitmapHeight, 0, 100d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU, glyph->mBitmapMinV, 101d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 102d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nPenX, nPenY - (int)glyph->mBitmapHeight, 0, 103d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU, glyph->mBitmapMinV); 104d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 105d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 106d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyphs, int x, int y) 107d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 108d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 109d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 110d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 111d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 112d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk int penX = x, penY = y; 113d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk int glyphsLeft = 1; 114d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(numGlyphs > 0) { 115d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft = numGlyphs; 116d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 117d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 118d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t index = start; 119d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t nextIndex = 0; 120d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 121d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk while (glyphsLeft > 0) { 122d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 123d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk int32_t utfChar = utf32_at(text, len, index, &nextIndex); 124d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 125d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reached the end of the string or encountered 126d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(utfChar < 0) { 127d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 128d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 129d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 130d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Move to the next character in the array 131d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk index = nextIndex; 132d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 13301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 134d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 135d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 136d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(cachedGlyph->mIsValid) { 137d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 138d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 139d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 140d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk penX += (cachedGlyph->mAdvance.x >> 6); 141d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 142d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 143d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(numGlyphs > 0) { 144d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft --; 145d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 146d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 147d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 148d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 14901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 15001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 15101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 15201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk if(cachedGlyph == NULL) { 15301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 15401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 15501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Is the glyph still in texture cache? 15601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk if(!cachedGlyph->mIsValid) { 15701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk updateGlyphCache(cachedGlyph); 15801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 15901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 16001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return cachedGlyph; 16101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 16201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 163d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) 164d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 165a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 166a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(error) { 167a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk LOGE("Couldn't load glyph."); 168a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return; 169a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 170d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 171a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mAdvance = mFace->glyph->advance; 172a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 173a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 174d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 175a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 176d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 177d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 179d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Let the font state figure out where to put the bitmap 182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 183a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!glyph->mIsValid) { 186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 189a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endX = startX + bitmap->width; 190a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endY = startY + bitmap->rows; 191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 192d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinX = startX; 193d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinY = startY; 194a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 195a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 196d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 197d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 198d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 199d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 200d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 201d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 202d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 203d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 204d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 205d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 206d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) 207d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 208d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 209d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 210d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 211d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mIsValid = false; 213d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk updateGlyphCache(newGlyph); 215d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 216d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newGlyph; 217d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 218d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 219d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi) 220d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 22135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk rsc->mStateFont.checkInit(); 222d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 223d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 224d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < activeFonts.size(); i ++) { 225d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *ithFont = activeFonts[i]; 226d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 227d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return ithFont; 228d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 229d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 230d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 231d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *newFont = new Font(rsc); 232d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi); 233d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(isInitialized) { 234d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk activeFonts.push(newFont); 23501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 236d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newFont; 237d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 238d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 239d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete newFont; 240d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return NULL; 241d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 242d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 243d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 244d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::~Font() 245d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 246d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mFace) { 247d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FT_Done_Face(mFace); 248d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 249d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (mRSC->mStateFont.mActiveFonts[ct] == this) { 252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->mStateFont.mActiveFonts.removeAt(ct); 253d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 255d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 259d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete glyph; 260d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 261d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 262d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::FontState() 264d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 266d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mMaxNumberOfQuads = 1024; 267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC = NULL; 2693659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 270ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 271d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::~FontState() 274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 280d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 282a1ccecd965c07c2739f1258989526051a010bdabAlex SakhartchoukFT_Library FontState::getLib() 283d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 284d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!mLibrary) { 285a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(error) { 287d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize freetype"); 288a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return NULL; 289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 2913659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 292a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 293a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 295a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchoukvoid FontState::init(Context *rsc) 296a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk{ 297a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 299d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 300d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::flushAllAndInvalidate() 301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex != 0) { 303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 305d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mActiveFonts.size(); i ++) { 307d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 308d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 309d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) 315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 316d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 317d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 319d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 322d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 325d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 327d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(bitmapFit) { 330d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 331d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 332d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 333d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 334d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 335d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!bitmapFit) { 336d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 337d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 338d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 339d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 340d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 341d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(bitmapFit) { 342d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 343d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 344d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 345d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 346d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 347d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!bitmapFit) { 348d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 349d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 350d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 351d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 352d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 353d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 354d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 355d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 356d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 357d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 358d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 359d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 360d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 361d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk unsigned char *cacheBuffer = (unsigned char*)mTextTexture->getPtr(); 362d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk unsigned char *bitmapBuffer = bitmap->buffer; 363d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 364d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 365d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 366d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 367d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk unsigned char tempCol = bitmapBuffer[bY * bitmap->width + bX]; 368d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 369d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 370d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 371d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 372d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 373d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 374d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 375d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF->bindTexture(0, mTextTexture.get()); 376d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 377d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 378d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 379d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 380d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 383d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 386d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 387d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initRenderState() 389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 3906445e5210c6d7f8689e94be9026153d017c9545bJason Sams uint32_t tmp[] = { 391d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk RS_TEX_ENV_MODE_REPLACE, 1, 392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk RS_TEX_ENV_MODE_NONE, 0, 3936445e5210c6d7f8689e94be9026153d017c9545bJason Sams 0, 0 394d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }; 3956445e5210c6d7f8689e94be9026153d017c9545bJason Sams ProgramFragment *pf = new ProgramFragment(mRSC, tmp, 6); 396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF->init(mRSC); 398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 399d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 401d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSampler.set(sampler); 402d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF->bindSampler(0, sampler); 403d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore.set(fontStore); 406d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 407d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initTextTexture() 413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Type *texType = new Type(mRSC); 418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->setElement(alphaElem); 419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->setDimX(1024); 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->setDimY(256); 421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->compute(); 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *cacheAlloc = new Allocation(mRSC, texType); 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk int nextLine = 0; 429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 43301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 43401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initVertexArrayBuffers() 446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Type *indexType = new Type(mRSC); 450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexType->setDimX(numIndicies); 452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexType->setElement(indexElem); 453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexType->compute(); 454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *indexAlloc = new Allocation(mRSC, indexType); 456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk int i6 = i * 6; 461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk int i4 = i * 4; 462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 472d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 473d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 475d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 476d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 477d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 478d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *elemArray[2]; 479d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk elemArray[0] = posElem; 480d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk elemArray[1] = texElem; 481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 482d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 posName("position"); 483d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 texName("texture0"); 484d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 485d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const char *nameArray[2]; 486d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nameArray[0] = posName.string(); 487d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nameArray[1] = texName.string(); 488d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t lengths[2]; 489d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk lengths[0] = posName.size(); 490d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk lengths[1] = texName.size(); 49146e45548dc80e801139c9ccc2f2aa927e7f35027Jason Sams uint32_t arraySizes[2] = {1, 1}; 492d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 49346e45548dc80e801139c9ccc2f2aa927e7f35027Jason Sams const Element *vertexDataElem = Element::create(mRSC, 2, elemArray, nameArray, lengths, arraySizes); 494d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 495d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Type *vertexDataType = new Type(mRSC); 496d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk vertexDataType->setDimX(mMaxNumberOfQuads * 4); 497d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk vertexDataType->setElement(vertexDataElem); 498d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk vertexDataType->compute(); 499d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 500d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType); 501d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 502d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 503d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mVertexArray.set(vertexAlloc); 504d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 505d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 506d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 507d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::checkInit() 508d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 509d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mInitialized) { 510d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 511d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 512d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 513d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 514d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 515d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 516d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 517d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 51835b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 51935b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 52035b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 52135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 52235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("0123456789"); 52335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk 524d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 525d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 526d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 527d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex()); 530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex(mRSC->getDefaultProgramVertex()); 531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 532d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster()); 533d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster(mRSC->getDefaultProgramRaster()); 534d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk 535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment()); 536d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment(mFontShaderF.get()); 537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore()); 539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore(mFontProgramStore.get()); 540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 541ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk if(mFontColorDirty) { 542ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk mFontShaderF->setConstantColor(mFontColor[0], mFontColor[1], mFontColor[2], mFontColor[3]); 543ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk mFontColorDirty = false; 544ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 545ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 546d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 548d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *tex = vtx + 3; 556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk VertexArray va; 558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk va.add(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "position"); 559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk va.add(GL_FLOAT, 2, 20, false, (uint32_t)tex, "texture0"); 560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 562d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 566d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reset the state 567d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 568d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u1, float v1, 575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x2, float y2, float z2, 576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u2, float v2, 577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x3, float y3, float z3, 578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u3, float v3, 579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x4, float y4, float z4, 580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u4, float v4) 581d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 582d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t floatsPerVert = 5; 584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Cull things that are off the screen 587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float width = (float)mRSC->getWidth(); 588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float height = (float)mRSC->getHeight(); 589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 601d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 602d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 603d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 606d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 609d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 611d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 613d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 618d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 619d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 620d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 621d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 622d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex == mMaxNumberOfQuads) { 626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 627d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 630d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 63101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 63201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 63335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 63401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 63501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 63601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 63701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 63801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 63901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 64001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 64101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 64201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 64301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 64401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 64501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 64601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk while(remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 64701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 64801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 64901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 65001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 65101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 65201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 65301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 654d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, int numGlyphs, int x, int y) 655d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 656d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 657d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 660a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(!currentFont) { 661a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(!mDefault.get()) { 662a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96)); 663a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 664a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk currentFont = mDefault.get(); 665a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 6663659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk if(!currentFont) { 6673659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk LOGE("Unable to initialize any fonts"); 6683659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk return; 6693659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 6703659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk currentFont->renderUTF(text, len, startIndex, numGlyphs, x, y); 672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex != 0) { 674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 675d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 676d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 678d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::renderText(const char *text, int x, int y) 680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t textLen = strlen(text); 682d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk renderText(text, textLen, 0, -1, x, y); 683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::renderText(Allocation *alloc, int x, int y) 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!alloc) { 688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const char *text = (const char *)alloc->getPtr(); 692d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t allocSize = alloc->getType()->getSizeBytes(); 693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk renderText(text, allocSize, 0, -1, x, y); 694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::renderText(Allocation *alloc, uint32_t start, int len, int x, int y) 697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 698d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!alloc) { 699d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 701d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 702d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const char *text = (const char *)alloc->getPtr(); 703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t allocSize = alloc->getType()->getSizeBytes(); 704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk renderText(text, allocSize, start, len, x, y); 705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 7079fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 7089fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk mFontColor[0] = r; 7099fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk mFontColor[1] = g; 7109fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk mFontColor[2] = b; 7119fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk mFontColor[3] = a; 7129fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk mFontColorDirty = true; 7139fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk} 7149fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk 715ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 716ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk *r = mFontColor[0]; 717ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk *g = mFontColor[1]; 718ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk *b = mFontColor[2]; 719ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk *a = mFontColor[3]; 720ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk} 721ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 722d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::deinit(Context *rsc) 723d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 724a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mInitialized = false; 725a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 726a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mIndexBuffer.clear(); 727a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mVertexArray.clear(); 728a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 729a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontShaderF.clear(); 730a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontSampler.clear(); 731a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontProgramStore.clear(); 732a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 733a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mTextTexture.clear(); 734a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 735a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk delete mCacheLines[i]; 736d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 737a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mCacheLines.clear(); 738d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 739d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDefault.clear(); 740a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 7413659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk Vector<Font*> fontsToDereference = mActiveFonts; 7423659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk for(uint32_t i = 0; i < fontsToDereference.size(); i ++) { 7433659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk fontsToDereference[i]->zeroUserRef(); 7443659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 7453659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 746a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(mLibrary) { 747a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Done_FreeType( mLibrary ); 7483659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 749a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 752d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android { 753d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript { 754d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 755d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi) 756d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 757a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 758a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(newFont) { 759a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk newFont->incUserRef(); 760a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 761a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return newFont; 762d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 763d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 764d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript 765d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android 766