| Index: src/effects/gradients/SkGradientShader.cpp
|
| diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
|
| index 2f89352435c5ca8d72e5b4f007969f9a1e9f645c..e5a3767d498c84e3dc48d6031cf54c38bc0207c2 100644
|
| --- a/src/effects/gradients/SkGradientShader.cpp
|
| +++ b/src/effects/gradients/SkGradientShader.cpp
|
| @@ -290,10 +290,17 @@ bool SkGradientShaderBase::onAsLuminanceColor(SkColor* lum) const {
|
| return true;
|
| }
|
|
|
| +#define SK_SUPPORT_LEGACY_GRADIENT_DITHERING
|
| +
|
| SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext(
|
| const SkGradientShaderBase& shader, const ContextRec& rec)
|
| : INHERITED(shader, rec)
|
| - , fCache(shader.refCache(getPaintAlpha()))
|
| +#ifdef SK_SUPPORT_LEGACY_GRADIENT_DITHERING
|
| + , fDither(true)
|
| +#else
|
| + , fDither(rec.fPaint->isDither())
|
| +#endif
|
| + , fCache(shader.refCache(getPaintAlpha(), fDither))
|
| {
|
| const SkMatrix& inverse = this->getTotalInverse();
|
|
|
| @@ -317,8 +324,9 @@ SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext(
|
| }
|
|
|
| SkGradientShaderBase::GradientShaderCache::GradientShaderCache(
|
| - U8CPU alpha, const SkGradientShaderBase& shader)
|
| + U8CPU alpha, bool dither, const SkGradientShaderBase& shader)
|
| : fCacheAlpha(alpha)
|
| + , fCacheDither(dither)
|
| , fShader(shader)
|
| , fCache16Inited(false)
|
| , fCache32Inited(false)
|
| @@ -342,7 +350,7 @@ SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() {
|
| paint specifies a non-opaque alpha.
|
| */
|
| void SkGradientShaderBase::GradientShaderCache::Build16bitCache(
|
| - uint16_t cache[], SkColor c0, SkColor c1, int count) {
|
| + uint16_t cache[], SkColor c0, SkColor c1, int count, bool dither) {
|
| SkASSERT(count > 1);
|
| SkASSERT(SkColorGetA(c0) == 0xFF);
|
| SkASSERT(SkColorGetA(c1) == 0xFF);
|
| @@ -359,17 +367,31 @@ void SkGradientShaderBase::GradientShaderCache::Build16bitCache(
|
| g = SkIntToFixed(g) + 0x8000;
|
| b = SkIntToFixed(b) + 0x8000;
|
|
|
| - do {
|
| - unsigned rr = r >> 16;
|
| - unsigned gg = g >> 16;
|
| - unsigned bb = b >> 16;
|
| - cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb));
|
| - cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb);
|
| - cache += 1;
|
| - r += dr;
|
| - g += dg;
|
| - b += db;
|
| - } while (--count != 0);
|
| + if (dither) {
|
| + do {
|
| + unsigned rr = r >> 16;
|
| + unsigned gg = g >> 16;
|
| + unsigned bb = b >> 16;
|
| + cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb));
|
| + cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb);
|
| + cache += 1;
|
| + r += dr;
|
| + g += dg;
|
| + b += db;
|
| + } while (--count != 0);
|
| + } else {
|
| + do {
|
| + unsigned rr = r >> 16;
|
| + unsigned gg = g >> 16;
|
| + unsigned bb = b >> 16;
|
| + cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb));
|
| + cache[kCache16Count] = cache[0];
|
| + cache += 1;
|
| + r += dr;
|
| + g += dg;
|
| + b += db;
|
| + } while (--count != 0);
|
| + }
|
| }
|
|
|
| /*
|
| @@ -392,7 +414,7 @@ typedef uint32_t SkUFixed;
|
|
|
| void SkGradientShaderBase::GradientShaderCache::Build32bitCache(
|
| SkPMColor cache[], SkColor c0, SkColor c1,
|
| - int count, U8CPU paintAlpha, uint32_t gradFlags) {
|
| + int count, U8CPU paintAlpha, uint32_t gradFlags, bool dither) {
|
| SkASSERT(count > 1);
|
|
|
| // need to apply paintAlpha to our two endpoints
|
| @@ -432,10 +454,15 @@ void SkGradientShaderBase::GradientShaderCache::Build32bitCache(
|
| With this trick, we can add 0 for the first (no-op) and just adjust the
|
| others.
|
| */
|
| - SkUFixed a = SkIntToFixed(a0) + 0x2000;
|
| - SkUFixed r = SkIntToFixed(r0) + 0x2000;
|
| - SkUFixed g = SkIntToFixed(g0) + 0x2000;
|
| - SkUFixed b = SkIntToFixed(b0) + 0x2000;
|
| + const SkUFixed bias0 = dither ? 0x2000 : 0x8000;
|
| + const SkUFixed bias1 = dither ? 0x8000 : 0;
|
| + const SkUFixed bias2 = dither ? 0xC000 : 0;
|
| + const SkUFixed bias3 = dither ? 0x4000 : 0;
|
| +
|
| + SkUFixed a = SkIntToFixed(a0) + bias0;
|
| + SkUFixed r = SkIntToFixed(r0) + bias0;
|
| + SkUFixed g = SkIntToFixed(g0) + bias0;
|
| + SkUFixed b = SkIntToFixed(b0) + bias0;
|
|
|
| /*
|
| * Our dither-cell (spatially) is
|
| @@ -450,18 +477,18 @@ void SkGradientShaderBase::GradientShaderCache::Build32bitCache(
|
|
|
| if (0xFF == a0 && 0 == da) {
|
| do {
|
| - cache[kCache32Count*0] = SkPackARGB32(0xFF, (r + 0 ) >> 16,
|
| - (g + 0 ) >> 16,
|
| - (b + 0 ) >> 16);
|
| - cache[kCache32Count*1] = SkPackARGB32(0xFF, (r + 0x8000) >> 16,
|
| - (g + 0x8000) >> 16,
|
| - (b + 0x8000) >> 16);
|
| - cache[kCache32Count*2] = SkPackARGB32(0xFF, (r + 0xC000) >> 16,
|
| - (g + 0xC000) >> 16,
|
| - (b + 0xC000) >> 16);
|
| - cache[kCache32Count*3] = SkPackARGB32(0xFF, (r + 0x4000) >> 16,
|
| - (g + 0x4000) >> 16,
|
| - (b + 0x4000) >> 16);
|
| + cache[kCache32Count*0] = SkPackARGB32(0xFF, (r + 0 ) >> 16,
|
| + (g + 0 ) >> 16,
|
| + (b + 0 ) >> 16);
|
| + cache[kCache32Count*1] = SkPackARGB32(0xFF, (r + bias1) >> 16,
|
| + (g + bias1) >> 16,
|
| + (b + bias1) >> 16);
|
| + cache[kCache32Count*2] = SkPackARGB32(0xFF, (r + bias2) >> 16,
|
| + (g + bias2) >> 16,
|
| + (b + bias2) >> 16);
|
| + cache[kCache32Count*3] = SkPackARGB32(0xFF, (r + bias3) >> 16,
|
| + (g + bias3) >> 16,
|
| + (b + bias3) >> 16);
|
| cache += 1;
|
| r += dr;
|
| g += dg;
|
| @@ -469,22 +496,22 @@ void SkGradientShaderBase::GradientShaderCache::Build32bitCache(
|
| } while (--count != 0);
|
| } else if (interpInPremul) {
|
| do {
|
| - cache[kCache32Count*0] = SkPackARGB32((a + 0 ) >> 16,
|
| - (r + 0 ) >> 16,
|
| - (g + 0 ) >> 16,
|
| - (b + 0 ) >> 16);
|
| - cache[kCache32Count*1] = SkPackARGB32((a + 0x8000) >> 16,
|
| - (r + 0x8000) >> 16,
|
| - (g + 0x8000) >> 16,
|
| - (b + 0x8000) >> 16);
|
| - cache[kCache32Count*2] = SkPackARGB32((a + 0xC000) >> 16,
|
| - (r + 0xC000) >> 16,
|
| - (g + 0xC000) >> 16,
|
| - (b + 0xC000) >> 16);
|
| - cache[kCache32Count*3] = SkPackARGB32((a + 0x4000) >> 16,
|
| - (r + 0x4000) >> 16,
|
| - (g + 0x4000) >> 16,
|
| - (b + 0x4000) >> 16);
|
| + cache[kCache32Count*0] = SkPackARGB32((a + 0 ) >> 16,
|
| + (r + 0 ) >> 16,
|
| + (g + 0 ) >> 16,
|
| + (b + 0 ) >> 16);
|
| + cache[kCache32Count*1] = SkPackARGB32((a + bias1) >> 16,
|
| + (r + bias1) >> 16,
|
| + (g + bias1) >> 16,
|
| + (b + bias1) >> 16);
|
| + cache[kCache32Count*2] = SkPackARGB32((a + bias2) >> 16,
|
| + (r + bias2) >> 16,
|
| + (g + bias2) >> 16,
|
| + (b + bias2) >> 16);
|
| + cache[kCache32Count*3] = SkPackARGB32((a + bias3) >> 16,
|
| + (r + bias3) >> 16,
|
| + (g + bias3) >> 16,
|
| + (b + bias3) >> 16);
|
| cache += 1;
|
| a += da;
|
| r += dr;
|
| @@ -497,18 +524,18 @@ void SkGradientShaderBase::GradientShaderCache::Build32bitCache(
|
| (r + 0 ) >> 16,
|
| (g + 0 ) >> 16,
|
| (b + 0 ) >> 16);
|
| - cache[kCache32Count*1] = SkPremultiplyARGBInline((a + 0x8000) >> 16,
|
| - (r + 0x8000) >> 16,
|
| - (g + 0x8000) >> 16,
|
| - (b + 0x8000) >> 16);
|
| - cache[kCache32Count*2] = SkPremultiplyARGBInline((a + 0xC000) >> 16,
|
| - (r + 0xC000) >> 16,
|
| - (g + 0xC000) >> 16,
|
| - (b + 0xC000) >> 16);
|
| - cache[kCache32Count*3] = SkPremultiplyARGBInline((a + 0x4000) >> 16,
|
| - (r + 0x4000) >> 16,
|
| - (g + 0x4000) >> 16,
|
| - (b + 0x4000) >> 16);
|
| + cache[kCache32Count*1] = SkPremultiplyARGBInline((a + bias1) >> 16,
|
| + (r + bias1) >> 16,
|
| + (g + bias1) >> 16,
|
| + (b + bias1) >> 16);
|
| + cache[kCache32Count*2] = SkPremultiplyARGBInline((a + bias2) >> 16,
|
| + (r + bias2) >> 16,
|
| + (g + bias2) >> 16,
|
| + (b + bias2) >> 16);
|
| + cache[kCache32Count*3] = SkPremultiplyARGBInline((a + bias3) >> 16,
|
| + (r + bias3) >> 16,
|
| + (g + bias3) >> 16,
|
| + (b + bias3) >> 16);
|
| cache += 1;
|
| a += da;
|
| r += dr;
|
| @@ -540,7 +567,7 @@ void SkGradientShaderBase::GradientShaderCache::initCache16(GradientShaderCache*
|
| cache->fCache16 = cache->fCache16Storage;
|
| if (cache->fShader.fColorCount == 2) {
|
| Build16bitCache(cache->fCache16, cache->fShader.fOrigColors[0],
|
| - cache->fShader.fOrigColors[1], kCache16Count);
|
| + cache->fShader.fOrigColors[1], kCache16Count, cache->fCacheDither);
|
| } else {
|
| Rec* rec = cache->fShader.fRecs;
|
| int prevIndex = 0;
|
| @@ -550,7 +577,8 @@ void SkGradientShaderBase::GradientShaderCache::initCache16(GradientShaderCache*
|
|
|
| if (nextIndex > prevIndex)
|
| Build16bitCache(cache->fCache16 + prevIndex, cache->fShader.fOrigColors[i-1],
|
| - cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1);
|
| + cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1,
|
| + cache->fCacheDither);
|
| prevIndex = nextIndex;
|
| }
|
| }
|
| @@ -573,7 +601,7 @@ void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache*
|
| if (cache->fShader.fColorCount == 2) {
|
| Build32bitCache(cache->fCache32, cache->fShader.fOrigColors[0],
|
| cache->fShader.fOrigColors[1], kCache32Count, cache->fCacheAlpha,
|
| - cache->fShader.fGradFlags);
|
| + cache->fShader.fGradFlags, cache->fCacheDither);
|
| } else {
|
| Rec* rec = cache->fShader.fRecs;
|
| int prevIndex = 0;
|
| @@ -584,7 +612,7 @@ void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache*
|
| if (nextIndex > prevIndex)
|
| Build32bitCache(cache->fCache32 + prevIndex, cache->fShader.fOrigColors[i-1],
|
| cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1,
|
| - cache->fCacheAlpha, cache->fShader.fGradFlags);
|
| + cache->fCacheAlpha, cache->fShader.fGradFlags, cache->fCacheDither);
|
| prevIndex = nextIndex;
|
| }
|
| }
|
| @@ -594,10 +622,11 @@ void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache*
|
| * The gradient holds a cache for the most recent value of alpha. Successive
|
| * callers with the same alpha value will share the same cache.
|
| */
|
| -SkGradientShaderBase::GradientShaderCache* SkGradientShaderBase::refCache(U8CPU alpha) const {
|
| +SkGradientShaderBase::GradientShaderCache* SkGradientShaderBase::refCache(U8CPU alpha,
|
| + bool dither) const {
|
| SkAutoMutexAcquire ama(fCacheMutex);
|
| - if (!fCache || fCache->getAlpha() != alpha) {
|
| - fCache.reset(new GradientShaderCache(alpha, *this));
|
| + if (!fCache || fCache->getAlpha() != alpha || fCache->getDither() != dither) {
|
| + fCache.reset(new GradientShaderCache(alpha, dither, *this));
|
| }
|
| // Increment the ref counter inside the mutex to ensure the returned pointer is still valid.
|
| // Otherwise, the pointer may have been overwritten on a different thread before the object's
|
| @@ -618,7 +647,7 @@ SK_DECLARE_STATIC_MUTEX(gGradientCacheMutex);
|
| void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const {
|
| // our caller assumes no external alpha, so we ensure that our cache is
|
| // built with 0xFF
|
| - SkAutoTUnref<GradientShaderCache> cache(this->refCache(0xFF));
|
| + SkAutoTUnref<GradientShaderCache> cache(this->refCache(0xFF, true));
|
|
|
| // build our key: [numColors + colors[] + {positions[]} + flags ]
|
| int count = 1 + fColorCount + 1;
|
|
|