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