TextDropShadowCache.cpp revision 1e45aae5de003657e5d18f74d34998f5de5db5b7
11e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy/*
21e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * Copyright (C) 2010 The Android Open Source Project
31e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy *
41e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
51e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * you may not use this file except in compliance with the License.
61e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * You may obtain a copy of the License at
71e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy *
81e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
91e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy *
101e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * Unless required by applicable law or agreed to in writing, software
111e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
121e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * See the License for the specific language governing permissions and
141e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * limitations under the License.
151e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy */
161e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
171e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy#define LOG_TAG "OpenGLRenderer"
181e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
191e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy#include "TextDropShadowCache.h"
201e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
211e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guynamespace android {
221e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guynamespace uirenderer {
231e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
241e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy///////////////////////////////////////////////////////////////////////////////
251e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy// Constructors/destructor
261e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy///////////////////////////////////////////////////////////////////////////////
271e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
281e45aae5de003657e5d18f74d34998f5de5db5b7Romain GuyTextDropShadowCache::TextDropShadowCache(uint32_t maxByteSize):
291e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        mCache(GenerationCache<ShadowText, ShadowTexture*>::kUnlimitedCapacity),
301e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        mSize(0), mMaxSize(maxByteSize) {
311e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    mCache.setOnEntryRemovedListener(this);
321e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}
331e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
341e45aae5de003657e5d18f74d34998f5de5db5b7Romain GuyTextDropShadowCache::~TextDropShadowCache() {
351e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    mCache.clear();
361e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}
371e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
381e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy///////////////////////////////////////////////////////////////////////////////
391e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy// Size management
401e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy///////////////////////////////////////////////////////////////////////////////
411e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
421e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyuint32_t TextDropShadowCache::getSize() {
431e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    return mSize;
441e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}
451e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
461e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyuint32_t TextDropShadowCache::getMaxSize() {
471e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    return mMaxSize;
481e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}
491e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
501e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyvoid TextDropShadowCache::setMaxSize(uint32_t maxSize) {
511e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    mMaxSize = maxSize;
521e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    while (mSize > mMaxSize) {
531e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        mCache.removeOldest();
541e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
551e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}
561e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
571e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy///////////////////////////////////////////////////////////////////////////////
581e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy// Callbacks
591e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy///////////////////////////////////////////////////////////////////////////////
601e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
611e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyvoid TextDropShadowCache::operator()(ShadowText& text, ShadowTexture*& texture) {
621e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    const uint32_t size = texture->width * texture->height;
631e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    mSize -= size;
641e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
651e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    if (texture) {
661e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        glDeleteTextures(1, &texture->id);
671e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        delete texture;
681e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
691e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}
701e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
711e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy///////////////////////////////////////////////////////////////////////////////
721e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy// Caching
731e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy///////////////////////////////////////////////////////////////////////////////
741e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
751e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyvoid TextDropShadowCache::clear() {
761e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    mCache.clear();
771e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}
781e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
791e45aae5de003657e5d18f74d34998f5de5db5b7Romain GuyShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32_t len,
801e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        int numGlyphs, uint32_t radius) {
811e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ShadowText entry(paint, radius, len, text);
821e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ShadowTexture* texture = mCache.get(entry);
831e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
841e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    if (!texture) {
851e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(paint, text, 0,
861e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy                len, numGlyphs, radius);
871e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
881e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        texture = new ShadowTexture;
891e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        texture->left = shadow.penX;
901e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        texture->top = shadow.penY;
911e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        texture->width = shadow.width;
921e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        texture->height = shadow.height;
931e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        texture->generation = 0;
941e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        texture->blend = true;
951e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
961e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        const uint32_t size = shadow.width * shadow.height;
971e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        // Don't even try to cache a bitmap that's bigger than the cache
981e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        if (size < mMaxSize) {
991e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy            while (mSize + size > mMaxSize) {
1001e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy                mCache.removeOldest();
1011e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy            }
1021e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        }
1031e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1041e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        glGenTextures(1, &texture->id);
1051e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1061e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        glBindTexture(GL_TEXTURE_2D, texture->id);
1071e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        // Textures are Alpha8
1081e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1091e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1101e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
1111e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy                GL_ALPHA, GL_UNSIGNED_BYTE, shadow.image);
1121e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1131e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1141e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1151e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1161e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1171e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1181e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1191e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        if (size < mMaxSize) {
1201e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy            mSize += size;
1211e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy            mCache.put(entry, texture);
1221e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        } else {
1231e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy            texture->cleanup = true;
1241e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        }
1251e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1261e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        // Cleanup shadow
1271e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        delete[] shadow.image;
1281e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
1291e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1301e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    return texture;
1311e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}
1321e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1331e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // namespace uirenderer
1341e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // namespace android
135