rsFont.cpp revision 7b3e9bd825901e33661e3c385e3e7c6f40ca6000
1d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 2d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk/* 3d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Copyright (C) 2009 The Android Open Source Project 4d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * 5d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License"); 6d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * you may not use this file except in compliance with the License. 7d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * You may obtain a copy of the License at 8d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * 9d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * http://www.apache.org/licenses/LICENSE-2.0 10d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * 11d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * Unless required by applicable law or agreed to in writing, software 12d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS, 13d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * See the License for the specific language governing permissions and 15d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk * limitations under the License. 16d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk */ 17d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 18d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsContext.h" 19d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 20d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsFont.h" 21d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsProgramFragment.h" 22c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk#include <cutils/properties.h> 2302000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 2402000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk#include <ft2build.h> 2502000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk#include FT_FREETYPE_H 26d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include FT_BITMAP_H 27d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 28d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/gl.h> 29d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/glext.h> 30d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2.h> 31d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2ext.h> 32d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 33d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android; 34d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android::renderscript; 35d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 36afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) { 37d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 38d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = false; 393659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mFace = NULL; 40d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 41d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 425224a27798f89093b13722b41143551a057ce550Alex Sakhartchoukbool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) { 43afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 44d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 485224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk FT_Error error = 0; 495224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (data != NULL && dataLen > 0) { 505224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace); 515224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } else { 525224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace); 535224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } 545224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk 55afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 56c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk LOGE("Unable to initialize font %s", name); 57d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontName = name; 61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSize = fontSize; 62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDpi = dpi; 63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 64c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0); 65afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 66c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk LOGE("Unable to set font size on %s", name); 67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 762e8665de7c0eb4514c67baf8693d61c892e5303dJason Samsvoid Font::preDestroy() const { 772e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 782e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams if (mRSC->mStateFont.mActiveFonts[ct] == this) { 792e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams mRSC->mStateFont.mActiveFonts.removeAt(ct); 802e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams break; 812e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams } 822e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams } 832e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams} 842e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams 85afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::invalidateTextureCache() { 86afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 87d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 88d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 89d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 90d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 91afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { 92d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 93d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 9509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 96d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 9809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 9909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 101d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 10309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 104d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk const uint8_t* cacheBuffer = state->getTextTextureData(); 12209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t bX = 0, bY = 0; 12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 12709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 12809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("Skipping invalid index"); 12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk continue; 13009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 13209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 13309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 135d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 136d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 13709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 1445224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk // 0, 0 is top left, so bottom is a positive number 1455224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (bounds->bottom < nPenY) { 14609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->bottom = nPenY; 14709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->left > nPenX) { 14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->left = nPenX; 15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->right < nPenX + width) { 15209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->right = nPenX + width; 15309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 1545224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (bounds->top > nPenY - height) { 1555224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->top = nPenY - height; 15609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 15809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 15909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 16009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 16109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk RenderMode mode, Rect *bounds, 162afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 163afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 164d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 165d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 166d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 167afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mode == Font::MEASURE) { 16809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds == NULL) { 16909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("No return rectangle provided to measure text"); 17009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk return; 17109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk // Reset min and max of the bounding box to something large 1735224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->set(1e6, -1e6, 1e6, -1e6); 17409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 17509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 17609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t penX = x, penY = y; 17709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t glyphsLeft = 1; 178afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 179d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft = numGlyphs; 180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 182d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t index = start; 183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t nextIndex = 0; 184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk while (glyphsLeft > 0) { 186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 187c9c38dd8508a2f805213abee1f9f44f103ac0a0dKenny Root int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); 188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 189d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reached the end of the string or encountered 190afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (utfChar < 0) { 191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 192d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 193d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 194d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Move to the next character in the array 195d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk index = nextIndex; 196d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 19701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 198d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 199d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 200afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph->mIsValid) { 201afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk switch (mode) { 20209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case FRAMEBUFFER: 20309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 20409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case BITMAP: 20609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 20709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case MEASURE: 20909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 21009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 21109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 213d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 21402000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk penX += (cachedGlyph->mAdvanceX >> 6); 215d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 216d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 217afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 218d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft --; 219d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 220d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 221d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 222d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 22301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 22401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 22501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 226afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph == NULL) { 22701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 22801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 22901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Is the glyph still in texture cache? 230afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!cachedGlyph->mIsValid) { 23101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk updateGlyphCache(cachedGlyph); 23201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 23301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 23401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return cachedGlyph; 23501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 23601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 237afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) { 238a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 239afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 240a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk LOGE("Couldn't load glyph."); 241a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return; 242a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 243d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 24402000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk glyph->mAdvanceX = mFace->glyph->advance.x; 24502000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk glyph->mAdvanceY = mFace->glyph->advance.y; 246a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 247a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 248d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 249a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 253d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 255d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Let the font state figure out where to put the bitmap 256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 257a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 259afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!glyph->mIsValid) { 260d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 261d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 262d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 263a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endX = startX + bitmap->width; 264a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endY = startY + bitmap->rows; 265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 266d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinX = startX; 267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinY = startY; 268a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 269a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 271d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 280afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { 281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 283d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 284d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 285d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mIsValid = false; 286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 287d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk updateGlyphCache(newGlyph); 288d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newGlyph; 290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 291d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 2925224a27798f89093b13722b41143551a057ce550Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi, 2935224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk const void *data, uint32_t dataLen) { 29435b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk rsc->mStateFont.checkInit(); 295d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 296d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 297afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < activeFonts.size(); i ++) { 298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *ithFont = activeFonts[i]; 299afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 300d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return ithFont; 301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *newFont = new Font(rsc); 3055224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen); 306afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (isInitialized) { 307d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk activeFonts.push(newFont); 30801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 309d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newFont; 310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 312225afd317e101a7be5fe02c0a86361146ea89f05Jason Sams ObjectBase::checkDelete(newFont); 313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return NULL; 314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 316afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::~Font() { 317afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mFace) { 318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FT_Done_Face(mFace); 319d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 321afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 322d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete glyph; 324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 325d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 327afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::FontState() { 328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mMaxNumberOfQuads = 1024; 330d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 331d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC = NULL; 3323659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 333c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 334c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the renderer properties 335c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 336c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 337c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the gamma 338c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 339c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 340c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk gamma = atof(property); 341c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 342c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the black gamma threshold 34409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk blackThreshold = atoi(property); 347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the white gamma threshold 35109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk whiteThreshold = atoi(property); 354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 356c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Compute the gamma tables 358c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackGamma = gamma; 359c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteGamma = 1.0f / gamma; 3604f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 3614f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 362d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 363d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 364afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::~FontState() { 365afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 366d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 367d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 368d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 369d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 370d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 371d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 372afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFT_Library FontState::getLib() { 373afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mLibrary) { 374a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 375afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 376d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize freetype"); 377a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return NULL; 378d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 379d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 3803659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 381a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 382a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 383d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 384afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::init(Context *rsc) { 385a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 386d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 387d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 388afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::flushAllAndInvalidate() { 389afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 391d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 393afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { 394d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 395d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 396afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 399d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 401afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 402d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 403afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 406d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 407d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 411d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 413afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 415afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 421afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 423d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 425afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 427afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 433afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 44709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 44809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 450d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 451afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 452afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 45309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 460b7e83bda41e66c966b98935b44140692bfe0c4caJason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 461383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 464afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 472d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 473d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 474afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initRenderState() { 4757ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk String8 shaderString("varying vec2 varTex0;\n"); 476e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("void main() {\n"); 477e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 478e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 479c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 480e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 481e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("}\n"); 482e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 483e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 484c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 485e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 486e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 487c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); 488e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); 489e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 490f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false); 491e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 492e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk uint32_t tmp[4]; 493e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 494e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[1] = (uint32_t)inputType; 49584e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; 49684e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[3] = RS_TEXTURE_2D; 497e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 498366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams mFontShaderFConstant.set(new Allocation(mRSC, inputType, 499366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); 500e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 501e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.length(), tmp, 4); 502d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 503383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 504d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 505d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 506d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 507d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSampler.set(sampler); 508383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, sampler); 509d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 510d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 511d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore.set(fontStore); 512d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 513d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 514d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 515d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 516d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 517d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 518afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initTextTexture() { 519d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 520d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 521d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 522f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false); 523d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 524366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams Allocation *cacheAlloc = new Allocation(mRSC, texType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE); 525d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 526b7e83bda41e66c966b98935b44140692bfe0c4caJason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 527d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 52909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nextLine = 0; 530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 53401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 53501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 536d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 546afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initVertexArrayBuffers() { 547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 548d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 550f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false); 551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 552366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams Allocation *indexAlloc = new Allocation(mRSC, indexType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 556afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 55709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i6 = i * 6; 55809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i4 = i * 4; 559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 562d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 566d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 567d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 568d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 574d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 57564cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 57664cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1); 57764cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1); 57864cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC); 579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 580f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *vertexDataType = Type::getType(mRSC, vertexDataElem, 581f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams mMaxNumberOfQuads * 4, 582f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams 0, 0, false, false); 583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 584366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mVertexArray.set(vertexAlloc); 588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 591afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::checkInit() { 592afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 60135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 60235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 60335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 60435b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 60535b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("0123456789"); 60635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk 607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 609d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 61160709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams Context::PushState ps(mRSC); 612d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 61360709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramVertex(mRSC->getDefaultProgramVertex()); 61460709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramRaster(mRSC->getDefaultProgramRaster()); 61560709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramFragment(mFontShaderF.get()); 61660709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramStore(mFontProgramStore.get()); 617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 618afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mConstantsDirty) { 6194b45b8998e0d7038efaea80c70d23c086640b4e3Jason Sams mFontShaderFConstant->data(mRSC, 0, 0, 1, &mConstants, sizeof(mConstants)); 620c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = false; 621ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 622ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 627d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *tex = vtx + 3; 629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 63054929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk VertexArray::Attrib attribs[2]; 63154929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position"); 63254929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0"); 63354929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk VertexArray va(attribs, 2); 634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 642afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u1, float v1, 643afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x2, float y2, float z2, 644afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u2, float v2, 645afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x3, float y3, float z3, 646afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u3, float v3, 647afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x4, float y4, float z4, 648afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u4, float v4) { 649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t floatsPerVert = 5; 651d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 652d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 653d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Cull things that are off the screen 654d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float width = (float)mRSC->getWidth(); 655d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float height = (float)mRSC->getHeight(); 656d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 657afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 665d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 666d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 667d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 668d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 669d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 675d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 676d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 678d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 682d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 690d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 692afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex == mMaxNumberOfQuads) { 693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 696d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 697d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 69801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 69901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 70035b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 701afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 70201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 70301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 70401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 70501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 70601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 70701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 70801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 70901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 71001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 71101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 71201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 713afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 71401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 71501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 71601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 71701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 71801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 71901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 72001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 72109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 72209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 72309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::RenderMode mode, 72409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::Rect *bounds, 725afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 726d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 727d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 728d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 729d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 730afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 731afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mDefault.get()) { 732c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk String8 fontsDir("/fonts/DroidSans.ttf"); 733c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 734c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk fullPath += fontsDir; 735c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk 7367b3e9bd825901e33661e3c385e3e7c6f40ca6000Alex Sakhartchouk mDefault.set(Font::create(mRSC, fullPath.string(), 8, mRSC->getDPI())); 737a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 738a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk currentFont = mDefault.get(); 739a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 740afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 7413659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk LOGE("Unable to initialize any fonts"); 7423659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk return; 7433659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 7443659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 74509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 74609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 747d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 748afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 749d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 752d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 753d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 75409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 75509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 7565224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->bottom = - bounds->bottom; 7575224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->top = - bounds->top; 758d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 759d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 7609fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 761c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[0] = r; 762c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[1] = g; 763c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[2] = b; 764c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[3] = a; 765c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 766c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = 1.0f; 767c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 768c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (luminance <= mBlackThreshold) { 769c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mBlackGamma; 770c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 771c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mWhiteGamma; 772c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 7734f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 774c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = true; 7759fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk} 7769fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk 777ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 778c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *r = mConstants.mFontColor[0]; 779c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *g = mConstants.mFontColor[1]; 780c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *b = mConstants.mFontColor[2]; 781c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *a = mConstants.mFontColor[3]; 782ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk} 783ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 784afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::deinit(Context *rsc) { 785a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mInitialized = false; 786a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 78701b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines mFontShaderFConstant.clear(); 78801b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines 789a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mIndexBuffer.clear(); 790a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mVertexArray.clear(); 791a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 792a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontShaderF.clear(); 793a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontSampler.clear(); 794a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontProgramStore.clear(); 795a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 796a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mTextTexture.clear(); 797afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 798a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk delete mCacheLines[i]; 799d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 800a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mCacheLines.clear(); 801d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 802d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDefault.clear(); 803a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 804afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mLibrary) { 805a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Done_FreeType( mLibrary ); 8063659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 807a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 808d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 809d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 81002000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchoukbool FontState::CacheTextureLine::fitBitmap(FT_Bitmap_ *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 81102000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk if ((uint32_t)bitmap->rows > mMaxHeight) { 81202000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk return false; 81302000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk } 81402000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 81502000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk if (mCurrentCol + (uint32_t)bitmap->width < mMaxWidth) { 81602000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk *retOriginX = mCurrentCol; 81702000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk *retOriginY = mCurrentRow; 81802000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk mCurrentCol += bitmap->width; 81902000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk mDirty = true; 82002000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk return true; 82102000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk } 82202000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 82302000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk return false; 82402000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk} 82502000b3cdcb2ac369bd06313932b26d4b8e023a9Alex Sakhartchouk 826d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android { 827d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript { 828d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 829c17ace2391783dcabc6c1482edf0362654fd83e5Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, float fontSize, uint32_t dpi) { 830a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 831afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (newFont) { 832a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk newFont->incUserRef(); 833a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 834a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return newFont; 835d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 836d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8375224a27798f89093b13722b41143551a057ce550Alex SakhartchoukRsFont rsi_FontCreateFromMemory(Context *rsc, char const *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) { 8385224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi, data, dataLen); 8395224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (newFont) { 8405224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk newFont->incUserRef(); 8415224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } 8425224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk return newFont; 8435224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk} 8445224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk 845d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript 846d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android 847