add localmatrix parameter to shader's asNewEffect

BUG=skia:
R=bsalomon@google.com, dominikg@chromium.org

Author: reed@google.com

Review URL: https://codereview.chromium.org/278963002

git-svn-id: http://skia.googlecode.com/svn/trunk@14686 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 00d938b..d726a46 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -393,7 +393,8 @@
     }
 }
 
-GrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
+GrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint,
+                                             const SkMatrix* localMatrix) const {
     SkMatrix matrix;
     matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height());
 
@@ -401,6 +402,13 @@
     if (!this->getLocalMatrix().invert(&lmInverse)) {
         return NULL;
     }
+    if (localMatrix) {
+        SkMatrix inv;
+        if (!localMatrix->invert(&inv)) {
+            return NULL;
+        }
+        lmInverse.postConcat(inv);
+    }
     matrix.preConcat(lmInverse);
 
     SkShader::TileMode tm[] = {
diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h
index 8d31256..80e4550 100644
--- a/src/core/SkBitmapProcShader.h
+++ b/src/core/SkBitmapProcShader.h
@@ -31,7 +31,7 @@
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBitmapProcShader)
 
 #if SK_SUPPORT_GPU
-    GrEffectRef* asNewEffect(GrContext*, const SkPaint&) const SK_OVERRIDE;
+    GrEffectRef* asNewEffect(GrContext*, const SkPaint&, const SkMatrix*) const SK_OVERRIDE;
 #endif
 
     class BitmapProcShaderContext : public SkShader::Context {
diff --git a/src/core/SkLocalMatrixShader.cpp b/src/core/SkLocalMatrixShader.cpp
index 802e72e..7af025c 100644
--- a/src/core/SkLocalMatrixShader.cpp
+++ b/src/core/SkLocalMatrixShader.cpp
@@ -30,8 +30,13 @@
     }
 
     // TODO: need to augment this API to pass in a localmatrix (which we can augment)
-    virtual GrEffectRef* asNewEffect(GrContext* ctx, const SkPaint& paint) const SK_OVERRIDE {
-        return fProxyShader->asNewEffect(ctx, paint);
+    virtual GrEffectRef* asNewEffect(GrContext* ctx, const SkPaint& paint,
+                                     const SkMatrix* localMatrix) const SK_OVERRIDE {
+        SkMatrix tmp = fProxyLocalMatrix;
+        if (localMatrix) {
+            tmp.preConcat(*localMatrix);
+        }
+        return fProxyShader->asNewEffect(ctx, paint, &tmp);
     }
 
     virtual SkShader* refAsALocalMatrixShader(SkMatrix* localMatrix) const SK_OVERRIDE {
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp
index 9655e85..300a653 100644
--- a/src/core/SkPictureShader.cpp
+++ b/src/core/SkPictureShader.cpp
@@ -192,11 +192,12 @@
 #endif
 
 #if SK_SUPPORT_GPU
-GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
-    SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(context->getMatrix(), NULL));
+GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& paint,
+                                          const SkMatrix* localMatrix) const {
+    SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(context->getMatrix(), localMatrix));
     if (!bitmapShader) {
         return NULL;
     }
-    return bitmapShader->asNewEffect(context, paint);
+    return bitmapShader->asNewEffect(context, paint, NULL);
 }
 #endif
diff --git a/src/core/SkPictureShader.h b/src/core/SkPictureShader.h
index 27fb674..936a69e 100644
--- a/src/core/SkPictureShader.h
+++ b/src/core/SkPictureShader.h
@@ -30,7 +30,7 @@
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPictureShader)
 
 #if SK_SUPPORT_GPU
-    GrEffectRef* asNewEffect(GrContext*, const SkPaint&) const SK_OVERRIDE;
+    GrEffectRef* asNewEffect(GrContext*, const SkPaint&, const SkMatrix*) const SK_OVERRIDE;
 #endif
 
 protected:
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index ebe1a74..75a5fdb 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -211,7 +211,7 @@
     return kNone_GradientType;
 }
 
-GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const {
+GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&, const SkMatrix*) const {
     return NULL;
 }
 
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index c6d6118..1015377 100644
--- a/src/effects/SkPerlinNoiseShader.cpp
+++ b/src/effects/SkPerlinNoiseShader.cpp
@@ -723,7 +723,7 @@
                                              stitchTiles ? &tileSize : NULL);
 
     SkPaint paint;
-    GrEffectRef* effect = shader->asNewEffect(context, paint);
+    GrEffectRef* effect = shader->asNewEffect(context, paint, NULL);
 
     SkDELETE(shader);
 
@@ -1275,9 +1275,15 @@
 
 /////////////////////////////////////////////////////////////////////
 
-GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
+GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext* context, const SkPaint& paint,
+                                              const SkMatrix* externalLocalMatrix) const {
     SkASSERT(NULL != context);
 
+    SkMatrix localMatrix = this->getLocalMatrix();
+    if (externalLocalMatrix) {
+        localMatrix.preConcat(*externalLocalMatrix);
+    }
+
     if (0 == fNumOctaves) {
         SkColor clearColor = 0;
         if (kFractalNoise_Type == fType) {
@@ -1309,7 +1315,7 @@
                                     fNumOctaves, fStitchTiles,
                                     fPaintingData->fStitchDataInit,
                                     permutationsTexture, noiseTexture,
-                                    this->getLocalMatrix(), paint.getAlpha()) :
+                                    localMatrix, paint.getAlpha()) :
         NULL;
 
     // Unlock immediately, this is not great, but we don't have a way of
@@ -1328,7 +1334,7 @@
 
 #else
 
-GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext*, const SkPaint&) const {
+GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext*, const SkPaint&, const SkMatrix*) const {
     SkDEBUGFAIL("Should not call in GPU-less build");
     return NULL;
 }
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index f37759c..4fe6547 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -527,7 +527,7 @@
                                                                  colors, stops, colorCount,
                                                                  tm));
     SkPaint paint;
-    return shader->asNewEffect(context, paint);
+    return shader->asNewEffect(context, paint, NULL);
 }
 
 /////////////////////////////////////////////////////////////////////
@@ -547,12 +547,20 @@
 
 /////////////////////////////////////////////////////////////////////
 
-GrEffectRef* SkLinearGradient::asNewEffect(GrContext* context, const SkPaint&) const {
+GrEffectRef* SkLinearGradient::asNewEffect(GrContext* context, const SkPaint&,
+                                           const SkMatrix* localMatrix) const {
     SkASSERT(NULL != context);
     SkMatrix matrix;
     if (!this->getLocalMatrix().invert(&matrix)) {
         return NULL;
     }
+    if (localMatrix) {
+        SkMatrix inv;
+        if (!localMatrix->invert(&inv)) {
+            return NULL;
+        }
+        matrix.postConcat(inv);
+    }
     matrix.postConcat(fPtsToUnit);
     return GrLinearGradient::Create(context, *this, matrix, fTileMode);
 }
diff --git a/src/effects/gradients/SkLinearGradient.h b/src/effects/gradients/SkLinearGradient.h
index e892fe3..432dac0 100644
--- a/src/effects/gradients/SkLinearGradient.h
+++ b/src/effects/gradients/SkLinearGradient.h
@@ -30,7 +30,7 @@
 
     virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*) const SK_OVERRIDE;
     virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
-    virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE;
+    virtual GrEffectRef* asNewEffect(GrContext*, const SkPaint&, const SkMatrix*) const SK_OVERRIDE;
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLinearGradient)
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index e379f36..ce4c16a 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -538,7 +538,7 @@
                                                                  colors, stops, colorCount,
                                                                  tm));
     SkPaint paint;
-    return shader->asNewEffect(context, paint);
+    return shader->asNewEffect(context, paint, NULL);
 }
 
 /////////////////////////////////////////////////////////////////////
@@ -559,13 +559,21 @@
 
 /////////////////////////////////////////////////////////////////////
 
-GrEffectRef* SkRadialGradient::asNewEffect(GrContext* context, const SkPaint&) const {
+GrEffectRef* SkRadialGradient::asNewEffect(GrContext* context, const SkPaint&,
+                                           const SkMatrix* localMatrix) const {
     SkASSERT(NULL != context);
 
     SkMatrix matrix;
     if (!this->getLocalMatrix().invert(&matrix)) {
         return NULL;
     }
+    if (localMatrix) {
+        SkMatrix inv;
+        if (!localMatrix->invert(&inv)) {
+            return NULL;
+        }
+        matrix.postConcat(inv);
+    }
     matrix.postConcat(fPtsToUnit);
     return GrRadialGradient::Create(context, *this, matrix, fTileMode);
 }
diff --git a/src/effects/gradients/SkRadialGradient.h b/src/effects/gradients/SkRadialGradient.h
index 2c60ba5..aade31e 100644
--- a/src/effects/gradients/SkRadialGradient.h
+++ b/src/effects/gradients/SkRadialGradient.h
@@ -33,7 +33,7 @@
                                  SkMatrix* matrix,
                                  TileMode* xy) const SK_OVERRIDE;
     virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
-    virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE;
+    virtual GrEffectRef* asNewEffect(GrContext*, const SkPaint&, const SkMatrix*) const SK_OVERRIDE;
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkRadialGradient)
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index 81ebb34..ba43571 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -247,7 +247,7 @@
     SkAutoTUnref<SkShader> shader(SkGradientShader::CreateSweep(center.fX, center.fY,
                                                                 colors, stops, colorCount));
     SkPaint paint;
-    return shader->asNewEffect(context, paint);
+    return shader->asNewEffect(context, paint, NULL);
 }
 
 /////////////////////////////////////////////////////////////////////
@@ -279,11 +279,19 @@
 
 /////////////////////////////////////////////////////////////////////
 
-GrEffectRef* SkSweepGradient::asNewEffect(GrContext* context, const SkPaint&) const {
+GrEffectRef* SkSweepGradient::asNewEffect(GrContext* context, const SkPaint&,
+                                          const SkMatrix* localMatrix) const {
     SkMatrix matrix;
     if (!this->getLocalMatrix().invert(&matrix)) {
         return NULL;
     }
+    if (localMatrix) {
+        SkMatrix inv;
+        if (!localMatrix->invert(&inv)) {
+            return NULL;
+        }
+        matrix.postConcat(inv);
+    }
     matrix.postConcat(fPtsToUnit);
     return GrSweepGradient::Create(context, *this, matrix);
 }
diff --git a/src/effects/gradients/SkSweepGradient.h b/src/effects/gradients/SkSweepGradient.h
index 36cdd63..2f798e8 100644
--- a/src/effects/gradients/SkSweepGradient.h
+++ b/src/effects/gradients/SkSweepGradient.h
@@ -35,7 +35,7 @@
 
     virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
 
-    virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE;
+    virtual GrEffectRef* asNewEffect(GrContext*, const SkPaint&, const SkMatrix*) const SK_OVERRIDE;
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSweepGradient)
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index 574df08..cbe9e83 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -380,11 +380,12 @@
 
 #if SK_SUPPORT_GPU
 
-GrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext* context, const SkPaint&) const {
+GrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext* context, const SkPaint&,
+                                                    const SkMatrix* localMatrix) const {
     SkASSERT(NULL != context);
     SkASSERT(fPtsToUnit.isIdentity());
 
-    return Gr2PtConicalGradientEffect::Create(context, *this, fTileMode);
+    return Gr2PtConicalGradientEffect::Create(context, *this, fTileMode, localMatrix);
 }
 
 #else
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.h b/src/effects/gradients/SkTwoPointConicalGradient.h
index 85e0bc0..78998a8 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.h
+++ b/src/effects/gradients/SkTwoPointConicalGradient.h
@@ -65,7 +65,7 @@
                                  SkMatrix* matrix,
                                  TileMode* xy) const;
     virtual SkShader::GradientType asAGradient(GradientInfo* info) const  SK_OVERRIDE;
-    virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const SK_OVERRIDE;
+    virtual GrEffectRef* asNewEffect(GrContext*, const SkPaint&, const SkMatrix*) const SK_OVERRIDE;
     virtual bool isOpaque() const SK_OVERRIDE;
 
     SkScalar getCenterX1() const { return SkPoint::Distance(fCenter1, fCenter2); }
diff --git a/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
index 7986d82..23fee85 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
@@ -199,7 +199,7 @@
                                                                           colors, stops, colorCount,
                                                                           tm));
     SkPaint paint;
-    return shader->asNewEffect(context, paint);
+    return shader->asNewEffect(context, paint, NULL);
 }
 
 GLEdge2PtConicalEffect::GLEdge2PtConicalEffect(const GrBackendEffectFactory& factory,
@@ -470,7 +470,7 @@
                                                                           colors, stops, colorCount,
                                                                           tm));
     SkPaint paint;
-    return shader->asNewEffect(context, paint);
+    return shader->asNewEffect(context, paint, NULL);
 }
 
 GLFocalOutside2PtConicalEffect::GLFocalOutside2PtConicalEffect(const GrBackendEffectFactory& factory,
@@ -679,7 +679,7 @@
                                                                           colors, stops, colorCount,
                                                                           tm));
     SkPaint paint;
-    return shader->asNewEffect(context, paint);
+    return shader->asNewEffect(context, paint, NULL);
 }
 
 GLFocalInside2PtConicalEffect::GLFocalInside2PtConicalEffect(const GrBackendEffectFactory& factory,
@@ -920,7 +920,7 @@
                                                                           colors, stops, colorCount,
                                                                           tm));
     SkPaint paint;
-    return shader->asNewEffect(context, paint);
+    return shader->asNewEffect(context, paint, NULL);
 }
 
 GLCircleInside2PtConicalEffect::GLCircleInside2PtConicalEffect(const GrBackendEffectFactory& factory,
@@ -1148,7 +1148,7 @@
                                                                           colors, stops, colorCount,
                                                                           tm));
     SkPaint paint;
-    return shader->asNewEffect(context, paint);
+    return shader->asNewEffect(context, paint, NULL);
 }
 
 GLCircleOutside2PtConicalEffect::GLCircleOutside2PtConicalEffect(const GrBackendEffectFactory& factory,
@@ -1267,11 +1267,19 @@
 
 GrEffectRef* Gr2PtConicalGradientEffect::Create(GrContext* ctx,
                                                 const SkTwoPointConicalGradient& shader,
-                                                SkShader::TileMode tm) {
+                                                SkShader::TileMode tm,
+                                                const SkMatrix* localMatrix) {
     SkMatrix matrix;
     if (!shader.getLocalMatrix().invert(&matrix)) {
         return NULL;
     }
+    if (localMatrix) {
+        SkMatrix inv;
+        if (!localMatrix->invert(&inv)) {
+            return NULL;
+        }
+        matrix.postConcat(inv);
+    }
 
     if (shader.getStartRadius() < kErrorTol) {
         SkScalar focalX;
diff --git a/src/effects/gradients/SkTwoPointConicalGradient_gpu.h b/src/effects/gradients/SkTwoPointConicalGradient_gpu.h
index f8c0493..2b0f061 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient_gpu.h
+++ b/src/effects/gradients/SkTwoPointConicalGradient_gpu.h
@@ -19,7 +19,7 @@
      * shader passed in.
      */
     GrEffectRef* Create(GrContext* ctx, const SkTwoPointConicalGradient& shader,
-                        SkShader::TileMode tm);
+                        SkShader::TileMode tm, const SkMatrix* localMatrix);
 };
 
 #endif
diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp
index d85be5d..ac0b0bd 100644
--- a/src/effects/gradients/SkTwoPointRadialGradient.cpp
+++ b/src/effects/gradients/SkTwoPointRadialGradient.cpp
@@ -530,7 +530,7 @@
                                                                          colors, stops, colorCount,
                                                                          tm));
     SkPaint paint;
-    return shader->asNewEffect(context, paint);
+    return shader->asNewEffect(context, paint, NULL);
 }
 
 /////////////////////////////////////////////////////////////////////
@@ -670,13 +670,21 @@
 
 /////////////////////////////////////////////////////////////////////
 
-GrEffectRef* SkTwoPointRadialGradient::asNewEffect(GrContext* context, const SkPaint&) const {
+GrEffectRef* SkTwoPointRadialGradient::asNewEffect(GrContext* context, const SkPaint&,
+                                                   const SkMatrix* localMatrix) const {
     SkASSERT(NULL != context);
     // invert the localM, translate to center1 (fPtsToUni), rotate so center2 is on x axis.
     SkMatrix matrix;
     if (!this->getLocalMatrix().invert(&matrix)) {
         return NULL;
     }
+    if (localMatrix) {
+        SkMatrix inv;
+        if (!localMatrix->invert(&inv)) {
+            return NULL;
+        }
+        matrix.postConcat(inv);
+    }
     matrix.postConcat(fPtsToUnit);
 
     SkScalar diffLen = fDiff.length();
diff --git a/src/effects/gradients/SkTwoPointRadialGradient.h b/src/effects/gradients/SkTwoPointRadialGradient.h
index 6d36fe4..90052eb 100644
--- a/src/effects/gradients/SkTwoPointRadialGradient.h
+++ b/src/effects/gradients/SkTwoPointRadialGradient.h
@@ -21,7 +21,8 @@
                                  SkMatrix* matrix,
                                  TileMode* xy) const SK_OVERRIDE;
     virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
-    virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE;
+    virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&,
+                                     const SkMatrix*) const SK_OVERRIDE;
 
     virtual size_t contextSize() const SK_OVERRIDE;
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index f90b906..0aee983 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -463,7 +463,7 @@
     GrContext::AutoWideOpenIdentityDraw awo(dev->context(), NULL);
 
     // setup the shader as the first color effect on the paint
-    SkAutoTUnref<GrEffectRef> effect(shader->asNewEffect(dev->context(), skPaint));
+    SkAutoTUnref<GrEffectRef> effect(shader->asNewEffect(dev->context(), skPaint, NULL));
     if (NULL != effect.get()) {
         grPaint->addColorEffect(effect);
         // Now setup the rest of the paint.