rsFont.cpp revision e27cdeeecba5b445e307d653d9cb7da007adfac3
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 43e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchoukbool Font::init(const char *name, float fontSize, uint32_t dpi) { 44ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mInitialized) { 459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 49e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace); 50ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 51e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk LOGE("Unable to initialize font %s", name); 529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontName = name; 569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontSize = fontSize; 579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mDpi = dpi; 589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 59e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0); 60ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 61e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk LOGE("Unable to set font size on %s", name); 629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = true; 689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return true; 699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 71ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid Font::invalidateTextureCache() { 72ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 77ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { 789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 8110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 8410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 8510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 8610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 8910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 9110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 9210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 9310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 9410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 9510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk} 9610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 9710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 9810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 9910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 10010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 10110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 10210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 10310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 10410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 10510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 10610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 10710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk const uint8_t* cacheBuffer = state->getTextTextureData(); 10810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 10910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 11010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t bX = 0, bY = 0; 11110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 11210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 11310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 11410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk LOGE("Skipping invalid index"); 11510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk continue; 11610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 11710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 11810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 11910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 12010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 1219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 1229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 12310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 12410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 12510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 12610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 12710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 12810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 12910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 13010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds->bottom > nPenY) { 13110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->bottom = nPenY; 13210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 13310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds->left > nPenX) { 13410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->left = nPenX; 13510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 13610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds->right < nPenX + width) { 13710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->right = nPenX + width; 13810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 13910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds->top < nPenY + height) { 14010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->top = nPenY + height; 14110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 14210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk} 14310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 14410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 14510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 14610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk RenderMode mode, Rect *bounds, 147ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 148ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 1499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 1509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 152ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mode == Font::MEASURE) { 15310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk if (bounds == NULL) { 15410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk LOGE("No return rectangle provided to measure text"); 15510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk return; 15610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 15710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk // Reset min and max of the bounding box to something large 15810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk bounds->set(1e6, -1e6, -1e6, 1e6); 15910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 16010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk 16110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t penX = x, penY = y; 16210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t glyphsLeft = 1; 163ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (numGlyphs > 0) { 1649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyphsLeft = numGlyphs; 1659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t index = start; 1689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk size_t nextIndex = 0; 1699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk while (glyphsLeft > 0) { 1719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 172300ba6846949f5b21c6d93d7698dbc39716cf832Kenny Root int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); 1739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Reached the end of the string or encountered 175ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (utfChar < 0) { 1769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 1779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Move to the next character in the array 1809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk index = nextIndex; 1819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 18294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 1839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 185ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (cachedGlyph->mIsValid) { 186ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk switch (mode) { 18710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk case FRAMEBUFFER: 18810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 18910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk break; 19010825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk case BITMAP: 19110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 19210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk break; 19310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk case MEASURE: 19410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 19510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk break; 19610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk } 1979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 1989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 1999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk penX += (cachedGlyph->mAdvance.x >> 6); 2009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 202ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (numGlyphs > 0) { 2039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyphsLeft --; 2049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 20894bbccc36322168a596369c8341dad938c8f949fAlex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 20994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 21094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 211ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (cachedGlyph == NULL) { 21294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 21394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 21494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk // Is the glyph still in texture cache? 215ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!cachedGlyph->mIsValid) { 21694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk updateGlyphCache(cachedGlyph); 21794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 21894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 21994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk return cachedGlyph; 22094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk} 22194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 222ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) { 223071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 224ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 225071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk LOGE("Couldn't load glyph."); 226071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return; 227071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 2289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 229071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mAdvance = mFace->glyph->advance; 230071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 231071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 2329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 233071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 2349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now copy the bitmap into the cache texture 2369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startX = 0; 2379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startY = 0; 2389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Let the font state figure out where to put the bitmap 2409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 241071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 2429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 243ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!glyph->mIsValid) { 2449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 2459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 247071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 248071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 2499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinX = startX; 2519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinY = startY; 252071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 253071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 2549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 2569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 2579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 2599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 2609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 2619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 2629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 264ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { 2659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 2669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 2679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 2699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk newGlyph->mIsValid = false; 2709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk updateGlyphCache(newGlyph); 2729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return newGlyph; 2749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 276e27cdeeecba5b445e307d653d9cb7da007adfac3Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi) { 27727f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk rsc->mStateFont.checkInit(); 2789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 2799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 280ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < activeFonts.size(); i ++) { 2819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *ithFont = activeFonts[i]; 282ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 2839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return ithFont; 2849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 2879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *newFont = new Font(rsc); 2889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi); 289ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (isInitialized) { 2909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk activeFonts.push(newFont); 29194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 2929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return newFont; 2939b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 2949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 295b38d534873ca514f5a5230596c838aa37eca1568Jason Sams ObjectBase::checkDelete(newFont); 2969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return NULL; 2979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 2989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 299ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFont::~Font() { 300ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mFace) { 3019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk FT_Done_Face(mFace); 3029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 3059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if (mRSC->mStateFont.mActiveFonts[ct] == this) { 3069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC->mStateFont.mActiveFonts.removeAt(ct); 3079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 3089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 311ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 3129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 3139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk delete glyph; 3149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 317ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFontState::FontState() { 3189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = false; 3199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mMaxNumberOfQuads = 1024; 3209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 3219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mRSC = NULL; 322b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mLibrary = NULL; 3233bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3243bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the renderer properties 3253bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 3263bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3273bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the gamma 3283bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 3293bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 3303bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk gamma = atof(property); 3313bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 3323bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3333bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the black gamma threshold 33410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 3353bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 3363bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk blackThreshold = atoi(property); 3373bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 3383bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 3393bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3403bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Get the white gamma threshold 34110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 3423bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 3433bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk whiteThreshold = atoi(property); 3443bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 3453bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 3463bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 3473bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk // Compute the gamma tables 3483bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mBlackGamma = gamma; 3493bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mWhiteGamma = 1.0f / gamma; 350960ae15cf37fe31790e255521ee2045312e82d36Alex Sakhartchouk 351960ae15cf37fe31790e255521ee2045312e82d36Alex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 3529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 354ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFontState::~FontState() { 355ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 3569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk delete mCacheLines[i]; 3579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 3609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 362ed9f210568082dd6d1d8a0c92c693d574d87d545Alex SakhartchoukFT_Library FontState::getLib() { 363ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!mLibrary) { 364071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 365ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (error) { 3669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Unable to initialize freetype"); 367071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return NULL; 3689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 370b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 371071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return mLibrary; 372071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk} 3739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 374ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::init(Context *rsc) { 375071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mRSC = rsc; 3769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 378ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::flushAllAndInvalidate() { 379ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mCurrentQuadIndex != 0) { 3809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 3819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 3829b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 383ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { 3849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 3859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 386ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 3879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 3889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 3909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 391ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 3929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If the glyph is too tall, don't cache it 393ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 3949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 3959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 3969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 3979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 3989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now copy the bitmap into the cache texture 3999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startX = 0; 4009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t startY = 0; 4019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bool bitmapFit = false; 403ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 405ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (bitmapFit) { 4069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 4079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4089b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 411ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!bitmapFit) { 4129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk flushAllAndInvalidate(); 4139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Try to fit it again 415ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 417ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (bitmapFit) { 4189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk break; 4199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 423ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!bitmapFit) { 4249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 4259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return false; 4269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *retOriginX = startX; 4309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk *retOriginY = startY; 4319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 4339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 4349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 4369b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 43710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 43810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 4399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 441ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 442ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 44310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 4449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 4459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 4479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // This will dirty the texture and the shader so next time 4499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // we draw it will upload the data 4506d8eb266dd398abf0511685fdaf98abba3396174Jason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 451b89aaacb2ca9d062e0a17a32e3d4dbf3f6948a17Alex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 4529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Some debug code 454ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 4559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 4569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 4579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 4589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk }*/ 4609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return true; 4629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 4639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 464ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::initRenderState() { 465d2091639be426574c04f74969fe553162d7a51c9Alex Sakhartchouk String8 shaderString("varying vec2 varTex0;\n"); 466c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append("void main() {\n"); 467c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 468c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 4693bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 470c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 471c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.append("}\n"); 472c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 473c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 4743bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 475c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 476c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 4773bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); 478c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); 479c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 48031a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false); 481c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 482c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk uint32_t tmp[4]; 483c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 484c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk tmp[1] = (uint32_t)inputType; 48567f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; 48667f2e442a31b8395e3c1951f8e91139ec7f2be99Alex Sakhartchouk tmp[3] = RS_TEXTURE_2D; 487c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk 4885476b450e50939940dcf3f15c92335cee2fc572dJason Sams mFontShaderFConstant.set(new Allocation(mRSC, inputType, 4895476b450e50939940dcf3f15c92335cee2fc572dJason Sams RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); 490c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 491c984dd73c6f96d16e11813ae433ef70f7648ae77Alex Sakhartchouk shaderString.length(), tmp, 4); 4929b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontShaderF.set(pf); 493b89aaacb2ca9d062e0a17a32e3d4dbf3f6948a17Alex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 4949b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 4959b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 4969b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 4979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontSampler.set(sampler); 498b89aaacb2ca9d062e0a17a32e3d4dbf3f6948a17Alex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, sampler); 4999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 5019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore.set(fontStore); 5029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 5039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 5049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 5059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 5069b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 508ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::initTextTexture() { 5099b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 5109b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5119b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 51231a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false); 5139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5145476b450e50939940dcf3f15c92335cee2fc572dJason Sams Allocation *cacheAlloc = new Allocation(mRSC, texType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE); 5159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mTextTexture.set(cacheAlloc); 5166d8eb266dd398abf0511685fdaf98abba3396174Jason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 5179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Split up our cache texture into lines of certain widths 51910825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t nextLine = 0; 5209b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 5219b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5229b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 5239b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 52494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 52594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 5279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 5299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 5319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 5329b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 5339b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5349b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5359b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 536ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::initVertexArrayBuffers() { 5379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Now lets write index data 5389b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 5399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 54031a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false); 5419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5425476b450e50939940dcf3f15c92335cee2fc572dJason Sams Allocation *indexAlloc = new Allocation(mRSC, indexType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 5439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 5449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Four verts, two triangles , six indices per quad 546ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 54710825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t i6 = i * 6; 54810825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk int32_t i4 = i * 4; 5499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 5519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 5529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 5539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 5559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 5569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 5579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 5589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 5609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 5619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 5639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 5649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 56598bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 56698bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1); 56798bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1); 56898bfe5d02a81c15fff52570178a2edd830701665Alex Sakhartchouk const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC); 5699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 57031a7e42f4baa059352f0db119de38428e655eab2Jason Sams Type *vertexDataType = Type::getType(mRSC, vertexDataElem, 57131a7e42f4baa059352f0db119de38428e655eab2Jason Sams mMaxNumberOfQuads * 4, 57231a7e42f4baa059352f0db119de38428e655eab2Jason Sams 0, 0, false, false); 5739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5745476b450e50939940dcf3f15c92335cee2fc572dJason Sams Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 5759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 5769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mVertexArray.set(vertexAlloc); 5789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 581ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::checkInit() { 582ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mInitialized) { 5839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 5849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 5859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initTextTexture(); 5879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initRenderState(); 5889b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 5899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk initVertexArrayBuffers(); 5909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 59127f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 59227f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 59327f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 59427f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 59527f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk mLatinPrecache += String8("0123456789"); 59627f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk 5979b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mInitialized = true; 5989b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 5999b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6009b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::issueDrawCommand() { 601a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams Context::PushState ps(mRSC); 6029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 603a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramVertex(mRSC->getDefaultProgramVertex()); 604a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramRaster(mRSC->getDefaultProgramRaster()); 605a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramFragment(mFontShaderF.get()); 606a17af04e62a3f40f729e7ebb8bd868d192e18405Jason Sams mRSC->setProgramStore(mFontProgramStore.get()); 6079b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 608ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mConstantsDirty) { 6093bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants)); 6103bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstantsDirty = false; 61155e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk } 61255e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk 6139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk if (!mRSC->setupCheck()) { 6149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 6159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 6189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float *tex = vtx + 3; 6199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6209d71e2180062931416092f26276a07e55b318f62Alex Sakhartchouk VertexArray::Attrib attribs[2]; 6219d71e2180062931416092f26276a07e55b318f62Alex Sakhartchouk attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position"); 6229d71e2180062931416092f26276a07e55b318f62Alex Sakhartchouk attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0"); 6239d71e2180062931416092f26276a07e55b318f62Alex Sakhartchouk VertexArray va(attribs, 2); 6249b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 6259b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6269b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 6279b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 6289b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 6299b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 6309b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6319b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 632ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float u1, float v1, 633ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float x2, float y2, float z2, 634ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float u2, float v2, 635ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float x3, float y3, float z3, 636ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float u3, float v3, 637ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float x4, float y4, float z4, 638ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk float u4, float v4) { 6399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 6409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk const uint32_t floatsPerVert = 5; 6419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 6429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Cull things that are off the screen 6449b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float width = (float)mRSC->getWidth(); 6459b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk float height = (float)mRSC->getHeight(); 6469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 647ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 6489b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk return; 6499b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6509b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6519b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 6529b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 6539b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 6549b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 6559b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6569b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x1; 6579b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y1; 6589b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z1; 6599b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u1; 6609b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v1; 6619b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6629b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x2; 6639b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y2; 6649b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z2; 6659b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u2; 6669b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v2; 6679b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6689b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x3; 6699b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y3; 6709b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z3; 6719b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u3; 6729b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v3; 6739b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6749b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = x4; 6759b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = y4; 6769b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = z4; 6779b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = u4; 6789b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk (*currentPos++) = v4; 6799b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 6809b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex ++; 6819b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 682ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mCurrentQuadIndex == mMaxNumberOfQuads) { 6839b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 6849b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 6859b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 6869b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 6879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 68894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 68994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk uint32_t remainingCapacity = 0; 69027f50523a45100f3b4861762b6263e0b9ba6e22eAlex Sakhartchouk uint32_t totalPixels = 0; 691ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 69294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 69394bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 69494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 69594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 69694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk return remainingCapacity; 69794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk} 69894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 69994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 70094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk // Remaining capacity is measured in % 70194bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 70294bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk uint32_t precacheIdx = 0; 703ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 70494bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 70594bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 70694bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk precacheIdx ++; 70794bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk } 70894bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk} 70994bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 71094bbccc36322168a596369c8341dad938c8f949fAlex Sakhartchouk 71110825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 71210825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 71310825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk Font::RenderMode mode, 71410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk Font::Rect *bounds, 715ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 7169b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk checkInit(); 7179b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 7189b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk // Render code here 7199b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 720ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!currentFont) { 721ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!mDefault.get()) { 722e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk String8 fontsDir("/fonts/DroidSans.ttf"); 723e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 724e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk fullPath += fontsDir; 725e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk 726e27cdeeecba5b445e307d653d9cb7da007adfac3Alex Sakhartchouk mDefault.set(Font::create(mRSC, fullPath.string(), 16, 96)); 727071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 728071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk currentFont = mDefault.get(); 729071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 730ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (!currentFont) { 731b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk LOGE("Unable to initialize any fonts"); 732b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk return; 733b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk } 734b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 73510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 73610825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 7379b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 738ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mCurrentQuadIndex != 0) { 7399b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk issueDrawCommand(); 7409b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mCurrentQuadIndex = 0; 7419b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 7429b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 7439b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 74410825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 74510825a07ae3a7520110a5fb642a6c8745d7b3956Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 7469b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 7479b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 748fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 7493bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[0] = r; 7503bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[1] = g; 7513bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[2] = b; 7523bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mFontColor[3] = a; 7533bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk 7543bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mGamma = 1.0f; 75576322af2a6c109a79431f019dcef6e038c030686Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 7563bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk if (luminance <= mBlackThreshold) { 7573bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mGamma = mBlackGamma; 7583bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 7593bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstants.mGamma = mWhiteGamma; 7603bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk } 761960ae15cf37fe31790e255521ee2045312e82d36Alex Sakhartchouk 7623bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk mConstantsDirty = true; 763fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk} 764fb10c16a0528a418053e4b8e75eebe57476b86efAlex Sakhartchouk 76555e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 7663bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *r = mConstants.mFontColor[0]; 7673bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *g = mConstants.mFontColor[1]; 7683bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *b = mConstants.mFontColor[2]; 7693bf3ea0d839010cc9e0e5a6bd51c325d375f679dAlex Sakhartchouk *a = mConstants.mFontColor[3]; 77055e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk} 77155e81983562ca507883f32f817e9d24e1c49b909Alex Sakhartchouk 772ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchoukvoid FontState::deinit(Context *rsc) { 773071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mInitialized = false; 774071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 77501f0ad7c13b8878c2167bff10ea875d7509edca5Stephen Hines mFontShaderFConstant.clear(); 77601f0ad7c13b8878c2167bff10ea875d7509edca5Stephen Hines 777071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mIndexBuffer.clear(); 778071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mVertexArray.clear(); 779071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 780071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontShaderF.clear(); 781071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontSampler.clear(); 782071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mFontProgramStore.clear(); 783071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 784071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mTextTexture.clear(); 785ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 786071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk delete mCacheLines[i]; 7879b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk } 788071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk mCacheLines.clear(); 7899b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 7909b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk mDefault.clear(); 791071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk 792b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk Vector<Font*> fontsToDereference = mActiveFonts; 793ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk for (uint32_t i = 0; i < fontsToDereference.size(); i ++) { 794b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk fontsToDereference[i]->zeroUserRef(); 795b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk } 796b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk 797ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (mLibrary) { 798071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk FT_Done_FreeType( mLibrary ); 799b6b34891fa7f76c99f5e9a3096576ada86c99f1eAlex Sakhartchouk mLibrary = NULL; 800071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 8019b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 8029b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8039b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouknamespace android { 8049b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouknamespace renderscript { 8059b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 806e27cdeeecba5b445e307d653d9cb7da007adfac3Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, float fontSize, uint32_t dpi) { 807071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 808ed9f210568082dd6d1d8a0c92c693d574d87d545Alex Sakhartchouk if (newFont) { 809071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk newFont->incUserRef(); 810071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk } 811071508d9f3d1c004cd9ef8d5329949e7a8a949c8Alex Sakhartchouk return newFont; 8129b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} 8139b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk 8149b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} // renderscript 8159b949fce39f0f39ce9275b71d7c347210775e7a8Alex Sakhartchouk} // android 816