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" 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 292a1576ff5147497b18f9f62b97a6c4fa40035e93Michael Butler#include <string.h> 30d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 3111496ac131bb691edf5bdcab3029dceef5c1e4e1Chih-Hung Hsiehnamespace android { 3211496ac131bb691edf5bdcab3029dceef5c1e4e1Chih-Hung Hsiehnamespace renderscript { 33d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 34b8353c5943f4038fd7f08db3d958390ce9418798Yang NiFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) { 35d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 36d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = false; 3744bef6fba6244292b751387f3d6c31cca96c28adChris Wailes mFace = nullptr; 38d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 39d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 405224a27798f89093b13722b41143551a057ce550Alex Sakhartchoukbool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) { 41b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 42afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 43af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Reinitialization of fonts not supported"); 44d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 475224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk FT_Error error = 0; 4844bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (data != nullptr && dataLen > 0) { 495224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace); 505224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } else { 515224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace); 525224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } 535224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk 54afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 55af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Unable to initialize font %s", name); 56d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 57d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 5948ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams mFontName = rsuCopyString(name); 60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSize = fontSize; 61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDpi = dpi; 62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 63c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0); 64afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 65af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Unable to set font size on %s", name); 66d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 72b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 762e8665de7c0eb4514c67baf8693d61c892e5303dJason Samsvoid Font::preDestroy() const { 7782e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang auto& activeFonts = mRSC->mStateFont.mActiveFonts; 7882e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang for (uint32_t ct = 0; ct < activeFonts.size(); ct++) { 7982e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang if (activeFonts[ct] == this) { 8082e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang activeFonts.erase(activeFonts.begin() + ct); 81b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni break; 822e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams } 832e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams } 842e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams} 852e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams 86afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::invalidateTextureCache() { 87afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 88b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCachedGlyphs.valueAt(i)->mIsValid = false; 89d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 90d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 91d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 92afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { 93d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 94d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 9609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 97d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 9909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 10109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 102d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 10309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 105d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 122a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams const uint8_t* cacheBuffer = state->mCacheBuffer; 12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t bX = 0, bY = 0; 12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 12709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 12809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 129af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Skipping invalid index"); 13009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk continue; 13109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 13309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 13409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 136d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 137d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 14409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 1455224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk // 0, 0 is top left, so bottom is a positive number 1465224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (bounds->bottom < nPenY) { 14709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->bottom = nPenY; 14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->left > nPenX) { 15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->left = nPenX; 15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->right < nPenX + width) { 15309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->right = nPenX + width; 15409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 1555224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (bounds->top > nPenY - height) { 1565224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->top = nPenY - height; 15709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 15909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 16009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 16109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 16209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk RenderMode mode, Rect *bounds, 163afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 16444bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (!mInitialized || numGlyphs == 0 || text == nullptr || len == 0) { 165d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 166d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 167d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 168afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mode == Font::MEASURE) { 16944bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (bounds == nullptr) { 170af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("No return rectangle provided to measure text"); 17109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk return; 17209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk // Reset min and max of the bounding box to something large 1745224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->set(1e6, -1e6, 1e6, -1e6); 17509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 17709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t penX = x, penY = y; 17809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t glyphsLeft = 1; 179afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft = numGlyphs; 181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t index = start; 184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t nextIndex = 0; 185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk while (glyphsLeft > 0) { 187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 188c9c38dd8508a2f805213abee1f9f44f103ac0a0dKenny Root int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); 189d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 190d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reached the end of the string or encountered 191afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (utfChar < 0) { 192d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 193d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 194d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 195d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Move to the next character in the array 196d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk index = nextIndex; 197d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 19801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 199d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 200d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 201afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph->mIsValid) { 202afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk switch (mode) { 20309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case FRAMEBUFFER: 20409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 20509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case BITMAP: 20709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 20809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case MEASURE: 21009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 21109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 21209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 213d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 21502000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk penX += (cachedGlyph->mAdvanceX >> 6); 216d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 217d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 218afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 219d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft --; 220d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 221d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 222d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 223d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 22401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 22501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 226b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 22744bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (cachedGlyph == nullptr) { 22801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 22901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 23001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Is the glyph still in texture cache? 231afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!cachedGlyph->mIsValid) { 23201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk updateGlyphCache(cachedGlyph); 23301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 23401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 23501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return cachedGlyph; 23601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 23701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 238afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) { 239b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 240a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 241afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 242af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Couldn't load glyph."); 243a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return; 244a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 245d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 24602000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk glyph->mAdvanceX = mFace->glyph->advance.x; 24702000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk glyph->mAdvanceY = mFace->glyph->advance.y; 248a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 249a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 251a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 253d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 255d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Let the font state figure out where to put the bitmap 258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 259a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 260d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 261afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!glyph->mIsValid) { 262d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 264d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 265a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endX = startX + bitmap->width; 266a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endY = startY + bitmap->rows; 267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinX = startX; 269d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinY = startY; 270a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 271a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 280b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 283afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { 284d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 285b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni mCachedGlyphs.add(glyph, newGlyph); 286b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 287d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 288d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mIsValid = false; 289b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk updateGlyphCache(newGlyph); 291d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newGlyph; 293d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 2955224a27798f89093b13722b41143551a057ce550Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi, 2965224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk const void *data, uint32_t dataLen) { 29735b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk rsc->mStateFont.checkInit(); 29882e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang auto& activeFonts = rsc->mStateFont.mActiveFonts; 299d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 300afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < activeFonts.size(); i ++) { 301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *ithFont = activeFonts[i]; 302b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return ithFont; 304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 305d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 307d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *newFont = new Font(rsc); 3085224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen); 309afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (isInitialized) { 31082e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang activeFonts.push_back(newFont); 31101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newFont; 313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 315225afd317e101a7be5fe02c0a86361146ea89f05Jason Sams ObjectBase::checkDelete(newFont); 31644bef6fba6244292b751387f3d6c31cca96c28adChris Wailes return nullptr; 317d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 319afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::~Font() { 320b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 321afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mFace) { 322d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FT_Done_Face(mFace); 323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 324b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif 325d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 326afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 327b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete glyph; 329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 330d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 331d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 332afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::FontState() { 333d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 334d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mMaxNumberOfQuads = 1024; 335d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 33644bef6fba6244292b751387f3d6c31cca96c28adChris Wailes mRSC = nullptr; 337b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 33844bef6fba6244292b751387f3d6c31cca96c28adChris Wailes mLibrary = nullptr; 339b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 340c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 3417e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich float gamma = DEFAULT_TEXT_GAMMA; 3427e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 3437e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 3447e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich 345e5e18cca3eefccf3a6aabd254ceb2c59f120a7d2Elliott Hughes#ifdef __ANDROID__ 346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the renderer properties 34782e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang char property[PROP_VALUE_MAX]; 348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the gamma 35044bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (property_get(PROPERTY_TEXT_GAMMA, property, nullptr) > 0) { 351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk gamma = atof(property); 352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the black gamma threshold 35544bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, nullptr) > 0) { 356c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk blackThreshold = atoi(property); 357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the white gamma threshold 36044bef6fba6244292b751387f3d6c31cca96c28adChris Wailes if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, nullptr) > 0) { 361c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk whiteThreshold = atoi(property); 362c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 3637e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich#endif 3647e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich 3657e85ca20affa9655d9033ec2b0fdff034f19a9bfNick Kralevich mBlackThreshold = (float)(blackThreshold) / 255.0f; 366c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 367c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 368c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Compute the gamma tables 369c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackGamma = gamma; 370c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteGamma = 1.0f / gamma; 3714f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 3724f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 373d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 374d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 375afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::~FontState() { 376afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 377d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 378d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 379d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 380d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 382b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 383afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFT_Library FontState::getLib() { 384afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mLibrary) { 385a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 386afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 387af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Unable to initialize freetype"); 38844bef6fba6244292b751387f3d6c31cca96c28adChris Wailes return nullptr; 389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 3913659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 392a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 393a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 394b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 395b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk 396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 397afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::init(Context *rsc) { 398a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 399d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 401afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::flushAllAndInvalidate() { 402afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 403d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 406afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { 407d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 409afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 414b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#ifndef ANDROID_RS_SERIALIZE 415afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 417afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 418af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 427afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 429afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 435afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 439afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 441afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 447afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 448af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 451d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 461a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams uint8_t *cacheBuffer = mCacheBuffer; 46209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 465afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 466afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 46709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 472d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 473d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 474eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams 475a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mRSC->mHal.funcs.allocation.data2D(mRSC, mTextTexture.get(), 0, 0, 0, 476a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, mCacheWidth, mCacheHeight, 477358747a3118301c5faeee73c98dd5f839bbfb54aTim Murray mCacheBuffer, mCacheWidth*mCacheHeight, mCacheWidth); 478a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams 479383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 480d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 481d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 482afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 483af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("Cache Line: H: %u Empty Space: %f", 484d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 485d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 486d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 487d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 488d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 489d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 490d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 491b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk#endif //ANDROID_RS_SERIALIZE 492d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 493afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initRenderState() { 49448ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams const char *shaderString = "varying vec2 varTex0;\n" 49548ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams "void main() {\n" 49648ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams " lowp vec4 col = UNI_Color;\n" 49748ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams " col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n" 49848ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams " col.a = pow(col.a, UNI_Gamma);\n" 49948ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams " gl_FragColor = col;\n" 50048ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams "}\n"; 501e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 502748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk const char *textureNames[] = { "Tex0" }; 503748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk const size_t textureNamesLengths[] = { 4 }; 504748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk size_t numTextures = sizeof(textureNamesLengths)/sizeof(*textureNamesLengths); 505748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk 506748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk ObjectBaseRef<const Element> colorElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, 507748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_KIND_USER, false, 4); 508748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk ObjectBaseRef<const Element> gammaElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, 509748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_KIND_USER, false, 1); 510f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams 511f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams const char *ebn1[] = { "Color", "Gamma" }; 512f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams const Element *ebe1[] = {colorElem.get(), gammaElem.get()}; 513f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams ObjectBaseRef<const Element> constInput = Element::create(mRSC, 2, ebe1, ebn1); 514c7968a0ac24f05d978616a79a5068b6b16dbbda6Jason Sams ObjectBaseRef<Type> inputType = Type::getTypeRef(mRSC, constInput.get(), 1); 515e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 516f8852d0494a260c583795a96a2a06c49b86a9b10Ian Rogers uintptr_t tmp[4]; 517e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 518f8852d0494a260c583795a96a2a06c49b86a9b10Ian Rogers tmp[1] = (uintptr_t)inputType.get(); 51984e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; 52084e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[3] = RS_TEXTURE_2D; 521e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 522c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType.get(), 523748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_ALLOCATION_USAGE_SCRIPT | 524748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); 52548ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams ProgramFragment *pf = new ProgramFragment(mRSC, shaderString, strlen(shaderString), 526748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk textureNames, numTextures, textureNamesLengths, 527748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk tmp, 4); 528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 529383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 531c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontSampler.set(Sampler::getSampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 532748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, 533748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_SAMPLER_CLAMP).get()); 534c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, mFontSampler.get()); 535c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk 536c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk mFontProgramStore.set(ProgramStore::getProgramStore(mRSC, true, true, true, true, 537c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk false, false, 538c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk RS_BLEND_SRC_SRC_ALPHA, 539c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, 540c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk RS_DEPTH_FUNC_ALWAYS).get()); 5418feea4e0dec48ea03bd6d32706d058b86dddc5baJason Sams mFontProgramStore->init(); 542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 544afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initTextTexture() { 545748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk ObjectBaseRef<const Element> alphaElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_8, 546748eb07e805b93c2bf79340d4937963ab739d17cAlex Sakhartchouk RS_KIND_PIXEL_A, true, 1); 547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 549a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mCacheHeight = 256; 550a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mCacheWidth = 1024; 551c7968a0ac24f05d978616a79a5068b6b16dbbda6Jason Sams ObjectBaseRef<Type> texType = Type::getTypeRef(mRSC, alphaElem.get(), mCacheWidth, mCacheHeight); 55293d6bc872b7d9fba63abfa7513d56b38d9c3d371Chris Wailes 553a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mCacheBuffer = new uint8_t[mCacheWidth * mCacheHeight]; 554a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams 555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 556b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType.get(), 557b8353c5943f4038fd7f08db3d958390ce9418798Yang Ni RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE); 558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 56109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nextLine = 0; 56282e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang mCacheLines.push_back(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 56382e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang nextLine += mCacheLines.back()->mMaxHeight; 56482e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang mCacheLines.push_back(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 56582e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang nextLine += mCacheLines.back()->mMaxHeight; 56682e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang mCacheLines.push_back(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 56782e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang nextLine += mCacheLines.back()->mMaxHeight; 56882e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang mCacheLines.push_back(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 56982e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang nextLine += mCacheLines.back()->mMaxHeight; 57082e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang mCacheLines.push_back(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 57182e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang nextLine += mCacheLines.back()->mMaxHeight; 57282e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang mCacheLines.push_back(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 57382e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang nextLine += mCacheLines.back()->mMaxHeight; 57482e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang mCacheLines.push_back(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 578afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initVertexArrayBuffers() { 579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 580c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> indexElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 581c7968a0ac24f05d978616a79a5068b6b16dbbda6Jason Sams ObjectBaseRef<Type> indexType = Type::getTypeRef(mRSC, indexElem.get(), mMaxNumberOfQuads * 6); 582d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 583c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType.get(), 584eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams RS_ALLOCATION_USAGE_SCRIPT | 585eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 586a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams uint16_t *indexPtr = (uint16_t*)mRSC->mHal.funcs.allocation.lock1D(mRSC, indexAlloc); 587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 589afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 59009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i6 = i * 6; 59109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i4 = i * 4; 592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 601d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 602eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams indexAlloc->sendDirty(mRSC); 603d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 604c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> posElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 605c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk ObjectBaseRef<const Element> texElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 606d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 607f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams const char *ebn1[] = { "position", "texture0" }; 608f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams const Element *ebe1[] = {posElem.get(), texElem.get()}; 609f313dc32d5ea68a7c48fb4ec6e131ec2fb97ce2dJason Sams ObjectBaseRef<const Element> vertexDataElem = Element::create(mRSC, 2, ebe1, ebn1); 610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 611c7968a0ac24f05d978616a79a5068b6b16dbbda6Jason Sams ObjectBaseRef<Type> vertexDataType = Type::getTypeRef(mRSC, vertexDataElem.get(), mMaxNumberOfQuads * 4); 612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 613c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType.get(), 614eb4fe18dd88634330f9566cbb9e785d8c7ec5813Jason Sams RS_ALLOCATION_USAGE_SCRIPT); 615a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mTextMeshPtr = (float*)mRSC->mHal.funcs.allocation.lock1D(mRSC, vertexAlloc); 616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 617a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh.set(new Mesh(mRSC, 1, 1)); 618a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->setVertexBuffer(vertexAlloc, 0); 619a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->setPrimitive(indexAlloc, RS_PRIMITIVE_TRIANGLE, 0); 620a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->init(); 621a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mRSC->mHal.funcs.allocation.unlock1D(mRSC, indexAlloc); 622a6dd823b9dcbd7ce7dfc34eda52a1e4104771f79Jason Sams mRSC->mHal.funcs.allocation.unlock1D(mRSC, vertexAlloc); 623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 626afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::checkInit() { 627afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 630d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 631d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 63635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 637a7f5e0406825151660c1c2e75c287e2fc8368023Jason Sams mLatinPrecache = " eisarntolcdugpmhbyfvkwzxjq" 638a7f5e0406825151660c1c2e75c287e2fc8368023Jason Sams "EISARNTOLCDUGPMHBYFVKWZXJQ" 639a7f5e0406825151660c1c2e75c287e2fc8368023Jason Sams ",.?!()-+@;:`'0123456789"; 640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 642d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 643d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 64460709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams Context::PushState ps(mRSC); 645d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 64660709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramVertex(mRSC->getDefaultProgramVertex()); 64760709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramRaster(mRSC->getDefaultProgramRaster()); 64860709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramFragment(mFontShaderF.get()); 64960709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramStore(mFontProgramStore.get()); 650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 651afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mConstantsDirty) { 6524b45b8998e0d7038efaea80c70d23c086640b4e3Jason Sams mFontShaderFConstant->data(mRSC, 0, 0, 1, &mConstants, sizeof(mConstants)); 653c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = false; 654ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 655ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 656d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 657d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 660a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk mMesh->renderPrimitiveRange(mRSC, 0, 0, mCurrentQuadIndex * 6); 661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 664afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u1, float v1, 665afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x2, float y2, float z2, 666afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u2, float v2, 667afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x3, float y3, float z3, 668afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u3, float v3, 669afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x4, float y4, float z4, 670afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u4, float v4) { 671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 6722d1220c27ae91f0b307f283fe66cb767b63dfe38Alex Sakhartchouk const uint32_t floatsPerVert = 6; 673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 675a74a8f635ce4fae0a9d4b9c79e9fa412787bf6a2Alex Sakhartchouk if (x1 > mSurfaceWidth || y1 < 0.0f || x2 < 0 || y4 > mSurfaceHeight) { 676d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 678d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 680af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 681af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 682af12ac6a08651464f8d823add667c706f993b587Steve Block ALOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 6872d1220c27ae91f0b307f283fe66cb767b63dfe38Alex Sakhartchouk (*currentPos++) = 0; 688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 692d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 6942d1220c27ae91f0b307f283fe66cb767b63dfe38Alex Sakhartchouk (*currentPos++) = 0; 695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 698d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 699d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 700d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 7012d1220c27ae91f0b307f283fe66cb767b63dfe38Alex Sakhartchouk (*currentPos++) = 0; 702d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 703d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 704d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 705d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 706d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 707d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 7082d1220c27ae91f0b307f283fe66cb767b63dfe38Alex Sakhartchouk (*currentPos++) = 0; 709d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 710d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 711d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 712d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 713d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 714afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex == mMaxNumberOfQuads) { 715d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 716d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 717d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 718d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 719d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 72001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 72101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 72235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 723afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 72401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 72501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 72601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 72701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 72801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 72901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 73001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 73101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 73201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 73301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 73401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 735a7f5e0406825151660c1c2e75c287e2fc8368023Jason Sams const size_t l = strlen(mLatinPrecache); 736a7f5e0406825151660c1c2e75c287e2fc8368023Jason Sams while ((remainingCapacity > 25) && (precacheIdx < l)) { 73701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 73801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 73901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 74001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 74101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 74201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 74301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 74409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 74509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 74609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::RenderMode mode, 74709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::Rect *bounds, 748afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 749d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 752d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 753afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 754afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mDefault.get()) { 75548ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams char fullPath[1024]; 75648ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams const char * root = getenv("ANDROID_ROOT"); 75748ecf6a5e85a9a832f41393ed2802385bb8b5db8Jason Sams rsAssert(strlen(root) < 256); 7582a1576ff5147497b18f9f62b97a6c4fa40035e93Michael Butler strlcpy(fullPath, root, sizeof(fullPath)); 7592a1576ff5147497b18f9f62b97a6c4fa40035e93Michael Butler strlcat(fullPath, "/fonts/Roboto-Regular.ttf", sizeof(fullPath)); 7607305bb3390497843a6a530f68cc07be88adc7c52Michael Butler fullPath[sizeof(fullPath)-1] = '\0'; 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