From e61414ce7b426da43a1e6d37a2802b3c80f84d6b Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Fri, 15 Apr 2011 18:14:16 +0000 Subject: [PATCH] add SK_USE_SLOW_2POINT_RADIAL_GRADIENT option for clients that like slowness (or the previous images) git-svn-id: http://skia.googlecode.com/svn/trunk@1140 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/effects/SkGradientShader.cpp | 117 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp index ea90e26..84d7440 100644 --- a/src/effects/SkGradientShader.cpp +++ b/src/effects/SkGradientShader.cpp @@ -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, -- 2.7.4