rsFont.cpp revision c8fb69e4a3e01501a3d38a6d3ea185e583d3f493
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; 342ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the renderer properties 345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the gamma 348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text gamma to %s", property); 351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk gamma = atof(property); 352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA); 354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 356c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the black gamma threshold 35709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text black gamma threshold to %s", property); 360c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk blackThreshold = atoi(property); 361c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 362c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default text black gamma threshold of %d", 363c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD); 364c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 365c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 366c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 367c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the white gamma threshold 36809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 369c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 370c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text white gamma threshold to %s", property); 371c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk whiteThreshold = atoi(property); 372c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 373c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default white black gamma threshold of %d", 374c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD); 375c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 376c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 377c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 378c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Compute the gamma tables 379c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackGamma = gamma; 380c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteGamma = 1.0f / gamma; 381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 383d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::~FontState() 384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 386d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 387d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 391d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 392a1ccecd965c07c2739f1258989526051a010bdabAlex SakhartchoukFT_Library FontState::getLib() 393d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 394d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!mLibrary) { 395a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(error) { 397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize freetype"); 398a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return NULL; 399d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 4013659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 402a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 403a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 405a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchoukvoid FontState::init(Context *rsc) 406a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk{ 407a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::flushAllAndInvalidate() 411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex != 0) { 413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mActiveFonts.size(); i ++) { 417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) 425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(bitmapFit) { 440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!bitmapFit) { 446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(bitmapFit) { 452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!bitmapFit) { 458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 47109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 47209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 473d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 475d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 476d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 47709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 478d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 479d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 480d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 482d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 483d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 484d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 485383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 486d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 487d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 488d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 489d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 490d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 491d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 492d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 493d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 494d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 495d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 496d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 497d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 498d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initRenderState() 499d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 500e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk String8 shaderString("varying vec4 varTex0;\n"); 501e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("void main() {\n"); 502e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 503e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 504c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 505e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 506e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("}\n"); 507e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 508e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 509c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 510e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 511e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 512c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); 513e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); 514e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 515e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk Type *inputType = new Type(mRSC); 516e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk inputType->setElement(constInput); 517e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk inputType->setDimX(1); 518e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk inputType->compute(); 519e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 520e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk uint32_t tmp[4]; 521e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 522e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[1] = (uint32_t)inputType; 523e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT; 524e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[3] = 1; 525e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 526e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mFontShaderFConstant.set(new Allocation(mRSC, inputType)); 527e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 528e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.length(), tmp, 4); 529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 530383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 534d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSampler.set(sampler); 535383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, sampler); 536d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore.set(fontStore); 539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initTextTexture() 546d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Type *texType = new Type(mRSC); 551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->setElement(alphaElem); 552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->setDimX(1024); 553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->setDimY(256); 554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk texType->compute(); 555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *cacheAlloc = new Allocation(mRSC, texType); 557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 56109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nextLine = 0; 562d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 56601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 56701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 568d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initVertexArrayBuffers() 579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 581d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 582d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Type *indexType = new Type(mRSC); 583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexType->setDimX(numIndicies); 585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexType->setElement(indexElem); 586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexType->compute(); 587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *indexAlloc = new Allocation(mRSC, indexType); 589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 59309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i6 = i * 6; 59409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i4 = i * 4; 595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 601d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 602d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 603d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 606d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 609d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 611d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *elemArray[2]; 612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk elemArray[0] = posElem; 613d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk elemArray[1] = texElem; 614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 posName("position"); 616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 texName("texture0"); 617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 618d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const char *nameArray[2]; 619d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nameArray[0] = posName.string(); 620d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nameArray[1] = texName.string(); 621d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t lengths[2]; 622d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk lengths[0] = posName.size(); 623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk lengths[1] = texName.size(); 62446e45548dc80e801139c9ccc2f2aa927e7f35027Jason Sams uint32_t arraySizes[2] = {1, 1}; 625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 62646e45548dc80e801139c9ccc2f2aa927e7f35027Jason Sams const Element *vertexDataElem = Element::create(mRSC, 2, elemArray, nameArray, lengths, arraySizes); 627d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Type *vertexDataType = new Type(mRSC); 629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk vertexDataType->setDimX(mMaxNumberOfQuads * 4); 630d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk vertexDataType->setElement(vertexDataElem); 631d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk vertexDataType->compute(); 632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType); 634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mVertexArray.set(vertexAlloc); 637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::checkInit() 641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 642d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mInitialized) { 643d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 645d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 646d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 647d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 648d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 65135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 65235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 65335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 65435b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 65535b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("0123456789"); 65635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk 657d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex()); 663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex(mRSC->getDefaultProgramVertex()); 664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 665d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster()); 666d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster(mRSC->getDefaultProgramRaster()); 667d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk 668d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment()); 669d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment(mFontShaderF.get()); 670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore()); 672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore(mFontProgramStore.get()); 673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 674c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if(mConstantsDirty) { 675c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants)); 676c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = false; 677ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 678ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 681d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 682d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *tex = vtx + 3; 689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk VertexArray va; 691886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk va.add(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position"); 692886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk va.add(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0"); 693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 698d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 699d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reset the state 700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 701d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 702d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 707d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u1, float v1, 708d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x2, float y2, float z2, 709d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u2, float v2, 710d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x3, float y3, float z3, 711d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u3, float v3, 712d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x4, float y4, float z4, 713d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u4, float v4) 714d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 715d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 716d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t floatsPerVert = 5; 717d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 718d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 719d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Cull things that are off the screen 720d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float width = (float)mRSC->getWidth(); 721d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float height = (float)mRSC->getHeight(); 722d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 723d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 724d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 725d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 726d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 727d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 728d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 729d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 730d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 731d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 732d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 733d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 734d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 735d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 736d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 737d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 738d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 739d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 740d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 741d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 742d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 743d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 744d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 745d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 746d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 747d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 748d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 749d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 752d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 753d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 754d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 755d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 756d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 757d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 758d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex == mMaxNumberOfQuads) { 759d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 760d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 761d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 762d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 763d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 76401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 76501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 76635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 76701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 76801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 76901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 77001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 77101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 77201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 77301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 77401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 77501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 77601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 77701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 77801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 77901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk while(remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 78001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 78101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 78201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 78301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 78401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 78501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 78601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 78709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 78809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 78909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::RenderMode mode, 79009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::Rect *bounds, 79109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) 792d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 793d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 794d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 795d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 796d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 797a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(!currentFont) { 798a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(!mDefault.get()) { 799a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96)); 800a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 801a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk currentFont = mDefault.get(); 802a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 8033659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk if(!currentFont) { 8043659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk LOGE("Unable to initialize any fonts"); 8053659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk return; 8063659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 8073659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 80809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 80909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 810d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 811d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex != 0) { 812d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 813d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 814d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 815d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 816d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 81709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 81809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 819d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 820d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8219fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 822c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[0] = r; 823c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[1] = g; 824c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[2] = b; 825c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[3] = a; 826c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 827c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = 1.0f; 828c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 829c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (luminance <= mBlackThreshold) { 830c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mBlackGamma; 831c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 832c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mWhiteGamma; 833c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 834c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = true; 8359fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk} 8369fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk 837ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 838c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *r = mConstants.mFontColor[0]; 839c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *g = mConstants.mFontColor[1]; 840c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *b = mConstants.mFontColor[2]; 841c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *a = mConstants.mFontColor[3]; 842ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk} 843ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 844d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::deinit(Context *rsc) 845d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 846a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mInitialized = false; 847a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 84801b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines mFontShaderFConstant.clear(); 84901b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines 850a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mIndexBuffer.clear(); 851a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mVertexArray.clear(); 852a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 853a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontShaderF.clear(); 854a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontSampler.clear(); 855a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontProgramStore.clear(); 856a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 857a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mTextTexture.clear(); 858a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 859a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk delete mCacheLines[i]; 860d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 861a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mCacheLines.clear(); 862d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 863d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDefault.clear(); 864a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 8653659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk Vector<Font*> fontsToDereference = mActiveFonts; 8663659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk for(uint32_t i = 0; i < fontsToDereference.size(); i ++) { 8673659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk fontsToDereference[i]->zeroUserRef(); 8683659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 8693659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 870a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(mLibrary) { 871a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Done_FreeType( mLibrary ); 8723659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 873a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 874d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 875d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 876d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android { 877d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript { 878d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 879d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi) 880d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 881a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 882a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(newFont) { 883a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk newFont->incUserRef(); 884a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 885a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return newFont; 886d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 887d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 888d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript 889d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android 890