rsFont.cpp revision 94bbccc36322168a596369c8341dad938c8f949f
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; 42b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mFace = NULL; 439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukbool Font::init(const char *name, uint32_t fontSize, uint32_t dpi) 469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(mInitialized) { 489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk String8 fontsDir("/fonts/"); 539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk fullPath += fontsDir; 559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk fullPath += name; 569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 57071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace); 589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(error) { 599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Unable to initialize font %s", fullPath.string()); 609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontName = name; 649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontSize = fontSize; 659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mDpi = dpi; 669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0); 689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(error) { 699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Unable to set font size on %s", fullPath.string()); 709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = true; 769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return true; 779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid Font::invalidateTextureCache() 809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y) 879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk int nPenX = x + glyph->mBitmapLeft; 919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk int nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, 949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinU, glyph->mBitmapMaxV, 959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nPenX + (int)glyph->mBitmapWidth, nPenY, 0, 979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMaxU, glyph->mBitmapMaxV, 989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nPenX + (int)glyph->mBitmapWidth, nPenY - (int)glyph->mBitmapHeight, 0, 1009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMaxU, glyph->mBitmapMinV, 1019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nPenX, nPenY - (int)glyph->mBitmapHeight, 0, 1039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinU, glyph->mBitmapMinV); 1049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 1059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, uint32_t start, int numGlyphs, int x, int y) 1079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 1089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 1099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 1109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk int penX = x, penY = y; 1139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk int glyphsLeft = 1; 1149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(numGlyphs > 0) { 1159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyphsLeft = numGlyphs; 1169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t index = start; 1199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t nextIndex = 0; 1209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk while (glyphsLeft > 0) { 1229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk int32_t utfChar = utf32_at(text, len, index, &nextIndex); 1249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Reached the end of the string or encountered 1269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(utfChar < 0) { 1279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 1289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Move to the next character in the array 1319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk index = nextIndex; 1329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 13394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 1349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 1369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(cachedGlyph->mIsValid) { 1379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 1389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk penX += (cachedGlyph->mAdvance.x >> 6); 1419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 1439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(numGlyphs > 0) { 1449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyphsLeft --; 1459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 1489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 14994bbccc36322168a596369c8341dad938c8f949fAlex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 15094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 15194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 15294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk if(cachedGlyph == NULL) { 15394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 15494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 15594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk // Is the glyph still in texture cache? 15694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk if(!cachedGlyph->mIsValid) { 15794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk updateGlyphCache(cachedGlyph); 15894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 15994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 16094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk return cachedGlyph; 16194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk} 16294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 1639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) 1649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 165071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 166071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk if(error) { 167071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk LOGE("Couldn't load glyph."); 168071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return; 169071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 1709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 171071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mAdvance = mFace->glyph->advance; 172071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 173071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 1749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 175071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 1769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now copy the bitmap into the cache texture 1789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startX = 0; 1799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startY = 0; 1809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Let the font state figure out where to put the bitmap 1829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 183071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 1849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(!glyph->mIsValid) { 1869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 1879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 189071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 190071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 1919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinX = startX; 1939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinY = startY; 194071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 195071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 1969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 1989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 1999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 2019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 2029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 2039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 2049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2069b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) 2079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 2089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 2099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 2109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 2129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk newGlyph->mIsValid = false; 2139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk updateGlyphCache(newGlyph); 2159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return newGlyph; 2179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2199b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi) 2209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 2219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 2229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(uint32_t i = 0; i < activeFonts.size(); i ++) { 2249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *ithFont = activeFonts[i]; 2259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 2269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return ithFont; 2279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *newFont = new Font(rsc); 2319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi); 2329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(isInitialized) { 2339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk activeFonts.push(newFont); 23494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 2359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return newFont; 2369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk delete newFont; 2399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return NULL; 2409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2439b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFont::~Font() 2449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 2459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(mFace) { 2469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FT_Done_Face(mFace); 2479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 2509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if (mRSC->mStateFont.mActiveFonts[ct] == this) { 2519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->mStateFont.mActiveFonts.removeAt(ct); 2529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 2539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 2579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 2589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk delete glyph; 2599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2629b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFontState::FontState() 2639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 2649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = false; 2659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mMaxNumberOfQuads = 1024; 2669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 2679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC = NULL; 268b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mLibrary = NULL; 26955e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 2709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2729b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukFontState::~FontState() 2739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 2749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 2759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk delete mCacheLines[i]; 2769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 2799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 281071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex SakhartchoukFT_Library FontState::getLib() 2829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 2839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(!mLibrary) { 284071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 2859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(error) { 2869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Unable to initialize freetype"); 287071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return NULL; 2889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 290b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 291071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return mLibrary; 292071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk} 2939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 294071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchoukvoid FontState::init(Context *rsc) 295071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk{ 296071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mRSC = rsc; 2979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::flushAllAndInvalidate() 3009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 3019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(mCurrentQuadIndex != 0) { 3029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 3039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 3049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(uint32_t i = 0; i < mActiveFonts.size(); i ++) { 3069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 3079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 3099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 3109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) 3149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 3159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If the glyph is too tall, don't cache it 3169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 3179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 3189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 3199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now copy the bitmap into the cache texture 3229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startX = 0; 3239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startY = 0; 3249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bool bitmapFit = false; 3269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 3279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 3289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(bitmapFit) { 3299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 3309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 3349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(!bitmapFit) { 3359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk flushAllAndInvalidate(); 3369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Try to fit it again 3389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 3399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 3409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(bitmapFit) { 3419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 3429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 3469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(!bitmapFit) { 3479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 3489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 3499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *retOriginX = startX; 3539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *retOriginY = startY; 3549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 3569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 3579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 3599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk unsigned char *cacheBuffer = (unsigned char*)mTextTexture->getPtr(); 3619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk unsigned char *bitmapBuffer = bitmap->buffer; 3629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 3649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 3659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 3669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk unsigned char tempCol = bitmapBuffer[bY * bitmap->width + bX]; 3679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 3689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // This will dirty the texture and the shader so next time 3729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // we draw it will upload the data 3739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 3749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontShaderF->bindTexture(0, mTextTexture.get()); 3759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Some debug code 3779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk /*for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 3789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 3799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 3809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 3819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk }*/ 3839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return true; 3859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::initRenderState() 3889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 389442a647424e6537e94341654e3ae5d52efd84862Jason Sams uint32_t tmp[] = { 3909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk RS_TEX_ENV_MODE_REPLACE, 1, 3919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk RS_TEX_ENV_MODE_NONE, 0, 392442a647424e6537e94341654e3ae5d52efd84862Jason Sams 0, 0 3939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk }; 394442a647424e6537e94341654e3ae5d52efd84862Jason Sams ProgramFragment *pf = new ProgramFragment(mRSC, tmp, 6); 3959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontShaderF.set(pf); 3969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontShaderF->init(mRSC); 3979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 3999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 4009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontSampler.set(sampler); 4019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontShaderF->bindSampler(0, sampler); 4029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 4049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore.set(fontStore); 4059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 4069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 4079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 4089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 4099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 4109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::initTextTexture() 4129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 4139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 4149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 4169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Type *texType = new Type(mRSC); 4179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk texType->setElement(alphaElem); 4189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk texType->setDimX(1024); 4199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk texType->setDimY(256); 4209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk texType->compute(); 4219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Allocation *cacheAlloc = new Allocation(mRSC, texType); 4239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mTextTexture.set(cacheAlloc); 4249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 4259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Split up our cache texture into lines of certain widths 4279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk int nextLine = 0; 4289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 4299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 4309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 4319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 43294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 43394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 4349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 4359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 4369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 4379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 4389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 4399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 4409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 4419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 4429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 4449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::initVertexArrayBuffers() 4459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 4469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now lets write index data 4479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 4489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Type *indexType = new Type(mRSC); 4499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 4509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexType->setDimX(numIndicies); 4519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexType->setElement(indexElem); 4529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexType->compute(); 4539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Allocation *indexAlloc = new Allocation(mRSC, indexType); 4559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 4569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Four verts, two triangles , six indices per quad 4589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 4599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk int i6 = i * 6; 4609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk int i4 = i * 4; 4619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 4639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 4649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 4659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 4679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 4689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 4699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 4729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 4739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 4759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 4769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *elemArray[2]; 4789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk elemArray[0] = posElem; 4799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk elemArray[1] = texElem; 4809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk String8 posName("position"); 4829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk String8 texName("texture0"); 4839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const char *nameArray[2]; 4859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nameArray[0] = posName.string(); 4869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nameArray[1] = texName.string(); 4879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t lengths[2]; 4889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk lengths[0] = posName.size(); 4899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk lengths[1] = texName.size(); 4909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *vertexDataElem = Element::create(mRSC, 2, elemArray, nameArray, lengths); 4929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Type *vertexDataType = new Type(mRSC); 4949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk vertexDataType->setDimX(mMaxNumberOfQuads * 4); 4959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk vertexDataType->setElement(vertexDataElem); 4969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk vertexDataType->compute(); 4979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType); 4999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 5009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mVertexArray.set(vertexAlloc); 5029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 5059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::checkInit() 5069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 5079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(mInitialized) { 5089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 5099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 5109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initTextTexture(); 5129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initRenderState(); 5139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initVertexArrayBuffers(); 5159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = true; 5179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::issueDrawCommand() { 5209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex()); 5229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->setVertex(mRSC->getDefaultProgramVertex()); 5239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 52480a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster()); 52580a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk mRSC->setRaster(mRSC->getDefaultProgramRaster()); 52680a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk 5279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment()); 5289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->setFragment(mFontShaderF.get()); 5299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore()); 5319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->setFragmentStore(mFontProgramStore.get()); 5329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 53355e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk if(mFontColorDirty) { 53455e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk mFontShaderF->setConstantColor(mFontColor[0], mFontColor[1], mFontColor[2], mFontColor[3]); 53555e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk mFontColorDirty = false; 53655e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk } 53755e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk 5389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if (!mRSC->setupCheck()) { 5399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 54080a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 5419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 5429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 5439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 5449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 5459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 5479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float *tex = vtx + 3; 5489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk VertexArray va; 5509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk va.add(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "position"); 5519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk va.add(GL_FLOAT, 2, 20, false, (uint32_t)tex, "texture0"); 5529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 5539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 5559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 5569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 5579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Reset the state 5599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 56080a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 5619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 5629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 5639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 5669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float u1, float v1, 5679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float x2, float y2, float z2, 5689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float u2, float v2, 5699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float x3, float y3, float z3, 5709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float u3, float v3, 5719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float x4, float y4, float z4, 5729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float u4, float v4) 5739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 5749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 5759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const uint32_t floatsPerVert = 5; 5769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 5779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Cull things that are off the screen 5799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float width = (float)mRSC->getWidth(); 5809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float height = (float)mRSC->getHeight(); 5819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 5839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 5849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 5859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 5879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 5889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 5899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 5909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x1; 5929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y1; 5939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z1; 5949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u1; 5959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v1; 5969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x2; 5989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y2; 5999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z2; 6009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u2; 6019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v2; 6029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x3; 6049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y3; 6059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z3; 6069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u3; 6079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v3; 6089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x4; 6109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y4; 6119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z4; 6129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u4; 6139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v4; 6149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex ++; 6169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(mCurrentQuadIndex == mMaxNumberOfQuads) { 6189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 6199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 6209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 6229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 62394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 62494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk uint32_t remainingCapacity = 0; 62594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk float totalPixels = 0; 62694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 62794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 62894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 62994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 63094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 63194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk return remainingCapacity; 63294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk} 63394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 63494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 63594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk // Remaining capacity is measured in % 63694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 63794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk uint32_t precacheIdx = 0; 63894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk while(remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 63994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 64094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 64194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk precacheIdx ++; 64294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 64394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk} 64494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 64594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 6469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, uint32_t startIndex, int numGlyphs, int x, int y) 6479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 6489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk checkInit(); 6499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Render code here 6519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 652071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk if(!currentFont) { 653071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk if(!mDefault.get()) { 654071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96)); 655071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 656071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk currentFont = mDefault.get(); 657071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 658b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk if(!currentFont) { 659b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk LOGE("Unable to initialize any fonts"); 660b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk return; 661b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk } 662b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 6639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk currentFont->renderUTF(text, len, startIndex, numGlyphs, x, y); 6649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(mCurrentQuadIndex != 0) { 6669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 6679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 6689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 66994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 67094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 67194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 67294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 67394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 67494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk mLatinPrecache += String8("0123456789"); 6759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 6769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::renderText(const char *text, int x, int y) 6789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 6799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t textLen = strlen(text); 6809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk renderText(text, textLen, 0, -1, x, y); 6819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 6829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::renderText(Allocation *alloc, int x, int y) 6849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 6859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(!alloc) { 6869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 6879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const char *text = (const char *)alloc->getPtr(); 6909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t allocSize = alloc->getType()->getSizeBytes(); 6919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk renderText(text, allocSize, 0, -1, x, y); 6929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 6939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::renderText(Allocation *alloc, uint32_t start, int len, int x, int y) 6959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 6969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if(!alloc) { 6979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 6989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 7009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const char *text = (const char *)alloc->getPtr(); 7019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t allocSize = alloc->getType()->getSizeBytes(); 7029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk renderText(text, allocSize, start, len, x, y); 7039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 7049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 705fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 706fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk mFontColor[0] = r; 707fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk mFontColor[1] = g; 708fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk mFontColor[2] = b; 709fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk mFontColor[3] = a; 710fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk mFontColorDirty = true; 711fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk} 712fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk 71355e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 71455e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk *r = mFontColor[0]; 71555e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk *g = mFontColor[1]; 71655e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk *b = mFontColor[2]; 71755e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk *a = mFontColor[3]; 71855e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk} 71955e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk 7209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::deinit(Context *rsc) 7219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 722071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mInitialized = false; 723071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 724071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mIndexBuffer.clear(); 725071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mVertexArray.clear(); 726071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 727071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontShaderF.clear(); 728071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontSampler.clear(); 729071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontProgramStore.clear(); 730071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 731071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mTextTexture.clear(); 732071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 733071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk delete mCacheLines[i]; 7349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 735071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mCacheLines.clear(); 7369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 7379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mDefault.clear(); 738071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 739b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk Vector<Font*> fontsToDereference = mActiveFonts; 740b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk for(uint32_t i = 0; i < fontsToDereference.size(); i ++) { 741b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk fontsToDereference[i]->zeroUserRef(); 742b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk } 743b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 744071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk if(mLibrary) { 745071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Done_FreeType( mLibrary ); 746b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mLibrary = NULL; 747071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 7489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 7499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 7509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouknamespace android { 7519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouknamespace renderscript { 7529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 7539b949fce39f0f39ce9275b71d7c347210775e7a8Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi) 7549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk{ 755071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 756071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk if(newFont) { 757071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk newFont->incUserRef(); 758071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 759071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return newFont; 7609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 7619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 7629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} // renderscript 7639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} // android 764