rsFont.cpp revision 54929cce0bf44090424b1f91b676529a2422378f
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{ 39d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 40d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = false; 413659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mFace = NULL; 42d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 43d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 44d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool Font::init(const char *name, uint32_t fontSize, uint32_t dpi) 45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mInitialized) { 47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 49d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 50d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 51d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 fontsDir("/fonts/"); 52d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 53d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk fullPath += fontsDir; 54d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk fullPath += name; 55d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 56a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace); 57d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(error) { 58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize font %s", fullPath.string()); 59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontName = name; 63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSize = fontSize; 64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDpi = dpi; 65d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 66d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0); 67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(error) { 68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to set font size on %s", fullPath.string()); 69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 76d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 77d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 78d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::invalidateTextureCache() 79d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 80d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 81d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 82d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 83d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 84d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) 86d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 87d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 88d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 9009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 91d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 9309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 9409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 9509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 96d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 9809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 99d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 10109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 10309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk const uint8_t* cacheBuffer = state->getTextTextureData(); 11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t bX = 0, bY = 0; 12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 12209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("Skipping invalid index"); 12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk continue; 12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 12709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 12809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 130d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 131d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 132d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 13309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 13409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 13509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 13609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 13709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->bottom > nPenY) { 14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->bottom = nPenY; 14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->left > nPenX) { 14409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->left = nPenX; 14509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->right < nPenX + width) { 14709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->right = nPenX + width; 14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->top < nPenY + height) { 15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->top = nPenY + height; 15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 15309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 15409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 15509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 15609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk RenderMode mode, Rect *bounds, 15709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) 158d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 159d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 160d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 161d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 162d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 16309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if(mode == Font::MEASURE) { 16409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds == NULL) { 16509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("No return rectangle provided to measure text"); 16609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk return; 16709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 16809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk // Reset min and max of the bounding box to something large 16909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->set(1e6, -1e6, -1e6, 1e6); 17009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 17209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t penX = x, penY = y; 17309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t glyphsLeft = 1; 174d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(numGlyphs > 0) { 175d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft = numGlyphs; 176d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 177d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t index = start; 179d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t nextIndex = 0; 180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk while (glyphsLeft > 0) { 182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk int32_t utfChar = utf32_at(text, len, index, &nextIndex); 184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reached the end of the string or encountered 186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(utfChar < 0) { 187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 189d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 190d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Move to the next character in the array 191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk index = nextIndex; 192d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 19301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 194d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 195d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 196d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(cachedGlyph->mIsValid) { 19709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk switch(mode) { 19809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case FRAMEBUFFER: 19909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 20009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case BITMAP: 20209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 20309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case MEASURE: 20509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 20609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 208d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 209d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 210d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk penX += (cachedGlyph->mAdvance.x >> 6); 211d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 213d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(numGlyphs > 0) { 214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft --; 215d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 216d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 217d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 218d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 21901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 22001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 22101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 22201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk if(cachedGlyph == NULL) { 22301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 22401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 22501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Is the glyph still in texture cache? 22601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk if(!cachedGlyph->mIsValid) { 22701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk updateGlyphCache(cachedGlyph); 22801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 22901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 23001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return cachedGlyph; 23101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 23201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 233d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) 234d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 235a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 236a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(error) { 237a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk LOGE("Couldn't load glyph."); 238a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return; 239a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 240d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 241a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mAdvance = mFace->glyph->advance; 242a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 243a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 244d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 245a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 246d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 247d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 248d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 249d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Let the font state figure out where to put the bitmap 252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 253a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 255d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!glyph->mIsValid) { 256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 259a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endX = startX + bitmap->width; 260a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endY = startY + bitmap->rows; 261d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 262d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinX = startX; 263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinY = startY; 264a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 265a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 266d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 269d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 271d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) 277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 280d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mIsValid = false; 283d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 284d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk updateGlyphCache(newGlyph); 285d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newGlyph; 287d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 288d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi) 290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 29135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk rsc->mStateFont.checkInit(); 292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 293d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < activeFonts.size(); i ++) { 295d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *ithFont = activeFonts[i]; 296d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 297d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return ithFont; 298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 299d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 300d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *newFont = new Font(rsc); 302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi); 303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(isInitialized) { 304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk activeFonts.push(newFont); 30501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newFont; 307d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 308d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 309225afd317e101a7be5fe02c0a86361146ea89f05Jason Sams ObjectBase::checkDelete(newFont); 310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return NULL; 311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFont::~Font() 315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 316d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mFace) { 317d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FT_Done_Face(mFace); 318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 319d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (mRSC->mStateFont.mActiveFonts[ct] == this) { 322d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->mStateFont.mActiveFonts.removeAt(ct); 323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 325d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 327d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete glyph; 330d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 331d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 332d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 333d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::FontState() 334d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 335d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 336d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mMaxNumberOfQuads = 1024; 337d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 338d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC = NULL; 3393659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 340c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 341c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the renderer properties 342c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the gamma 345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text gamma to %s", property); 348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk gamma = atof(property); 349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA); 351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the black gamma threshold 35409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 356c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text black gamma threshold to %s", property); 357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk blackThreshold = atoi(property); 358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default text black gamma threshold of %d", 360c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD); 361c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 362c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 363c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 364c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the white gamma threshold 36509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 366c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 367c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text white gamma threshold to %s", property); 368c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk whiteThreshold = atoi(property); 369c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 370c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default white black gamma threshold of %d", 371c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD); 372c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 373c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 374c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 375c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Compute the gamma tables 376c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackGamma = gamma; 377c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteGamma = 1.0f / gamma; 3784f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 3794f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 380d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukFontState::~FontState() 383d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 386d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 387d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 391a1ccecd965c07c2739f1258989526051a010bdabAlex SakhartchoukFT_Library FontState::getLib() 392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 393d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!mLibrary) { 394a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 395d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(error) { 396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize freetype"); 397a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return NULL; 398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 399d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 4003659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 401a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 402a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 403d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 404a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchoukvoid FontState::init(Context *rsc) 405a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk{ 406a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 407d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::flushAllAndInvalidate() 410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex != 0) { 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mActiveFonts.size(); i ++) { 416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(bitmapFit) { 439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!bitmapFit) { 445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(bitmapFit) { 451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(!bitmapFit) { 457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 47009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 47109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 472d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 473d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 475d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 47609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 477d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 478d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 479d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 480d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 482d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 483d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 484383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 485d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 486d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 487d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 488d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 489d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 490d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 491d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 492d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 493d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 494d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 495d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 496d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 497d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initRenderState() 498d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 4997ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk String8 shaderString("varying vec2 varTex0;\n"); 500e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("void main() {\n"); 501e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 502e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 503c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 504e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 505e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("}\n"); 506e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 507e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 508c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 509e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 510e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 511c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); 512e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); 513e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 514f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false); 515e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 516e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk uint32_t tmp[4]; 517e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 518e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[1] = (uint32_t)inputType; 519e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT; 520e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[3] = 1; 521e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 522e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mFontShaderFConstant.set(new Allocation(mRSC, inputType)); 523e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 524e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.length(), tmp, 4); 525d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 526383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 527d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSampler.set(sampler); 531383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, sampler); 532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 534d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore.set(fontStore); 535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 536d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initTextTexture() 542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 546f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false); 547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *cacheAlloc = new Allocation(mRSC, texType); 549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 55309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nextLine = 0; 554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 55801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 55901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 562d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 566d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 567d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 568d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::initVertexArrayBuffers() 571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 575f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false); 576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *indexAlloc = new Allocation(mRSC, indexType); 578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 581d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for(uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 58209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i6 = i * 6; 58309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i4 = i * 4; 584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 60064cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 60164cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1); 60264cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1); 60364cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC); 604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 605f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *vertexDataType = Type::getType(mRSC, vertexDataElem, 606f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams mMaxNumberOfQuads * 4, 607f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams 0, 0, false, false); 608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 609d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType); 610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 611d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mVertexArray.set(vertexAlloc); 613d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::checkInit() 617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 618d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mInitialized) { 619d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 620d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 621d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 622d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 62735b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 62835b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 62935b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 63035b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 63135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("0123456789"); 63235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk 633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex()); 639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex(mRSC->getDefaultProgramVertex()); 640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 641d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster()); 642d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster(mRSC->getDefaultProgramRaster()); 643d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk 644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment()); 645d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment(mFontShaderF.get()); 646d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 647d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore()); 648d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore(mFontProgramStore.get()); 649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 650c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if(mConstantsDirty) { 651c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants)); 652c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = false; 653ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 654ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 655d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 656d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 657d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *tex = vtx + 3; 665d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 66654929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk VertexArray::Attrib attribs[2]; 66754929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position"); 66854929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0"); 66954929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk VertexArray va(attribs, 2); 670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 675d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 676d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reset the state 677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 678d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 682d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u1, float v1, 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x2, float y2, float z2, 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u2, float v2, 687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x3, float y3, float z3, 688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u3, float v3, 689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float x4, float y4, float z4, 690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float u4, float v4) 691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 692d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t floatsPerVert = 5; 694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Cull things that are off the screen 697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float width = (float)mRSC->getWidth(); 698d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float height = (float)mRSC->getHeight(); 699d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 701d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 702d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 707d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 708d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 709d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 710d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 711d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 712d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 713d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 714d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 715d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 716d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 717d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 718d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 719d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 720d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 721d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 722d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 723d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 724d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 725d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 726d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 727d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 728d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 729d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 730d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 731d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 732d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 733d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 734d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 735d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex == mMaxNumberOfQuads) { 736d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 737d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 738d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 739d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 740d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 74101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 74201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 74335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 74401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 74501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 74601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 74701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 74801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 74901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 75001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 75101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 75201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 75301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 75401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 75501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 75601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk while(remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 75701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 75801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 75901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 76001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 76101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 76201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 76301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 76409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 76509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 76609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::RenderMode mode, 76709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::Rect *bounds, 76809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) 769d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 770d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 771d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 772d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 773d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 774a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(!currentFont) { 775a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(!mDefault.get()) { 776a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96)); 777a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 778a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk currentFont = mDefault.get(); 779a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 7803659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk if(!currentFont) { 7813659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk LOGE("Unable to initialize any fonts"); 7823659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk return; 7833659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 7843659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 78509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 78609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 787d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 788d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if(mCurrentQuadIndex != 0) { 789d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 790d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 791d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 792d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 793d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 79409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 79509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 796d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 797d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 7989fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 799c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[0] = r; 800c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[1] = g; 801c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[2] = b; 802c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[3] = a; 803c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 804c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = 1.0f; 805c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 806c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (luminance <= mBlackThreshold) { 807c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mBlackGamma; 808c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 809c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mWhiteGamma; 810c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 8114f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 812c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = true; 8139fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk} 8149fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk 815ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 816c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *r = mConstants.mFontColor[0]; 817c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *g = mConstants.mFontColor[1]; 818c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *b = mConstants.mFontColor[2]; 819c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *a = mConstants.mFontColor[3]; 820ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk} 821ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 822d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::deinit(Context *rsc) 823d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 824a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mInitialized = false; 825a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 82601b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines mFontShaderFConstant.clear(); 82701b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines 828a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mIndexBuffer.clear(); 829a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mVertexArray.clear(); 830a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 831a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontShaderF.clear(); 832a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontSampler.clear(); 833a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontProgramStore.clear(); 834a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 835a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mTextTexture.clear(); 836a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk for(uint32_t i = 0; i < mCacheLines.size(); i ++) { 837a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk delete mCacheLines[i]; 838d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 839a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mCacheLines.clear(); 840d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 841d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDefault.clear(); 842a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 8433659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk Vector<Font*> fontsToDereference = mActiveFonts; 8443659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk for(uint32_t i = 0; i < fontsToDereference.size(); i ++) { 8453659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk fontsToDereference[i]->zeroUserRef(); 8463659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 8473659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 848a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(mLibrary) { 849a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Done_FreeType( mLibrary ); 8503659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 851a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 852d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 853d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 854d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android { 855d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript { 856d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 857d3e0ad43dc758c409fc23d1893dab67b18520c24Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi) 858d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{ 859a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 860a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk if(newFont) { 861a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk newFont->incUserRef(); 862a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 863a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return newFont; 864d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 865d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 866d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript 867d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android 868