add SK_USE_SLOW_2POINT_RADIAL_GRADIENT option for clients that like slowness
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 15 Apr 2011 18:14:16 +0000 (18:14 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 15 Apr 2011 18:14:16 +0000 (18:14 +0000)
(or the previous images)

git-svn-id: http://skia.googlecode.com/svn/trunk@1140 2bbb7eff-a529-9590-31e7-b0007b416f81

src/effects/SkGradientShader.cpp

index ea90e26..84d7440 100644 (file)
@@ -1454,6 +1454,21 @@ private:
 
 */
 
+#ifdef SK_USE_SLOW_2POINT_RADIAL_GRADIENT
+static inline SkFixed two_point_radial(SkFixed b, SkFixed fx, SkFixed fy, SkFixed sr2d2, SkFixed foura, SkFixed oneOverTwoA, bool posRoot) {
+    SkFixed c = SkFixedSquare(fx) + SkFixedSquare(fy) - sr2d2;
+    SkFixed discrim = SkFixedSquare(b) - SkFixedMul(foura, c);
+    if (discrim < 0) {
+        discrim = -discrim;
+    }
+    SkFixed rootDiscrim = SkFixedSqrt(discrim);
+    if (posRoot) {
+        return SkFixedMul(-b + rootDiscrim, oneOverTwoA);
+    } else {
+        return SkFixedMul(-b - rootDiscrim, oneOverTwoA);
+    }
+}
+#else
 static inline SkFixed two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
                                        SkScalar sr2d2, SkScalar foura,
                                        SkScalar oneOverTwoA, bool posRoot) {
@@ -1471,6 +1486,7 @@ static inline SkFixed two_point_radial(SkScalar b, SkScalar fx, SkScalar fy,
     }
     return SkScalarToFixed(result);
 }
+#endif
 
 class Two_Point_Radial_Gradient : public Gradient_Shader {
 public:
@@ -1532,6 +1548,106 @@ public:
         return kRadial2_GradientType;
     }
 
+#ifdef SK_USE_SLOW_2POINT_RADIAL_GRADIENT
+    virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
+    {
+        SkASSERT(count > 0);
+        
+        // Zero difference between radii:  fill with transparent black.
+        if (fDiffRadius == 0) {
+            sk_bzero(dstC, count * sizeof(*dstC));
+            return;
+        }
+        SkMatrix::MapXYProc dstProc = fDstToIndexProc;
+        TileProc            proc = fTileProc;
+        const SkPMColor*    cache = this->getCache32();
+        SkFixed diffx = SkScalarToFixed(fDiff.fX);
+        SkFixed diffy = SkScalarToFixed(fDiff.fY);
+        SkFixed foura = SkScalarToFixed(SkScalarMul(fA, 4));
+        SkFixed startRadius = SkScalarToFixed(fStartRadius);
+        SkFixed sr2D2 = SkScalarToFixed(fSr2D2);
+        SkFixed oneOverTwoA = SkScalarToFixed(fOneOverTwoA);
+        bool posRoot = fDiffRadius < 0;
+        if (fDstToIndexClass != kPerspective_MatrixClass)
+        {
+            SkPoint srcPt;
+            dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
+                    SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
+            SkFixed dx, fx = SkScalarToFixed(srcPt.fX);
+            SkFixed dy, fy = SkScalarToFixed(srcPt.fY);
+            
+            if (fDstToIndexClass == kFixedStepInX_MatrixClass)
+            {
+                (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &dx, &dy);
+            }
+            else
+            {
+                SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
+                dx = SkScalarToFixed(fDstToIndex.getScaleX());
+                dy = SkScalarToFixed(fDstToIndex.getSkewY());
+            }
+            SkFixed b = (SkFixedMul(diffx, fx) +
+                         SkFixedMul(diffy, fy) - startRadius) << 1;
+            SkFixed db = (SkFixedMul(diffx, dx) +
+                          SkFixedMul(diffy, dy)) << 1;
+            if (proc == clamp_tileproc)
+            {
+                for (; count > 0; --count) {
+                    SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
+                    SkFixed index = SkClampMax(t, 0xFFFF);
+                    SkASSERT(index <= 0xFFFF);
+                    *dstC++ = cache[index >> (16 - kCache32Bits)];
+                    fx += dx;
+                    fy += dy;
+                    b += db;
+                }
+            }
+            else if (proc == mirror_tileproc)
+            {
+                for (; count > 0; --count) {
+                    SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
+                    SkFixed index = mirror_tileproc(t);
+                    SkASSERT(index <= 0xFFFF);
+                    *dstC++ = cache[index >> (16 - kCache32Bits)];
+                    fx += dx;
+                    fy += dy;
+                    b += db;
+                }
+            }
+            else
+            {
+                SkASSERT(proc == repeat_tileproc);
+                for (; count > 0; --count) {
+                    SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
+                    SkFixed index = repeat_tileproc(t);
+                    SkASSERT(index <= 0xFFFF);
+                    *dstC++ = cache[index >> (16 - kCache32Bits)];
+                    fx += dx;
+                    fy += dy;
+                    b += db;
+                }
+            }
+        }
+        else    // perspective case
+        {
+            SkScalar dstX = SkIntToScalar(x);
+            SkScalar dstY = SkIntToScalar(y);
+            for (; count > 0; --count) {
+                SkPoint             srcPt;
+                dstProc(fDstToIndex, dstX, dstY, &srcPt);
+                SkFixed fx = SkScalarToFixed(srcPt.fX);
+                SkFixed fy = SkScalarToFixed(srcPt.fY);
+                SkFixed b = (SkFixedMul(diffx, fx) +
+                             SkFixedMul(diffy, fy) - startRadius) << 1;
+                SkFixed t = two_point_radial(b, fx, fy, sr2D2, foura, oneOverTwoA, posRoot);
+                SkFixed index = proc(t);
+                SkASSERT(index <= 0xFFFF);
+                *dstC++ = cache[index >> (16 - kCache32Bits)];
+                dstX += SK_Scalar1;
+            }
+        }
+    }
+#else
     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) {
         SkASSERT(count > 0);
 
@@ -1617,6 +1733,7 @@ public:
             }
         }
     }
+#endif
 
     virtual bool setContext(const SkBitmap& device,
                             const SkPaint& paint,