rsFont.cpp revision 17a8a1939d4cbc74de54954c67f3dd61882420aa
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#include "rsContext.h" 199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include "rsFont.h" 219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include "rsProgramFragment.h" 223bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk#include <cutils/properties.h> 23ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk 2417a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 25ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk#include <ft2build.h> 26ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk#include FT_FREETYPE_H 279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk#include FT_BITMAP_H 2817a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukusing namespace android; 319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukusing namespace android::renderscript; 329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 33ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) { 349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = false; 359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mHasKerning = false; 36b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mFace = NULL; 379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 39b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchoukbool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) { 4017a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 41ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mInitialized) { 429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 46b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk FT_Error error = 0; 47b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk if (data != NULL && dataLen > 0) { 48b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace); 49b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk } else { 50b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace); 51b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk } 52b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk 53ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 54e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk LOGE("Unable to initialize font %s", name); 559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontName = name; 599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontSize = fontSize; 609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mDpi = dpi; 619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 62e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0); 63ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 64e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk LOGE("Unable to set font size on %s", name); 659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = true; 7117a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return true; 739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 7538f8d9d7a17037a34f4df229b1089536a6cdc8dcJason Samsvoid Font::preDestroy() const { 7638f8d9d7a17037a34f4df229b1089536a6cdc8dcJason Sams for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 7738f8d9d7a17037a34f4df229b1089536a6cdc8dcJason Sams if (mRSC->mStateFont.mActiveFonts[ct] == this) { 7838f8d9d7a17037a34f4df229b1089536a6cdc8dcJason Sams mRSC->mStateFont.mActiveFonts.removeAt(ct); 7938f8d9d7a17037a34f4df229b1089536a6cdc8dcJason Sams break; 8038f8d9d7a17037a34f4df229b1089536a6cdc8dcJason Sams } 8138f8d9d7a17037a34f4df229b1089536a6cdc8dcJason Sams } 8238f8d9d7a17037a34f4df229b1089536a6cdc8dcJason Sams} 8338f8d9d7a17037a34f4df229b1089536a6cdc8dcJason Sams 84ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid Font::invalidateTextureCache() { 85ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 90ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { 919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 9310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 9410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 9610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 9710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 9810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 9910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 1009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 10110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 10210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 1039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 10410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 10510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 10610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 10710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 10810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk} 10910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 11010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 11110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 11210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 11310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 11410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 11510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 11610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 11710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 11810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 11910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 12010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk const uint8_t* cacheBuffer = state->getTextTextureData(); 12110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 12210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 12310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t bX = 0, bY = 0; 12410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 12510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 12610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 12710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk LOGE("Skipping invalid index"); 12810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk continue; 12910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 13010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 13110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 13210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 13310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 1349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 1359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 13610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 13710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 13810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 13910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 14010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 14110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 14210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 143b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk // 0, 0 is top left, so bottom is a positive number 144b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk if (bounds->bottom < nPenY) { 14510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->bottom = nPenY; 14610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 14710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds->left > nPenX) { 14810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->left = nPenX; 14910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 15010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds->right < nPenX + width) { 15110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->right = nPenX + width; 15210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 153b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk if (bounds->top > nPenY - height) { 154b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk bounds->top = nPenY - height; 15510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 15610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk} 15710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 15810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 15910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 16010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk RenderMode mode, Rect *bounds, 161ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 162ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 1639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 1649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 166ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mode == Font::MEASURE) { 16710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds == NULL) { 16810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk LOGE("No return rectangle provided to measure text"); 16910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk return; 17010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 17110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk // Reset min and max of the bounding box to something large 172b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk bounds->set(1e6, -1e6, 1e6, -1e6); 17310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 17410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 17510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t penX = x, penY = y; 17610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t glyphsLeft = 1; 177ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (numGlyphs > 0) { 1789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyphsLeft = numGlyphs; 1799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t index = start; 1829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t nextIndex = 0; 1839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk while (glyphsLeft > 0) { 1859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 186300ba6846949f5b21c6d93d7698dbc39716cf832Kenny Root int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); 1879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Reached the end of the string or encountered 189ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (utfChar < 0) { 1909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 1919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Move to the next character in the array 1949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk index = nextIndex; 1959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 19694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 1979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 199ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (cachedGlyph->mIsValid) { 200ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk switch (mode) { 20110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk case FRAMEBUFFER: 20210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 20310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk break; 20410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk case BITMAP: 20510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 20610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk break; 20710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk case MEASURE: 20810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 20910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk break; 21010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 2119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 213ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk penX += (cachedGlyph->mAdvanceX >> 6); 2149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 216ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (numGlyphs > 0) { 2179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyphsLeft --; 2189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 22294bbccc36322168a596369c8341dad938c8f949fAlex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 22394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 22494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 225ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (cachedGlyph == NULL) { 22694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 22794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 22894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk // Is the glyph still in texture cache? 229ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!cachedGlyph->mIsValid) { 23094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk updateGlyphCache(cachedGlyph); 23194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 23294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 23394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk return cachedGlyph; 23494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk} 23594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 236ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) { 23717a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 238071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 239ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 240071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk LOGE("Couldn't load glyph."); 241071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return; 242071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 2439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 244ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk glyph->mAdvanceX = mFace->glyph->advance.x; 245ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk glyph->mAdvanceY = mFace->glyph->advance.y; 246071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 247071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 2489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 249071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 2509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now copy the bitmap into the cache texture 2529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startX = 0; 2539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startY = 0; 2549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Let the font state figure out where to put the bitmap 2569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 257071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 2589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 259ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!glyph->mIsValid) { 2609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 2619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 263071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 264071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 2659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinX = startX; 2679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinY = startY; 268071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 269071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 2709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 2729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 2739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 2759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 2769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 2779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 27817a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 2799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 281ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { 2829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 2839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 28417a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 2859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 2869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk newGlyph->mIsValid = false; 28717a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 2889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk updateGlyphCache(newGlyph); 2899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return newGlyph; 2919b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 293b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex SakhartchoukFont * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi, 294b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk const void *data, uint32_t dataLen) { 29527f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk rsc->mStateFont.checkInit(); 2969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 2979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 298ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < activeFonts.size(); i ++) { 2999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *ithFont = activeFonts[i]; 300ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 3019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return ithFont; 3029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *newFont = new Font(rsc); 306b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen); 307ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (isInitialized) { 3089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk activeFonts.push(newFont); 30994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 3109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return newFont; 3119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 313b38d534873ca514f5a5230596c838aa37eca1568Jason Sams ObjectBase::checkDelete(newFont); 3149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return NULL; 3159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 317ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFont::~Font() { 31817a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 319ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mFace) { 3209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FT_Done_Face(mFace); 3219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 32217a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#endif 3239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 324ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 3259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 3269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk delete glyph; 3279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 330ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFontState::FontState() { 3319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = false; 3329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mMaxNumberOfQuads = 1024; 3339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 3349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC = NULL; 33517a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 336b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mLibrary = NULL; 33717a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 3383bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3393bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the renderer properties 3403bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 3413bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3423bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the gamma 3433bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 3443bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 3453bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk gamma = atof(property); 3463bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 3473bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3483bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the black gamma threshold 34910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 3503bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 3513bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk blackThreshold = atoi(property); 3523bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 3533bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 3543bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3553bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the white gamma threshold 35610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 3573bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 3583bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk whiteThreshold = atoi(property); 3593bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 3603bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 3613bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3623bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Compute the gamma tables 3633bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mBlackGamma = gamma; 3643bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mWhiteGamma = 1.0f / gamma; 365960ae15cf37fe31790e255521ee2045312e82d36Alex Sakhartchouk 366960ae15cf37fe31790e255521ee2045312e82d36Alex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 3679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 369ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFontState::~FontState() { 370ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 3719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk delete mCacheLines[i]; 3729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 3759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 37617a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 377ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFT_Library FontState::getLib() { 378ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!mLibrary) { 379071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 380ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 3819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Unable to initialize freetype"); 382071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return NULL; 3839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 385b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 386071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return mLibrary; 387071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk} 38817a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 38917a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk 3909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 391ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::init(Context *rsc) { 392071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mRSC = rsc; 3939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 395ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::flushAllAndInvalidate() { 396ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mCurrentQuadIndex != 0) { 3979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 3989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 3999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 400ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { 4019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 4029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 403ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 4059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 4079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 40817a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 409ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 4109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If the glyph is too tall, don't cache it 411ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 4129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 4139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 4149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now copy the bitmap into the cache texture 4179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startX = 0; 4189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startY = 0; 4199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bool bitmapFit = false; 421ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 423ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (bitmapFit) { 4249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 4259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 429ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!bitmapFit) { 4309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk flushAllAndInvalidate(); 4319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Try to fit it again 433ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 435ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (bitmapFit) { 4369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 4379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 441ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!bitmapFit) { 4429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 4439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 4449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *retOriginX = startX; 4489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *retOriginY = startY; 4499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 4519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 4529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 4549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 45510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 45610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 4579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 459ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 460ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 46110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 4629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 4639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // This will dirty the texture and the shader so next time 4679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // we draw it will upload the data 4687e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams 4697e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams mTextTexture->sendDirty(mRSC); 470b89aaacb2ca9d062e0a17a32e3d4dbf3f6948a17Alex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 4719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Some debug code 473ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 4759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 4769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 4779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk }*/ 4799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return true; 4819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 48217a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 4839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 484ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::initRenderState() { 485d2091639be426574c04f74969fe553162d7a51c9Alex Sakhartchouk String8 shaderString("varying vec2 varTex0;\n"); 486c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append("void main() {\n"); 487c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 488c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 4893bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 490c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 491c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append("}\n"); 492c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 493c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 4943bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 495c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 496c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 4973bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); 498c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); 499c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 50031a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false); 501c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 502c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk uint32_t tmp[4]; 503c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 504c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk tmp[1] = (uint32_t)inputType; 50567f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; 50667f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk tmp[3] = RS_TEXTURE_2D; 507c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 5087e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType, 5095476b450e50939940dcf3f15c92335cee2fc572dJason Sams RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); 510c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 511c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.length(), tmp, 4); 5129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontShaderF.set(pf); 513b89aaacb2ca9d062e0a17a32e3d4dbf3f6948a17Alex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 5149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 5169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 5179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontSampler.set(sampler); 518b89aaacb2ca9d062e0a17a32e3d4dbf3f6948a17Alex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, sampler); 5199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 520331bf9b14b1c5c1e88f5c4092b6e24fae887fb3bJason Sams ProgramStore *fontStore = new ProgramStore(mRSC, true, true, true, true, 521331bf9b14b1c5c1e88f5c4092b6e24fae887fb3bJason Sams false, false, 522bd184c55850997a5c5e285357998dadbe95b7b5dJason Sams RS_BLEND_SRC_SRC_ALPHA, 523bd184c55850997a5c5e285357998dadbe95b7b5dJason Sams RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, 524331bf9b14b1c5c1e88f5c4092b6e24fae887fb3bJason Sams RS_DEPTH_FUNC_ALWAYS); 5259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore.set(fontStore); 52648f505657adba4d9156856e7d5593f23af5d5d5aJason Sams mFontProgramStore->init(); 5279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 529ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::initTextTexture() { 5309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 5319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 53331a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false); 5349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5357e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType, 5367e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE); 5379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mTextTexture.set(cacheAlloc); 5386d8eb266dd398abf0511685fdaf98abba3396174Jason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 5399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Split up our cache texture into lines of certain widths 54110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nextLine = 0; 5429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 5439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 5459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 54694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 54794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 5499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 5519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 5539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 5559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 558ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::initVertexArrayBuffers() { 5599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now lets write index data 5609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 5619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 56231a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false); 5639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5647e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType, 5657e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams RS_ALLOCATION_USAGE_SCRIPT | 5667e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 5679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 5689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Four verts, two triangles , six indices per quad 570ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 57110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t i6 = i * 6; 57210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t i4 = i * 4; 5739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 5759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 5769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 5779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 5799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 5809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 5819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 5829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5837e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams indexAlloc->sendDirty(mRSC); 5849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 5869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 5879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 58898bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 58998bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1); 59098bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1); 59198bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC); 5929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 59331a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *vertexDataType = Type::getType(mRSC, vertexDataElem, 59431a7e42f4baa059352f0db119de38428e655eab2Jason Sams mMaxNumberOfQuads * 4, 59531a7e42f4baa059352f0db119de38428e655eab2Jason Sams 0, 0, false, false); 5969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5977e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType, 5987e8aae7f76f221905fba7ccbcb3442c6f96dfad2Jason Sams RS_ALLOCATION_USAGE_SCRIPT); 5999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 6009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6014a36b45c72b91045db49c54d33fd7a05fc5a7a3dAlex Sakhartchouk mMesh.set(new Mesh(mRSC, 1, 1)); 6024a36b45c72b91045db49c54d33fd7a05fc5a7a3dAlex Sakhartchouk mMesh->setVertexBuffer(vertexAlloc, 0); 6034a36b45c72b91045db49c54d33fd7a05fc5a7a3dAlex Sakhartchouk mMesh->setPrimitive(indexAlloc, RS_PRIMITIVE_TRIANGLE, 0); 6044a36b45c72b91045db49c54d33fd7a05fc5a7a3dAlex Sakhartchouk mMesh->init(); 6059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 6069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 608ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::checkInit() { 609ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mInitialized) { 6109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 6119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initTextTexture(); 6149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initRenderState(); 6159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initVertexArrayBuffers(); 6179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 61827f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 61927f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 62027f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 62127f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 62227f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache += String8("0123456789"); 62327f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk 6249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = true; 6259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 6269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::issueDrawCommand() { 628a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams Context::PushState ps(mRSC); 6299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 630a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramVertex(mRSC->getDefaultProgramVertex()); 631a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramRaster(mRSC->getDefaultProgramRaster()); 632a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramFragment(mFontShaderF.get()); 633a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramStore(mFontProgramStore.get()); 6349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 635ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mConstantsDirty) { 63649a05d7b82956009f03acbb92a064eed054eb031Jason Sams mFontShaderFConstant->data(mRSC, 0, 0, 1, &mConstants, sizeof(mConstants)); 6373bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstantsDirty = false; 63855e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk } 63955e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk 6409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if (!mRSC->setupCheck()) { 6419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 6429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6444a36b45c72b91045db49c54d33fd7a05fc5a7a3dAlex Sakhartchouk mMesh->renderPrimitiveRange(mRSC, 0, 0, mCurrentQuadIndex * 6); 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()) { 738e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk String8 fontsDir("/fonts/DroidSans.ttf"); 739e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 740e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk fullPath += fontsDir; 741e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk 7422c74ad9aae29cc64fece926f353825a7925792c2Alex Sakhartchouk mDefault.set(Font::create(mRSC, fullPath.string(), 8, mRSC->getDPI())); 743071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 744071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk currentFont = mDefault.get(); 745071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 746ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!currentFont) { 747b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk LOGE("Unable to initialize any fonts"); 748b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk return; 749b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk } 750b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 75110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 75210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 7539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 754ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mCurrentQuadIndex != 0) { 7559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 7569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 7579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 7589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 7599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 76010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 76110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 762b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk bounds->bottom = - bounds->bottom; 763b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk bounds->top = - bounds->top; 7649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 7659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 766fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 7673bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[0] = r; 7683bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[1] = g; 7693bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[2] = b; 7703bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[3] = a; 7713bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 7723bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mGamma = 1.0f; 77376322af2a6c109a79431f019dcef6e038c030686Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 7743bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (luminance <= mBlackThreshold) { 7753bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mGamma = mBlackGamma; 7763bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 7773bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mGamma = mWhiteGamma; 7783bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 779960ae15cf37fe31790e255521ee2045312e82d36Alex Sakhartchouk 7803bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstantsDirty = true; 781fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk} 782fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk 78355e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 7843bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *r = mConstants.mFontColor[0]; 7853bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *g = mConstants.mFontColor[1]; 7863bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *b = mConstants.mFontColor[2]; 7873bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *a = mConstants.mFontColor[3]; 78855e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk} 78955e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk 790ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::deinit(Context *rsc) { 791071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mInitialized = false; 792071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 79301f0ad7c13b8878c2167bff10ea875d7509edca5Stephen Hines mFontShaderFConstant.clear(); 79401f0ad7c13b8878c2167bff10ea875d7509edca5Stephen Hines 7954a36b45c72b91045db49c54d33fd7a05fc5a7a3dAlex Sakhartchouk mMesh.clear(); 796071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 797071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontShaderF.clear(); 798071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontSampler.clear(); 799071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontProgramStore.clear(); 800071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 801071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mTextTexture.clear(); 802ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 803071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk delete mCacheLines[i]; 8049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 805071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mCacheLines.clear(); 8069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mDefault.clear(); 80817a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 809ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mLibrary) { 810071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Done_FreeType( mLibrary ); 811b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mLibrary = NULL; 812071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 81317a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 8149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 8159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 81617a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 817ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchoukbool FontState::CacheTextureLine::fitBitmap(FT_Bitmap_ *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 818ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk if ((uint32_t)bitmap->rows > mMaxHeight) { 819ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk return false; 820ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk } 821ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk 822ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk if (mCurrentCol + (uint32_t)bitmap->width < mMaxWidth) { 823ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk *retOriginX = mCurrentCol; 824ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk *retOriginY = mCurrentRow; 825ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk mCurrentCol += bitmap->width; 826ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk mDirty = true; 827ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk return true; 828ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk } 829ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk 830ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk return false; 831ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk} 83217a8a1939d4cbc74de54954c67f3dd61882420aaAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 833ebd65bbb848b2f3ee8dc55e485d201c681361d15Alex Sakhartchouk 8349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouknamespace android { 8359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouknamespace renderscript { 8369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 837e7c4a7565c7f8c8fc1ec92dc0692577fcc474750Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, 838e7c4a7565c7f8c8fc1ec92dc0692577fcc474750Alex Sakhartchouk char const *name, size_t name_length, 839e7c4a7565c7f8c8fc1ec92dc0692577fcc474750Alex Sakhartchouk float fontSize, uint32_t dpi) { 840071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 841ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (newFont) { 842071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk newFont->incUserRef(); 843071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 844071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return newFont; 8459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 8469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 847e7c4a7565c7f8c8fc1ec92dc0692577fcc474750Alex SakhartchoukRsFont rsi_FontCreateFromMemory(Context *rsc, 848e7c4a7565c7f8c8fc1ec92dc0692577fcc474750Alex Sakhartchouk char const *name, size_t name_length, 849e7c4a7565c7f8c8fc1ec92dc0692577fcc474750Alex Sakhartchouk float fontSize, uint32_t dpi, 850e7c4a7565c7f8c8fc1ec92dc0692577fcc474750Alex Sakhartchouk const void *data, size_t data_length) { 851e7c4a7565c7f8c8fc1ec92dc0692577fcc474750Alex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi, data, data_length); 852b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk if (newFont) { 853b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk newFont->incUserRef(); 854b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk } 855b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk return newFont; 856b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk} 857b0253ea6969bdd27bf574e0da7fa91aa6d09f44fAlex Sakhartchouk 8589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} // renderscript 8599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} // android 860