aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-04 22:03:41 +0000
committerGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-10-04 22:03:41 +0000
commitb1a72cb90a9b515978bc9abda1f267f31a544e08 (patch)
treeff264233155a95cfd61df13b37f58acd627f523d /src/core
parent30efb8a94fa228d9f7ae4333548d1180cae8fbf4 (diff)
Remove state from SkColorSpaceLuminance to avoid memory management.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkMaskGamma.cpp94
-rw-r--r--src/core/SkMaskGamma.h54
-rw-r--r--src/core/SkPaint.cpp69
3 files changed, 76 insertions, 141 deletions
diff --git a/src/core/SkMaskGamma.cpp b/src/core/SkMaskGamma.cpp
index 2070dda17e..9066fb7d9f 100644
--- a/src/core/SkMaskGamma.cpp
+++ b/src/core/SkMaskGamma.cpp
@@ -11,45 +11,61 @@
#include "SkFloatingPoint.h"
#include "SkMaskGamma.h"
-SkScalar SkSRGBLuminance::toLuma(SkScalar luminance) const {
- //The magic numbers are derived from the sRGB specification.
- //See http://www.color.org/chardata/rgb/srgb.xalter .
- if (luminance <= SkFloatToScalar(0.04045f)) {
- return luminance / SkFloatToScalar(12.92f);
+class SkLinearColorSpaceLuminance : public SkColorSpaceLuminance {
+ virtual SkScalar toLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luminance) const SK_OVERRIDE {
+ SkASSERT(SK_Scalar1 == gamma);
+ return luminance;
}
- return SkScalarPow((luminance + SkFloatToScalar(0.055f)) / SkFloatToScalar(1.055f),
- SkFloatToScalar(2.4f));
-}
-
-SkScalar SkSRGBLuminance::fromLuma(SkScalar luma) const {
- //The magic numbers are derived from the sRGB specification.
- //See http://www.color.org/chardata/rgb/srgb.xalter .
- if (luma <= SkFloatToScalar(0.0031308f)) {
- return luma * SkFloatToScalar(12.92f);
+ virtual SkScalar fromLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luma) const SK_OVERRIDE {
+ SkASSERT(SK_Scalar1 == gamma);
+ return luma;
}
- return SkFloatToScalar(1.055f) * SkScalarPow(luma, SkScalarInvert(SkFloatToScalar(2.4f)))
- - SkFloatToScalar(0.055f);
-}
-
-SkGammaLuminance::SkGammaLuminance(SkScalar gamma)
- : fGamma(gamma)
- , fGammaInverse(SkScalarInvert(gamma)) {
-}
+};
-SkScalar SkGammaLuminance::toLuma(SkScalar luminance) const {
- return SkScalarPow(luminance, fGamma);
-}
-
-SkScalar SkGammaLuminance::fromLuma(SkScalar luma) const {
- return SkScalarPow(luma, fGammaInverse);
-}
+class SkGammaColorSpaceLuminance : public SkColorSpaceLuminance {
+ virtual SkScalar toLuma(SkScalar gamma, SkScalar luminance) const SK_OVERRIDE {
+ return SkScalarPow(luminance, gamma);
+ }
+ virtual SkScalar fromLuma(SkScalar gamma, SkScalar luma) const SK_OVERRIDE {
+ return SkScalarPow(luma, SkScalarInvert(gamma));
+ }
+};
+
+class SkSRGBColorSpaceLuminance : public SkColorSpaceLuminance {
+ virtual SkScalar toLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luminance) const SK_OVERRIDE {
+ SkASSERT(0 == gamma);
+ //The magic numbers are derived from the sRGB specification.
+ //See http://www.color.org/chardata/rgb/srgb.xalter .
+ if (luminance <= SkFloatToScalar(0.04045f)) {
+ return luminance / SkFloatToScalar(12.92f);
+ }
+ return SkScalarPow((luminance + SkFloatToScalar(0.055f)) / SkFloatToScalar(1.055f),
+ SkFloatToScalar(2.4f));
+ }
+ virtual SkScalar fromLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luma) const SK_OVERRIDE {
+ SkASSERT(0 == gamma);
+ //The magic numbers are derived from the sRGB specification.
+ //See http://www.color.org/chardata/rgb/srgb.xalter .
+ if (luma <= SkFloatToScalar(0.0031308f)) {
+ return luma * SkFloatToScalar(12.92f);
+ }
+ return SkFloatToScalar(1.055f) * SkScalarPow(luma, SkScalarInvert(SkFloatToScalar(2.4f)))
+ - SkFloatToScalar(0.055f);
+ }
+};
-SkScalar SkLinearLuminance::toLuma(SkScalar luminance) const {
- return luminance;
-}
+/*static*/ const SkColorSpaceLuminance& SkColorSpaceLuminance::Fetch(SkScalar gamma) {
+ static SkLinearColorSpaceLuminance gSkLinearColorSpaceLuminance;
+ static SkGammaColorSpaceLuminance gSkGammaColorSpaceLuminance;
+ static SkSRGBColorSpaceLuminance gSkSRGBColorSpaceLuminance;
-SkScalar SkLinearLuminance::fromLuma(SkScalar luma) const {
- return luma;
+ if (0 == gamma) {
+ return gSkSRGBColorSpaceLuminance;
+ } else if (SK_Scalar1 == gamma) {
+ return gSkLinearColorSpaceLuminance;
+ } else {
+ return gSkGammaColorSpaceLuminance;
+ }
}
static float apply_contrast(float srca, float contrast) {
@@ -57,16 +73,16 @@ static float apply_contrast(float srca, float contrast) {
}
void SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar contrast,
- const SkColorSpaceLuminance& srcConvert,
- const SkColorSpaceLuminance& dstConvert) {
+ const SkColorSpaceLuminance& srcConvert, SkScalar srcGamma,
+ const SkColorSpaceLuminance& dstConvert, SkScalar dstGamma) {
const float src = (float)srcI / 255.0f;
- const float linSrc = srcConvert.toLuma(src);
+ const float linSrc = srcConvert.toLuma(srcGamma, src);
//Guess at the dst. The perceptual inverse provides smaller visual
//discontinuities when slight changes to desaturated colors cause a channel
//to map to a different correcting lut with neighboring srcI.
//See https://code.google.com/p/chromium/issues/detail?id=141425#c59 .
const float dst = 1.0f - src;
- const float linDst = dstConvert.toLuma(dst);
+ const float linDst = dstConvert.toLuma(dstGamma, dst);
//Contrast value tapers off to 0 as the src luminance becomes white
const float adjustedContrast = SkScalarToFloat(contrast) * linDst;
@@ -96,7 +112,7 @@ void SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar
//Calculate the output we want.
float linOut = (linSrc * srca + dsta * linDst);
SkASSERT(linOut <= 1.0f);
- float out = dstConvert.fromLuma(linOut);
+ float out = dstConvert.fromLuma(dstGamma, linOut);
//Undo what the blit blend will do.
float result = (out - dst) / (src - dst);
diff --git a/src/core/SkMaskGamma.h b/src/core/SkMaskGamma.h
index 961c1b1924..a092b209ee 100644
--- a/src/core/SkMaskGamma.h
+++ b/src/core/SkMaskGamma.h
@@ -22,46 +22,28 @@
*/
class SkColorSpaceLuminance : SkNoncopyable {
public:
- virtual ~SkColorSpaceLuminance() {};
+ virtual ~SkColorSpaceLuminance() { }
/** Converts a color component luminance in the color space to a linear luma. */
- virtual SkScalar toLuma(SkScalar luminance) const = 0;
+ virtual SkScalar toLuma(SkScalar gamma, SkScalar luminance) const = 0;
/** Converts a linear luma to a color component luminance in the color space. */
- virtual SkScalar fromLuma(SkScalar luma) const = 0;
+ virtual SkScalar fromLuma(SkScalar gamma, SkScalar luma) const = 0;
/** Converts a color to a luminance value. */
- U8CPU computeLuminance(SkColor c) const {
- SkScalar r = toLuma(SkIntToScalar(SkColorGetR(c)) / 255);
- SkScalar g = toLuma(SkIntToScalar(SkColorGetG(c)) / 255);
- SkScalar b = toLuma(SkIntToScalar(SkColorGetB(c)) / 255);
+ static U8CPU computeLuminance(SkScalar gamma, SkColor c) {
+ const SkColorSpaceLuminance& luminance = Fetch(gamma);
+ SkScalar r = luminance.toLuma(gamma, SkIntToScalar(SkColorGetR(c)) / 255);
+ SkScalar g = luminance.toLuma(gamma, SkIntToScalar(SkColorGetG(c)) / 255);
+ SkScalar b = luminance.toLuma(gamma, SkIntToScalar(SkColorGetB(c)) / 255);
SkScalar luma = r * SkFloatToScalar(SK_LUM_COEFF_R) +
g * SkFloatToScalar(SK_LUM_COEFF_G) +
b * SkFloatToScalar(SK_LUM_COEFF_B);
SkASSERT(luma <= SK_Scalar1);
- return SkScalarRoundToInt(fromLuma(luma) * 255);
+ return SkScalarRoundToInt(luminance.fromLuma(gamma, luma) * 255);
}
-};
-class SkSRGBLuminance : public SkColorSpaceLuminance {
-public:
- SkScalar toLuma(SkScalar luminance) const SK_OVERRIDE;
- SkScalar fromLuma(SkScalar luma) const SK_OVERRIDE;
-};
-
-class SkGammaLuminance : public SkColorSpaceLuminance {
-public:
- SkGammaLuminance(SkScalar gamma);
- SkScalar toLuma(SkScalar luminance) const SK_OVERRIDE;
- SkScalar fromLuma(SkScalar luma) const SK_OVERRIDE;
-private:
- SkScalar fGamma;
- SkScalar fGammaInverse;
-};
-
-class SkLinearLuminance : public SkColorSpaceLuminance {
-public:
- SkScalar toLuma(SkScalar luminance) const SK_OVERRIDE;
- SkScalar fromLuma(SkScalar luma) const SK_OVERRIDE;
+ /** Retrieves the SkColorSpaceLuminance for the given gamma. */
+ static const SkColorSpaceLuminance& Fetch(SkScalar gamma);
};
///@{
@@ -95,8 +77,8 @@ template<> /*static*/ inline U8CPU sk_t_scale255<8>(U8CPU base) {
template <int R_LUM_BITS, int G_LUM_BITS, int B_LUM_BITS> class SkTMaskPreBlend;
void SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar contrast,
- const SkColorSpaceLuminance& srcConvert,
- const SkColorSpaceLuminance& dstConvert);
+ const SkColorSpaceLuminance& srcConvert, SkScalar srcGamma,
+ const SkColorSpaceLuminance& dstConvert, SkScalar dstGamma);
/**
* A regular mask contains linear alpha values. A gamma correcting mask
@@ -125,12 +107,14 @@ public:
* @param paint The color space in which the paint color was chosen.
* @param device The color space of the target device.
*/
- SkTMaskGamma(SkScalar contrast,
- const SkColorSpaceLuminance& paint,
- const SkColorSpaceLuminance& device) : fIsLinear(false) {
+ SkTMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) : fIsLinear(false) {
+ const SkColorSpaceLuminance& paintConvert = SkColorSpaceLuminance::Fetch(paintGamma);
+ const SkColorSpaceLuminance& deviceConvert = SkColorSpaceLuminance::Fetch(deviceGamma);
for (U8CPU i = 0; i < (1 << kLuminanceBits_Max); ++i) {
U8CPU lum = sk_t_scale255<kLuminanceBits_Max>(i);
- SkTMaskGamma_build_correcting_lut(fGammaTables[i], lum, contrast, paint, device);
+ SkTMaskGamma_build_correcting_lut(fGammaTables[i], lum, contrast,
+ paintConvert, paintGamma,
+ deviceConvert, deviceGamma);
}
}
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 7088a94ac1..f611e6d847 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1634,58 +1634,6 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
*/
SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
-static SkColorSpaceLuminance* gLinearLuminance = NULL;
-
-static SkColorSpaceLuminance* gDeviceLuminance = NULL;
-static SkScalar gDeviceGammaExponent = SK_ScalarMin;
-/**
- * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
- * the returned SkColorSpaceLuminance pointer is forgotten.
- */
-static SkColorSpaceLuminance* cachedDeviceLuminance(SkScalar gammaExponent) {
- if (SK_Scalar1 == gammaExponent) {
- if (NULL == gLinearLuminance) {
- gLinearLuminance = SkNEW(SkLinearLuminance);
- }
- return gLinearLuminance;
- }
- if (gDeviceGammaExponent != gammaExponent) {
- SkDELETE(gDeviceLuminance);
- if (0 == gammaExponent) {
- gDeviceLuminance = SkNEW(SkSRGBLuminance);
- } else {
- gDeviceLuminance = SkNEW_ARGS(SkGammaLuminance, (gammaExponent));
- }
- gDeviceGammaExponent = gammaExponent;
- }
- return gDeviceLuminance;
-}
-
-static SkColorSpaceLuminance* gPaintLuminance = NULL;
-static SkScalar gPaintGammaExponent = SK_ScalarMin;
-/**
- * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
- * the returned SkColorSpaceLuminance pointer is forgotten.
- */
-static SkColorSpaceLuminance* cachedPaintLuminance(SkScalar gammaExponent) {
- if (SK_Scalar1 == gammaExponent) {
- if (NULL == gLinearLuminance) {
- gLinearLuminance = SkNEW(SkLinearLuminance);
- }
- return gLinearLuminance;
- }
- if (gPaintGammaExponent != gammaExponent) {
- SkDELETE(gPaintLuminance);
- if (0 == gammaExponent) {
- gPaintLuminance = SkNEW(SkSRGBLuminance);
- } else {
- gPaintLuminance = SkNEW_ARGS(SkGammaLuminance, (gammaExponent));
- }
- gPaintGammaExponent = gammaExponent;
- }
- return gPaintLuminance;
-}
-
static SkMaskGamma* gLinearMaskGamma = NULL;
static SkMaskGamma* gMaskGamma = NULL;
static SkScalar gContrast = SK_ScalarMin;
@@ -1704,9 +1652,7 @@ static SkMaskGamma* cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkSc
}
if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
SkSafeUnref(gMaskGamma);
- SkColorSpaceLuminance* paintLuminance = cachedPaintLuminance(paintGamma);
- SkColorSpaceLuminance* deviceLuminance = cachedDeviceLuminance(deviceGamma);
- gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, *paintLuminance, *deviceLuminance));
+ gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma));
gContrast = contrast;
gPaintGamma = paintGamma;
gDeviceGamma = deviceGamma;
@@ -1724,16 +1670,6 @@ static SkMaskGamma* cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkSc
SkDEBUGCODE(gContrast = SK_ScalarMin;)
SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
-
- SkDELETE(gLinearLuminance);
-
- SkDELETE(gPaintLuminance);
- SkDEBUGCODE(gPaintLuminance = NULL;)
- SkDEBUGCODE(gPaintGammaExponent = SK_ScalarMin;)
-
- SkDELETE(gDeviceLuminance);
- SkDEBUGCODE(gDeviceLuminance = NULL;)
- SkDEBUGCODE(gDeviceGammaExponent = SK_ScalarMin;)
}
/**
@@ -1758,8 +1694,7 @@ void SkScalerContext::PostMakeRec(const SkPaint& paint, SkScalerContext::Rec* re
// use per-component information
SkColor color = rec->getLuminanceColor();
- SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
- U8CPU lum = cachedPaintLuminance(rec->getPaintGamma())->computeLuminance(color);
+ U8CPU lum = SkColorSpaceLuminance::computeLuminance(rec->getPaintGamma(), color);
//If we are asked to look like LCD, look like LCD.
if (!(rec->fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
// HACK: Prevents green from being pre-blended as white.