GammaFontRenderer.cpp revision 11718bc17bcfc56dfb9f4362eebf640b025c4415
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#include "Debug.h" 18#include "GammaFontRenderer.h" 19#include "Properties.h" 20 21namespace android { 22namespace uirenderer { 23 24/////////////////////////////////////////////////////////////////////////////// 25// Utils 26/////////////////////////////////////////////////////////////////////////////// 27 28static int luminance(const SkPaint* paint) { 29 uint32_t c = paint->getColor(); 30 const int r = (c >> 16) & 0xFF; 31 const int g = (c >> 8) & 0xFF; 32 const int b = (c ) & 0xFF; 33 return (r * 2 + g * 5 + b) >> 3; 34} 35 36/////////////////////////////////////////////////////////////////////////////// 37// Base class GammaFontRenderer 38/////////////////////////////////////////////////////////////////////////////// 39 40GammaFontRenderer* GammaFontRenderer::createRenderer() { 41 // Choose the best renderer 42 char property[PROPERTY_VALUE_MAX]; 43 if (property_get(PROPERTY_TEXT_GAMMA_METHOD, property, DEFAULT_TEXT_GAMMA_METHOD) > 0) { 44 if (!strcasecmp(property, "lookup")) { 45 return new LookupGammaFontRenderer(); 46 } 47 } 48 49 return new Lookup3GammaFontRenderer(); 50} 51 52GammaFontRenderer::GammaFontRenderer() { 53 // Get the renderer properties 54 char property[PROPERTY_VALUE_MAX]; 55 56 // Get the gamma 57 mGamma = DEFAULT_TEXT_GAMMA; 58 if (property_get(PROPERTY_TEXT_GAMMA, property, nullptr) > 0) { 59 INIT_LOGD(" Setting text gamma to %s", property); 60 mGamma = atof(property); 61 } else { 62 INIT_LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA); 63 } 64 65 // Get the black gamma threshold 66 mBlackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD; 67 if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, nullptr) > 0) { 68 INIT_LOGD(" Setting text black gamma threshold to %s", property); 69 mBlackThreshold = atoi(property); 70 } else { 71 INIT_LOGD(" Using default text black gamma threshold of %d", 72 DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD); 73 } 74 75 // Get the white gamma threshold 76 mWhiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD; 77 if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, nullptr) > 0) { 78 INIT_LOGD(" Setting text white gamma threshold to %s", property); 79 mWhiteThreshold = atoi(property); 80 } else { 81 INIT_LOGD(" Using default white black gamma threshold of %d", 82 DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD); 83 } 84} 85 86GammaFontRenderer::~GammaFontRenderer() { 87} 88 89/////////////////////////////////////////////////////////////////////////////// 90// Lookup-based renderer 91/////////////////////////////////////////////////////////////////////////////// 92 93LookupGammaFontRenderer::LookupGammaFontRenderer() 94 : GammaFontRenderer() { 95 INIT_LOGD("Creating lookup gamma font renderer"); 96 97 // Compute the gamma tables 98 const float gamma = 1.0f / mGamma; 99 100 for (uint32_t i = 0; i <= 255; i++) { 101 mGammaTable[i] = uint8_t((float)::floor(pow(i / 255.0f, gamma) * 255.0f + 0.5f)); 102 } 103 104 mRenderer = nullptr; 105} 106 107void LookupGammaFontRenderer::endPrecaching() { 108 if (mRenderer) { 109 mRenderer->endPrecaching(); 110 } 111} 112 113/////////////////////////////////////////////////////////////////////////////// 114// Lookup-based renderer, using 3 different correction tables 115/////////////////////////////////////////////////////////////////////////////// 116 117Lookup3GammaFontRenderer::Lookup3GammaFontRenderer() 118 : GammaFontRenderer() { 119 INIT_LOGD("Creating lookup3 gamma font renderer"); 120 121 // Compute the gamma tables 122 const float blackGamma = mGamma; 123 const float whiteGamma = 1.0f / mGamma; 124 125 for (uint32_t i = 0; i <= 255; i++) { 126 const float v = i / 255.0f; 127 const float black = pow(v, blackGamma); 128 const float white = pow(v, whiteGamma); 129 130 mGammaTable[i] = i; 131 mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f)); 132 mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f)); 133 } 134 135 memset(mRenderers, 0, sizeof(FontRenderer*) * kGammaCount); 136 memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount); 137} 138 139void Lookup3GammaFontRenderer::endPrecaching() { 140 for (int i = 0; i < kGammaCount; i++) { 141 if (mRenderers[i]) { 142 mRenderers[i]->endPrecaching(); 143 } 144 } 145} 146 147void Lookup3GammaFontRenderer::clear() { 148 for (int i = 0; i < kGammaCount; i++) { 149 mRenderers[i].release(); 150 } 151} 152 153void Lookup3GammaFontRenderer::flush() { 154 int count = 0; 155 int min = -1; 156 uint32_t minCount = UINT_MAX; 157 158 for (int i = 0; i < kGammaCount; i++) { 159 if (mRenderers[i]) { 160 count++; 161 if (mRenderersUsageCount[i] < minCount) { 162 minCount = mRenderersUsageCount[i]; 163 min = i; 164 } 165 } 166 } 167 168 if (count <= 1 || min < 0) return; 169 170 mRenderers[min].release(); 171 172 // Also eliminate the caches for large glyphs, as they consume significant memory 173 for (int i = 0; i < kGammaCount; ++i) { 174 if (mRenderers[i]) { 175 mRenderers[i]->flushLargeCaches(); 176 } 177 } 178} 179 180FontRenderer* Lookup3GammaFontRenderer::getRenderer(Gamma gamma) { 181 if (!mRenderers[gamma]) { 182 mRenderers[gamma].reset(new FontRenderer()); 183 mRenderers[gamma]->setGammaTable(&mGammaTable[gamma * 256]); 184 } 185 mRenderersUsageCount[gamma]++; 186 return mRenderers[gamma].get(); 187} 188 189FontRenderer& Lookup3GammaFontRenderer::getFontRenderer(const SkPaint* paint) { 190 if (paint->getShader() == nullptr) { 191 const int l = luminance(paint); 192 193 if (l <= mBlackThreshold) { 194 return *getRenderer(kGammaBlack); 195 } else if (l >= mWhiteThreshold) { 196 return *getRenderer(kGammaWhite); 197 } 198 } 199 return *getRenderer(kGammaDefault); 200} 201 202}; // namespace uirenderer 203}; // namespace android 204