Added asNewCustomStage to SkShader and implemented it for all the gradient shaders.

Not actually hooked up yet, but it should be ready to replace asABitmap for a future CL.
Review URL: https://codereview.appspot.com/6351113

git-svn-id: http://skia.googlecode.com/svn/trunk@4702 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp
index b86c4e2..8838e77 100644
--- a/src/effects/SkGradientShader.cpp
+++ b/src/effects/SkGradientShader.cpp
@@ -15,6 +15,9 @@
 #include "SkUtils.h"
 #include "SkTemplates.h"
 #include "SkBitmapCache.h"
+#include "../gpu/effects/GrGradientEffects.h"
+#include "../gpu/GrSamplerState.h"
+#include "../gpu/SkGr.h"
 
 #ifndef SK_DISABLE_DITHER_32BIT_GRADIENT
     #define USE_DITHER_32BIT_GRADIENT
@@ -796,6 +799,8 @@
     virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*,
                              SkScalar* twoPointRadialParams) const SK_OVERRIDE;
     virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
+    virtual GrCustomStage* asNewCustomStage(GrContext* context, 
+                                            GrSamplerState* sampler) const SK_OVERRIDE;
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Linear_Gradient)
 
@@ -1044,6 +1049,16 @@
     return kLinear_GradientType;
 }
 
+GrCustomStage* Linear_Gradient::asNewCustomStage(GrContext* context,
+                                                 GrSamplerState* sampler) const {
+    SkASSERT(NULL != context && NULL != sampler);
+    sampler->matrix()->preConcat(fPtsToUnit);
+    sampler->setWrapX(sk_tile_mode_to_grwrap(fTileMode));
+    sampler->setWrapY(sk_tile_mode_to_grwrap(kClamp_TileMode));
+    sampler->setFilter(GrSamplerState::kBilinear_Filter);
+    return SkNEW_ARGS(GrLinearGradient, (context, *this));
+}
+
 static void dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
                             int count) {
     if (reinterpret_cast<uintptr_t>(dst) & 2) {
@@ -1444,6 +1459,7 @@
         }
         return kRadial_BitmapType;
     }
+
     virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE {
         if (info) {
             commonAsAGradient(info);
@@ -1453,6 +1469,16 @@
         return kRadial_GradientType;
     }
 
+    virtual GrCustomStage* asNewCustomStage(GrContext* context,
+        GrSamplerState* sampler) const SK_OVERRIDE {
+        SkASSERT(NULL != context && NULL != sampler);
+        sampler->matrix()->preConcat(fPtsToUnit);
+        sampler->setWrapX(sk_tile_mode_to_grwrap(fTileMode));
+        sampler->setWrapY(sk_tile_mode_to_grwrap(kClamp_TileMode));
+        sampler->setFilter(GrSamplerState::kBilinear_Filter);
+        return SkNEW_ARGS(GrRadialGradient, (context, *this));
+    }
+
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Radial_Gradient)
 
 protected:
@@ -1903,6 +1929,24 @@
         return kRadial2_GradientType;
     }
 
+    virtual GrCustomStage* asNewCustomStage(GrContext* context,
+        GrSamplerState* sampler) const SK_OVERRIDE {
+        SkASSERT(NULL != context && NULL != sampler);
+        SkScalar diffLen = fDiff.length();
+        if (0 != diffLen) {
+            SkScalar invDiffLen = SkScalarInvert(diffLen);
+            sampler->matrix()->setSinCos(-SkScalarMul(invDiffLen, fDiff.fY),
+                              SkScalarMul(invDiffLen, fDiff.fX));
+        } else {
+            sampler->matrix()->reset();
+        }
+        sampler->matrix()->preConcat(fPtsToUnit);
+        sampler->setWrapX(sk_tile_mode_to_grwrap(fTileMode));
+        sampler->setWrapY(sk_tile_mode_to_grwrap(kClamp_TileMode));
+        sampler->setFilter(GrSamplerState::kBilinear_Filter);
+        return SkNEW_ARGS(GrRadial2Gradient, (context, *this));
+    }
+
     virtual void shadeSpan(int x, int y, SkPMColor* dstCParam,
                            int count) SK_OVERRIDE {
         SkASSERT(count > 0);
@@ -2355,6 +2399,25 @@
         return kConical_GradientType;
     }
 
+    virtual GrCustomStage* asNewCustomStage(GrContext* context,
+        GrSamplerState* sampler) const SK_OVERRIDE {
+        SkASSERT(NULL != context && NULL != sampler);
+        SkPoint diff = fCenter2 - fCenter1;
+        SkScalar diffLen = diff.length();
+        if (0 != diffLen) {
+            SkScalar invDiffLen = SkScalarInvert(diffLen);
+            sampler->matrix()->setSinCos(-SkScalarMul(invDiffLen, diff.fY),
+                              SkScalarMul(invDiffLen, diff.fX));
+        } else {
+            sampler->matrix()->reset();
+        }
+        sampler->matrix()->preTranslate(-fCenter1.fX, -fCenter1.fY);
+        sampler->setWrapX(sk_tile_mode_to_grwrap(fTileMode));
+        sampler->setWrapY(sk_tile_mode_to_grwrap(kClamp_TileMode));
+        sampler->setFilter(GrSamplerState::kBilinear_Filter);
+        return SkNEW_ARGS(GrConical2Gradient, (context, *this));
+    }
+
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Two_Point_Conical_Gradient)
     
 protected:
@@ -2422,6 +2485,15 @@
         return kSweep_GradientType;
     }
 
+    virtual GrCustomStage* asNewCustomStage(GrContext* context,
+        GrSamplerState* sampler) const SK_OVERRIDE {
+        sampler->matrix()->preConcat(fPtsToUnit);
+        sampler->setWrapX(sk_tile_mode_to_grwrap(fTileMode));
+        sampler->setWrapY(sk_tile_mode_to_grwrap(kClamp_TileMode));
+        sampler->setFilter(GrSamplerState::kBilinear_Filter);
+        return SkNEW_ARGS(GrSweepGradient, (context, *this));
+    }
+
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sweep_Gradient)
 
 protected: