Add dithering to 32b radial gradients. Behind the same #ifdef as dithered
32b linear gradients so that we don't impact clients unexpectedly.
This commit *will* break GM.

http://codereview.appspot.com/5599050/



git-svn-id: http://skia.googlecode.com/svn/trunk@3126 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp
index e32acb2..cfae9aa 100644
--- a/src/effects/SkGradientShader.cpp
+++ b/src/effects/SkGradientShader.cpp
@@ -1557,20 +1557,22 @@
 
 #define UNPINNED_RADIAL_STEP \
     fi = (fx * fx + fy * fy) >> (14 + 16 - kSQRT_TABLE_BITS); \
-    *dstC++ = cache[sqrt_table[fi] >> Gradient_Shader::kSqrt32Shift]; \
+    *dstC++ = cache[toggle + \
+                    (sqrt_table[fi] >> Gradient_Shader::kSqrt32Shift)]; \
+    toggle ^= Gradient_Shader::kDitherStride32; \
     fx += dx; \
     fy += dy;
 
 typedef void (* RadialShadeProc)(SkScalar sfx, SkScalar sdx,
         SkScalar sfy, SkScalar sdy,
         SkPMColor* dstC, const SkPMColor* cache,
-        int count);
+        int count, int toggle);
 
 // On Linux, this is faster with SkPMColor[] params than SkPMColor* SK_RESTRICT
 void shadeSpan_radial_clamp(SkScalar sfx, SkScalar sdx,
         SkScalar sfy, SkScalar sdy,
         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
-        int count) {
+        int count, int toggle) {
     // Floating point seems to be slower than fixed point,
     // even when we have float hardware.
     const uint8_t* SK_RESTRICT sqrt_table = gSqrt8Table;
@@ -1579,7 +1581,11 @@
     SkFixed fy = SkScalarToFixed(sfy) >> 1;
     SkFixed dy = SkScalarToFixed(sdy) >> 1;
     if ((count > 4) && radial_completely_pinned(fx, dx, fy, dy)) {
-        sk_memset32(dstC, cache[Gradient_Shader::kGradient32Length], count);
+        unsigned fi = Gradient_Shader::kGradient32Length;
+        sk_memset32_dither(dstC,
+            cache[toggle + fi],
+            cache[(toggle ^ Gradient_Shader::kDitherStride32) + fi],
+            count);
     } else if ((count > 4) &&
                no_need_for_radial_pin(fx, dx, fy, dy, count)) {
         unsigned fi;
@@ -1602,8 +1608,9 @@
                 unsigned xx = SkPin32(fx, -0xFFFF >> 1, 0xFFFF >> 1);
                 unsigned fi = (xx * xx + yy) >> (14 + 16 - kSQRT_TABLE_BITS);
                 fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
-                *dstC++ = cache[sqrt_table[fi] >>
-                    Gradient_Shader::kSqrt32Shift];
+                *dstC++ = cache[toggle + (sqrt_table[fi] >>
+                    Gradient_Shader::kSqrt32Shift)];
+                toggle ^= Gradient_Shader::kDitherStride32;
                 fx += dx;
             } while (--count != 0);
         } else {
@@ -1612,8 +1619,9 @@
                 unsigned fi = SkPin32(fy, -0xFFFF >> 1, 0xFFFF >> 1);
                 fi = (xx * xx + fi * fi) >> (14 + 16 - kSQRT_TABLE_BITS);
                 fi = SkFastMin32(fi, 0xFFFF >> (16 - kSQRT_TABLE_BITS));
-                *dstC++ = cache[sqrt_table[fi] >>
-                    Gradient_Shader::kSqrt32Shift];
+                *dstC++ = cache[toggle + (sqrt_table[fi] >>
+                    Gradient_Shader::kSqrt32Shift)];
+                toggle ^= Gradient_Shader::kDitherStride32;
                 fx += dx;
                 fy += dy;
             } while (--count != 0);
@@ -1627,7 +1635,7 @@
 void shadeSpan_radial_mirror(SkScalar sfx, SkScalar sdx,
         SkScalar sfy, SkScalar sdy,
         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
-        int count) {
+        int count, int toggle) {
     do {
 #ifdef SK_SCALAR_IS_FLOAT
         float fdist = sk_float_sqrt(sfx*sfx + sfy*sfy);
@@ -1641,7 +1649,8 @@
 #endif
         unsigned fi = mirror_tileproc(dist);
         SkASSERT(fi <= 0xFFFF);
-        *dstC++ = cache[fi >> Gradient_Shader::kCache32Shift];
+        *dstC++ = cache[toggle + (fi >> Gradient_Shader::kCache32Shift)];
+        toggle ^= Gradient_Shader::kDitherStride32;
         sfx += sdx;
         sfy += sdy;
     } while (--count != 0);
@@ -1650,7 +1659,7 @@
 void shadeSpan_radial_repeat(SkScalar sfx, SkScalar sdx,
         SkScalar sfy, SkScalar sdy,
         SkPMColor* SK_RESTRICT dstC, const SkPMColor* SK_RESTRICT cache,
-        int count) {
+        int count, int toggle) {
     SkFixed fx = SkScalarToFixed(sfx);
     SkFixed dx = SkScalarToFixed(sdx);
     SkFixed fy = SkScalarToFixed(sfy);
@@ -1663,7 +1672,8 @@
         SkFixed dist = SkFixedSqrt(magnitudeSquared);
         unsigned fi = repeat_tileproc(dist);
         SkASSERT(fi <= 0xFFFF);
-        *dstC++ = cache[fi >> Gradient_Shader::kCache32Shift];
+        *dstC++ = cache[toggle + (fi >> Gradient_Shader::kCache32Shift)];
+        toggle ^= Gradient_Shader::kDitherStride32;
         fx += dx;
         fy += dy;
     } while (--count != 0);
@@ -1678,6 +1688,11 @@
     SkMatrix::MapXYProc dstProc = fDstToIndexProc;
     TileProc            proc = fTileProc;
     const SkPMColor* SK_RESTRICT cache = this->getCache32();
+#ifdef USE_DITHER_32BIT_GRADIENT
+    int toggle = ((x ^ y) & 1) * Gradient_Shader::kDitherStride32;
+#else
+    int toggle = 0;
+#endif
 
     if (fDstToIndexClass != kPerspective_MatrixClass) {
         dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
@@ -1703,7 +1718,7 @@
         } else {
             SkASSERT(proc == repeat_tileproc);
         }
-        (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count);
+        (*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count, toggle);
     } else {    // perspective case
         SkScalar dstX = SkIntToScalar(x);
         SkScalar dstY = SkIntToScalar(y);