| Index: src/effects/gradients/SkTwoPointConicalGradient.cpp
 | 
| diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
 | 
| index 1e6a0d81268a28c30e630a3be37039510e761aea..b7aba827bbe77df4c5c8955b751facd4be7258e8 100644
 | 
| --- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
 | 
| +++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
 | 
| @@ -9,6 +9,18 @@
 | 
|  
 | 
|  #include "SkTwoPointConicalGradient_gpu.h"
 | 
|  
 | 
| +struct TwoPtRadialContext {
 | 
| +    const TwoPtRadial&  fRec;
 | 
| +    float               fRelX, fRelY;
 | 
| +    const float         fIncX, fIncY;
 | 
| +    float               fB;
 | 
| +    const float         fDB;
 | 
| +
 | 
| +    TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy,
 | 
| +                       SkScalar dfx, SkScalar dfy);
 | 
| +    SkFixed nextT();
 | 
| +};
 | 
| +
 | 
|  static int valid_divide(float numer, float denom, float* ratio) {
 | 
|      SkASSERT(ratio);
 | 
|      if (0 == denom) {
 | 
| @@ -83,47 +95,48 @@ void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0,
 | 
|      fFlipped = flipped;
 | 
|  }
 | 
|  
 | 
| -void TwoPtRadial::setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy) {
 | 
| -    fRelX = SkScalarToFloat(fx) - fCenterX;
 | 
| -    fRelY = SkScalarToFloat(fy) - fCenterY;
 | 
| -    fIncX = SkScalarToFloat(dfx);
 | 
| -    fIncY = SkScalarToFloat(dfy);
 | 
| -    fB = -2 * (fDCenterX * fRelX + fDCenterY * fRelY + fRDR);
 | 
| -    fDB = -2 * (fDCenterX * fIncX + fDCenterY * fIncY);
 | 
| -}
 | 
| -
 | 
| -SkFixed TwoPtRadial::nextT() {
 | 
| +TwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy,
 | 
| +                                       SkScalar dfx, SkScalar dfy)
 | 
| +    : fRec(rec)
 | 
| +    , fRelX(SkScalarToFloat(fx) - rec.fCenterX)
 | 
| +    , fRelY(SkScalarToFloat(fy) - rec.fCenterY)
 | 
| +    , fIncX(SkScalarToFloat(dfx))
 | 
| +    , fIncY(SkScalarToFloat(dfy))
 | 
| +    , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR))
 | 
| +    , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {}
 | 
| +
 | 
| +SkFixed TwoPtRadialContext::nextT() {
 | 
|      float roots[2];
 | 
|  
 | 
| -    float C = sqr(fRelX) + sqr(fRelY) - fRadius2;
 | 
| -    int countRoots = find_quad_roots(fA, fB, C, roots, fFlipped);
 | 
| +    float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2;
 | 
| +    int countRoots = find_quad_roots(fRec.fA, fB, C, roots, fRec.fFlipped);
 | 
|  
 | 
|      fRelX += fIncX;
 | 
|      fRelY += fIncY;
 | 
|      fB += fDB;
 | 
|  
 | 
|      if (0 == countRoots) {
 | 
| -        return kDontDrawT;
 | 
| +        return TwoPtRadial::kDontDrawT;
 | 
|      }
 | 
|  
 | 
|      // Prefer the bigger t value if both give a radius(t) > 0
 | 
|      // find_quad_roots returns the values sorted, so we start with the last
 | 
|      float t = roots[countRoots - 1];
 | 
| -    float r = lerp(fRadius, fDRadius, t);
 | 
| +    float r = lerp(fRec.fRadius, fRec.fDRadius, t);
 | 
|      if (r <= 0) {
 | 
|          t = roots[0];   // might be the same as roots[countRoots-1]
 | 
| -        r = lerp(fRadius, fDRadius, t);
 | 
| +        r = lerp(fRec.fRadius, fRec.fDRadius, t);
 | 
|          if (r <= 0) {
 | 
| -            return kDontDrawT;
 | 
| +            return TwoPtRadial::kDontDrawT;
 | 
|          }
 | 
|      }
 | 
|      return SkFloatToFixed(t);
 | 
|  }
 | 
|  
 | 
| -typedef void (*TwoPointConicalProc)(TwoPtRadial* rec, SkPMColor* dstC,
 | 
| +typedef void (*TwoPointConicalProc)(TwoPtRadialContext* rec, SkPMColor* dstC,
 | 
|                                      const SkPMColor* cache, int toggle, int count);
 | 
|  
 | 
| -static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
 | 
| +static void twopoint_clamp(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
 | 
|                             const SkPMColor* SK_RESTRICT cache, int toggle,
 | 
|                             int count) {
 | 
|      for (; count > 0; --count) {
 | 
| @@ -140,7 +153,7 @@ static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
 | 
|      }
 | 
|  }
 | 
|  
 | 
| -static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
 | 
| +static void twopoint_repeat(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
 | 
|                              const SkPMColor* SK_RESTRICT cache, int toggle,
 | 
|                              int count) {
 | 
|      for (; count > 0; --count) {
 | 
| @@ -157,7 +170,7 @@ static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
 | 
|      }
 | 
|  }
 | 
|  
 | 
| -static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
 | 
| +static void twopoint_mirror(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
 | 
|                              const SkPMColor* SK_RESTRICT cache, int toggle,
 | 
|                              int count) {
 | 
|      for (; count > 0; --count) {
 | 
| @@ -203,8 +216,39 @@ bool SkTwoPointConicalGradient::isOpaque() const {
 | 
|      return false;
 | 
|  }
 | 
|  
 | 
| -void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
 | 
| -                                          int count) {
 | 
| +size_t SkTwoPointConicalGradient::contextSize() const {
 | 
| +    return sizeof(TwoPointConicalGradientContext);
 | 
| +}
 | 
| +
 | 
| +SkShader::Context* SkTwoPointConicalGradient::createContext(
 | 
| +        const SkBitmap& device, const SkPaint& paint,
 | 
| +        const SkMatrix& matrix, void* storage) const {
 | 
| +    if (!this->validContext(device, paint, matrix)) {
 | 
| +        return NULL;
 | 
| +    }
 | 
| +
 | 
| +    return SkNEW_PLACEMENT_ARGS(storage, TwoPointConicalGradientContext,
 | 
| +                                (*this, device, paint, matrix));
 | 
| +}
 | 
| +
 | 
| +SkTwoPointConicalGradient::TwoPointConicalGradientContext::TwoPointConicalGradientContext(
 | 
| +        const SkTwoPointConicalGradient& shader, const SkBitmap& device,
 | 
| +        const SkPaint& paint, const SkMatrix& matrix)
 | 
| +    : INHERITED(shader, device, paint, matrix)
 | 
| +{
 | 
| +    // we don't have a span16 proc
 | 
| +    fFlags &= ~kHasSpan16_Flag;
 | 
| +
 | 
| +    // in general, we might discard based on computed-radius, so clear
 | 
| +    // this flag (todo: sometimes we can detect that we never discard...)
 | 
| +    fFlags &= ~kOpaqueAlpha_Flag;
 | 
| +}
 | 
| +
 | 
| +void SkTwoPointConicalGradient::TwoPointConicalGradientContext::shadeSpan(
 | 
| +        int x, int y, SkPMColor* dstCParam, int count) {
 | 
| +    const SkTwoPointConicalGradient& twoPointConicalGradient =
 | 
| +            static_cast<const SkTwoPointConicalGradient&>(fShader);
 | 
| +
 | 
|      int toggle = init_dither_toggle(x, y);
 | 
|  
 | 
|      SkASSERT(count > 0);
 | 
| @@ -213,15 +257,15 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
 | 
|  
 | 
|      SkMatrix::MapXYProc dstProc = fDstToIndexProc;
 | 
|  
 | 
| -    const SkPMColor* SK_RESTRICT cache = this->getCache32();
 | 
| +    const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
 | 
|  
 | 
|      TwoPointConicalProc shadeProc = twopoint_repeat;
 | 
| -    if (SkShader::kClamp_TileMode == fTileMode) {
 | 
| +    if (SkShader::kClamp_TileMode == twoPointConicalGradient.fTileMode) {
 | 
|          shadeProc = twopoint_clamp;
 | 
| -    } else if (SkShader::kMirror_TileMode == fTileMode) {
 | 
| +    } else if (SkShader::kMirror_TileMode == twoPointConicalGradient.fTileMode) {
 | 
|          shadeProc = twopoint_mirror;
 | 
|      } else {
 | 
| -        SkASSERT(SkShader::kRepeat_TileMode == fTileMode);
 | 
| +        SkASSERT(SkShader::kRepeat_TileMode == twoPointConicalGradient.fTileMode);
 | 
|      }
 | 
|  
 | 
|      if (fDstToIndexClass != kPerspective_MatrixClass) {
 | 
| @@ -242,16 +286,16 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
 | 
|              dy = fDstToIndex.getSkewY();
 | 
|          }
 | 
|  
 | 
| -        fRec.setup(fx, fy, dx, dy);
 | 
| -        (*shadeProc)(&fRec, dstC, cache, toggle, count);
 | 
| +        TwoPtRadialContext rec(twoPointConicalGradient.fRec, fx, fy, dx, dy);
 | 
| +        (*shadeProc)(&rec, dstC, cache, toggle, count);
 | 
|      } else {    // perspective case
 | 
|          SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf;
 | 
|          SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf;
 | 
|          for (; count > 0; --count) {
 | 
|              SkPoint srcPt;
 | 
|              dstProc(fDstToIndex, dstX, dstY, &srcPt);
 | 
| -            fRec.setup(srcPt.fX, srcPt.fY, 0, 0);
 | 
| -            (*shadeProc)(&fRec, dstC, cache, toggle, 1);
 | 
| +            TwoPtRadialContext rec(twoPointConicalGradient.fRec, srcPt.fX, srcPt.fY, 0, 0);
 | 
| +            (*shadeProc)(&rec, dstC, cache, toggle, 1);
 | 
|  
 | 
|              dstX += SK_Scalar1;
 | 
|              toggle = next_dither_toggle(toggle);
 | 
| @@ -260,23 +304,6 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
 | 
|      }
 | 
|  }
 | 
|  
 | 
| -bool SkTwoPointConicalGradient::setContext(const SkBitmap& device,
 | 
| -                                           const SkPaint& paint,
 | 
| -                                           const SkMatrix& matrix) {
 | 
| -    if (!this->INHERITED::setContext(device, paint, matrix)) {
 | 
| -        return false;
 | 
| -    }
 | 
| -
 | 
| -    // we don't have a span16 proc
 | 
| -    fFlags &= ~kHasSpan16_Flag;
 | 
| -
 | 
| -    // in general, we might discard based on computed-radius, so clear
 | 
| -    // this flag (todo: sometimes we can detect that we never discard...)
 | 
| -    fFlags &= ~kOpaqueAlpha_Flag;
 | 
| -
 | 
| -    return true;
 | 
| -}
 | 
| -
 | 
|  SkShader::BitmapType SkTwoPointConicalGradient::asABitmap(
 | 
|      SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const {
 | 
|      SkPoint diff = fCenter2 - fCenter1;
 | 
| 
 |