rsFont.cpp revision 6d8eb266dd398abf0511685fdaf98abba3396174
19b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 29b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk/* 39b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * Copyright (C) 2009 The Android Open Source Project 49b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * 59b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License"); 69b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * you may not use this file except in compliance with the License. 79b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * You may obtain a copy of the License at 89b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * 99b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * http://www.apache.org/licenses/LICENSE-2.0 109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * 119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * Unless required by applicable law or agreed to in writing, software 129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS, 139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * See the License for the specific language governing permissions and 159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk * limitations under the License. 169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk */ 179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#ifndef ANDROID_RS_BUILD_FOR_HOST 199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include "rsContext.h" 209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#else 219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include "rsContextHostStub.h" 229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#endif 239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include "rsFont.h" 259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include "rsProgramFragment.h" 263bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk#include <cutils/properties.h> 279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include FT_BITMAP_H 289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include <GLES/gl.h> 309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include <GLES/glext.h> 319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include <GLES2/gl2.h> 329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include <GLES2/gl2ext.h> 339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukusing namespace android; 359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukusing namespace android::renderscript; 369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 37ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) { 389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = false; 399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mHasKerning = false; 40b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mFace = NULL; 419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 43ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukbool Font::init(const char *name, uint32_t fontSize, uint32_t dpi) { 44ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mInitialized) { 459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk String8 fontsDir("/fonts/"); 509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk fullPath += fontsDir; 529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk fullPath += name; 539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 54071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace); 55ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Unable to initialize font %s", fullPath.string()); 579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontName = name; 619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontSize = fontSize; 629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mDpi = dpi; 639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0); 65ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Unable to set font size on %s", fullPath.string()); 679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = true; 739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return true; 749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 76ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid Font::invalidateTextureCache() { 77ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 82ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { 839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 8610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 8910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 9010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 9110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 9310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 9410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 9610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 9710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 9810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 9910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 10010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk} 10110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 10210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 10310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 10410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 10510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 10610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 10710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 10810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 10910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 11010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 11110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 11210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk const uint8_t* cacheBuffer = state->getTextTextureData(); 11310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 11410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 11510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t bX = 0, bY = 0; 11610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 11710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 11810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 11910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk LOGE("Skipping invalid index"); 12010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk continue; 12110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 12210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 12310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 12410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 12510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 1269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 1279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 12810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 12910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 13010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 13110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 13210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 13310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 13410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 13510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds->bottom > nPenY) { 13610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->bottom = nPenY; 13710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 13810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds->left > nPenX) { 13910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->left = nPenX; 14010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 14110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds->right < nPenX + width) { 14210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->right = nPenX + width; 14310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 14410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds->top < nPenY + height) { 14510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->top = nPenY + height; 14610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 14710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk} 14810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 14910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 15010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 15110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk RenderMode mode, Rect *bounds, 152ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 153ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 1549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 1559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 157ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mode == Font::MEASURE) { 15810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds == NULL) { 15910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk LOGE("No return rectangle provided to measure text"); 16010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk return; 16110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 16210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk // Reset min and max of the bounding box to something large 16310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->set(1e6, -1e6, -1e6, 1e6); 16410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 16510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 16610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t penX = x, penY = y; 16710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t glyphsLeft = 1; 168ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (numGlyphs > 0) { 1699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyphsLeft = numGlyphs; 1709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t index = start; 1739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t nextIndex = 0; 1749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk while (glyphsLeft > 0) { 1769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 177300ba6846949f5b21c6d93d7698dbc39716cf832Kenny Root int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); 1789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Reached the end of the string or encountered 180ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (utfChar < 0) { 1819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 1829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Move to the next character in the array 1859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk index = nextIndex; 1869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 18794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 1889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 190ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (cachedGlyph->mIsValid) { 191ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk switch (mode) { 19210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk case FRAMEBUFFER: 19310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 19410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk break; 19510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk case BITMAP: 19610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 19710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk break; 19810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk case MEASURE: 19910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 20010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk break; 20110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 2029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk penX += (cachedGlyph->mAdvance.x >> 6); 2059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 207ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (numGlyphs > 0) { 2089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyphsLeft --; 2099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 21394bbccc36322168a596369c8341dad938c8f949fAlex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 21494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 21594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 216ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (cachedGlyph == NULL) { 21794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 21894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 21994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk // Is the glyph still in texture cache? 220ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!cachedGlyph->mIsValid) { 22194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk updateGlyphCache(cachedGlyph); 22294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 22394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 22494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk return cachedGlyph; 22594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk} 22694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 227ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) { 228071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 229ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 230071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk LOGE("Couldn't load glyph."); 231071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return; 232071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 2339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 234071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mAdvance = mFace->glyph->advance; 235071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 236071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 2379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 238071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 2399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now copy the bitmap into the cache texture 2419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startX = 0; 2429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startY = 0; 2439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Let the font state figure out where to put the bitmap 2459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 246071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 2479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 248ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!glyph->mIsValid) { 2499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 2509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 252071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 253071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 2549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinX = startX; 2569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinY = startY; 257071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 258071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 2599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 2619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 2629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 2649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 2659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 2669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 2679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 269ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { 2709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 2719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 2729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 2749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk newGlyph->mIsValid = false; 2759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk updateGlyphCache(newGlyph); 2779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return newGlyph; 2799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 281ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi) { 28227f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk rsc->mStateFont.checkInit(); 2839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 2849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 285ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < activeFonts.size(); i ++) { 2869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *ithFont = activeFonts[i]; 287ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 2889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return ithFont; 2899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *newFont = new Font(rsc); 2939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi); 294ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (isInitialized) { 2959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk activeFonts.push(newFont); 29694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 2979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return newFont; 2989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 300b38d534873ca514f5a5230596c838aa37eca1568Jason Sams ObjectBase::checkDelete(newFont); 3019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return NULL; 3029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 304ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFont::~Font() { 305ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mFace) { 3069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FT_Done_Face(mFace); 3079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 3109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if (mRSC->mStateFont.mActiveFonts[ct] == this) { 3119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->mStateFont.mActiveFonts.removeAt(ct); 3129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 3139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 316ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 3179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 3189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk delete glyph; 3199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 322ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFontState::FontState() { 3239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = false; 3249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mMaxNumberOfQuads = 1024; 3259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 3269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC = NULL; 327b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mLibrary = NULL; 3283bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3293bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the renderer properties 3303bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 3313bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3323bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the gamma 3333bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 3343bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 3353bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk LOGD(" Setting text gamma to %s", property); 3363bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk gamma = atof(property); 3373bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } else { 3383bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA); 3393bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 3403bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3413bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the black gamma threshold 34210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 3433bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 3443bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk LOGD(" Setting text black gamma threshold to %s", property); 3453bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk blackThreshold = atoi(property); 3463bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } else { 3473bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk LOGD(" Using default text black gamma threshold of %d", 3483bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD); 3493bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 3503bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 3513bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3523bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the white gamma threshold 35310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 3543bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 3553bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk LOGD(" Setting text white gamma threshold to %s", property); 3563bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk whiteThreshold = atoi(property); 3573bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } else { 3583bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk LOGD(" Using default white black gamma threshold of %d", 3593bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD); 3603bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 3613bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 3623bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3633bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Compute the gamma tables 3643bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mBlackGamma = gamma; 3653bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mWhiteGamma = 1.0f / gamma; 366960ae15cf37fe31790e255521ee2045312e82d36Alex Sakhartchouk 367960ae15cf37fe31790e255521ee2045312e82d36Alex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 3689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 370ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFontState::~FontState() { 371ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 3729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk delete mCacheLines[i]; 3739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 3769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 378ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFT_Library FontState::getLib() { 379ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!mLibrary) { 380071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 381ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 3829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Unable to initialize freetype"); 383071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return NULL; 3849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 386b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 387071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return mLibrary; 388071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk} 3899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 390ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::init(Context *rsc) { 391071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mRSC = rsc; 3929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 394ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::flushAllAndInvalidate() { 395ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mCurrentQuadIndex != 0) { 3969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 3979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 3989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 399ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { 4009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 4019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 402ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 4049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 4069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 407ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 4089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If the glyph is too tall, don't cache it 409ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 4109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 4119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 4129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now copy the bitmap into the cache texture 4159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startX = 0; 4169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startY = 0; 4179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bool bitmapFit = false; 419ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 421ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (bitmapFit) { 4229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 4239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 427ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!bitmapFit) { 4289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk flushAllAndInvalidate(); 4299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Try to fit it again 431ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 433ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (bitmapFit) { 4349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 4359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 439ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!bitmapFit) { 4409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 4419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 4429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *retOriginX = startX; 4469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *retOriginY = startY; 4479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 4499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 4509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 4529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 45310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 45410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 4559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 457ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 458ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 45910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 4609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 4619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // This will dirty the texture and the shader so next time 4659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // we draw it will upload the data 4666d8eb266dd398abf0511685fdaf98abba3396174Jason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 467b89aaacb2ca9d062e0a17a32e3d4dbf3f6948a17Alex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 4689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Some debug code 470ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 4729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 4739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 4749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk }*/ 4769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return true; 4789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 4799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 480ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::initRenderState() { 481d2091639be426574c04f74969fe553162d7a51c9Alex Sakhartchouk String8 shaderString("varying vec2 varTex0;\n"); 482c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append("void main() {\n"); 483c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 484c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 4853bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 486c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 487c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append("}\n"); 488c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 489c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 4903bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 491c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 492c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 4933bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); 494c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); 495c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 49631a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false); 497c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 498c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk uint32_t tmp[4]; 499c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 500c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk tmp[1] = (uint32_t)inputType; 50167f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; 50267f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk tmp[3] = RS_TEXTURE_2D; 503c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 5045476b450e50939940dcf3f15c92335cee2fc572dJason Sams mFontShaderFConstant.set(new Allocation(mRSC, inputType, 5055476b450e50939940dcf3f15c92335cee2fc572dJason Sams RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); 506c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 507c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.length(), tmp, 4); 5089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontShaderF.set(pf); 509b89aaacb2ca9d062e0a17a32e3d4dbf3f6948a17Alex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 5109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 5129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 5139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontSampler.set(sampler); 514b89aaacb2ca9d062e0a17a32e3d4dbf3f6948a17Alex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, sampler); 5159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 5179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore.set(fontStore); 5189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 5199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 5209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 5219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 5229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 524ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::initTextTexture() { 5259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 5269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 52831a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false); 5299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5305476b450e50939940dcf3f15c92335cee2fc572dJason Sams Allocation *cacheAlloc = new Allocation(mRSC, texType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE); 5319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mTextTexture.set(cacheAlloc); 5326d8eb266dd398abf0511685fdaf98abba3396174Jason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 5339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Split up our cache texture into lines of certain widths 53510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nextLine = 0; 5369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 5379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 5399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 54094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 54194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 5439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 5459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 5479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 5499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 552ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::initVertexArrayBuffers() { 5539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now lets write index data 5549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 5559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 55631a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false); 5579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5585476b450e50939940dcf3f15c92335cee2fc572dJason Sams Allocation *indexAlloc = new Allocation(mRSC, indexType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 5599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 5609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Four verts, two triangles , six indices per quad 562ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 56310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t i6 = i * 6; 56410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t i4 = i * 4; 5659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 5679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 5689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 5699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 5719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 5729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 5739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 5749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 5769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 5779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 5799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 5809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 58198bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 58298bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1); 58398bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1); 58498bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC); 5859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 58631a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *vertexDataType = Type::getType(mRSC, vertexDataElem, 58731a7e42f4baa059352f0db119de38428e655eab2Jason Sams mMaxNumberOfQuads * 4, 58831a7e42f4baa059352f0db119de38428e655eab2Jason Sams 0, 0, false, false); 5899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5905476b450e50939940dcf3f15c92335cee2fc572dJason Sams Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 5919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 5929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mVertexArray.set(vertexAlloc); 5949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 597ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::checkInit() { 598ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mInitialized) { 5999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 6009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initTextTexture(); 6039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initRenderState(); 6049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initVertexArrayBuffers(); 6069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 60727f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 60827f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 60927f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 61027f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 61127f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache += String8("0123456789"); 61227f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk 6139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = true; 6149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 6159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::issueDrawCommand() { 617a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams Context::PushState ps(mRSC); 6189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 619a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramVertex(mRSC->getDefaultProgramVertex()); 620a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramRaster(mRSC->getDefaultProgramRaster()); 621a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramFragment(mFontShaderF.get()); 622a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramStore(mFontProgramStore.get()); 6239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 624ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mConstantsDirty) { 6253bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants)); 6263bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstantsDirty = false; 62755e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk } 62855e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk 6299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if (!mRSC->setupCheck()) { 6309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 6319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 6349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float *tex = vtx + 3; 6359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6369d71e2180062931416092f26276a07e55b318f62Alex Sakhartchouk VertexArray::Attrib attribs[2]; 6379d71e2180062931416092f26276a07e55b318f62Alex Sakhartchouk attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position"); 6389d71e2180062931416092f26276a07e55b318f62Alex Sakhartchouk attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0"); 6399d71e2180062931416092f26276a07e55b318f62Alex Sakhartchouk VertexArray va(attribs, 2); 6409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 6419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 6439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 6449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 6459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 6469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 648ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float u1, float v1, 649ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float x2, float y2, float z2, 650ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float u2, float v2, 651ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float x3, float y3, float z3, 652ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float u3, float v3, 653ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float x4, float y4, float z4, 654ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float u4, float v4) { 6559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 6569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const uint32_t floatsPerVert = 5; 6579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 6589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Cull things that are off the screen 6609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float width = (float)mRSC->getWidth(); 6619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float height = (float)mRSC->getHeight(); 6629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 663ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 6649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 6659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 6689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 6699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 6709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 6719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x1; 6739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y1; 6749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z1; 6759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u1; 6769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v1; 6779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x2; 6799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y2; 6809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z2; 6819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u2; 6829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v2; 6839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x3; 6859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y3; 6869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z3; 6879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u3; 6889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v3; 6899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x4; 6919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y4; 6929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z4; 6939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u4; 6949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v4; 6959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex ++; 6979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 698ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mCurrentQuadIndex == mMaxNumberOfQuads) { 6999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 7009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 7019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 7029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 7039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 70494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 70594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk uint32_t remainingCapacity = 0; 70627f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk uint32_t totalPixels = 0; 707ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 70894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 70994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 71094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 71194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 71294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk return remainingCapacity; 71394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk} 71494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 71594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 71694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk // Remaining capacity is measured in % 71794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 71894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk uint32_t precacheIdx = 0; 719ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 72094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 72194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 72294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk precacheIdx ++; 72394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 72494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk} 72594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 72694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 72710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 72810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 72910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk Font::RenderMode mode, 73010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk Font::Rect *bounds, 731ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 7329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk checkInit(); 7339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 7349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Render code here 7359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 736ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!currentFont) { 737ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!mDefault.get()) { 738071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96)); 739071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 740071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk currentFont = mDefault.get(); 741071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 742ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!currentFont) { 743b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk LOGE("Unable to initialize any fonts"); 744b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk return; 745b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk } 746b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 74710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 74810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 7499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 750ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mCurrentQuadIndex != 0) { 7519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 7529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 7539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 7549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 7559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 75610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 75710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 7589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 7599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 760fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 7613bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[0] = r; 7623bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[1] = g; 7633bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[2] = b; 7643bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[3] = a; 7653bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 7663bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mGamma = 1.0f; 76776322af2a6c109a79431f019dcef6e038c030686Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 7683bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (luminance <= mBlackThreshold) { 7693bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mGamma = mBlackGamma; 7703bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 7713bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mGamma = mWhiteGamma; 7723bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 773960ae15cf37fe31790e255521ee2045312e82d36Alex Sakhartchouk 7743bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstantsDirty = true; 775fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk} 776fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk 77755e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 7783bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *r = mConstants.mFontColor[0]; 7793bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *g = mConstants.mFontColor[1]; 7803bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *b = mConstants.mFontColor[2]; 7813bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *a = mConstants.mFontColor[3]; 78255e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk} 78355e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk 784ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::deinit(Context *rsc) { 785071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mInitialized = false; 786071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 78701f0ad7c13b8878c2167bff10ea875d7509edca5Stephen Hines mFontShaderFConstant.clear(); 78801f0ad7c13b8878c2167bff10ea875d7509edca5Stephen Hines 789071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mIndexBuffer.clear(); 790071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mVertexArray.clear(); 791071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 792071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontShaderF.clear(); 793071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontSampler.clear(); 794071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontProgramStore.clear(); 795071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 796071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mTextTexture.clear(); 797ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 798071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk delete mCacheLines[i]; 7999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 800071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mCacheLines.clear(); 8019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mDefault.clear(); 803071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 804b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk Vector<Font*> fontsToDereference = mActiveFonts; 805ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < fontsToDereference.size(); i ++) { 806b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk fontsToDereference[i]->zeroUserRef(); 807b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk } 808b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 809ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mLibrary) { 810071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Done_FreeType( mLibrary ); 811b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mLibrary = NULL; 812071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 8139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 8149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouknamespace android { 8169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouknamespace renderscript { 8179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 818ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi) { 819071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 820ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (newFont) { 821071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk newFont->incUserRef(); 822071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 823071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return newFont; 8249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 8259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} // renderscript 8279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} // android 828