GammaFontRenderer.cpp revision b1d0a4ed21168fefcb82232c8f22cb95d60acb85
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "OpenGLRenderer" 18 19#include "Debug.h" 20#include "GammaFontRenderer.h" 21#include "Properties.h" 22 23namespace android { 24namespace uirenderer { 25 26/////////////////////////////////////////////////////////////////////////////// 27// Base class GammaFontRenderer 28/////////////////////////////////////////////////////////////////////////////// 29 30GammaFontRenderer* GammaFontRenderer::createRenderer() { 31 // Choose the best renderer 32 char property[PROPERTY_VALUE_MAX]; 33 if (property_get(PROPERTY_TEXT_GAMMA_SHADER, property, DEFAULT_TEXT_GAMMA_SHADER) > 0) { 34 if (!strcasecmp(property, "true")) { 35 return new ShaderGammaFontRenderer(); 36 } 37 } 38 39 return new LookupGammaFontRenderer(); 40} 41 42GammaFontRenderer::GammaFontRenderer() { 43 // Get the renderer properties 44 char property[PROPERTY_VALUE_MAX]; 45 46 // Get the gamma 47 mGamma = DEFAULT_TEXT_GAMMA; 48 if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) { 49 INIT_LOGD(" Setting text gamma to %s", property); 50 mGamma = atof(property); 51 } else { 52 INIT_LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA); 53 } 54 55 // Get the black gamma threshold 56 mBlackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 57 if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) { 58 INIT_LOGD(" Setting text black gamma threshold to %s", property); 59 mBlackThreshold = atoi(property); 60 } else { 61 INIT_LOGD(" Using default text black gamma threshold of %d", 62 DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD); 63 } 64 65 // Get the white gamma threshold 66 mWhiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 67 if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) { 68 INIT_LOGD(" Setting text white gamma threshold to %s", property); 69 mWhiteThreshold = atoi(property); 70 } else { 71 INIT_LOGD(" Using default white black gamma threshold of %d", 72 DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD); 73 } 74} 75 76GammaFontRenderer::~GammaFontRenderer() { 77} 78 79/////////////////////////////////////////////////////////////////////////////// 80// Shader-based renderer 81/////////////////////////////////////////////////////////////////////////////// 82 83ShaderGammaFontRenderer::ShaderGammaFontRenderer(): GammaFontRenderer() { 84 INIT_LOGD("Creating shader gamma font renderer"); 85} 86 87/////////////////////////////////////////////////////////////////////////////// 88// Lookup-based renderer 89/////////////////////////////////////////////////////////////////////////////// 90 91LookupGammaFontRenderer::LookupGammaFontRenderer(): GammaFontRenderer() { 92 INIT_LOGD("Creating lookup gamma font renderer"); 93 94 // Compute the gamma tables 95 const float blackGamma = mGamma; 96 const float whiteGamma = 1.0f / mGamma; 97 98 for (uint32_t i = 0; i <= 255; i++) { 99 mGammaTable[i] = i; 100 101 const float v = i / 255.0f; 102 const float black = pow(v, blackGamma); 103 const float white = pow(v, whiteGamma); 104 105 mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f)); 106 mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f)); 107 } 108 109 memset(mRenderers, 0, sizeof(FontRenderer*) * kGammaCount); 110 memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount); 111} 112 113LookupGammaFontRenderer::~LookupGammaFontRenderer() { 114 for (int i = 0; i < kGammaCount; i++) { 115 delete mRenderers[i]; 116 } 117} 118 119void LookupGammaFontRenderer::clear() { 120 for (int i = 0; i < kGammaCount; i++) { 121 delete mRenderers[i]; 122 mRenderers[i] = NULL; 123 } 124} 125 126void LookupGammaFontRenderer::flush() { 127 int count = 0; 128 int min = -1; 129 uint32_t minCount = UINT_MAX; 130 131 for (int i = 0; i < kGammaCount; i++) { 132 if (mRenderers[i]) { 133 count++; 134 if (mRenderersUsageCount[i] < minCount) { 135 minCount = mRenderersUsageCount[i]; 136 min = i; 137 } 138 } 139 } 140 141 if (count <= 1 || min < 0) return; 142 143 delete mRenderers[min]; 144 mRenderers[min] = NULL; 145 146 // Also eliminate the caches for large glyphs, as they consume significant memory 147 for (int i = 0; i < kGammaCount; ++i) { 148 if (mRenderers[i]) { 149 mRenderers[i]->flushLargeCaches(); 150 } 151 } 152} 153 154FontRenderer* LookupGammaFontRenderer::getRenderer(Gamma gamma) { 155 FontRenderer* renderer = mRenderers[gamma]; 156 if (!renderer) { 157 renderer = new FontRenderer(); 158 mRenderers[gamma] = renderer; 159 renderer->setGammaTable(&mGammaTable[gamma * 256]); 160 } 161 mRenderersUsageCount[gamma]++; 162 return renderer; 163} 164 165FontRenderer& LookupGammaFontRenderer::getFontRenderer(const SkPaint* paint) { 166 if (paint->getShader() == NULL) { 167 uint32_t c = paint->getColor(); 168 const int r = (c >> 16) & 0xFF; 169 const int g = (c >> 8) & 0xFF; 170 const int b = (c ) & 0xFF; 171 const int luminance = (r * 2 + g * 5 + b) >> 3; 172 173 if (luminance <= mBlackThreshold) { 174 return *getRenderer(kGammaBlack); 175 } else if (luminance >= mWhiteThreshold) { 176 return *getRenderer(kGammaWhite); 177 } 178 } 179 return *getRenderer(kGammaDefault); 180} 181 182}; // namespace uirenderer 183}; // namespace android 184