rsFont.cpp revision c9c38dd8508a2f805213abee1f9f44f103ac0a0d
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 37afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) { 38d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 39d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = false; 403659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mFace = NULL; 41d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 42d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 43afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukbool Font::init(const char *name, uint32_t fontSize, uint32_t dpi) { 44afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 49d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 fontsDir("/fonts/"); 50d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 51d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk fullPath += fontsDir; 52d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk fullPath += name; 53d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 54a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace); 55afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 56d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize font %s", fullPath.string()); 57d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontName = name; 61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSize = fontSize; 62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDpi = dpi; 63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0); 65afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 66d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to set font size on %s", fullPath.string()); 67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 76afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::invalidateTextureCache() { 77afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 78d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 79d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 80d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 81d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 82afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { 83d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 84d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 8609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 87d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 8909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 9009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 9109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 92d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 9409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 95d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 9809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 9909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 10109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 10309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk const uint8_t* cacheBuffer = state->getTextTextureData(); 11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t bX = 0, bY = 0; 11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("Skipping invalid index"); 12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk continue; 12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 12209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 126d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 127d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 12809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 13009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 13109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 13209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 13309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 13409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 13509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->bottom > nPenY) { 13609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->bottom = nPenY; 13709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->left > nPenX) { 13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->left = nPenX; 14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->right < nPenX + width) { 14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->right = nPenX + width; 14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->top < nPenY + height) { 14509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->top = nPenY + height; 14609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk RenderMode mode, Rect *bounds, 152afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 153afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 154d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 155d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 156d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 157afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mode == Font::MEASURE) { 15809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds == NULL) { 15909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("No return rectangle provided to measure text"); 16009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk return; 16109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 16209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk // Reset min and max of the bounding box to something large 16309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->set(1e6, -1e6, -1e6, 1e6); 16409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 16509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 16609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t penX = x, penY = y; 16709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t glyphsLeft = 1; 168afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 169d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft = numGlyphs; 170d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 171d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 172d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t index = start; 173d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t nextIndex = 0; 174d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 175d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk while (glyphsLeft > 0) { 176d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 177c9c38dd8508a2f805213abee1f9f44f103ac0a0dKenny Root int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); 178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 179d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reached the end of the string or encountered 180afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (utfChar < 0) { 181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Move to the next character in the array 185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk index = nextIndex; 186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 18701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 189d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 190afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph->mIsValid) { 191afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk switch (mode) { 19209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case FRAMEBUFFER: 19309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 19409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 19509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case BITMAP: 19609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 19709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 19809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case MEASURE: 19909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 20009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 202d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 203d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 204d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk penX += (cachedGlyph->mAdvance.x >> 6); 205d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 206d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 207afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 208d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft --; 209d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 210d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 211d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 21301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 21401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 21501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 216afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph == NULL) { 21701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 21801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 21901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Is the glyph still in texture cache? 220afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!cachedGlyph->mIsValid) { 22101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk updateGlyphCache(cachedGlyph); 22201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 22301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 22401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return cachedGlyph; 22501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 22601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 227afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) { 228a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 229afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 230a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk LOGE("Couldn't load glyph."); 231a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return; 232a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 233d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 234a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mAdvance = mFace->glyph->advance; 235a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 236a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 237d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 238a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 239d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 240d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 241d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 242d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 243d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 244d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Let the font state figure out where to put the bitmap 245d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 246a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 247d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 248afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!glyph->mIsValid) { 249d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 252a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endX = startX + bitmap->width; 253a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endY = startY + bitmap->rows; 254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 255d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinX = startX; 256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinY = startY; 257a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 258a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 259d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 260d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 261d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 262d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 264d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 266d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 269afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { 270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 271d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mIsValid = false; 275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk updateGlyphCache(newGlyph); 277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newGlyph; 279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 280d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 281afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi) { 28235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk rsc->mStateFont.checkInit(); 283d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 284d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 285afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < activeFonts.size(); i ++) { 286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *ithFont = activeFonts[i]; 287afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 288d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return ithFont; 289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 291d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *newFont = new Font(rsc); 293d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi); 294afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (isInitialized) { 295d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk activeFonts.push(newFont); 29601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 297d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newFont; 298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 299d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 300225afd317e101a7be5fe02c0a86361146ea89f05Jason Sams ObjectBase::checkDelete(newFont); 301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return NULL; 302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 304afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::~Font() { 305afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mFace) { 306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FT_Done_Face(mFace); 307d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 308d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 309d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (mRSC->mStateFont.mActiveFonts[ct] == this) { 311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->mStateFont.mActiveFonts.removeAt(ct); 312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 316afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 317d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete glyph; 319d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 322afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::FontState() { 323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mMaxNumberOfQuads = 1024; 325d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC = NULL; 3273659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 328c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 329c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the renderer properties 330c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 331c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 332c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the gamma 333c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 334c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 335c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text gamma to %s", property); 336c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk gamma = atof(property); 337c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 338c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA); 339c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 340c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 341c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the black gamma threshold 34209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text black gamma threshold to %s", property); 345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk blackThreshold = atoi(property); 346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default text black gamma threshold of %d", 348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD); 349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the white gamma threshold 35309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Setting text white gamma threshold to %s", property); 356c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk whiteThreshold = atoi(property); 357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else { 358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk LOGD(" Using default white black gamma threshold of %d", 359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD); 360c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 361c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 362c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 363c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Compute the gamma tables 364c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackGamma = gamma; 365c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteGamma = 1.0f / gamma; 3664f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 3674f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 368d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 369d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 370afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::~FontState() { 371afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 372d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 373d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 374d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 375d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 376d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 377d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 378afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFT_Library FontState::getLib() { 379afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mLibrary) { 380a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 381afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize freetype"); 383a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return NULL; 384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 3863659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 387a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 388a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 390afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::init(Context *rsc) { 391a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 393d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 394afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::flushAllAndInvalidate() { 395afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 399afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { 400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 401d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 402afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 403d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 406d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 407afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 409afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 419afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 421afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 427afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 431afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 433afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 439afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 45309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 45409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 457afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 458afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 45909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 467383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 470afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 472d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 473d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 475d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 476d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 477d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 478d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 479d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 480afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initRenderState() { 4817ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk String8 shaderString("varying vec2 varTex0;\n"); 482e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("void main() {\n"); 483e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 484e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 485c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 486e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 487e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("}\n"); 488e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 489e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 490c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 491e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 492e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 493c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); 494e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); 495e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 496f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false); 497e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 498e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk uint32_t tmp[4]; 499e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 500e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[1] = (uint32_t)inputType; 501e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT; 502e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[3] = 1; 503e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 504e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mFontShaderFConstant.set(new Allocation(mRSC, inputType)); 505e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 506e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.length(), tmp, 4); 507d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 508383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 509d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 510d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 511d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 512d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSampler.set(sampler); 513383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, sampler); 514d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 515d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 516d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore.set(fontStore); 517d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 518d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 519d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 520d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 521d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 522d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 523afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initTextTexture() { 524d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 525d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 526d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 527f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false); 528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *cacheAlloc = new Allocation(mRSC, texType); 530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture->deferedUploadToTexture(mRSC, false, 0); 532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 53409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nextLine = 0; 535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 536d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 53901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 54001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 546d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 551afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initVertexArrayBuffers() { 552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 555f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false); 556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *indexAlloc = new Allocation(mRSC, indexType); 558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 561afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 56209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i6 = i * 6; 56309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i4 = i * 4; 564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 566d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 567d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 568d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 58064cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 58164cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1); 58264cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1); 58364cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC); 584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 585f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *vertexDataType = Type::getType(mRSC, vertexDataElem, 586f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams mMaxNumberOfQuads * 4, 587f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams 0, 0, false, false); 588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType); 590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mVertexArray.set(vertexAlloc); 593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 596afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::checkInit() { 597afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 601d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 602d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 603d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 60635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 60735b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 60835b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 60935b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 61035b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("0123456789"); 61135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk 612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 613d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramVertex> tmpV(mRSC->getVertex()); 618d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex(mRSC->getDefaultProgramVertex()); 619d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 620d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk ObjectBaseRef<const ProgramRaster> tmpR(mRSC->getRaster()); 621d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster(mRSC->getDefaultProgramRaster()); 622d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk 623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramFragment> tmpF(mRSC->getFragment()); 624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment(mFontShaderF.get()); 625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ObjectBaseRef<const ProgramStore> tmpPS(mRSC->getFragmentStore()); 627d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore(mFontProgramStore.get()); 628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 629afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mConstantsDirty) { 630c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants)); 631c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = false; 632ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 633ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setVertex((ProgramVertex *)tmpV.get()); 636d18c744a37441311c9b65254a35db456835adad3Alex Sakhartchouk mRSC->setRaster((ProgramRaster *)tmpR.get()); 637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragment((ProgramFragment *)tmpF.get()); 638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->setFragmentStore((ProgramStore *)tmpPS.get()); 639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 642d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 643d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *tex = vtx + 3; 644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 64554929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk VertexArray::Attrib attribs[2]; 64654929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position"); 64754929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0"); 64854929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk VertexArray va(attribs, 2); 649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 651d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 652d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 653d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 654d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 655d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reset the state 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} 661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 663afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u1, float v1, 664afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x2, float y2, float z2, 665afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u2, float v2, 666afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x3, float y3, float z3, 667afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u3, float v3, 668afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x4, float y4, float z4, 669afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u4, float v4) { 670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t floatsPerVert = 5; 672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Cull things that are off the screen 675d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float width = (float)mRSC->getWidth(); 676d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float height = (float)mRSC->getHeight(); 677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 678afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 682d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 692d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 698d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 699d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 701d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 702d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 707d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 708d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 709d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 710d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 711d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 712d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 713afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex == mMaxNumberOfQuads) { 714d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 715d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 716d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 717d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 718d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 71901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 72001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 72135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 722afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 72301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 72401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 72501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 72601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 72701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 72801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 72901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 73001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 73101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 73201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 73301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 734afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 73501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 73601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 73701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 73801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 73901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 74001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 74101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 74209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 74309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 74409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::RenderMode mode, 74509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::Rect *bounds, 746afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 747d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 748d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 749d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 751afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 752afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mDefault.get()) { 753a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96)); 754a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 755a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk currentFont = mDefault.get(); 756a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 757afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 7583659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk LOGE("Unable to initialize any fonts"); 7593659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk return; 7603659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 7613659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 76209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 76309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 764d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 765afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 766d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 767d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 768d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 769d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 770d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 77109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 77209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 773d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 774d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 7759fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 776c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[0] = r; 777c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[1] = g; 778c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[2] = b; 779c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[3] = a; 780c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 781c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = 1.0f; 782c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 783c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (luminance <= mBlackThreshold) { 784c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mBlackGamma; 785c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 786c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mWhiteGamma; 787c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 7884f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 789c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = true; 7909fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk} 7919fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk 792ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 793c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *r = mConstants.mFontColor[0]; 794c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *g = mConstants.mFontColor[1]; 795c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *b = mConstants.mFontColor[2]; 796c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *a = mConstants.mFontColor[3]; 797ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk} 798ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 799afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::deinit(Context *rsc) { 800a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mInitialized = false; 801a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 80201b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines mFontShaderFConstant.clear(); 80301b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines 804a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mIndexBuffer.clear(); 805a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mVertexArray.clear(); 806a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 807a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontShaderF.clear(); 808a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontSampler.clear(); 809a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontProgramStore.clear(); 810a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 811a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mTextTexture.clear(); 812afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 813a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk delete mCacheLines[i]; 814d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 815a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mCacheLines.clear(); 816d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 817d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDefault.clear(); 818a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 8193659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk Vector<Font*> fontsToDereference = mActiveFonts; 820afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < fontsToDereference.size(); i ++) { 8213659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk fontsToDereference[i]->zeroUserRef(); 8223659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 8233659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 824afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mLibrary) { 825a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Done_FreeType( mLibrary ); 8263659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 827a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 828d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 829d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 830d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android { 831d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript { 832d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 833afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi) { 834a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 835afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (newFont) { 836a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk newFont->incUserRef(); 837a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 838a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return newFont; 839d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 840d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 841d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript 842d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android 843