rsFont.cpp revision c17ace2391783dcabc6c1482edf0362654fd83e5
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#ifndef ANDROID_RS_BUILD_FOR_HOST 19d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsContext.h" 20d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#else 21d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsContextHostStub.h" 22d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#endif 23d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 24d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsFont.h" 25d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include "rsProgramFragment.h" 26c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk#include <cutils/properties.h> 27d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include FT_BITMAP_H 28d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 29d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/gl.h> 30d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES/glext.h> 31d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2.h> 32d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk#include <GLES2/gl2ext.h> 33d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 34d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android; 35d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukusing namespace android::renderscript; 36d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 37afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::Font(Context *rsc) : ObjectBase(rsc), mCachedGlyphs(NULL) { 38d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 39d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = false; 403659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mFace = NULL; 41d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 42d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 43c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchoukbool Font::init(const char *name, float fontSize, uint32_t dpi) { 44afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 49c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace); 50afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 51c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk LOGE("Unable to initialize font %s", name); 52d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 53d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 54d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 55d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontName = name; 56d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSize = fontSize; 57d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDpi = dpi; 58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 59c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0); 60afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 61c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk LOGE("Unable to set font size on %s", name); 62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 65d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 66d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 67d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 71afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::invalidateTextureCache() { 72afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 76d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 77afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { 78d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 79d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 8109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 82d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 8409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 8509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 8609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 87d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 8909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 90d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 9209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 9309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 9409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 9509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 9609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 9809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 9909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 10109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 10309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk const uint8_t* cacheBuffer = state->getTextTextureData(); 10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t bX = 0, bY = 0; 11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("Skipping invalid index"); 11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk continue; 11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 121d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 122d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 12709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 12809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 13009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->bottom > nPenY) { 13109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->bottom = nPenY; 13209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->left > nPenX) { 13409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->left = nPenX; 13509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->right < nPenX + width) { 13709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->right = nPenX + width; 13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->top < nPenY + height) { 14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->top = nPenY + height; 14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 14409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 14509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 14609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk RenderMode mode, Rect *bounds, 147afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 148afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 149d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 150d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 151d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 152afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mode == Font::MEASURE) { 15309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds == NULL) { 15409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("No return rectangle provided to measure text"); 15509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk return; 15609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 15709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk // Reset min and max of the bounding box to something large 15809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->set(1e6, -1e6, -1e6, 1e6); 15909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 16009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 16109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t penX = x, penY = y; 16209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t glyphsLeft = 1; 163afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 164d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft = numGlyphs; 165d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 166d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 167d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t index = start; 168d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t nextIndex = 0; 169d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 170d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk while (glyphsLeft > 0) { 171d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 172c9c38dd8508a2f805213abee1f9f44f103ac0a0dKenny Root int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); 173d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 174d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reached the end of the string or encountered 175afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (utfChar < 0) { 176d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 177d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 179d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Move to the next character in the array 180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk index = nextIndex; 181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 18201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 185afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph->mIsValid) { 186afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk switch (mode) { 18709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case FRAMEBUFFER: 18809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 18909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 19009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case BITMAP: 19109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 19209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 19309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case MEASURE: 19409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 19509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 19609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 197d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 198d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 199d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk penX += (cachedGlyph->mAdvance.x >> 6); 200d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 201d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 202afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 203d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft --; 204d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 205d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 206d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 207d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 20801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 20901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 21001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 211afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph == NULL) { 21201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 21301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 21401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Is the glyph still in texture cache? 215afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!cachedGlyph->mIsValid) { 21601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk updateGlyphCache(cachedGlyph); 21701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 21801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 21901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return cachedGlyph; 22001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 22101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 222afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) { 223a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 224afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 225a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk LOGE("Couldn't load glyph."); 226a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return; 227a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 228d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 229a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mAdvance = mFace->glyph->advance; 230a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 231a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 232d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 233a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 234d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 235d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 236d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 237d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 238d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 239d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Let the font state figure out where to put the bitmap 240d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 241a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 242d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 243afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!glyph->mIsValid) { 244d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 245d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 246d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 247a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endX = startX + bitmap->width; 248a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endY = startY + bitmap->rows; 249d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 250d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinX = startX; 251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinY = startY; 252a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 253a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 254d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 255d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 259d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 260d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 261d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 262d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 264afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { 265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 266d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 269d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mIsValid = false; 270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 271d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk updateGlyphCache(newGlyph); 272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newGlyph; 274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 276c17ace2391783dcabc6c1482edf0362654fd83e5Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi) { 27735b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk rsc->mStateFont.checkInit(); 278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 280afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < activeFonts.size(); i ++) { 281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *ithFont = activeFonts[i]; 282afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 283d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return ithFont; 284d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 285d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 287d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *newFont = new Font(rsc); 288d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi); 289afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (isInitialized) { 290d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk activeFonts.push(newFont); 29101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newFont; 293d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 295225afd317e101a7be5fe02c0a86361146ea89f05Jason Sams ObjectBase::checkDelete(newFont); 296d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return NULL; 297d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 299afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::~Font() { 300afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mFace) { 301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FT_Done_Face(mFace); 302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 303d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 305d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (mRSC->mStateFont.mActiveFonts[ct] == this) { 306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->mStateFont.mActiveFonts.removeAt(ct); 307d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 308d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 309d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 311afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete glyph; 314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 316d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 317afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::FontState() { 318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 319d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mMaxNumberOfQuads = 1024; 320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC = NULL; 3223659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 323c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 324c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the renderer properties 325c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 326c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 327c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the gamma 328c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 329c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 330c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk gamma = atof(property); 331c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 332c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 333c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the black gamma threshold 33409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 335c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 336c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk blackThreshold = atoi(property); 337c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 338c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 339c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 340c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the white gamma threshold 34109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 342c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk whiteThreshold = atoi(property); 344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Compute the gamma tables 348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackGamma = gamma; 349c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteGamma = 1.0f / gamma; 3504f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 3514f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 352d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 353d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 354afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::~FontState() { 355afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 356d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 357d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 358d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 359d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 360d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 361d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 362afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFT_Library FontState::getLib() { 363afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mLibrary) { 364a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 365afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 366d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize freetype"); 367a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return NULL; 368d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 369d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 3703659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 371a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 372a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 373d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 374afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::init(Context *rsc) { 375a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 376d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 377d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 378afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::flushAllAndInvalidate() { 379afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 380d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 382d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 383afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { 384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 386afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 387d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 391afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 393afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 394d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 395d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 399d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 401d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 402d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 403afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 405afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 406d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 407d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 411afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 413d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 415afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 417afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 419d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 423afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 425d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 431d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 43709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 43809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 441afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 442afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 44309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 445d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 446d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 449d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 450b7e83bda41e66c966b98935b44140692bfe0c4caJason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 451383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 454afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 458d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 459d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 462d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 464afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initRenderState() { 4657ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk String8 shaderString("varying vec2 varTex0;\n"); 466e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("void main() {\n"); 467e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 468e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 469c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 470e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 471e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("}\n"); 472e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 473e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 474c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 475e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 476e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 477c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); 478e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); 479e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 480f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false); 481e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 482e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk uint32_t tmp[4]; 483e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 484e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[1] = (uint32_t)inputType; 48584e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; 48684e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[3] = RS_TEXTURE_2D; 487e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 488366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams mFontShaderFConstant.set(new Allocation(mRSC, inputType, 489366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); 490e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 491e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.length(), tmp, 4); 492d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 493383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 494d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 495d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 496d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 497d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSampler.set(sampler); 498383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, sampler); 499d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 500d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 501d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore.set(fontStore); 502d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 503d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 504d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 505d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 506d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 507d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 508afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initTextTexture() { 509d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 510d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 511d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 512f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false); 513d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 514366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams Allocation *cacheAlloc = new Allocation(mRSC, texType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE); 515d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 516b7e83bda41e66c966b98935b44140692bfe0c4caJason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 517d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 518d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 51909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nextLine = 0; 520d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 521d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 522d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 523d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 52401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 52501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 526d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 527d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(40, texType->getDimX(), nextLine, 0)); 531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 534d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 536afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initVertexArrayBuffers() { 537d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 538d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 540f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false); 541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 542366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams Allocation *indexAlloc = new Allocation(mRSC, indexType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 544d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 546afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 54709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i6 = i * 6; 54809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i4 = i * 4; 549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 550d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 554d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 555d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 556d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 562d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 56564cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 56664cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1); 56764cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1); 56864cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC); 569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 570f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *vertexDataType = Type::getType(mRSC, vertexDataElem, 571f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams mMaxNumberOfQuads * 4, 572f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams 0, 0, false, false); 573d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 574366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 575d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 576d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mVertexArray.set(vertexAlloc); 578d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 579d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 580d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 581afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::checkInit() { 582afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 589d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 590d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 59135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 59235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 59335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 59435b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 59535b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("0123456789"); 59635b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk 597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 599d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 600d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 60160709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams Context::PushState ps(mRSC); 602d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 60360709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramVertex(mRSC->getDefaultProgramVertex()); 60460709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramRaster(mRSC->getDefaultProgramRaster()); 60560709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramFragment(mFontShaderF.get()); 60660709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramStore(mFontProgramStore.get()); 607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 608afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mConstantsDirty) { 609c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants)); 610c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = false; 611ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 612ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 613d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 614d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 616d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 617d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 618d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *tex = vtx + 3; 619d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 62054929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk VertexArray::Attrib attribs[2]; 62154929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position"); 62254929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0"); 62354929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk VertexArray va(attribs, 2); 624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 627d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 628d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 629d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 630d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 631d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 632afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u1, float v1, 633afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x2, float y2, float z2, 634afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u2, float v2, 635afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x3, float y3, float z3, 636afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u3, float v3, 637afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x4, float y4, float z4, 638afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u4, float v4) { 639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 640d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t floatsPerVert = 5; 641d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 642d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 643d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Cull things that are off the screen 644d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float width = (float)mRSC->getWidth(); 645d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float height = (float)mRSC->getHeight(); 646d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 647afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 648d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 651d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 652d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 653d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 654d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 655d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 656d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 657d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 665d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 666d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 667d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 668d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 669d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 675d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 676d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 678d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 682afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex == mMaxNumberOfQuads) { 683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 68801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 68901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 69035b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 691afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 69201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 69301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 69401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 69501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 69601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 69701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 69801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 69901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 70001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 70101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 70201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 703afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 70401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 70501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 70601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 70701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 70801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 70901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 71001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 71109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 71209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 71309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::RenderMode mode, 71409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::Rect *bounds, 715afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 716d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 717d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 718d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 719d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 720afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 721afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mDefault.get()) { 722c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk String8 fontsDir("/fonts/DroidSans.ttf"); 723c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 724c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk fullPath += fontsDir; 725c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk 726c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk mDefault.set(Font::create(mRSC, fullPath.string(), 16, 96)); 727a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 728a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk currentFont = mDefault.get(); 729a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 730afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 7313659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk LOGE("Unable to initialize any fonts"); 7323659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk return; 7333659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 7343659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 73509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 73609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 737d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 738afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 739d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 740d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 741d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 742d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 743d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 74409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 74509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 746d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 747d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 7489fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 749c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[0] = r; 750c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[1] = g; 751c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[2] = b; 752c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[3] = a; 753c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 754c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = 1.0f; 755c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 756c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (luminance <= mBlackThreshold) { 757c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mBlackGamma; 758c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 759c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mWhiteGamma; 760c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 7614f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 762c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = true; 7639fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk} 7649fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk 765ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 766c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *r = mConstants.mFontColor[0]; 767c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *g = mConstants.mFontColor[1]; 768c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *b = mConstants.mFontColor[2]; 769c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *a = mConstants.mFontColor[3]; 770ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk} 771ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 772afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::deinit(Context *rsc) { 773a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mInitialized = false; 774a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 77501b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines mFontShaderFConstant.clear(); 77601b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines 777a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mIndexBuffer.clear(); 778a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mVertexArray.clear(); 779a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 780a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontShaderF.clear(); 781a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontSampler.clear(); 782a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontProgramStore.clear(); 783a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 784a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mTextTexture.clear(); 785afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 786a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk delete mCacheLines[i]; 787d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 788a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mCacheLines.clear(); 789d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 790d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDefault.clear(); 791a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 7923659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk Vector<Font*> fontsToDereference = mActiveFonts; 793afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < fontsToDereference.size(); i ++) { 7943659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk fontsToDereference[i]->zeroUserRef(); 7953659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 7963659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 797afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mLibrary) { 798a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Done_FreeType( mLibrary ); 7993659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 800a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 801d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 802d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 803d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android { 804d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript { 805d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 806c17ace2391783dcabc6c1482edf0362654fd83e5Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, float fontSize, uint32_t dpi) { 807a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 808afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (newFont) { 809a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk newFont->incUserRef(); 810a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 811a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return newFont; 812d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 813d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 814d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript 815d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android 816