android_frameworks_base/libs/hwui/GammaFontRenderer.cpp
Chris Craik d41c4d8c73 Add overrides and switch to nullptr keyword for all files
Adds remaining missing overrides and nullptr usages, missed due to
an extreme failure in tool usage.

Change-Id: I56abd72975a3999ad13330003c348db40f59aebf
2015-01-05 16:49:13 -08:00

251 lines
7.9 KiB
C++

/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "OpenGLRenderer"
#include "Debug.h"
#include "GammaFontRenderer.h"
#include "Properties.h"
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Utils
///////////////////////////////////////////////////////////////////////////////
static int luminance(const SkPaint* paint) {
uint32_t c = paint->getColor();
const int r = (c >> 16) & 0xFF;
const int g = (c >> 8) & 0xFF;
const int b = (c ) & 0xFF;
return (r * 2 + g * 5 + b) >> 3;
}
///////////////////////////////////////////////////////////////////////////////
// Base class GammaFontRenderer
///////////////////////////////////////////////////////////////////////////////
GammaFontRenderer* GammaFontRenderer::createRenderer() {
// Choose the best renderer
char property[PROPERTY_VALUE_MAX];
if (property_get(PROPERTY_TEXT_GAMMA_METHOD, property, DEFAULT_TEXT_GAMMA_METHOD) > 0) {
if (!strcasecmp(property, "lookup")) {
return new LookupGammaFontRenderer();
} else if (!strcasecmp(property, "shader")) {
return new ShaderGammaFontRenderer(false);
} else if (!strcasecmp(property, "shader3")) {
return new ShaderGammaFontRenderer(true);
}
}
return new Lookup3GammaFontRenderer();
}
GammaFontRenderer::GammaFontRenderer() {
// Get the renderer properties
char property[PROPERTY_VALUE_MAX];
// Get the gamma
mGamma = DEFAULT_TEXT_GAMMA;
if (property_get(PROPERTY_TEXT_GAMMA, property, nullptr) > 0) {
INIT_LOGD(" Setting text gamma to %s", property);
mGamma = atof(property);
} else {
INIT_LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA);
}
// Get the black gamma threshold
mBlackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, nullptr) > 0) {
INIT_LOGD(" Setting text black gamma threshold to %s", property);
mBlackThreshold = atoi(property);
} else {
INIT_LOGD(" Using default text black gamma threshold of %d",
DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD);
}
// Get the white gamma threshold
mWhiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, nullptr) > 0) {
INIT_LOGD(" Setting text white gamma threshold to %s", property);
mWhiteThreshold = atoi(property);
} else {
INIT_LOGD(" Using default white black gamma threshold of %d",
DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD);
}
}
GammaFontRenderer::~GammaFontRenderer() {
}
///////////////////////////////////////////////////////////////////////////////
// Shader-based renderer
///////////////////////////////////////////////////////////////////////////////
ShaderGammaFontRenderer::ShaderGammaFontRenderer(bool multiGamma): GammaFontRenderer() {
INIT_LOGD("Creating shader gamma font renderer");
mRenderer = nullptr;
mMultiGamma = multiGamma;
}
void ShaderGammaFontRenderer::describe(ProgramDescription& description,
const SkPaint* paint) const {
if (paint->getShader() == nullptr) {
if (mMultiGamma) {
const int l = luminance(paint);
if (l <= mBlackThreshold) {
description.hasGammaCorrection = true;
description.gamma = mGamma;
} else if (l >= mWhiteThreshold) {
description.hasGammaCorrection = true;
description.gamma = 1.0f / mGamma;
}
} else {
description.hasGammaCorrection = true;
description.gamma = 1.0f / mGamma;
}
}
}
void ShaderGammaFontRenderer::setupProgram(ProgramDescription& description,
Program* program) const {
if (description.hasGammaCorrection) {
glUniform1f(program->getUniform("gamma"), description.gamma);
}
}
void ShaderGammaFontRenderer::endPrecaching() {
if (mRenderer) {
mRenderer->endPrecaching();
}
}
///////////////////////////////////////////////////////////////////////////////
// Lookup-based renderer
///////////////////////////////////////////////////////////////////////////////
LookupGammaFontRenderer::LookupGammaFontRenderer(): GammaFontRenderer() {
INIT_LOGD("Creating lookup gamma font renderer");
// Compute the gamma tables
const float gamma = 1.0f / mGamma;
for (uint32_t i = 0; i <= 255; i++) {
mGammaTable[i] = uint8_t((float)::floor(pow(i / 255.0f, gamma) * 255.0f + 0.5f));
}
mRenderer = nullptr;
}
void LookupGammaFontRenderer::endPrecaching() {
if (mRenderer) {
mRenderer->endPrecaching();
}
}
///////////////////////////////////////////////////////////////////////////////
// Lookup-based renderer, using 3 different correction tables
///////////////////////////////////////////////////////////////////////////////
Lookup3GammaFontRenderer::Lookup3GammaFontRenderer(): GammaFontRenderer() {
INIT_LOGD("Creating lookup3 gamma font renderer");
// Compute the gamma tables
const float blackGamma = mGamma;
const float whiteGamma = 1.0f / mGamma;
for (uint32_t i = 0; i <= 255; i++) {
const float v = i / 255.0f;
const float black = pow(v, blackGamma);
const float white = pow(v, whiteGamma);
mGammaTable[i] = i;
mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f));
mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f));
}
memset(mRenderers, 0, sizeof(FontRenderer*) * kGammaCount);
memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount);
}
void Lookup3GammaFontRenderer::endPrecaching() {
for (int i = 0; i < kGammaCount; i++) {
if (mRenderers[i]) {
mRenderers[i]->endPrecaching();
}
}
}
void Lookup3GammaFontRenderer::clear() {
for (int i = 0; i < kGammaCount; i++) {
mRenderers[i].release();
}
}
void Lookup3GammaFontRenderer::flush() {
int count = 0;
int min = -1;
uint32_t minCount = UINT_MAX;
for (int i = 0; i < kGammaCount; i++) {
if (mRenderers[i]) {
count++;
if (mRenderersUsageCount[i] < minCount) {
minCount = mRenderersUsageCount[i];
min = i;
}
}
}
if (count <= 1 || min < 0) return;
mRenderers[min].release();
// Also eliminate the caches for large glyphs, as they consume significant memory
for (int i = 0; i < kGammaCount; ++i) {
if (mRenderers[i]) {
mRenderers[i]->flushLargeCaches();
}
}
}
FontRenderer* Lookup3GammaFontRenderer::getRenderer(Gamma gamma) {
if (!mRenderers[gamma]) {
mRenderers[gamma].reset(new FontRenderer());
mRenderers[gamma]->setGammaTable(&mGammaTable[gamma * 256]);
}
mRenderersUsageCount[gamma]++;
return mRenderers[gamma].get();
}
FontRenderer& Lookup3GammaFontRenderer::getFontRenderer(const SkPaint* paint) {
if (paint->getShader() == nullptr) {
const int l = luminance(paint);
if (l <= mBlackThreshold) {
return *getRenderer(kGammaBlack);
} else if (l >= mWhiteThreshold) {
return *getRenderer(kGammaWhite);
}
}
return *getRenderer(kGammaDefault);
}
}; // namespace uirenderer
}; // namespace android