rsFont.cpp revision a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2
1d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 2d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk/* 3d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Copyright (C) 2009 The Android Open Source Project 4d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * 5d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License"); 6d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * you may not use this file except in compliance with the License. 7d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * You may obtain a copy of the License at 8d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * 9d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * http://www.apache.org/licenses/LICENSE-2.0 10d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * 11d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Unless required by applicable law or agreed to in writing, software 12d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS, 13d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * See the License for the specific language governing permissions and 15d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * limitations under the License. 16d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk */ 17d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 18d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsContext.h" 19d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 20d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsFont.h" 21d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsProgramFragment.h" 22c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk#include <cutils/properties.h> 2302000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 24b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 2502000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk#include <ft2build.h> 2602000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk#include FT_FREETYPE_H 27d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include FT_BITMAP_H 28b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 29d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 30d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android; 31d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android::renderscript; 32d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 33afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) { 34d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 35d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = false; 363659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mFace = NULL; 37d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 38d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 395224a27798f89093b13722b41143551a057ce550Alex Sakhartchoukbool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) { 40b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 41afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 42d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 43d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 44d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 465224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk FT_Error error = 0; 475224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (data != NULL && dataLen > 0) { 485224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace); 495224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } else { 505224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace); 515224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } 525224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk 53afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 54c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk LOGE("Unable to initialize font %s", name); 55d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 56d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 57d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontName = name; 59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSize = fontSize; 60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDpi = dpi; 61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 62c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0); 63afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 64c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk LOGE("Unable to set font size on %s", name); 65d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 66d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 71b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 752e8665de7c0eb4514c67baf8693d61c892e5303dJason Samsvoid Font::preDestroy() const { 762e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 772e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams if (mRSC->mStateFont.mActiveFonts[ct] == this) { 782e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams mRSC->mStateFont.mActiveFonts.removeAt(ct); 792e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams break; 802e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams } 812e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams } 822e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams} 832e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams 84afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::invalidateTextureCache() { 85afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 86d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 87d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 88d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 89d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 90afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { 91d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 92d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 9409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 95d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 9809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 9909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 100d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 10109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 103d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk const uint8_t* cacheBuffer = state->getTextTextureData(); 12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 12209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t bX = 0, bY = 0; 12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 12709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("Skipping invalid index"); 12809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk continue; 12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 13109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 13209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 134d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 135d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 13609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 13709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 1435224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk // 0, 0 is top left, so bottom is a positive number 1445224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (bounds->bottom < nPenY) { 14509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->bottom = nPenY; 14609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->left > nPenX) { 14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->left = nPenX; 14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->right < nPenX + width) { 15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->right = nPenX + width; 15209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 1535224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (bounds->top > nPenY - height) { 1545224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->top = nPenY - height; 15509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 15709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 15809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 15909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 16009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk RenderMode mode, Rect *bounds, 161afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 162afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 163d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 164d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 165d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 166afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mode == Font::MEASURE) { 16709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds == NULL) { 16809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("No return rectangle provided to measure text"); 16909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk return; 17009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk // Reset min and max of the bounding box to something large 1725224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->set(1e6, -1e6, 1e6, -1e6); 17309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 17509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t penX = x, penY = y; 17609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t glyphsLeft = 1; 177afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft = numGlyphs; 179d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t index = start; 182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t nextIndex = 0; 183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk while (glyphsLeft > 0) { 185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 186c9c38dd8508a2f805213abee1f9f44f103ac0a0dKenny Root int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); 187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reached the end of the string or encountered 189afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (utfChar < 0) { 190d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 192d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 193d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Move to the next character in the array 194d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk index = nextIndex; 195d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 19601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 197d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 198d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 199afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph->mIsValid) { 200afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk switch (mode) { 20109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case FRAMEBUFFER: 20209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 20309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case BITMAP: 20509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 20609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case MEASURE: 20809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 20909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 21009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 211d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 21302000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk penX += (cachedGlyph->mAdvanceX >> 6); 214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 215d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 216afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 217d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft --; 218d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 219d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 220d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 221d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 22201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 22301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 22401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 225afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph == NULL) { 22601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 22701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 22801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Is the glyph still in texture cache? 229afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!cachedGlyph->mIsValid) { 23001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk updateGlyphCache(cachedGlyph); 23101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 23201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 23301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return cachedGlyph; 23401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 23501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 236afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) { 237b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 238a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 239afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 240a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk LOGE("Couldn't load glyph."); 241a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return; 242a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 243d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 24402000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk glyph->mAdvanceX = mFace->glyph->advance.x; 24502000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk glyph->mAdvanceY = mFace->glyph->advance.y; 246a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 247a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 248d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 249a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 253d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 255d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Let the font state figure out where to put the bitmap 256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 257a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 259afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!glyph->mIsValid) { 260d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 261d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 262d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 263a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endX = startX + bitmap->width; 264a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endY = startY + bitmap->rows; 265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 266d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinX = startX; 267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinY = startY; 268a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 269a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 271d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 278b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 280d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 281afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { 282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 283d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 284b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 285d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mIsValid = false; 287b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 288d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk updateGlyphCache(newGlyph); 289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newGlyph; 291d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 2935224a27798f89093b13722b41143551a057ce550Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi, 2945224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk const void *data, uint32_t dataLen) { 29535b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk rsc->mStateFont.checkInit(); 296d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 297d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 298afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < activeFonts.size(); i ++) { 299d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *ithFont = activeFonts[i]; 300afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return ithFont; 302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 305d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *newFont = new Font(rsc); 3065224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen); 307afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (isInitialized) { 308d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk activeFonts.push(newFont); 30901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newFont; 311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 313225afd317e101a7be5fe02c0a86361146ea89f05Jason Sams ObjectBase::checkDelete(newFont); 314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return NULL; 315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 316d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 317afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::~Font() { 318b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 319afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mFace) { 320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FT_Done_Face(mFace); 321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 322b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif 323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 324afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 325d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete glyph; 327d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 330afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::FontState() { 331d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 332d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mMaxNumberOfQuads = 1024; 333d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 334d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC = NULL; 335b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 3363659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 337b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 338c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 339c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the renderer properties 340c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 341c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 342c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the gamma 343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk gamma = atof(property); 346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the black gamma threshold 34909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk blackThreshold = atoi(property); 352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the white gamma threshold 35609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk whiteThreshold = atoi(property); 359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 360c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 361c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 362c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Compute the gamma tables 363c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackGamma = gamma; 364c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteGamma = 1.0f / gamma; 3654f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 3664f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 367d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 368d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 369afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::~FontState() { 370afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 371d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 372d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 373d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 374d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 375d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 376b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 377afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFT_Library FontState::getLib() { 378afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mLibrary) { 379a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 380afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize freetype"); 382a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return NULL; 383d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 3853659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 386a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 387a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 388b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 389b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk 390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 391afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::init(Context *rsc) { 392a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 393d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 394d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 395afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::flushAllAndInvalidate() { 396afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 399d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 400afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { 401d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 402d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 403afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 406d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 407d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 408b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 409afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 411afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 421afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 423afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 429afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 433afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 435afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 441afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 45509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 45609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 459afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 460afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 46109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 468eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams 469eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams mTextTexture->sendDirty(mRSC); 470383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 472d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 473afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 475d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 476d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 477d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 478d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 479d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 480d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 482b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 483d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 484afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initRenderState() { 4857ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk String8 shaderString("varying vec2 varTex0;\n"); 486e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("void main() {\n"); 487e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 488e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 489c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 490e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 491e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("}\n"); 492e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 493c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> colorElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 494c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> gammaElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 495c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk Element::Builder builder; 496c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk builder.add(colorElem.get(), "Color", 1); 497c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk builder.add(gammaElem.get(), "Gamma", 1); 498c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> constInput = builder.create(mRSC); 499e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 500c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<Type> inputType = Type::getTypeRef(mRSC, constInput.get(), 1, 0, 0, false, false); 501e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 502e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk uint32_t tmp[4]; 503e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 504c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk tmp[1] = (uint32_t)inputType.get(); 50584e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; 50684e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[3] = RS_TEXTURE_2D; 507e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 508c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType.get(), 509366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); 510e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 511e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.length(), tmp, 4); 512d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 513383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 514d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 515c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontSampler.set(Sampler::getSampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 516c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP).get()); 517c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, mFontSampler.get()); 518c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk 519c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontProgramStore.set(ProgramStore::getProgramStore(mRSC, true, true, true, true, 520c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk false, false, 521c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk RS_BLEND_SRC_SRC_ALPHA, 522c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, 523c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk RS_DEPTH_FUNC_ALWAYS).get()); 5248feea4e0dec48ea03bd6d32706d058b86dddc5baJason Sams mFontProgramStore->init(); 525d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 526d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 527afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initTextTexture() { 528c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> alphaElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 531c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<Type> texType = Type::getTypeRef(mRSC, alphaElem.get(), 1024, 256, 0, false, false); 532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 533c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType.get(), 534eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE); 535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 536b7e83bda41e66c966b98935b44140692bfe0c4caJason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 53909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nextLine = 0; 540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 54401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 54501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 546d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 556afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initVertexArrayBuffers() { 557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 558c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> indexElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 560c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<Type> indexType = Type::getTypeRef(mRSC, indexElem.get(), numIndicies, 0, 0, false, false); 561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 562c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType.get(), 563eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams RS_ALLOCATION_USAGE_SCRIPT | 564eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 566d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 567d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 568afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 56909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i6 = i * 6; 57009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i4 = i * 4; 571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 581eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams indexAlloc->sendDirty(mRSC); 582d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 583c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> posElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 584c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> texElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 586c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk Element::Builder builder; 587c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk builder.add(posElem.get(), "position", 1); 588c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk builder.add(texElem.get(), "texture0", 1); 589c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> vertexDataElem = builder.create(mRSC); 590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 591c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<Type> vertexDataType = Type::getTypeRef(mRSC, vertexDataElem.get(), 592c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mMaxNumberOfQuads * 4, 593c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk 0, 0, false, false); 594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 595c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType.get(), 596eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams RS_ALLOCATION_USAGE_SCRIPT); 597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 599a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh.set(new Mesh(mRSC, 1, 1)); 600a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->setVertexBuffer(vertexAlloc, 0); 601a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->setPrimitive(indexAlloc, RS_PRIMITIVE_TRIANGLE, 0); 602a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->init(); 603d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 606afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::checkInit() { 607afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 609d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 611d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 613d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 61635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 61735b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 61835b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 61935b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 62035b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("0123456789"); 62135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk 622d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 62660709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams Context::PushState ps(mRSC); 627d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 62860709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramVertex(mRSC->getDefaultProgramVertex()); 62960709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramRaster(mRSC->getDefaultProgramRaster()); 63060709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramFragment(mFontShaderF.get()); 63160709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramStore(mFontProgramStore.get()); 632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 633afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mConstantsDirty) { 6344b45b8998e0d7038efaea80c70d23c086640b4e3Jason Sams mFontShaderFConstant->data(mRSC, 0, 0, 1, &mConstants, sizeof(mConstants)); 635c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = false; 636ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 637ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 642a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->renderPrimitiveRange(mRSC, 0, 0, mCurrentQuadIndex * 6); 643d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 645d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 646afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u1, float v1, 647afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x2, float y2, float z2, 648afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u2, float v2, 649afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x3, float y3, float z3, 650afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u3, float v3, 651afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x4, float y4, float z4, 652afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u4, float v4) { 653d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 654d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t floatsPerVert = 5; 655d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 656d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 657a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk if (x1 > mSurfaceWidth || y1 < 0.0f || x2 < 0 || y4 > mSurfaceHeight) { 658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 665d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 666d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 667d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 668d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 669d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 675d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 676d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 678d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 682d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 692afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex == mMaxNumberOfQuads) { 693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 69801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 69901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 70035b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 701afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 70201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 70301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 70401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 70501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 70601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 70701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 70801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 70901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 71001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 71101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 71201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 713afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 71401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 71501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 71601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 71701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 71801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 71901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 72001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 72109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 72209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 72309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::RenderMode mode, 72409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::Rect *bounds, 725afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 726d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 727d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 728d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 729d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 730afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 731afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mDefault.get()) { 7321f5f9a30d71973f0c54e0142ed80740b71c720e3Christian Robertson String8 fontsDir("/fonts/Roboto-Regular.ttf"); 733c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 734c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk fullPath += fontsDir; 735c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk 7367b3e9bd825901e33661e3c385e3e7c6f40ca6000Alex Sakhartchouk mDefault.set(Font::create(mRSC, fullPath.string(), 8, mRSC->getDPI())); 737a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 738a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk currentFont = mDefault.get(); 739a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 740afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 7413659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk LOGE("Unable to initialize any fonts"); 7423659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk return; 7433659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 7443659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 745a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk // Cull things that are off the screen 746a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk mSurfaceWidth = (float)mRSC->getCurrentSurfaceWidth(); 747a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk mSurfaceHeight = (float)mRSC->getCurrentSurfaceHeight(); 748a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk 74909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 75009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 752afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 753d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 754d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 755d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 756d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 757d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 75809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 75909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 7605224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->bottom = - bounds->bottom; 7615224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->top = - bounds->top; 762d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 763d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 7649fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 765c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[0] = r; 766c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[1] = g; 767c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[2] = b; 768c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[3] = a; 769c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 770c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = 1.0f; 771c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 772c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (luminance <= mBlackThreshold) { 773c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mBlackGamma; 774c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 775c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mWhiteGamma; 776c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 7774f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 778c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = true; 7799fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk} 7809fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk 781ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 782c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *r = mConstants.mFontColor[0]; 783c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *g = mConstants.mFontColor[1]; 784c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *b = mConstants.mFontColor[2]; 785c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *a = mConstants.mFontColor[3]; 786ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk} 787ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 788afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::deinit(Context *rsc) { 789a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mInitialized = false; 790a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 79101b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines mFontShaderFConstant.clear(); 79201b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines 793a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh.clear(); 794a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 795a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontShaderF.clear(); 796a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontSampler.clear(); 797a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontProgramStore.clear(); 798a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 799a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mTextTexture.clear(); 800afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 801a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk delete mCacheLines[i]; 802d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 803a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mCacheLines.clear(); 804d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 805d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDefault.clear(); 806b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 807afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mLibrary) { 808a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Done_FreeType( mLibrary ); 8093659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 810a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 811b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 812d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 813d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 814b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 81502000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchoukbool FontState::CacheTextureLine::fitBitmap(FT_Bitmap_ *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 81602000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk if ((uint32_t)bitmap->rows > mMaxHeight) { 81702000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk return false; 81802000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk } 81902000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 82002000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk if (mCurrentCol + (uint32_t)bitmap->width < mMaxWidth) { 82102000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk *retOriginX = mCurrentCol; 82202000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk *retOriginY = mCurrentRow; 82302000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk mCurrentCol += bitmap->width; 82402000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk mDirty = true; 82502000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk return true; 82602000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk } 82702000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 82802000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk return false; 82902000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk} 830b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 83102000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 832d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android { 833d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript { 834d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 83570b83c111beceaf8fbb700580833e7fec99272cfAlex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, 83670b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk char const *name, size_t name_length, 83770b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk float fontSize, uint32_t dpi) { 838a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 839afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (newFont) { 840a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk newFont->incUserRef(); 841a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 842a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return newFont; 843d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 844d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 84570b83c111beceaf8fbb700580833e7fec99272cfAlex SakhartchoukRsFont rsi_FontCreateFromMemory(Context *rsc, 84670b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk char const *name, size_t name_length, 84770b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk float fontSize, uint32_t dpi, 84870b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk const void *data, size_t data_length) { 84970b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi, data, data_length); 8505224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (newFont) { 8515224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk newFont->incUserRef(); 8525224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } 8535224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk return newFont; 8545224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk} 8555224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk 856d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript 857d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android 858