rsFont.cpp revision 5224a27798f89093b13722b41143551a057ce550
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 435224a27798f89093b13722b41143551a057ce550Alex Sakhartchoukbool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) { 44afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 45d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Reinitialization of fonts not supported"); 46d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 47d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 48d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 495224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk FT_Error error = 0; 505224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (data != NULL && dataLen > 0) { 515224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace); 525224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } else { 535224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace); 545224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } 555224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk 56afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 57c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk LOGE("Unable to initialize font %s", name); 58d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 59d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 60d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 61d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontName = name; 62d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSize = fontSize; 63d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDpi = dpi; 64d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 65c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0); 66afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 67c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk LOGE("Unable to set font size on %s", name); 68d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 69d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 70d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 71d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mHasKerning = FT_HAS_KERNING(mFace); 72d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 73d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 74d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 75d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 76d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 77afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::invalidateTextureCache() { 78afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 79d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.valueAt(i)->mIsValid = false; 80d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 81d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 82d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 83afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y) { 84d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 85d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 8709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 88d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u1 = glyph->mBitmapMinU; 9009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float u2 = glyph->mBitmapMaxU; 9109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v1 = glyph->mBitmapMinV; 9209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk float v2 = glyph->mBitmapMaxV; 93d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 9509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 96d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 9709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk state->appendMeshQuad(nPenX, nPenY, 0, u1, v2, 9809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY, 0, u2, v2, 9909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX + width, nPenY - height, 0, u2, v1, 10009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk nPenX, nPenY - height, 0, u1, v1); 10109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 10209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 10309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::drawCachedGlyph(CachedGlyphInfo* glyph, int32_t x, int32_t y, 10409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH) { 10509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 10609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y + glyph->mBitmapTop; 10709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 10809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endX = glyph->mBitmapMinX + glyph->mBitmapWidth; 10909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t endY = glyph->mBitmapMinY + glyph->mBitmapHeight; 11009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 11209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 11309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk const uint8_t* cacheBuffer = state->getTextTextureData(); 11409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 11509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t cacheX = 0, cacheY = 0; 11609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t bX = 0, bY = 0; 11709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheX = glyph->mBitmapMinX, bX = nPenX; cacheX < endX; cacheX++, bX++) { 11809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk for (cacheY = glyph->mBitmapMinY, bY = nPenY; cacheY < endY; cacheY++, bY++) { 11909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bX < 0 || bY < 0 || bX >= (int32_t) bitmapW || bY >= (int32_t) bitmapH) { 12009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("Skipping invalid index"); 12109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk continue; 12209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 12309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = cacheBuffer[cacheY * cacheWidth + cacheX]; 12409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bitmap[bY * bitmapW + bX] = tempCol; 12509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 12609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 127d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 128d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 12909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::measureCachedGlyph(CachedGlyphInfo *glyph, int32_t x, int32_t y, Rect *bounds) { 13009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenX = x + glyph->mBitmapLeft; 13109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nPenY = y - glyph->mBitmapTop + glyph->mBitmapHeight; 13209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 13309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t width = (int32_t) glyph->mBitmapWidth; 13409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t height = (int32_t) glyph->mBitmapHeight; 13509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 1365224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk // 0, 0 is top left, so bottom is a positive number 1375224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (bounds->bottom < nPenY) { 13809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->bottom = nPenY; 13909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->left > nPenX) { 14109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->left = nPenX; 14209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds->right < nPenX + width) { 14409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk bounds->right = nPenX + width; 14509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 1465224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (bounds->top > nPenY - height) { 1475224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->top = nPenY - height; 14809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 14909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk} 15009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 15109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid Font::renderUTF(const char *text, uint32_t len, int32_t x, int32_t y, 15209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t start, int32_t numGlyphs, 15309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk RenderMode mode, Rect *bounds, 154afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 155afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mInitialized || numGlyphs == 0 || text == NULL || len == 0) { 156d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 157d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 158d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 159afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mode == Font::MEASURE) { 16009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk if (bounds == NULL) { 16109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk LOGE("No return rectangle provided to measure text"); 16209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk return; 16309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 16409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk // Reset min and max of the bounding box to something large 1655224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->set(1e6, -1e6, 1e6, -1e6); 16609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 16709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk 16809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t penX = x, penY = y; 16909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t glyphsLeft = 1; 170afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 171d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft = numGlyphs; 172d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 173d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 174d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t index = start; 175d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk size_t nextIndex = 0; 176d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 177d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk while (glyphsLeft > 0) { 178d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 179c9c38dd8508a2f805213abee1f9f44f103ac0a0dKenny Root int32_t utfChar = utf32_from_utf8_at(text, len, index, &nextIndex); 180d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 181d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Reached the end of the string or encountered 182afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (utfChar < 0) { 183d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 184d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 185d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 186d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Move to the next character in the array 187d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk index = nextIndex; 188d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 18901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = getCachedUTFChar(utfChar); 190d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 191d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If it's still not valid, we couldn't cache it, so we shouldn't draw garbage 192afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph->mIsValid) { 193afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk switch (mode) { 19409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case FRAMEBUFFER: 19509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY); 19609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 19709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case BITMAP: 19809c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk drawCachedGlyph(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH); 19909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk case MEASURE: 20109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk measureCachedGlyph(cachedGlyph, penX, penY, bounds); 20209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk break; 20309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk } 204d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 205d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 206d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk penX += (cachedGlyph->mAdvance.x >> 6); 207d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 208d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If we were given a specific number of glyphs, decrement 209afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (numGlyphs > 0) { 210d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyphsLeft --; 211d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 212d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 213d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 214d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 21501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex SakhartchoukFont::CachedGlyphInfo* Font::getCachedUTFChar(int32_t utfChar) { 21601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 21701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor((uint32_t)utfChar); 218afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (cachedGlyph == NULL) { 21901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk cachedGlyph = cacheGlyph((uint32_t)utfChar); 22001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 22101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Is the glyph still in texture cache? 222afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!cachedGlyph->mIsValid) { 22301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk updateGlyphCache(cachedGlyph); 22401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 22501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 22601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return cachedGlyph; 22701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 22801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 229afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid Font::updateGlyphCache(CachedGlyphInfo *glyph) { 230a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Load_Glyph( mFace, glyph->mGlyphIndex, FT_LOAD_RENDER ); 231afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 232a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk LOGE("Couldn't load glyph."); 233a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return; 234a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 235d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 236a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mAdvance = mFace->glyph->advance; 237a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapLeft = mFace->glyph->bitmap_left; 238a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapTop = mFace->glyph->bitmap_top; 239d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 240a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Bitmap *bitmap = &mFace->glyph->bitmap; 241d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 242d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 243d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 244d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 245d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 246d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Let the font state figure out where to put the bitmap 247d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FontState *state = &mRSC->mStateFont; 248a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mIsValid = state->cacheBitmap(bitmap, &startX, &startY); 249d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 250afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!glyph->mIsValid) { 251d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 252d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 253d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 254a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endX = startX + bitmap->width; 255a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk uint32_t endY = startY + bitmap->rows; 256d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 257d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinX = startX; 258d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinY = startY; 259a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapWidth = bitmap->width; 260a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk glyph->mBitmapHeight = bitmap->rows; 261d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 262d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = state->getCacheTextureType()->getDimX(); 263d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheHeight = state->getCacheTextureType()->getDimY(); 264d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 265d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinU = (float)startX / (float)cacheWidth; 266d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMinV = (float)startY / (float)cacheHeight; 267d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxU = (float)endX / (float)cacheWidth; 268d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glyph->mBitmapMaxV = (float)endY / (float)cacheHeight; 269d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 270d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 271afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::CachedGlyphInfo *Font::cacheGlyph(uint32_t glyph) { 272d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *newGlyph = new CachedGlyphInfo(); 273d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCachedGlyphs.add(glyph, newGlyph); 274d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 275d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mGlyphIndex = FT_Get_Char_Index(mFace, glyph); 276d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk newGlyph->mIsValid = false; 277d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 278d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk updateGlyphCache(newGlyph); 279d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 280d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newGlyph; 281d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 282d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 2835224a27798f89093b13722b41143551a057ce550Alex SakhartchoukFont * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi, 2845224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk const void *data, uint32_t dataLen) { 28535b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk rsc->mStateFont.checkInit(); 286d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts; 287d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 288afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < activeFonts.size(); i ++) { 289d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *ithFont = activeFonts[i]; 290afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (ithFont->mFontName == name && ithFont->mFontSize == fontSize && ithFont->mDpi == dpi) { 291d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return ithFont; 292d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 293d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 294d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 295d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *newFont = new Font(rsc); 2965224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen); 297afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (isInitialized) { 298d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk activeFonts.push(newFont); 29901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk rsc->mStateFont.precacheLatin(newFont); 300d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return newFont; 301d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 302d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 303225afd317e101a7be5fe02c0a86361146ea89f05Jason Sams ObjectBase::checkDelete(newFont); 304d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return NULL; 305d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 306d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 307afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFont::~Font() { 308afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mFace) { 309d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk FT_Done_Face(mFace); 310d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 311d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 312d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for (uint32_t ct = 0; ct < mRSC->mStateFont.mActiveFonts.size(); ct++) { 313d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (mRSC->mStateFont.mActiveFonts[ct] == this) { 314d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC->mStateFont.mActiveFonts.removeAt(ct); 315d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 316d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 317d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 318d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 319afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCachedGlyphs.size(); i ++) { 320d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i); 321d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete glyph; 322d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 323d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 324d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 325afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::FontState() { 326d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = false; 327d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mMaxNumberOfQuads = 1024; 328d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 329d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mRSC = NULL; 3303659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 331c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 332c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the renderer properties 333c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk char property[PROPERTY_VALUE_MAX]; 334c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 335c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the gamma 336c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk float gamma = DEFAULT_TEXT_GAMMA; 337c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 338c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk gamma = atof(property); 339c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 340c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 341c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the black gamma threshold 34209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 343c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 344c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk blackThreshold = atoi(property); 345c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 346c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackThreshold = (float)(blackThreshold) / 255.0f; 347c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 348c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Get the white gamma threshold 34909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 350c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 351c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk whiteThreshold = atoi(property); 352c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 353c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteThreshold = (float)(whiteThreshold) / 255.0f; 354c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 355c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk // Compute the gamma tables 356c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mBlackGamma = gamma; 357c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mWhiteGamma = 1.0f / gamma; 3584f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 3594f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk setFontColor(0.1f, 0.1f, 0.1f, 1.0f); 360d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 361d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 362afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFontState::~FontState() { 363afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 364d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk delete mCacheLines[i]; 365d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 366d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 367d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk rsAssert(!mActiveFonts.size()); 368d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 369d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 370afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex SakhartchoukFT_Library FontState::getLib() { 371afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mLibrary) { 372a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Error error = FT_Init_FreeType(&mLibrary); 373afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (error) { 374d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Unable to initialize freetype"); 375a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return NULL; 376d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 377d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 3783659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 379a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return mLibrary; 380a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk} 381d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 382afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::init(Context *rsc) { 383a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mRSC = rsc; 384d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 385d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 386afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::flushAllAndInvalidate() { 387afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 388d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 389d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 390d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 391afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mActiveFonts.size(); i ++) { 392d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mActiveFonts[i]->invalidateTextureCache(); 393d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 394afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 395d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mCurrentCol = 0; 396d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 397d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 398d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 399afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukbool FontState::cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) { 400d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the glyph is too tall, don't cache it 401afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if ((uint32_t)bitmap->rows > mCacheLines[mCacheLines.size()-1]->mMaxHeight) { 402d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Font size to large to fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 403d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 404d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 405d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 406d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now copy the bitmap into the cache texture 407d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startX = 0; 408d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t startY = 0; 409d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 410d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bool bitmapFit = false; 411afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 412d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 413afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 414d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 415d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 416d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 417d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 418d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // If the new glyph didn't fit, flush the state so far and invalidate everything 419afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 420d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk flushAllAndInvalidate(); 421d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 422d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Try to fit it again 423afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 424d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk bitmapFit = mCacheLines[i]->fitBitmap(bitmap, &startX, &startY); 425afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (bitmapFit) { 426d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk break; 427d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 428d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 429d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 430d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // if we still don't fit, something is wrong and we shouldn't draw 431afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!bitmapFit) { 432d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Bitmap doesn't fit in cache. width, height = %i, %i", (int)bitmap->width, (int)bitmap->rows); 433d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return false; 434d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 435d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 436d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginX = startX; 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk *retOriginY = startY; 439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 440d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endX = startX + bitmap->width; 441d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t endY = startY + bitmap->rows; 442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 443d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheWidth = getCacheTextureType()->getDimX(); 444d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 44509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *cacheBuffer = (uint8_t*)mTextTexture->getPtr(); 44609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t *bitmapBuffer = bitmap->buffer; 447d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 448d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 449afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheX = startX, bX = 0; cacheX < endX; cacheX ++, bX ++) { 450afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (cacheY = startY, bY = 0; cacheY < endY; cacheY ++, bY ++) { 45109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint8_t tempCol = bitmapBuffer[bY * bitmap->width + bX]; 452d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk cacheBuffer[cacheY*cacheWidth + cacheX] = tempCol; 453d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 454d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 455d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 456d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // This will dirty the texture and the shader so next time 457d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // we draw it will upload the data 458b7e83bda41e66c966b98935b44140692bfe0c4caJason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 459383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindTexture(mRSC, 0, mTextTexture.get()); 460d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 461d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Some debug code 462afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk /*for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 463d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("Cache Line: H: %u Empty Space: %f", 464d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines[i]->mMaxHeight, 465d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (1.0f - (float)mCacheLines[i]->mCurrentCol/(float)mCacheLines[i]->mMaxWidth)*100.0f); 466d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 467d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk }*/ 468d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 469d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return true; 470d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 471d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 472afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initRenderState() { 4737ffcaf20cbb115326f3d72a983835d6c314a4cefAlex Sakhartchouk String8 shaderString("varying vec2 varTex0;\n"); 474e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("void main() {\n"); 475e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" lowp vec4 col = UNI_Color;\n"); 476e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" col.a = texture2D(UNI_Tex0, varTex0.xy).a;\n"); 477c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk shaderString.append(" col.a = pow(col.a, UNI_Gamma);\n"); 478e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append(" gl_FragColor = col;\n"); 479e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.append("}\n"); 480e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 481e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 482c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1); 483e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 484e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 485c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1); 486e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC); 487e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 488f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false); 489e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 490e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk uint32_t tmp[4]; 491e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 492e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk tmp[1] = (uint32_t)inputType; 49384e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE; 49484e4027f83b20af59f5b1fc52be6e45f159d3970Alex Sakhartchouk tmp[3] = RS_TEXTURE_2D; 495e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk 496366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams mFontShaderFConstant.set(new Allocation(mRSC, inputType, 497366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS)); 498e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), 499e7ae69f4a70f1813cf8086ebd9714192c635300aAlex Sakhartchouk shaderString.length(), tmp, 4); 500d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontShaderF.set(pf); 501383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0); 502d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 503d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST, 504d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP); 505d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontSampler.set(sampler); 506383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk mFontShaderF->bindSampler(mRSC, 0, sampler); 507d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 508d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk ProgramStore *fontStore = new ProgramStore(mRSC); 509d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore.set(fontStore); 510d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthFunc(RS_DEPTH_FUNC_ALWAYS); 511d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setBlendFunc(RS_BLEND_SRC_SRC_ALPHA, RS_BLEND_DST_ONE_MINUS_SRC_ALPHA); 512d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDitherEnable(false); 513d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mFontProgramStore->setDepthMask(false); 514d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 515d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 516afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initTextTexture() { 517d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1); 518d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 519d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // We will allocate a texture to initially hold 32 character bitmaps 520f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false); 521d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 522366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams Allocation *cacheAlloc = new Allocation(mRSC, texType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE); 523d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextTexture.set(cacheAlloc); 524b7e83bda41e66c966b98935b44140692bfe0c4caJason Sams mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT); 525d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 526d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Split up our cache texture into lines of certain widths 52709c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t nextLine = 0; 528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(16, texType->getDimX(), nextLine, 0)); 529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 53201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(24, texType->getDimX(), nextLine, 0)); 53301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 534d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(32, texType->getDimX(), nextLine, 0)); 535d3e0ad43dc758c409fc23d1893dab67b18520c24Alex 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(40, texType->getDimX(), nextLine, 0)); 539d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk nextLine += mCacheLines.top()->mMaxHeight; 540d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCacheLines.push(new CacheTextureLine(texType->getDimY() - nextLine, texType->getDimX(), nextLine, 0)); 541d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 542d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 543d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// Avoid having to reallocate memory and render quad by quad 544afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::initVertexArrayBuffers() { 545d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Now lets write index data 546d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); 547d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint32_t numIndicies = mMaxNumberOfQuads * 6; 548f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false); 549d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 550366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams Allocation *indexAlloc = new Allocation(mRSC, indexType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 551d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 552d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 553d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Four verts, two triangles , six indices per quad 554afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mMaxNumberOfQuads; i ++) { 55509c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i6 = i * 6; 55609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk int32_t i4 = i * 4; 557d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 558d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 0] = i4 + 0; 559d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 1] = i4 + 1; 560d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 2] = i4 + 2; 561d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 562d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 3] = i4 + 0; 563d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 4] = i4 + 2; 564d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexPtr[i6 + 5] = i4 + 3; 565d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 566d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 567d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk indexAlloc->deferedUploadToBufferObject(mRSC); 568d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer.set(indexAlloc); 569d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 570d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3); 571d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2); 572d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 57364cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderBegin(); 57464cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1); 57564cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1); 57664cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC); 577d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 578f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams Type *vertexDataType = Type::getType(mRSC, vertexDataElem, 579f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams mMaxNumberOfQuads * 4, 580f0c1df480304a72ce41e7d4b088319cbd7f0938aJason Sams 0, 0, false, false); 581d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 582366c9c85196675437a8dd74c1cf6b63ddbde3d6aJason Sams Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_VERTEX); 583d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mTextMeshPtr = (float*)vertexAlloc->getPtr(); 584d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 585d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mVertexArray.set(vertexAlloc); 586d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 587d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 588d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk// We don't want to allocate anything unless we actually draw text 589afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::checkInit() { 590afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mInitialized) { 591d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 592d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 593d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 594d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initTextTexture(); 595d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initRenderState(); 596d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 597d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk initVertexArrayBuffers(); 598d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 59935b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk // We store a string with letters in a rough frequency of occurrence 60035b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache = String8(" eisarntolcdugpmhbyfvkwzxjq"); 60135b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("EISARNTOLCDUGPMHBYFVKWZXJQ"); 60235b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8(",.?!()-+@;:`'"); 60335b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk mLatinPrecache += String8("0123456789"); 60435b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk 605d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mInitialized = true; 606d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 607d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 608d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::issueDrawCommand() { 60960709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams Context::PushState ps(mRSC); 610d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 61160709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramVertex(mRSC->getDefaultProgramVertex()); 61260709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramRaster(mRSC->getDefaultProgramRaster()); 61360709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramFragment(mFontShaderF.get()); 61460709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams mRSC->setProgramStore(mFontProgramStore.get()); 615d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 616afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mConstantsDirty) { 6174b45b8998e0d7038efaea80c70d23c086640b4e3Jason Sams mFontShaderFConstant->data(mRSC, 0, 0, 1, &mConstants, sizeof(mConstants)); 618c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = false; 619ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk } 620ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 621d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (!mRSC->setupCheck()) { 622d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 623d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 624d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 625d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *vtx = (float*)mVertexArray->getPtr(); 626d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *tex = vtx + 3; 627d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 62854929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk VertexArray::Attrib attribs[2]; 62954929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position"); 63054929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0"); 63154929cce0bf44090424b1f91b676529a2422378fAlex Sakhartchouk VertexArray va(attribs, 2); 632d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache); 633d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 634d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mIndexBuffer->uploadCheck(mRSC); 635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID()); 636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk glDrawElements(GL_TRIANGLES, mCurrentQuadIndex * 6, GL_UNSIGNED_SHORT, (uint16_t *)(0)); 637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 639d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchoukvoid FontState::appendMeshQuad(float x1, float y1, float z1, 640afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u1, float v1, 641afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x2, float y2, float z2, 642afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u2, float v2, 643afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x3, float y3, float z3, 644afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u3, float v3, 645afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float x4, float y4, float z4, 646afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk float u4, float v4) { 647d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t vertsPerQuad = 4; 648d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk const uint32_t floatsPerVert = 5; 649d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert; 650d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 651d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Cull things that are off the screen 652d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float width = (float)mRSC->getWidth(); 653d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk float height = (float)mRSC->getHeight(); 654d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 655afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (x1 > width || y1 < 0.0f || x2 < 0 || y4 > height) { 656d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk return; 657d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 658d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 659d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk /*LOGE("V0 x: %f y: %f z: %f", x1, y1, z1); 660d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V1 x: %f y: %f z: %f", x2, y2, z2); 661d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V2 x: %f y: %f z: %f", x3, y3, z3); 662d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk LOGE("V3 x: %f y: %f z: %f", x4, y4, z4);*/ 663d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 664d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x1; 665d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y1; 666d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z1; 667d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u1; 668d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v1; 669d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 670d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x2; 671d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y2; 672d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z2; 673d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u2; 674d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v2; 675d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 676d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x3; 677d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y3; 678d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z3; 679d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u3; 680d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v3; 681d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 682d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = x4; 683d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = y4; 684d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = z4; 685d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = u4; 686d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk (*currentPos++) = v4; 687d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 688d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex ++; 689d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 690afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex == mMaxNumberOfQuads) { 691d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 692d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 693d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 694d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 695d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 69601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukuint32_t FontState::getRemainingCacheCapacity() { 69701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = 0; 69835b96445f8bb4536e29ace64417710ed90527a56Alex Sakhartchouk uint32_t totalPixels = 0; 699afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 70001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol); 70101bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk totalPixels += mCacheLines[i]->mMaxWidth; 70201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 70301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = (remainingCapacity * 100) / totalPixels; 70401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk return remainingCapacity; 70501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 70601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 70701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchoukvoid FontState::precacheLatin(Font *font) { 70801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk // Remaining capacity is measured in % 70901bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t remainingCapacity = getRemainingCacheCapacity(); 71001bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk uint32_t precacheIdx = 0; 711afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) { 71201bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk font->getCachedUTFChar((int32_t)mLatinPrecache[precacheIdx]); 71301bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk remainingCapacity = getRemainingCacheCapacity(); 71401bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk precacheIdx ++; 71501bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk } 71601bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk} 71701bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 71801bcef6115dc6230b16d9d8e120e35279f46cfd5Alex Sakhartchouk 71909c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::renderText(const char *text, uint32_t len, int32_t x, int32_t y, 72009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk uint32_t startIndex, int32_t numGlyphs, 72109c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::RenderMode mode, 72209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk Font::Rect *bounds, 723afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) { 724d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk checkInit(); 725d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 726d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk // Render code here 727d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Font *currentFont = mRSC->getFont(); 728afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 729afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!mDefault.get()) { 730c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk String8 fontsDir("/fonts/DroidSans.ttf"); 731c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk String8 fullPath(getenv("ANDROID_ROOT")); 732c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk fullPath += fontsDir; 733c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk 734c17ace2391783dcabc6c1482edf0362654fd83e5Alex Sakhartchouk mDefault.set(Font::create(mRSC, fullPath.string(), 16, 96)); 735a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 736a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk currentFont = mDefault.get(); 737a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 738afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (!currentFont) { 7393659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk LOGE("Unable to initialize any fonts"); 7403659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk return; 7413659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 7423659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 74309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk currentFont->renderUTF(text, len, x, y, startIndex, numGlyphs, 74409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk mode, bounds, bitmap, bitmapW, bitmapH); 745d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 746afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mCurrentQuadIndex != 0) { 747d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk issueDrawCommand(); 748d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mCurrentQuadIndex = 0; 749d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 750d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 751d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 75209c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchoukvoid FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) { 75309c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds); 7545224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->bottom = - bounds->bottom; 7555224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk bounds->top = - bounds->top; 756d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 757d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 7589fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchoukvoid FontState::setFontColor(float r, float g, float b, float a) { 759c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[0] = r; 760c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[1] = g; 761c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[2] = b; 762c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mFontColor[3] = a; 763c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk 764c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = 1.0f; 765c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk const float luminance = (r * 2.0f + g * 5.0f + b) / 8.0f; 766c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk if (luminance <= mBlackThreshold) { 767c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mBlackGamma; 768c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } else if (luminance >= mWhiteThreshold) { 769c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstants.mGamma = mWhiteGamma; 770c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk } 7714f230b31d59b5f17100686bc1416b3b07a4a618dAlex Sakhartchouk 772c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk mConstantsDirty = true; 7739fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk} 7749fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk 775ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchoukvoid FontState::getFontColor(float *r, float *g, float *b, float *a) const { 776c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *r = mConstants.mFontColor[0]; 777c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *g = mConstants.mFontColor[1]; 778c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *b = mConstants.mFontColor[2]; 779c9fa30536fb41f0166153561388b7c42f7cb85a0Alex Sakhartchouk *a = mConstants.mFontColor[3]; 780ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk} 781ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk 782afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid FontState::deinit(Context *rsc) { 783a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mInitialized = false; 784a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 78501b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines mFontShaderFConstant.clear(); 78601b7d2995f9cbd33a9ccdf861fe959743a4b9954Stephen Hines 787a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mIndexBuffer.clear(); 788a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mVertexArray.clear(); 789a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 790a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontShaderF.clear(); 791a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontSampler.clear(); 792a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mFontProgramStore.clear(); 793a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 794a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mTextTexture.clear(); 795afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < mCacheLines.size(); i ++) { 796a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk delete mCacheLines[i]; 797d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 798a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk mCacheLines.clear(); 799d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 800d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk mDefault.clear(); 801a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk 8023659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk Vector<Font*> fontsToDereference = mActiveFonts; 803afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk for (uint32_t i = 0; i < fontsToDereference.size(); i ++) { 8043659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk fontsToDereference[i]->zeroUserRef(); 8053659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk } 8063659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk 807afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (mLibrary) { 808a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk FT_Done_FreeType( mLibrary ); 8093659d94d345c333bf98070dbe7b6daee233225a9Alex Sakhartchouk mLibrary = NULL; 810a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 811d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 812d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 813d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace android { 814d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouknamespace renderscript { 815d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 816c17ace2391783dcabc6c1482edf0362654fd83e5Alex SakhartchoukRsFont rsi_FontCreateFromFile(Context *rsc, char const *name, float fontSize, uint32_t dpi) { 817a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi); 818afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk if (newFont) { 819a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk newFont->incUserRef(); 820a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk } 821a1ccecd965c07c2739f1258989526051a010bdabAlex Sakhartchouk return newFont; 822d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} 823d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 8245224a27798f89093b13722b41143551a057ce550Alex SakhartchoukRsFont rsi_FontCreateFromMemory(Context *rsc, char const *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) { 8255224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk Font *newFont = Font::create(rsc, name, fontSize, dpi, data, dataLen); 8265224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk if (newFont) { 8275224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk newFont->incUserRef(); 8285224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk } 8295224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk return newFont; 8305224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk} 8315224a27798f89093b13722b41143551a057ce550Alex Sakhartchouk 832d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // renderscript 833d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk} // android 834