rsFont.cpp revision 7974fc03e11f3a8dd40f794f3b33b4889483090c
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" 19e23d239828a229eb7d4d33c9630070f0a87833e1Alex Sakhartchouk#include "rs.h" 20d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsFont.h" 21d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsProgramFragment.h" 224edf030cbb7c6ac08dc563335c2af73c20f6e2e5Alex Sakhartchouk#include "rsMesh.h" 23e5e18cca3eefccf3a6aabd254ceb2c59f120a7d2Elliott Hughes#ifdef __ANDROID__ 24c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk#include <cutils/properties.h> 257e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich#endif 2602000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 27b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 2802000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk#include <ft2build.h> 2902000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk#include FT_FREETYPE_H 30d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include FT_BITMAP_H 31b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 32d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 3311496ac131bb691edf5bdcab3029dceef5c1e4e1Chih-Hung Hsiehnamespace android { 3411496ac131bb691edf5bdcab3029dceef5c1e4e1Chih-Hung Hsiehnamespace renderscript { 35d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 36b8353c5943f4038fd7f08db3d958390ce9418798Yang NiFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) { 37d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 38d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = false; 3944bef6fba6244292b751387f3d6c31cca96c28adChris Wailes mFace = nullptr; 40d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 41d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 425224a27798f89093b13722b41143551a057ce550Alex Sakhartchoukbool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) { 43b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 44afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 45af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Reinitialization of fonts not supported"); 46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 495224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk FT_Error error = 0; 5044bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (data != nullptr && dataLen > 0) { 515224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace); 525224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } else { 535224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace); 545224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } 555224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk 56afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 57af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Unable to initialize font %s", name); 58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 6148ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams mFontName = rsuCopyString(name); 62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSize = fontSize; 63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDpi = dpi; 64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 65c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0); 66afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 67af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Unable to set font size on %s", name); 68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 74b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 76d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 77d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 782e8665de7c0eb4514c67baf8693d61c892e5303dJason Samsvoid Font::preDestroy() const { 79b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 80b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni if (mRSC->mStateFont.mActiveFonts[ct] == this) { 81b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mRSC->mStateFont.mActiveFonts.removeAt(ct); 82b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni break; 832e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams } 842e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams } 852e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams} 862e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams 87afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::invalidateTextureCache() { 88afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 89b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCachedGlyphs.valueAt(i)->mIsValid = false; 90d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 91d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 92d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 93afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { 94d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 95d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 98d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 10109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 103d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 106d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 12209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 123a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams const uint8_t* cacheBuffer = state->mCacheBuffer; 12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t bX = 0, bY = 0; 12709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 12809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 130af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Skipping invalid index"); 13109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk continue; 13209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 13409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 13509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 137d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 138d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 14409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 14509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 1465224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk // 0, 0 is top left, so bottom is a positive number 1475224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (bounds->bottom < nPenY) { 14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->bottom = nPenY; 14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->left > nPenX) { 15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->left = nPenX; 15209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->right < nPenX + width) { 15409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->right = nPenX + width; 15509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 1565224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (bounds->top > nPenY - height) { 1575224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->top = nPenY - height; 15809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 16009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 16109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 16209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 16309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk RenderMode mode, Rect *bounds, 164afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 16544bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (!mInitialized || numGlyphs == 0 || text == nullptr || len == 0) { 166d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 167d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 168d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 169afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mode == Font::MEASURE) { 17044bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (bounds == nullptr) { 171af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("No return rectangle provided to measure text"); 17209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk return; 17309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk // Reset min and max of the bounding box to something large 1755224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->set(1e6, -1e6, 1e6, -1e6); 17609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 17809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t penX = x, penY = y; 17909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t glyphsLeft = 1; 180afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft = numGlyphs; 182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t index = start; 185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t nextIndex = 0; 186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk while (glyphsLeft > 0) { 188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 189c9c38dd8508a2f805213abee1f9f44f103ac0a0dKenny Root int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); 190d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reached the end of the string or encountered 192afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (utfChar < 0) { 193d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 194d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 195d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 196d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Move to the next character in the array 197d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk index = nextIndex; 198d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 19901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 200d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 201d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 202afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph->mIsValid) { 203afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk switch (mode) { 20409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case FRAMEBUFFER: 20509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 20609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case BITMAP: 20809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 20909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 21009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case MEASURE: 21109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 21209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 21309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 215d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 21602000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk penX += (cachedGlyph->mAdvanceX >> 6); 217d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 218d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 219afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 220d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft --; 221d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 222d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 223d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 224d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 22501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 22601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 227b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 22844bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (cachedGlyph == nullptr) { 22901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 23001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 23101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Is the glyph still in texture cache? 232afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!cachedGlyph->mIsValid) { 23301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk updateGlyphCache(cachedGlyph); 23401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 23501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 23601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return cachedGlyph; 23701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 23801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 239afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) { 240b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 241a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 242afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 243af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Couldn't load glyph."); 244a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return; 245a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 246d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 24702000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk glyph->mAdvanceX = mFace->glyph->advance.x; 24802000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk glyph->mAdvanceY = mFace->glyph->advance.y; 249a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 250a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 252a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 253d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 255d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Let the font state figure out where to put the bitmap 259d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 260a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 261d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 262afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!glyph->mIsValid) { 263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 264d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 266a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endX = startX + bitmap->width; 267a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endY = startY + bitmap->rows; 268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 269d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinX = startX; 270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinY = startY; 271a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 272a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 280d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 281b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 283d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 284afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { 285d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 286b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCachedGlyphs.add(glyph, newGlyph); 287b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 288d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mIsValid = false; 290b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 291d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk updateGlyphCache(newGlyph); 292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 293d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newGlyph; 294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 295d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 2965224a27798f89093b13722b41143551a057ce550Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi, 2975224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk const void *data, uint32_t dataLen) { 29835b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk rsc->mStateFont.checkInit(); 299b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 300d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 301afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < activeFonts.size(); i ++) { 302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *ithFont = activeFonts[i]; 303b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return ithFont; 305d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 307d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 308d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *newFont = new Font(rsc); 3095224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen); 310afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (isInitialized) { 311b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni activeFonts.push(newFont); 31201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newFont; 314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 316225afd317e101a7be5fe02c0a86361146ea89f05Jason Sams ObjectBase::checkDelete(newFont); 31744bef6fba6244292b751387f3d6c31cca96c28adChris Wailes return nullptr; 318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 319d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 320afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::~Font() { 321b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 322afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mFace) { 323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FT_Done_Face(mFace); 324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 325b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif 326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 327afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 328b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete glyph; 330d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 331d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 332d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 333afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::FontState() { 334d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 335d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mMaxNumberOfQuads = 1024; 336d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 33744bef6fba6244292b751387f3d6c31cca96c28adChris Wailes mRSC = nullptr; 338b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 33944bef6fba6244292b751387f3d6c31cca96c28adChris Wailes mLibrary = nullptr; 340b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 341c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 3427e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich float gamma = DEFAULT_TEXT_GAMMA; 3437e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 3447e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 3457e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich 346e5e18cca3eefccf3a6aabd254ceb2c59f120a7d2Elliott Hughes#ifdef __ANDROID__ 347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the renderer properties 348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the gamma 35144bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (property_get(PROPERTY_TEXT_GAMMA, property, nullptr) > 0) { 352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk gamma = atof(property); 353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the black gamma threshold 35644bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, nullptr) > 0) { 357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk blackThreshold = atoi(property); 358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 360c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the white gamma threshold 36144bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, nullptr) > 0) { 362c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk whiteThreshold = atoi(property); 363c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 3647e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich#endif 3657e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich 3667e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich mBlackThreshold = (float)(blackThreshold) / 255.0f; 367c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 368c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 369c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Compute the gamma tables 370c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackGamma = gamma; 371c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteGamma = 1.0f / gamma; 3724f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 3734f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 374d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 375d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 376afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::~FontState() { 377afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 378d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 379d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 380d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 383b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 384afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFT_Library FontState::getLib() { 385afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mLibrary) { 386a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 387afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 388af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Unable to initialize freetype"); 38944bef6fba6244292b751387f3d6c31cca96c28adChris Wailes return nullptr; 390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 391d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 3923659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 393a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 394a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 395b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 396b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk 397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 398afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::init(Context *rsc) { 399a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 401d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 402afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::flushAllAndInvalidate() { 403afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 406d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 407afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { 408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 410afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 415b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 416afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 418afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 419af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 428afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 430afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 436afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 440afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 442afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 448afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 449af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 462a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams uint8_t *cacheBuffer = mCacheBuffer; 46309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 466afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 467afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 46809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 472d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 473d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 474d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 475eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams 476a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mRSC->mHal.funcs.allocation.data2D(mRSC, mTextTexture.get(), 0, 0, 0, 477a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, mCacheWidth, mCacheHeight, 478358747a3118301c5faeee73c98dd5f839bbfb54aTim Murray mCacheBuffer, mCacheWidth*mCacheHeight, mCacheWidth); 479a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams 480383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 482d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 483afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 484af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Cache Line: H: %u Empty Space: %f", 485d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 486d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 487d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 488d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 489d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 490d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 491d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 492b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 493d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 494afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initRenderState() { 49548ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams const char *shaderString = "varying vec2 varTex0;\n" 49648ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams "void main() {\n" 49748ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams " lowp vec4 col = UNI_Color;\n" 49848ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams " col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n" 49948ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams " col.a = pow(col.a, UNI_Gamma);\n" 50048ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams " gl_FragColor = col;\n" 50148ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams "}\n"; 502e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 503748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk const char *textureNames[] = { "Tex0" }; 504748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk const size_t textureNamesLengths[] = { 4 }; 505748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk size_t numTextures = sizeof(textureNamesLengths)/sizeof(*textureNamesLengths); 506748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk 507748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk ObjectBaseRef<const Element> colorElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, 508748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_KIND_USER, false, 4); 509748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk ObjectBaseRef<const Element> gammaElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, 510748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_KIND_USER, false, 1); 511f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams 512f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams const char *ebn1[] = { "Color", "Gamma" }; 513f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams const Element *ebe1[] = {colorElem.get(), gammaElem.get()}; 514f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams ObjectBaseRef<const Element> constInput = Element::create(mRSC, 2, ebe1, ebn1); 515c7968a0ac24f05d978616a79a5068b6b16dbbda6Jason Sams ObjectBaseRef<Type> inputType = Type::getTypeRef(mRSC, constInput.get(), 1); 516e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 517f8852d0494a260c583795a96a2a06c49b86a9b10Ian Rogers uintptr_t tmp[4]; 518e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 519f8852d0494a260c583795a96a2a06c49b86a9b10Ian Rogers tmp[1] = (uintptr_t)inputType.get(); 52084e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; 52184e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[3] = RS_TEXTURE_2D; 522e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 523c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType.get(), 524748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_ALLOCATION_USAGE_SCRIPT | 525748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); 52648ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams ProgramFragment *pf = new ProgramFragment(mRSC, shaderString, strlen(shaderString), 527748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk textureNames, numTextures, textureNamesLengths, 528748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk tmp, 4); 529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 530383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 532c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontSampler.set(Sampler::getSampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 533748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, 534748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_SAMPLER_CLAMP).get()); 535c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, mFontSampler.get()); 536c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk 537c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontProgramStore.set(ProgramStore::getProgramStore(mRSC, true, true, true, true, 538c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk false, false, 539c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk RS_BLEND_SRC_SRC_ALPHA, 540c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, 541c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk RS_DEPTH_FUNC_ALWAYS).get()); 5428feea4e0dec48ea03bd6d32706d058b86dddc5baJason Sams mFontProgramStore->init(); 543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 545afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initTextTexture() { 546748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk ObjectBaseRef<const Element> alphaElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_8, 547748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_KIND_PIXEL_A, true, 1); 548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 550a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mCacheHeight = 256; 551a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mCacheWidth = 1024; 552c7968a0ac24f05d978616a79a5068b6b16dbbda6Jason Sams ObjectBaseRef<Type> texType = Type::getTypeRef(mRSC, alphaElem.get(), mCacheWidth, mCacheHeight); 55393d6bc872b7d9fba63abfa7513d56b38d9c3d371Chris Wailes 554a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mCacheBuffer = new uint8_t[mCacheWidth * mCacheHeight]; 555a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams 556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 557b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType.get(), 558b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE); 559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 56209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nextLine = 0; 563b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 564b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni nextLine += mCacheLines.top()->mMaxHeight; 565b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 566b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni nextLine += mCacheLines.top()->mMaxHeight; 567b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 568b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni nextLine += mCacheLines.top()->mMaxHeight; 569b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 570b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni nextLine += mCacheLines.top()->mMaxHeight; 571b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 572b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni nextLine += mCacheLines.top()->mMaxHeight; 573b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 574b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni nextLine += mCacheLines.top()->mMaxHeight; 575b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 579afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initVertexArrayBuffers() { 580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 581c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> indexElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 582c7968a0ac24f05d978616a79a5068b6b16dbbda6Jason Sams ObjectBaseRef<Type> indexType = Type::getTypeRef(mRSC, indexElem.get(), mMaxNumberOfQuads * 6); 583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 584c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType.get(), 585eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams RS_ALLOCATION_USAGE_SCRIPT | 586eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 587a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams uint16_t *indexPtr = (uint16_t*)mRSC->mHal.funcs.allocation.lock1D(mRSC, indexAlloc); 588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 590afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 59109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i6 = i * 6; 59209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i4 = i * 4; 593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 601d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 602d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 603eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams indexAlloc->sendDirty(mRSC); 604d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 605c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> posElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 606c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> texElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 608f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams const char *ebn1[] = { "position", "texture0" }; 609f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams const Element *ebe1[] = {posElem.get(), texElem.get()}; 610f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams ObjectBaseRef<const Element> vertexDataElem = Element::create(mRSC, 2, ebe1, ebn1); 611d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 612c7968a0ac24f05d978616a79a5068b6b16dbbda6Jason Sams ObjectBaseRef<Type> vertexDataType = Type::getTypeRef(mRSC, vertexDataElem.get(), mMaxNumberOfQuads * 4); 613d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 614c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType.get(), 615eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams RS_ALLOCATION_USAGE_SCRIPT); 616a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mTextMeshPtr = (float*)mRSC->mHal.funcs.allocation.lock1D(mRSC, vertexAlloc); 617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 618a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh.set(new Mesh(mRSC, 1, 1)); 619a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->setVertexBuffer(vertexAlloc, 0); 620a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->setPrimitive(indexAlloc, RS_PRIMITIVE_TRIANGLE, 0); 621a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->init(); 622a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mRSC->mHal.funcs.allocation.unlock1D(mRSC, indexAlloc); 623a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mRSC->mHal.funcs.allocation.unlock1D(mRSC, vertexAlloc); 624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 627afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::checkInit() { 628afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 630d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 631d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 63735b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 638a7f5e0406825151660c1c2e75c287e2fc8368023Jason Sams mLatinPrecache = " eisarntolcdugpmhbyfvkwzxjq" 639a7f5e0406825151660c1c2e75c287e2fc8368023Jason Sams "EISARNTOLCDUGPMHBYFVKWZXJQ" 640a7f5e0406825151660c1c2e75c287e2fc8368023Jason Sams ",.?!()-+@;:`'0123456789"; 641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 642d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 643d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 64560709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams Context::PushState ps(mRSC); 646d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 64760709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramVertex(mRSC->getDefaultProgramVertex()); 64860709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramRaster(mRSC->getDefaultProgramRaster()); 64960709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramFragment(mFontShaderF.get()); 65060709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramStore(mFontProgramStore.get()); 651d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 652afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mConstantsDirty) { 6534b45b8998e0d7038efaea80c70d23c086640b4e3Jason Sams mFontShaderFConstant->data(mRSC, 0, 0, 1, &mConstants, sizeof(mConstants)); 654c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = false; 655ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 656ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 657d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 661a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->renderPrimitiveRange(mRSC, 0, 0, mCurrentQuadIndex * 6); 662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 665afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u1, float v1, 666afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x2, float y2, float z2, 667afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u2, float v2, 668afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x3, float y3, float z3, 669afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u3, float v3, 670afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x4, float y4, float z4, 671afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u4, float v4) { 672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 6732d1220c27ae91f0b307f283fe66cb767b63dfe38Alex Sakhartchouk const uint32_t floatsPerVert = 6; 674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 675d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 676a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk if (x1 > mSurfaceWidth || y1 < 0.0f || x2 < 0 || y4 > mSurfaceHeight) { 677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 678d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 681af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 682af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 683af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 6882d1220c27ae91f0b307f283fe66cb767b63dfe38Alex Sakhartchouk (*currentPos++) = 0; 689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 692d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 6952d1220c27ae91f0b307f283fe66cb767b63dfe38Alex Sakhartchouk (*currentPos++) = 0; 696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 698d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 699d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 701d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 7022d1220c27ae91f0b307f283fe66cb767b63dfe38Alex Sakhartchouk (*currentPos++) = 0; 703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 707d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 708d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 7092d1220c27ae91f0b307f283fe66cb767b63dfe38Alex Sakhartchouk (*currentPos++) = 0; 710d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 711d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 712d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 713d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 714d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 715afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex == mMaxNumberOfQuads) { 716d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 717d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 718d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 719d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 720d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 72101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 72201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 72335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 724afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 72501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 72601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 72701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 72801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 72901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 73001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 73101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 73201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 73301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 73401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 73501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 736a7f5e0406825151660c1c2e75c287e2fc8368023Jason Sams const size_t l = strlen(mLatinPrecache); 737a7f5e0406825151660c1c2e75c287e2fc8368023Jason Sams while ((remainingCapacity > 25) && (precacheIdx < l)) { 73801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 73901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 74001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 74101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 74201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 74301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 74401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 74509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 74609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 74709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::RenderMode mode, 74809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::Rect *bounds, 749afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 752d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 753d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 754afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 755afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mDefault.get()) { 75648ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams char fullPath[1024]; 75748ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams const char * root = getenv("ANDROID_ROOT"); 75848ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams rsAssert(strlen(root) < 256); 75948ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams strcpy(fullPath, root); 76048ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams strcat(fullPath, "/fonts/Roboto-Regular.ttf"); 76148ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams mDefault.set(Font::create(mRSC, fullPath, 8, mRSC->getDPI())); 762a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 763a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk currentFont = mDefault.get(); 764a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 765afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 766af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Unable to initialize any fonts"); 7673659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk return; 7683659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 7693659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 770a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk // Cull things that are off the screen 771a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk mSurfaceWidth = (float)mRSC->getCurrentSurfaceWidth(); 772a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk mSurfaceHeight = (float)mRSC->getCurrentSurfaceHeight(); 773a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk 77409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 77509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 776d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 777afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 778d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 779d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 780d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 781d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 782d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 78309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 78409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 7855224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->bottom = - bounds->bottom; 7865224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->top = - bounds->top; 787d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 788d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 7899fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 790c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[0] = r; 791c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[1] = g; 792c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[2] = b; 793c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[3] = a; 794c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 795c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = 1.0f; 796c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 797c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (luminance <= mBlackThreshold) { 798c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mBlackGamma; 799c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 800c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mWhiteGamma; 801c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 8024f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 803c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = true; 8049fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk} 8059fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk 806ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 807c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *r = mConstants.mFontColor[0]; 808c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *g = mConstants.mFontColor[1]; 809c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *b = mConstants.mFontColor[2]; 810c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *a = mConstants.mFontColor[3]; 811ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk} 812ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 813afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::deinit(Context *rsc) { 814a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mInitialized = false; 815a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 81601b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines mFontShaderFConstant.clear(); 81701b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines 818a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh.clear(); 819a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 820a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontShaderF.clear(); 821a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontSampler.clear(); 822a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontProgramStore.clear(); 823a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 824a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mTextTexture.clear(); 825afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 826a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk delete mCacheLines[i]; 827d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 828a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mCacheLines.clear(); 829d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 830d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDefault.clear(); 831b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 832afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mLibrary) { 833a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Done_FreeType( mLibrary ); 83444bef6fba6244292b751387f3d6c31cca96c28adChris Wailes mLibrary = nullptr; 835a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 836b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 837d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 838d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 839b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 84002000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchoukbool FontState::CacheTextureLine::fitBitmap(FT_Bitmap_ *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 84102000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk if ((uint32_t)bitmap->rows > mMaxHeight) { 84202000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk return false; 84302000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk } 84402000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 84502000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk if (mCurrentCol + (uint32_t)bitmap->width < mMaxWidth) { 84602000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk *retOriginX = mCurrentCol; 84702000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk *retOriginY = mCurrentRow; 84802000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk mCurrentCol += bitmap->width; 84902000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk mDirty = true; 85002000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk return true; 85102000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk } 85202000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 85302000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk return false; 85402000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk} 855b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 85602000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 85770b83c111beceaf8fbb700580833e7fec99272cfAlex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, 85870b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk char const *name, size_t name_length, 85970b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk float fontSize, uint32_t dpi) { 860a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 861afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (newFont) { 862a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk newFont->incUserRef(); 863a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 864a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return newFont; 865d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 866d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 86770b83c111beceaf8fbb700580833e7fec99272cfAlex SakhartchoukRsFont rsi_FontCreateFromMemory(Context *rsc, 86870b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk char const *name, size_t name_length, 86970b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk float fontSize, uint32_t dpi, 87070b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk const void *data, size_t data_length) { 87170b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi, data, data_length); 8725224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (newFont) { 8735224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk newFont->incUserRef(); 8745224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } 8755224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk return newFont; 8765224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk} 8775224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk 8787974fc03e11f3a8dd40f794f3b33b4889483090cRahul Chaudhry} // namespace renderscript 8797974fc03e11f3a8dd40f794f3b33b4889483090cRahul Chaudhry} // namespace android 880