diff options
author | bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-10-04 22:03:41 +0000 |
---|---|---|
committer | bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-10-04 22:03:41 +0000 |
commit | b1a72cb90a9b515978bc9abda1f267f31a544e08 (patch) | |
tree | ff264233155a95cfd61df13b37f58acd627f523d /src/core | |
parent | 30efb8a94fa228d9f7ae4333548d1180cae8fbf4 (diff) |
Remove state from SkColorSpaceLuminance to avoid memory management.
https://codereview.appspot.com/6610047/
git-svn-id: http://skia.googlecode.com/svn/trunk@5820 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkMaskGamma.cpp | 94 | ||||
-rw-r--r-- | src/core/SkMaskGamma.h | 54 | ||||
-rw-r--r-- | src/core/SkPaint.cpp | 69 |
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. |