rsFont.cpp revision 4f230b31d59b5f17100686bc1416b3b07a4a618d
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" 26c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk#include <cutils/properties.h> 27d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include FT_BITMAP_H 28d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 29d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/gl.h> 30d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/glext.h> 31d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2.h> 32d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2ext.h> 33d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 34d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android; 35d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android::renderscript; 36d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 37d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) 38d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 39a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mAllocFile = __FILE__; 40a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mAllocLine = __LINE__; 41d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 42d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = false; 433659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mFace = NULL; 44d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool Font::init(const char *name, uint32_t fontSize, uint32_t dpi) 47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mInitialized) { 49d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 50d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 51d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 52d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 53d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 fontsDir("/fonts/"); 54d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 55d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk fullPath += fontsDir; 56d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk fullPath += name; 57d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 58a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace); 59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(error) { 60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize font %s", fullPath.string()); 61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontName = name; 65d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSize = fontSize; 66d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDpi = dpi; 67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0); 69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(error) { 70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to set font size on %s", fullPath.string()); 71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 76d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 77d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 78d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 79d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 80d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::invalidateTextureCache() 81d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 82d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 83d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 84d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 85d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 86d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) 88d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 89d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 90d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 9209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 93d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 9509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 9609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 98d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 101d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 10309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk const uint8_t* cacheBuffer = state->getTextTextureData(); 11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t bX = 0, bY = 0; 12209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("Skipping invalid index"); 12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk continue; 12709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 12809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 13009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 132d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 133d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 134d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 13509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 13609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 13709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->bottom > nPenY) { 14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->bottom = nPenY; 14409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->left > nPenX) { 14609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->left = nPenX; 14709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->right < nPenX + width) { 14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->right = nPenX + width; 15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->top < nPenY + height) { 15209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->top = nPenY + height; 15309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 15509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 15609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 15709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 15809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk RenderMode mode, Rect *bounds, 15909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) 160d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 161d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 162d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 163d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 164d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 16509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if(mode == Font::MEASURE) { 16609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds == NULL) { 16709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("No return rectangle provided to measure text"); 16809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk return; 16909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk // Reset min and max of the bounding box to something large 17109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->set(1e6, -1e6, -1e6, 1e6); 17209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 17409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t penX = x, penY = y; 17509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t glyphsLeft = 1; 176d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(numGlyphs > 0) { 177d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft = numGlyphs; 178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 179d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t index = start; 181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t nextIndex = 0; 182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk while (glyphsLeft > 0) { 184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk int32_t utfChar = utf32_at(text, len, index, &nextIndex); 186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reached the end of the string or encountered 188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(utfChar < 0) { 189d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 190d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 192d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Move to the next character in the array 193d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk index = nextIndex; 194d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 19501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 196d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 197d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 198d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(cachedGlyph->mIsValid) { 19909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk switch(mode) { 20009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case FRAMEBUFFER: 20109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 20209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case BITMAP: 20409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 20509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case MEASURE: 20709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 20809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 210d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 211d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk penX += (cachedGlyph->mAdvance.x >> 6); 213d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 215d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(numGlyphs > 0) { 216d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft --; 217d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 218d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 219d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 220d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 22101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 22201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 22301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 22401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk if(cachedGlyph == NULL) { 22501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 22601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 22701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Is the glyph still in texture cache? 22801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk if(!cachedGlyph->mIsValid) { 22901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk updateGlyphCache(cachedGlyph); 23001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 23101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 23201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return cachedGlyph; 23301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 23401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 235d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) 236d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 237a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 238a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(error) { 239a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk LOGE("Couldn't load glyph."); 240a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return; 241a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 242d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 243a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mAdvance = mFace->glyph->advance; 244a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 245a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 246d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 247a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 248d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 249d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 253d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Let the font state figure out where to put the bitmap 254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 255a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!glyph->mIsValid) { 258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 259d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 260d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 261a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endX = startX + bitmap->width; 262a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endY = startY + bitmap->rows; 263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 264d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinX = startX; 265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinY = startY; 266a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 267a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 269d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 271d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) 279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 280d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 283d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 284d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mIsValid = false; 285d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk updateGlyphCache(newGlyph); 287d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 288d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newGlyph; 289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 291d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi) 292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 29335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk rsc->mStateFont.checkInit(); 294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 295d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 296d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < activeFonts.size(); i ++) { 297d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *ithFont = activeFonts[i]; 298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 299d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return ithFont; 300d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *newFont = new Font(rsc); 304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi); 305d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(isInitialized) { 306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk activeFonts.push(newFont); 30701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 308d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newFont; 309d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete newFont; 312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return NULL; 313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 316d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::~Font() 317d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mFace) { 319d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FT_Done_Face(mFace); 320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 322d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (mRSC->mStateFont.mActiveFonts[ct] == this) { 324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->mStateFont.mActiveFonts.removeAt(ct); 325d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 327d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 330d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 331d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete glyph; 332d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 333d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 334d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 335d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::FontState() 336d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 337d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 338d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mMaxNumberOfQuads = 1024; 339d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 340d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC = NULL; 3413659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 342c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the renderer properties 344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the gamma 347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text gamma to %s", property); 350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk gamma = atof(property); 351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA); 353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the black gamma threshold 35609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text black gamma threshold to %s", property); 359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk blackThreshold = atoi(property); 360c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 361c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default text black gamma threshold of %d", 362c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD); 363c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 364c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 365c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 366c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the white gamma threshold 36709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 368c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 369c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text white gamma threshold to %s", property); 370c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk whiteThreshold = atoi(property); 371c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 372c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default white black gamma threshold of %d", 373c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD); 374c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 375c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 376c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 377c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Compute the gamma tables 378c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackGamma = gamma; 379c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteGamma = 1.0f / gamma; 3804f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 3814f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 383d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::~FontState() 385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 386d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 387d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 391d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 393a1ccecd965c07c2739f1258989526051a010bdabAlex SakhartchoukFT_Library FontState::getLib() 394d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 395d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!mLibrary) { 396a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(error) { 398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize freetype"); 399a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return NULL; 400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 401d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 4023659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 403a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 404a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 406a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchoukvoid FontState::init(Context *rsc) 407a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk{ 408a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::flushAllAndInvalidate() 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex != 0) { 414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mActiveFonts.size(); i ++) { 418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(bitmapFit) { 441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!bitmapFit) { 447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(bitmapFit) { 453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!bitmapFit) { 459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 47209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 47309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 475d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 476d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 477d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 47809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 479d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 480d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 482d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 483d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 484d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 485d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 486383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 487d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 488d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 489d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 490d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 491d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 492d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 493d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 494d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 495d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 496d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 497d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 498d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 499d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initRenderState() 500d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 5017ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk String8 shaderString("varying vec2 varTex0;\n"); 502e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("void main() {\n"); 503e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 504e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 505c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 506e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 507e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("}\n"); 508e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 509e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 510c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 511e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 512e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 513c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); 514e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); 515e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 516e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk Type *inputType = new Type(mRSC); 517e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk inputType->setElement(constInput); 518e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk inputType->setDimX(1); 519e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk inputType->compute(); 520e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 521e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk uint32_t tmp[4]; 522e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 523e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[1] = (uint32_t)inputType; 524e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT; 525e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[3] = 1; 526e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 527e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mFontShaderFConstant.set(new Allocation(mRSC, inputType)); 528e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 529e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.length(), tmp, 4); 530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 531383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 534d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSampler.set(sampler); 536383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, sampler); 537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore.set(fontStore); 540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 546d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initTextTexture() 547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Type *texType = new Type(mRSC); 552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->setElement(alphaElem); 553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->setDimX(1024); 554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->setDimY(256); 555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->compute(); 556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *cacheAlloc = new Allocation(mRSC, texType); 558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 56209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nextLine = 0; 563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 566d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 56701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 56801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initVertexArrayBuffers() 580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 581d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 582d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Type *indexType = new Type(mRSC); 584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexType->setDimX(numIndicies); 586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexType->setElement(indexElem); 587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexType->compute(); 588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *indexAlloc = new Allocation(mRSC, indexType); 590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 59409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i6 = i * 6; 59509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i4 = i * 4; 596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 601d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 602d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 603d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 606d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 609d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 611d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *elemArray[2]; 613d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk elemArray[0] = posElem; 614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk elemArray[1] = texElem; 615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 posName("position"); 617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 texName("texture0"); 618d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 619d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const char *nameArray[2]; 620d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nameArray[0] = posName.string(); 621d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nameArray[1] = texName.string(); 622d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t lengths[2]; 623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk lengths[0] = posName.size(); 624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk lengths[1] = texName.size(); 62546e45548dc80e801139c9ccc2f2aa927e7f35027Jason Sams uint32_t arraySizes[2] = {1, 1}; 626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 62746e45548dc80e801139c9ccc2f2aa927e7f35027Jason Sams const Element *vertexDataElem = Element::create(mRSC, 2, elemArray, nameArray, lengths, arraySizes); 628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Type *vertexDataType = new Type(mRSC); 630d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk vertexDataType->setDimX(mMaxNumberOfQuads * 4); 631d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk vertexDataType->setElement(vertexDataElem); 632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk vertexDataType->compute(); 633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType); 635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mVertexArray.set(vertexAlloc); 638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::checkInit() 642d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 643d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mInitialized) { 644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 645d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 646d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 647d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 648d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 651d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 65235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 65335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 65435b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 65535b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 65635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("0123456789"); 65735b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk 658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex()); 664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex(mRSC->getDefaultProgramVertex()); 665d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 666d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster()); 667d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster(mRSC->getDefaultProgramRaster()); 668d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk 669d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment()); 670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment(mFontShaderF.get()); 671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore()); 673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore(mFontProgramStore.get()); 674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 675c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if(mConstantsDirty) { 676c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants)); 677c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = false; 678ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 679ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 682d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *tex = vtx + 3; 690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk VertexArray va; 692886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk va.add(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position"); 693886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk va.add(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0"); 694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 698d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 699d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reset the state 701d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 702d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 707d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 708d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u1, float v1, 709d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x2, float y2, float z2, 710d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u2, float v2, 711d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x3, float y3, float z3, 712d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u3, float v3, 713d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x4, float y4, float z4, 714d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u4, float v4) 715d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 716d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 717d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t floatsPerVert = 5; 718d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 719d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 720d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Cull things that are off the screen 721d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float width = (float)mRSC->getWidth(); 722d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float height = (float)mRSC->getHeight(); 723d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 724d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 725d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 726d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 727d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 728d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 729d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 730d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 731d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 732d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 733d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 734d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 735d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 736d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 737d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 738d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 739d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 740d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 741d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 742d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 743d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 744d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 745d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 746d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 747d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 748d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 749d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 752d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 753d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 754d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 755d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 756d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 757d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 758d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 759d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex == mMaxNumberOfQuads) { 760d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 761d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 762d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 763d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 764d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 76501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 76601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 76735b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 76801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 76901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 77001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 77101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 77201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 77301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 77401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 77501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 77601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 77701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 77801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 77901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 78001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk while(remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 78101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 78201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 78301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 78401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 78501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 78601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 78701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 78809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 78909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 79009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::RenderMode mode, 79109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::Rect *bounds, 79209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) 793d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 794d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 795d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 796d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 797d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 798a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(!currentFont) { 799a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(!mDefault.get()) { 800a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96)); 801a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 802a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk currentFont = mDefault.get(); 803a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 8043659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk if(!currentFont) { 8053659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk LOGE("Unable to initialize any fonts"); 8063659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk return; 8073659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 8083659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 80909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 81009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 811d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 812d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex != 0) { 813d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 814d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 815d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 816d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 817d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 81809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 81909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 820d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 821d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8229fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 823c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[0] = r; 824c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[1] = g; 825c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[2] = b; 826c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[3] = a; 827c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 828c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = 1.0f; 829c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 830c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (luminance <= mBlackThreshold) { 831c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mBlackGamma; 832c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 833c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mWhiteGamma; 834c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 8354f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 836c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = true; 8379fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk} 8389fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk 839ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 840c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *r = mConstants.mFontColor[0]; 841c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *g = mConstants.mFontColor[1]; 842c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *b = mConstants.mFontColor[2]; 843c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *a = mConstants.mFontColor[3]; 844ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk} 845ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 846d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::deinit(Context *rsc) 847d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 848a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mInitialized = false; 849a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 85001b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines mFontShaderFConstant.clear(); 85101b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines 852a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mIndexBuffer.clear(); 853a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mVertexArray.clear(); 854a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 855a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontShaderF.clear(); 856a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontSampler.clear(); 857a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontProgramStore.clear(); 858a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 859a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mTextTexture.clear(); 860a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 861a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk delete mCacheLines[i]; 862d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 863a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mCacheLines.clear(); 864d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 865d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDefault.clear(); 866a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 8673659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk Vector<Font*> fontsToDereference = mActiveFonts; 8683659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk for(uint32_t i = 0; i < fontsToDereference.size(); i ++) { 8693659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk fontsToDereference[i]->zeroUserRef(); 8703659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 8713659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 872a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(mLibrary) { 873a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Done_FreeType( mLibrary ); 8743659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 875a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 876d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 877d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 878d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android { 879d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript { 880d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 881d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi) 882d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 883a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 884a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(newFont) { 885a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk newFont->incUserRef(); 886a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 887a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return newFont; 888d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 889d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 890d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript 891d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android 892