FontRenderer.cpp revision 804ff38bff2fbb0ee258b13b4bb66eb33d565724
1d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka/*
2d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * Copyright (C) 2010 The Android Open Source Project
3d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka *
4d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * Licensed under the Apache License, Version 2.0 (the "License");
5d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * you may not use this file except in compliance with the License.
6d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * You may obtain a copy of the License at
7d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka *
8d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka *      http://www.apache.org/licenses/LICENSE-2.0
9d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka *
10d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * Unless required by applicable law or agreed to in writing, software
11d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * distributed under the License is distributed on an "AS IS" BASIS,
12d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * See the License for the specific language governing permissions and
14d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * limitations under the License.
15d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka */
16d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
17d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka#define LOG_TAG "OpenGLRenderer"
18d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
19b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa#include <SkGlyph.h>
20d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include <SkUtils.h>
21d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
22d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include <cutils/properties.h>
239b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
24d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa#include <utils/Log.h>
25d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
26d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka#ifdef ANDROID_ENABLE_RENDERSCRIPT
27d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka#include <RenderScript.h>
28d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka#endif
294013940b62ae2227c9b30d8761d7533ee6190a9fYohei Yukawa
304013940b62ae2227c9b30d8761d7533ee6190a9fYohei Yukawa#include "utils/Blur.h"
314013940b62ae2227c9b30d8761d7533ee6190a9fYohei Yukawa#include "utils/Timing.h"
32d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
33d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "Caches.h"
34d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "Debug.h"
35d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "Extensions.h"
36d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "FontRenderer.h"
37d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "OpenGLRenderer.h"
38d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#include "PixelBuffer.h"
3907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa#include "Rect.h"
40d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
41d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokanamespace android {
42d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokanamespace uirenderer {
43d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
445a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa// blur inputs smaller than this constant will bypass renderscript
455a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa#define RS_MIN_INPUT_CUTOFF 10000
465a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa
475a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa///////////////////////////////////////////////////////////////////////////////
48d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka// TextSetupFunctor
49d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka///////////////////////////////////////////////////////////////////////////////
50d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokastatus_t TextSetupFunctor::operator ()(int what, void* data) {
51d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    Data* typedData = reinterpret_cast<Data*>(data);
52d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    GLenum glyphFormat = typedData ? typedData->glyphFormat : GL_ALPHA;
53d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
54d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    renderer->setupDraw();
55d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    renderer->setupDrawTextGamma(paint);
56d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    renderer->setupDrawDirtyRegionsDisabled();
57d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    renderer->setupDrawWithTexture(glyphFormat == GL_ALPHA);
58d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    switch (glyphFormat) {
5971cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa        case GL_ALPHA: {
6071cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa            renderer->setupDrawAlpha8Color(paint->getColor(), alpha);
61d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            break;
62d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        }
63d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        case GL_RGBA: {
64d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            float floatAlpha = alpha / 255.0f;
65d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            renderer->setupDrawColor(floatAlpha, floatAlpha, floatAlpha, floatAlpha);
66d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            break;
67d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        }
68d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        default: {
69d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#if DEBUG_FONT_RENDERER
70d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            ALOGD("TextSetupFunctor: called with unknown glyph format %x", glyphFormat);
71d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#endif
72d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            break;
7371cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa        }
7471cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    }
7571cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    renderer->setupDrawColorFilter();
7671cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    renderer->setupDrawShader();
7771cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    renderer->setupDrawBlending(true, mode);
7871cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    renderer->setupDrawProgram();
7971cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    renderer->setupDrawModelView(x, y, x, y, pureTranslate, true);
8071cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    // Calling setupDrawTexture with the name 0 will enable the
8171cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    // uv attributes and increase the texture unit count
8271cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    // texture binding will be performed by the font renderer as
8371cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    // needed
8471cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    renderer->setupDrawTexture(0);
8571cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    renderer->setupDrawPureColorUniforms();
8671cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    renderer->setupDrawColorFilterUniforms();
8771cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    renderer->setupDrawShaderUniforms(pureTranslate);
8871cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    renderer->setupDrawTextGammaUniforms();
8971cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa
9071cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa    return NO_ERROR;
9171cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa}
9271cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa
9371cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa///////////////////////////////////////////////////////////////////////////////
9471cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa// FontRenderer
95d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka///////////////////////////////////////////////////////////////////////////////
96d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
97d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokastatic bool sLogFontRendererCreate = true;
98d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
99d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi KataokaFontRenderer::FontRenderer() :
100d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity) {
101d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
102d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    if (sLogFontRendererCreate) {
103d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        INIT_LOGD("Creating FontRenderer");
104d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
105d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
106d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    mGammaTable = NULL;
107d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    mInitialized = false;
108d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
109d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    mCurrentCacheTexture = NULL;
110d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
111d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    mLinearFiltering = false;
112d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
113d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    mSmallCacheWidth = DEFAULT_TEXT_SMALL_CACHE_WIDTH;
114d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    mSmallCacheHeight = DEFAULT_TEXT_SMALL_CACHE_HEIGHT;
115d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    mLargeCacheWidth = DEFAULT_TEXT_LARGE_CACHE_WIDTH;
116d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    mLargeCacheHeight = DEFAULT_TEXT_LARGE_CACHE_HEIGHT;
117d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
118d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    char property[PROPERTY_VALUE_MAX];
119d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    if (property_get(PROPERTY_TEXT_SMALL_CACHE_WIDTH, property, NULL) > 0) {
120d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mSmallCacheWidth = atoi(property);
121d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
122d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
123d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    if (property_get(PROPERTY_TEXT_SMALL_CACHE_HEIGHT, property, NULL) > 0) {
124d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mSmallCacheHeight = atoi(property);
125d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
126d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
127d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    if (property_get(PROPERTY_TEXT_LARGE_CACHE_WIDTH, property, NULL) > 0) {
128d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mLargeCacheWidth = atoi(property);
129d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
130d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
131d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    if (property_get(PROPERTY_TEXT_LARGE_CACHE_HEIGHT, property, NULL) > 0) {
1321c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa        mLargeCacheHeight = atoi(property);
1331c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa    }
1341c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa
1351c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa    uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize;
1361c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa    mSmallCacheWidth = mSmallCacheWidth > maxTextureSize ? maxTextureSize : mSmallCacheWidth;
1371c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa    mSmallCacheHeight = mSmallCacheHeight > maxTextureSize ? maxTextureSize : mSmallCacheHeight;
1381c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa    mLargeCacheWidth = mLargeCacheWidth > maxTextureSize ? maxTextureSize : mLargeCacheWidth;
1391c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa    mLargeCacheHeight = mLargeCacheHeight > maxTextureSize ? maxTextureSize : mLargeCacheHeight;
1401c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa
1411c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa    if (sLogFontRendererCreate) {
1421c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa        INIT_LOGD("  Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i",
14307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa                mSmallCacheWidth, mSmallCacheHeight,
14407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa                mLargeCacheWidth, mLargeCacheHeight >> 1,
14507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa                mLargeCacheWidth, mLargeCacheHeight >> 1,
14607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa                mLargeCacheWidth, mLargeCacheHeight);
14707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    }
14807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
14907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    sLogFontRendererCreate = false;
15007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa}
15107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
15207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawavoid clearCacheTextures(Vector<CacheTexture*>& cacheTextures) {
15307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
15407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa        delete cacheTextures[i];
15507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    }
15607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    cacheTextures.clear();
15707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa}
15807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
15907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei YukawaFontRenderer::~FontRenderer() {
16007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    clearCacheTextures(mACacheTextures);
161d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    clearCacheTextures(mRGBACacheTextures);
162d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
163d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa    LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
164d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    while (it.next()) {
165d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        delete it.value();
166d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
167d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    mActiveFonts.clear();
168d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka}
169d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
170d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawavoid FontRenderer::flushAllAndInvalidate() {
171d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    issueDrawCommand();
172d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
173d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
174d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    while (it.next()) {
175d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        it.value()->invalidateTextureCache();
176d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
177d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
178d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    for (uint32_t i = 0; i < mACacheTextures.size(); i++) {
1797025964d1230e4fc064658e1911fea9aab3def68Yohei Yukawa        mACacheTextures[i]->init();
180d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
181d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
182d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    for (uint32_t i = 0; i < mRGBACacheTextures.size(); i++) {
183d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mRGBACacheTextures[i]->init();
184d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
185d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka}
186d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
187d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokavoid FontRenderer::flushLargeCaches(Vector<CacheTexture*>& cacheTextures) {
188d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    // Start from 1; don't deallocate smallest/default texture
189d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    for (uint32_t i = 1; i < cacheTextures.size(); i++) {
190d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        CacheTexture* cacheTexture = cacheTextures[i];
191d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        if (cacheTexture->getPixelBuffer()) {
192d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            cacheTexture->init();
193d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
194d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            while (it.next()) {
195d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                it.value()->invalidateTextureCache(cacheTexture);
196d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            }
1975f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei Yukawa            cacheTexture->releaseTexture();
1987025964d1230e4fc064658e1911fea9aab3def68Yohei Yukawa        }
199d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
200d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka}
201d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
202d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokavoid FontRenderer::flushLargeCaches() {
203d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    flushLargeCaches(mACacheTextures);
204d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    flushLargeCaches(mRGBACacheTextures);
20514e139179be7daab6ed452105387a3922752c219Seigo Nonaka}
20614e139179be7daab6ed452105387a3922752c219Seigo Nonaka
20714e139179be7daab6ed452105387a3922752c219Seigo NonakaCacheTexture* FontRenderer::cacheBitmapInTexture(Vector<CacheTexture*>& cacheTextures,
20814e139179be7daab6ed452105387a3922752c219Seigo Nonaka        const SkGlyph& glyph, uint32_t* startX, uint32_t* startY) {
20914e139179be7daab6ed452105387a3922752c219Seigo Nonaka    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
21014e139179be7daab6ed452105387a3922752c219Seigo Nonaka        if (cacheTextures[i]->fitBitmap(glyph, startX, startY)) {
211d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            return cacheTextures[i];
212d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        }
213d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
214d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    // Could not fit glyph into current cache textures
215d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    return NULL;
216d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka}
217d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
2187025964d1230e4fc064658e1911fea9aab3def68Yohei Yukawavoid FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
219d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) {
220d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    checkInit();
221d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
222d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    // If the glyph bitmap is empty let's assum the glyph is valid
2235f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei Yukawa    // so we can avoid doing extra work later on
224d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    if (glyph.fWidth == 0 || glyph.fHeight == 0) {
225d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        cachedGlyph->mIsValid = true;
226d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        cachedGlyph->mCacheTexture = NULL;
227d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        return;
228d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
229d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
230d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    cachedGlyph->mIsValid = false;
231d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
232d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    // choose an appropriate cache texture list for this glyph format
23314e139179be7daab6ed452105387a3922752c219Seigo Nonaka    SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
234d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    Vector<CacheTexture*>* cacheTextures = NULL;
235d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    switch (format) {
236d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        case SkMask::kA8_Format:
237d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        case SkMask::kBW_Format:
238d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            cacheTextures = &mACacheTextures;
239d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            break;
240d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        case SkMask::kARGB32_Format:
241d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            cacheTextures = &mRGBACacheTextures;
242d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            break;
243d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        default:
244d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#if DEBUG_FONT_RENDERER
245d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            ALOGD("getCacheTexturesForFormat: unknown SkMask format %x", format);
246d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka#endif
247d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        return;
248d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
249d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
250d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    // If the glyph is too tall, don't cache it
251d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 >
252d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                (*cacheTextures)[cacheTextures->size() - 1]->getHeight()) {
253d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        ALOGE("Font size too large to fit in cache. width, height = %i, %i",
254d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                (int) glyph.fWidth, (int) glyph.fHeight);
255d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        return;
256d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    }
2579b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
2589b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    // Now copy the bitmap into the cache texture
2599b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    uint32_t startX = 0;
2609b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    uint32_t startY = 0;
261d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa
2629b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    CacheTexture* cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY);
2639b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
2649b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    if (!cacheTexture) {
2659b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        if (!precaching) {
266d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa            // If the new glyph didn't fit and we are not just trying to precache it,
2679b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            // clear out the cache and try again
2689b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            flushAllAndInvalidate();
2699b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY);
2709b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        }
2719b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
2729b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        if (!cacheTexture) {
2739b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            // either the glyph didn't fit or we're precaching and will cache it when we draw
2749b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            return;
2759b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        }
2769b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    }
2779b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
2789b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    cachedGlyph->mCacheTexture = cacheTexture;
2799b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
2809b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    *retOriginX = startX;
2819b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    *retOriginY = startY;
2829b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
2839b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    uint32_t endX = startX + glyph.fWidth;
2849b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    uint32_t endY = startY + glyph.fHeight;
2859b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
286d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa    uint32_t cacheWidth = cacheTexture->getWidth();
2879b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
288b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    if (!cacheTexture->getPixelBuffer()) {
289b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        Caches::getInstance().activeTexture(0);
290b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        // Large-glyph texture memory is allocated only as needed
291b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        cacheTexture->allocateTexture();
292b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    }
293b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    if (!cacheTexture->mesh()) {
294b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        cacheTexture->allocateMesh();
295b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    }
296b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa
297b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map();
298b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage;
299b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    int srcStride = glyph.rowBytes();
300b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa
301b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    // Copy the glyph image, taking the mask format into account
3029b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    switch (format) {
303b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        case SkMask::kA8_Format: {
3049b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
3059b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX
306a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa                    - TEXTURE_BORDER_SIZE;
3079b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            // write leading border line
3089b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
3099b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            // write glyph data
3109b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            if (mGammaTable) {
3119b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) {
3129b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                    row = cacheY * cacheWidth;
3139b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                    cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0;
3149b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                    for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
315d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa                        uint8_t tempCol = bitmapBuffer[bY + bX];
316b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa                        cacheBuffer[row + cacheX] = mGammaTable[tempCol];
317d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa                    }
3189b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                    cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0;
3199b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                }
320a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa            } else {
321a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa                for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) {
3229b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                    row = cacheY * cacheWidth;
323a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa                    memcpy(&cacheBuffer[row + startX], &bitmapBuffer[bY], glyph.fWidth);
324d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa                    cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0;
325a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa                    cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0;
326d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa                }
327a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa            }
328d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa            // write trailing border line
329d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE;
330d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
331d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            break;
332d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa        }
333d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa        case SkMask::kARGB32_Format: {
334d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            // prep data lengths
335d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            const size_t formatSize = PixelBuffer::formatSize(GL_RGBA);
336d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            const size_t borderSize = formatSize * TEXTURE_BORDER_SIZE;
337d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            size_t rowSize = formatSize * glyph.fWidth;
338d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa            // prep advances
339d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            size_t dstStride = formatSize * cacheWidth;
340a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            // prep indices
341a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            // - we actually start one row early, and then increment before first copy
342a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            uint8_t* src = &bitmapBuffer[0 - srcStride];
343a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            uint8_t* dst = &cacheBuffer[cacheTexture->getOffset(startX, startY - 1)];
344a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            uint8_t* dstEnd = &cacheBuffer[cacheTexture->getOffset(startX, endY - 1)];
34507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa            uint8_t* dstL = dst - borderSize;
346a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            uint8_t* dstR = dst + rowSize;
347a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            // write leading border line
348a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            memset(dstL, 0, rowSize + 2 * borderSize);
349a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            // write glyph data
350a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            while (dst < dstEnd) {
351a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                memset(dstL += dstStride, 0, borderSize); // leading border column
352a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                memcpy(dst += dstStride, src += srcStride, rowSize); // glyph data
353a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                memset(dstR += dstStride, 0, borderSize); // trailing border column
354a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            }
355a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            // write trailing border line
356a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            memset(dstL += dstStride, 0, rowSize + 2 * borderSize);
357a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            break;
358a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa        }
359a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa        case SkMask::kBW_Format: {
360a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
361a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX
362a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                    - TEXTURE_BORDER_SIZE;
363a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            static const uint8_t COLORS[2] = { 0, 255 };
364a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            // write leading border line
365a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
366a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            // write glyph data
367a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            for (cacheY = startY; cacheY < endY; cacheY++) {
368a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                cacheX = startX;
369a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                int rowBytes = srcStride;
370a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                uint8_t* buffer = bitmapBuffer;
371a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa
372a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                row = cacheY * cacheWidth;
373a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0;
374a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                while (--rowBytes >= 0) {
375a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                    uint8_t b = *buffer++;
376a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                    for (int8_t mask = 7; mask >= 0 && cacheX < endX; mask--) {
377a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                        cacheBuffer[cacheY * cacheWidth + cacheX++] = COLORS[(b >> mask) & 0x1];
378a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                    }
379a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                }
380a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0;
381a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa
382a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa                bitmapBuffer += srcStride;
383a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            }
384a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            // write trailing border line
385a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE;
386a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
387a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            break;
388a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa        }
389b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        default:
390b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa            ALOGW("Unknown glyph format: 0x%x", format);
391b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa            break;
392b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    }
393b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa
394b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    cachedGlyph->mIsValid = true;
395b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa}
396b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa
397b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei YukawaCacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format,
398b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        bool allocate) {
399b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    CacheTexture* cacheTexture = new CacheTexture(width, height, format, gMaxNumberOfQuads);
400b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa
401b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    if (allocate) {
402b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        Caches::getInstance().activeTexture(0);
403a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa        cacheTexture->allocateTexture();
404b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        cacheTexture->allocateMesh();
405a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    }
406a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa
407a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    return cacheTexture;
408a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa}
409a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa
410a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawavoid FontRenderer::initTextTexture() {
411a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    clearCacheTextures(mACacheTextures);
412a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    clearCacheTextures(mRGBACacheTextures);
413a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa
414d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa    mUploadTexture = false;
415d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa    mACacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight,
416a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            GL_ALPHA, true));
417a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1,
418a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            GL_ALPHA, false));
419a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1,
420a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            GL_ALPHA, false));
421a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight,
422a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            GL_ALPHA, false));
423a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    mRGBACacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight,
424a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            GL_RGBA, false));
425a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    mRGBACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1,
426a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            GL_RGBA, false));
427d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    mCurrentCacheTexture = mACacheTextures[0];
428d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa}
429d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa
430d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa// We don't want to allocate anything unless we actually draw text
431d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawavoid FontRenderer::checkInit() {
432d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    if (mInitialized) {
433d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa        return;
434d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    }
435a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa
436a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    initTextTexture();
4379b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
4389b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    mInitialized = true;
43907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa}
44007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
44107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawavoid checkTextureUpdateForCache(Caches& caches, Vector<CacheTexture*>& cacheTextures,
44207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa        bool& resetPixelStore, GLuint& lastTextureId) {
44307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
44407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa        CacheTexture* cacheTexture = cacheTextures[i];
44507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa        if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) {
44607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa            if (cacheTexture->getTextureId() != lastTextureId) {
44707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa                lastTextureId = cacheTexture->getTextureId();
44807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa                caches.activeTexture(0);
44907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa                caches.bindTexture(lastTextureId);
45007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa            }
45107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
45207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa            if (cacheTexture->upload()) {
45307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa                resetPixelStore = true;
45407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa            }
45507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa        }
45607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    }
45707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa}
45807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
45907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawavoid FontRenderer::checkTextureUpdate() {
46007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    if (!mUploadTexture) {
46107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa        return;
46207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    }
46307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
46407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    Caches& caches = Caches::getInstance();
46507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    GLuint lastTextureId = 0;
46607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
46707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    bool resetPixelStore = false;
46807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
46907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
47007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    // Iterate over all the cache textures and see which ones need to be updated
47107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    checkTextureUpdateForCache(caches, mACacheTextures, resetPixelStore, lastTextureId);
47207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId);
47307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
47407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    // Unbind any PBO we might have used to update textures
47507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    caches.unbindPixelBuffer();
47607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
47707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    // Reset to default unpack row length to avoid affecting texture
47807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    // uploads in other parts of the renderer
47907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    if (resetPixelStore) {
48007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
48107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    }
48207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
48307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa    mUploadTexture = false;
48407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa}
48507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
4869b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawavoid FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) {
4879b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    Caches& caches = Caches::getInstance();
488b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    bool first = true;
489b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    bool force = false;
490b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
491b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        CacheTexture* texture = cacheTextures[i];
492b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa        if (texture->canDraw()) {
493b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa            if (first) {
494b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa                if (mFunctor) {
495b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa                    TextSetupFunctor::Data functorData(texture->getFormat());
496b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa                    (*mFunctor)(0, &functorData);
497b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa                }
498b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa
499b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa                checkTextureUpdate();
500b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa                caches.bindIndicesBuffer();
501b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa
5029b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                if (!mDrawn) {
503b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa                    // If returns true, a VBO was bound and we must
5049b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                    // rebind our vertex attrib pointers even if
5059b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                    // they have the same values as the current pointers
5069b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                    force = caches.unbindMeshBuffer();
5079b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                }
50807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
509d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa                caches.activeTexture(0);
5109b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa                first = false;
51107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa            }
512d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa
5139b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            caches.bindTexture(texture->getTextureId());
5149b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa            texture->setLinearFiltering(mLinearFiltering, false);
5159b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
516a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            TextureVertex* mesh = texture->mesh();
517a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            caches.bindPositionVertexPointer(force, &mesh[0].position[0]);
518a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            caches.bindTexCoordsVertexPointer(force, &mesh[0].texture[0]);
519a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            force = false;
52007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
52107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa            glDrawElements(GL_TRIANGLES, texture->meshElementCount(),
52207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa                    GL_UNSIGNED_SHORT, texture->indices());
523a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa
524a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa            texture->resetMesh();
5259b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        }
5269b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    }
5279b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa}
5289b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
5299b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawavoid FontRenderer::issueDrawCommand() {
5309b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    issueDrawCommand(mACacheTextures);
5319b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    issueDrawCommand(mRGBACacheTextures);
5329b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
5339b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    mDrawn = true;
5349b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa}
5359b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
5369b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawavoid FontRenderer::appendMeshQuadNoClip(float x1, float y1, float u1, float v1,
5379b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3,
5389b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        float x4, float y4, float u4, float v4, CacheTexture* texture) {
539d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    if (texture != mCurrentCacheTexture) {
540d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa        // Now use the new texture id
541d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa        mCurrentCacheTexture = texture;
542d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    }
543d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa
544d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    mCurrentCacheTexture->addQuad(x1, y1, u1, v1, x2, y2, u2, v2,
545d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            x3, y3, u3, v3, x4, y4, u4, v4);
5469b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa}
5479b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
5489b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawavoid FontRenderer::appendMeshQuad(float x1, float y1, float u1, float v1,
5499b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3,
5509b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        float x4, float y4, float u4, float v4, CacheTexture* texture) {
5519b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
5525a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa    if (mClip &&
553d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) {
5545a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        return;
5555a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa    }
5565a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa
5575a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa    appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture);
5585a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa
5595a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa    if (mBounds) {
560d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mBounds->left = fmin(mBounds->left, x1);
561d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        mBounds->top = fmin(mBounds->top, y3);
5620297051162193ef2b7d906409868e404f77e4c31Yohei Yukawa        mBounds->right = fmax(mBounds->right, x3);
563a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa        mBounds->bottom = fmax(mBounds->bottom, y1);
564a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    }
565a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa
566a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    if (mCurrentCacheTexture->endOfMesh()) {
567a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa        issueDrawCommand();
568a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa    }
569a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa}
570d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
571d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokavoid FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1,
572d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3,
5735a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        float x4, float y4, float u4, float v4, CacheTexture* texture) {
57407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa
575e512f85002379c5949f65daeffdcae3198964dadYohei Yukawa    appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture);
576e512f85002379c5949f65daeffdcae3198964dadYohei Yukawa
577d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    if (mBounds) {
578d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mBounds->left = fmin(mBounds->left, fmin(x1, fmin(x2, fmin(x3, x4))));
5799b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        mBounds->top = fmin(mBounds->top, fmin(y1, fmin(y2, fmin(y3, y4))));
580d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa        mBounds->right = fmax(mBounds->right, fmax(x1, fmax(x2, fmax(x3, x4))));
5819b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        mBounds->bottom = fmax(mBounds->bottom, fmax(y1, fmax(y2, fmax(y3, y4))));
5829b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    }
5839b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa
5849b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    if (mCurrentCacheTexture->endOfMesh()) {
5859b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa        issueDrawCommand();
5869b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa    }
587d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa}
588d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka
589d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokavoid FontRenderer::setFont(SkPaint* paint, const mat4& matrix) {
5905f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei Yukawa    mCurrentFont = Font::create(this, paint, matrix);
59114e139179be7daab6ed452105387a3922752c219Seigo Nonaka}
5925a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa
5935f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei YukawaFontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text,
594d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) {
595d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    checkInit();
596d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa
597d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    DropShadow image;
598d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    image.width = 0;
599d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    image.height = 0;
600d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    image.image = NULL;
601d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    image.penX = 0;
602d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa    image.penY = 0;
603d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
604    if (!mCurrentFont) {
605        return image;
606    }
607
608    mDrawn = false;
609    mClip = NULL;
610    mBounds = NULL;
611
612    Rect bounds;
613    mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions);
614
615    uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
616    uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
617
618    uint32_t maxSize = Caches::getInstance().maxTextureSize;
619    if (paddedWidth > maxSize || paddedHeight > maxSize) {
620        return image;
621    }
622
623#ifdef ANDROID_ENABLE_RENDERSCRIPT
624    // Align buffers for renderscript usage
625    if (paddedWidth & (RS_CPU_ALLOCATION_ALIGNMENT - 1)) {
626        paddedWidth += RS_CPU_ALLOCATION_ALIGNMENT - paddedWidth % RS_CPU_ALLOCATION_ALIGNMENT;
627    }
628    int size = paddedWidth * paddedHeight;
629    uint8_t* dataBuffer = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, size);
630#else
631    int size = paddedWidth * paddedHeight;
632    uint8_t* dataBuffer = (uint8_t*) malloc(size);
633#endif
634
635    memset(dataBuffer, 0, size);
636
637    int penX = radius - bounds.left;
638    int penY = radius - bounds.bottom;
639
640    if ((bounds.right > bounds.left) && (bounds.top > bounds.bottom)) {
641        // text has non-whitespace, so draw and blur to create the shadow
642        // NOTE: bounds.isEmpty() can't be used here, since vertical coordinates are inverted
643        // TODO: don't draw pure whitespace in the first place, and avoid needing this check
644        mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY,
645                Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions);
646
647        // Unbind any PBO we might have used
648        Caches::getInstance().unbindPixelBuffer();
649
650        blurImage(&dataBuffer, paddedWidth, paddedHeight, radius);
651    }
652
653    image.width = paddedWidth;
654    image.height = paddedHeight;
655    image.image = dataBuffer;
656    image.penX = penX;
657    image.penY = penY;
658
659    return image;
660}
661
662void FontRenderer::initRender(const Rect* clip, Rect* bounds, Functor* functor) {
663    checkInit();
664
665    mDrawn = false;
666    mBounds = bounds;
667    mFunctor = functor;
668    mClip = clip;
669}
670
671void FontRenderer::finishRender() {
672    mBounds = NULL;
673    mClip = NULL;
674
675    issueDrawCommand();
676}
677
678void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix) {
679    Font* font = Font::create(this, paint, matrix);
680    font->precache(paint, text, numGlyphs);
681}
682
683void FontRenderer::endPrecaching() {
684    checkTextureUpdate();
685}
686
687bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text,
688        uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y,
689        const float* positions, Rect* bounds, Functor* functor, bool forceFinish) {
690    if (!mCurrentFont) {
691        ALOGE("No font set");
692        return false;
693    }
694
695    initRender(clip, bounds, functor);
696    mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y, positions);
697
698    if (forceFinish) {
699        finishRender();
700    }
701
702    return mDrawn;
703}
704
705bool FontRenderer::renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text,
706        uint32_t startIndex, uint32_t len, int numGlyphs, SkPath* path,
707        float hOffset, float vOffset, Rect* bounds, Functor* functor) {
708    if (!mCurrentFont) {
709        ALOGE("No font set");
710        return false;
711    }
712
713    initRender(clip, bounds, functor);
714    mCurrentFont->render(paint, text, startIndex, len, numGlyphs, path, hOffset, vOffset);
715    finishRender();
716
717    return mDrawn;
718}
719
720void FontRenderer::removeFont(const Font* font) {
721    mActiveFonts.remove(font->getDescription());
722
723    if (mCurrentFont == font) {
724        mCurrentFont = NULL;
725    }
726}
727
728void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int32_t radius) {
729#ifdef ANDROID_ENABLE_RENDERSCRIPT
730    if (width * height * radius >= RS_MIN_INPUT_CUTOFF) {
731        uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height);
732
733        if (mRs == 0) {
734            mRs = new RSC::RS();
735            // a null path is OK because there are no custom kernels used
736            // hence nothing gets cached by RS
737            if (!mRs->init("", RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) {
738                ALOGE("blur RS failed to init");
739            }
740
741            mRsElement = RSC::Element::A_8(mRs);
742            mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement);
743        }
744
745        RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0);
746        RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t,
747                RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
748                *image);
749        RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t,
750                RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
751                outImage);
752
753        mRsScript->setRadius(radius);
754        mRsScript->setInput(ain);
755        mRsScript->forEach(aout);
756
757        // replace the original image's pointer, avoiding a copy back to the original buffer
758        free(*image);
759        *image = outImage;
760
761        return;
762    }
763#endif
764
765    float *gaussian = new float[2 * radius + 1];
766    Blur::generateGaussianWeights(gaussian, radius);
767
768    uint8_t* scratch = new uint8_t[width * height];
769    Blur::horizontal(gaussian, radius, *image, scratch, width, height);
770    Blur::vertical(gaussian, radius, scratch, *image, width, height);
771
772    delete[] gaussian;
773    delete[] scratch;
774}
775
776static uint32_t calculateCacheSize(const Vector<CacheTexture*>& cacheTextures) {
777    uint32_t size = 0;
778    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
779        CacheTexture* cacheTexture = cacheTextures[i];
780        if (cacheTexture && cacheTexture->getPixelBuffer()) {
781            size += cacheTexture->getPixelBuffer()->getSize();
782        }
783    }
784    return size;
785}
786
787uint32_t FontRenderer::getCacheSize(GLenum format) const {
788    switch (format) {
789        case GL_ALPHA: {
790            return calculateCacheSize(mACacheTextures);
791        }
792        case GL_RGBA: {
793            return calculateCacheSize(mRGBACacheTextures);
794        }
795        default: {
796            return 0;
797        }
798    }
799}
800
801}; // namespace uirenderer
802}; // namespace android
803