Move SkShader::fLocalMatrix into SkShader constructor.

As a first step towards removing SkShader::setLocalMatrix, which will make
SkShader thread-safe, remove calls to setLocalMatrix that happen immediately
after the shader is being created. Instead, pass the matrix into the constructor
or factory method.

BUG=skia:1976
R=scroggo@google.com, reed@google.com, skyostil@google.com, mtklein@google.com

Author: dominikg@chromium.org

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

git-svn-id: http://skia.googlecode.com/svn/trunk@14401 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/aarectmodes.cpp b/gm/aarectmodes.cpp
index a614761..f12ff8c 100644
--- a/gm/aarectmodes.cpp
+++ b/gm/aarectmodes.cpp
@@ -113,13 +113,13 @@
     *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = SkPackARGB32(0xFF, 0xCC,
                                                              0xCC, 0xCC);
 
-    SkShader* s = SkShader::CreateBitmapShader(bm,
-                                               SkShader::kRepeat_TileMode,
-                                               SkShader::kRepeat_TileMode);
-
     SkMatrix m;
     m.setScale(SkIntToScalar(6), SkIntToScalar(6));
-    s->setLocalMatrix(m);
+    SkShader* s = SkShader::CreateBitmapShader(bm,
+                                               SkShader::kRepeat_TileMode,
+                                               SkShader::kRepeat_TileMode,
+                                               &m);
+
     return s;
 }
 
diff --git a/gm/bigmatrix.cpp b/gm/bigmatrix.cpp
index b663b2b..30de865 100644
--- a/gm/bigmatrix.cpp
+++ b/gm/bigmatrix.cpp
@@ -67,14 +67,14 @@
         pixels[3] = SkPackARGB32(0xFF, 0x00, 0x00, 0xFF);
         pt.set(30 * SK_Scalar1, 30 * SK_Scalar1);
         m.mapPoints(&pt, 1);
-        SkShader* shader = SkShader::CreateBitmapShader(
-                                            bmp,
-                                            SkShader::kRepeat_TileMode,
-                                            SkShader::kRepeat_TileMode);
         SkMatrix s;
         s.reset();
         s.setScale(SK_Scalar1 / 1000, SK_Scalar1 / 1000);
-        shader->setLocalMatrix(s);
+        SkShader* shader = SkShader::CreateBitmapShader(
+                                            bmp,
+                                            SkShader::kRepeat_TileMode,
+                                            SkShader::kRepeat_TileMode,
+                                            &s);
         paint.setShader(shader)->unref();
         paint.setAntiAlias(false);
         paint.setFilterLevel(SkPaint::kLow_FilterLevel);
diff --git a/gm/bitmapshader.cpp b/gm/bitmapshader.cpp
index acb2ecb..8085f5c 100644
--- a/gm/bitmapshader.cpp
+++ b/gm/bitmapshader.cpp
@@ -35,8 +35,7 @@
     canvas.drawCircle(10, 10, 10, circlePaint);
 }
 
-static void adopt_shader(SkPaint* paint, SkShader* shader, SkMatrix s) {
-    shader->setLocalMatrix(s);
+static void adopt_shader(SkPaint* paint, SkShader* shader) {
     paint->setShader(shader);
     SkSafeUnref(shader);
 }
@@ -72,7 +71,7 @@
 
             canvas->save();
             adopt_shader(&paint, SkShader::CreateBitmapShader(fBitmap, SkShader::kClamp_TileMode,
-                                                              SkShader::kClamp_TileMode), s);
+                                                              SkShader::kClamp_TileMode, &s));
 
             // draw the shader with a bitmap mask
             canvas->drawBitmap(fMask, 0, 0, &paint);
@@ -94,7 +93,7 @@
             canvas->translate(0, 25);
 
             adopt_shader(&paint, SkShader::CreateBitmapShader(fMask, SkShader::kRepeat_TileMode,
-                                                              SkShader::kRepeat_TileMode), s);
+                                                              SkShader::kRepeat_TileMode, &s));
             paint.setColor(SK_ColorRED);
 
             // draw the mask using the shader and a color
diff --git a/gm/clippedbitmapshaders.cpp b/gm/clippedbitmapshaders.cpp
index 72c0474..ee20847 100644
--- a/gm/clippedbitmapshaders.cpp
+++ b/gm/clippedbitmapshaders.cpp
@@ -78,15 +78,14 @@
 
     virtual void onDraw(SkCanvas* canvas) {
         SkBitmap bmp = create_bitmap();
-        SkShader* shader = SkShader::CreateBitmapShader(
-                bmp, fMode, fMode);
-
-        SkPaint paint;
         SkMatrix s;
         s.reset();
         s.setScale(8, 8);
         s.postTranslate(SLIDE_SIZE / 2, SLIDE_SIZE / 2);
-        shader->setLocalMatrix(s);
+        SkShader* shader = SkShader::CreateBitmapShader(
+                bmp, fMode, fMode, &s);
+
+        SkPaint paint;
         paint.setShader(shader)->unref();
 
         if (fHQ) {
diff --git a/gm/colortype.cpp b/gm/colortype.cpp
index a42c008..47bc8a9 100644
--- a/gm/colortype.cpp
+++ b/gm/colortype.cpp
@@ -17,11 +17,10 @@
             SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
             SK_ColorMAGENTA, SK_ColorCYAN, SK_ColorYELLOW
         };
-        SkShader* s = SkGradientShader::CreateSweep(0,0, colors, NULL,
-                                                    SK_ARRAY_COUNT(colors));
         SkMatrix local;
         local.setRotate(180);
-        s->setLocalMatrix(local);
+        SkShader* s = SkGradientShader::CreateSweep(0,0, colors, NULL,
+                                                    SK_ARRAY_COUNT(colors), NULL, 0, &local);
 
         SkPaint paint;
         paint.setAntiAlias(true);
diff --git a/gm/convexpolyclip.cpp b/gm/convexpolyclip.cpp
index a8037aa..ed67434 100644
--- a/gm/convexpolyclip.cpp
+++ b/gm/convexpolyclip.cpp
@@ -38,15 +38,15 @@
                          SK_Scalar1};
 
     SkPaint paint;
-    paint.setShader(SkGradientShader::CreateRadial(
-                    pt, radius,
-                    colors, pos,
-                    SK_ARRAY_COUNT(colors),
-                    SkShader::kRepeat_TileMode))->unref();
     SkRect rect = SkRect::MakeWH(wScalar, hScalar);
     SkMatrix mat = SkMatrix::I();
     for (int i = 0; i < 4; ++i) {
-        paint.getShader()->setLocalMatrix(mat);
+        paint.setShader(SkGradientShader::CreateRadial(
+                        pt, radius,
+                        colors, pos,
+                        SK_ARRAY_COUNT(colors),
+                        SkShader::kRepeat_TileMode,
+                        NULL, 0, &mat))->unref();
         canvas.drawRect(rect, paint);
         rect.inset(wScalar / 8, hScalar / 8);
         mat.preTranslate(6 * wScalar, 6 * hScalar);
diff --git a/gm/drawbitmaprect.cpp b/gm/drawbitmaprect.cpp
index 92e0c38..3cc9026 100644
--- a/gm/drawbitmaprect.cpp
+++ b/gm/drawbitmaprect.cpp
@@ -55,15 +55,15 @@
                          SK_Scalar1};
 
     SkPaint     paint;
-    paint.setShader(SkGradientShader::CreateRadial(
-                    pt, radius,
-                    colors, pos,
-                    SK_ARRAY_COUNT(colors),
-                    SkShader::kRepeat_TileMode))->unref();
     SkRect rect = SkRect::MakeWH(wScalar, hScalar);
     SkMatrix mat = SkMatrix::I();
     for (int i = 0; i < 4; ++i) {
-        paint.getShader()->setLocalMatrix(mat);
+        paint.setShader(SkGradientShader::CreateRadial(
+                        pt, radius,
+                        colors, pos,
+                        SK_ARRAY_COUNT(colors),
+                        SkShader::kRepeat_TileMode,
+                        NULL, 0, &mat))->unref();
         canvas.drawRect(rect, paint);
         rect.inset(wScalar / 8, hScalar / 8);
         mat.postScale(SK_Scalar1 / 4, SK_Scalar1 / 4);
diff --git a/gm/giantbitmap.cpp b/gm/giantbitmap.cpp
index c284809..ed4190a 100644
--- a/gm/giantbitmap.cpp
+++ b/gm/giantbitmap.cpp
@@ -95,7 +95,6 @@
 
     virtual void onDraw(SkCanvas* canvas) {
         SkPaint paint;
-        SkShader* s = SkShader::CreateBitmapShader(getBitmap(), fMode, fMode);
 
         SkMatrix m;
         if (fDoRotate) {
@@ -106,7 +105,7 @@
             SkScalar scale = 11*SK_Scalar1/12;
             m.setScale(scale, scale);
         }
-        s->setLocalMatrix(m);
+        SkShader* s = SkShader::CreateBitmapShader(getBitmap(), fMode, fMode, &m);
 
         paint.setShader(s)->unref();
         paint.setFilterLevel(fDoFilter ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel);
diff --git a/gm/gradient_matrix.cpp b/gm/gradient_matrix.cpp
index d1d0e42..b2bc5d1 100644
--- a/gm/gradient_matrix.cpp
+++ b/gm/gradient_matrix.cpp
@@ -61,21 +61,22 @@
 
 static const int IMAGES_X = 4;             // number of images per row
 
-static SkShader* make_linear_gradient(const SkPoint pts[2]) {
+static SkShader* make_linear_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) {
     return SkGradientShader::CreateLinear(pts, gColors, NULL, SK_ARRAY_COUNT(gColors),
-                                          SkShader::kClamp_TileMode, NULL);
+                                          SkShader::kClamp_TileMode, NULL, 0, &localMatrix);
 }
 
-static SkShader* make_radial_gradient(const SkPoint pts[2]) {
+static SkShader* make_radial_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) {
     SkPoint center;
     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
                SkScalarAve(pts[0].fY, pts[1].fY));
     float radius = (center - pts[0]).length();
     return SkGradientShader::CreateRadial(center, radius, gColors, NULL, SK_ARRAY_COUNT(gColors),
-                                          SkShader::kClamp_TileMode, NULL);
+                                          SkShader::kClamp_TileMode, NULL, 0, &localMatrix);
 }
 
-static void draw_gradients(SkCanvas* canvas, SkShader* (*makeShader)(const SkPoint[2]),
+static void draw_gradients(SkCanvas* canvas,
+                           SkShader* (*makeShader)(const SkPoint[2], const SkMatrix&),
                            const SkPoint ptsArray[][2], int numImages) {
     // Use some nice prime numbers for the rectangle and matrix with
     // different scaling along the x and y axes (which is the bug this
@@ -97,8 +98,7 @@
         }
 
         // Setup shader and draw.
-        SkAutoTUnref<SkShader> shader(makeShader(*ptsArray));
-        shader->setLocalMatrix(shaderMat);
+        SkAutoTUnref<SkShader> shader(makeShader(*ptsArray, shaderMat));
 
         SkPaint paint;
         paint.setShader(shader);
diff --git a/gm/gradients.cpp b/gm/gradients.cpp
index d4617bc..5f84d9f 100644
--- a/gm/gradients.cpp
+++ b/gm/gradients.cpp
@@ -40,31 +40,35 @@
 };
 
 static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
-                            SkShader::TileMode tm, SkUnitMapper* mapper) {
+                            SkShader::TileMode tm, SkUnitMapper* mapper,
+                            const SkMatrix& localMatrix) {
     return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
-                                          data.fCount, tm, mapper);
+                                          data.fCount, tm, mapper, 0, &localMatrix);
 }
 
 static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
-                            SkShader::TileMode tm, SkUnitMapper* mapper) {
+                            SkShader::TileMode tm, SkUnitMapper* mapper,
+                            const SkMatrix& localMatrix) {
     SkPoint center;
     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
                SkScalarAve(pts[0].fY, pts[1].fY));
     return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
-                                          data.fPos, data.fCount, tm, mapper);
+                                          data.fPos, data.fCount, tm, mapper, 0, &localMatrix);
 }
 
 static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
-                           SkShader::TileMode, SkUnitMapper* mapper) {
+                           SkShader::TileMode, SkUnitMapper* mapper,
+                           const SkMatrix& localMatrix) {
     SkPoint center;
     center.set(SkScalarAve(pts[0].fX, pts[1].fX),
                SkScalarAve(pts[0].fY, pts[1].fY));
     return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
-                                         data.fPos, data.fCount, mapper);
+                                         data.fPos, data.fCount, mapper, 0, &localMatrix);
 }
 
 static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                 SkScalarAve(pts[0].fY, pts[1].fY));
@@ -73,11 +77,13 @@
     return SkGradientShader::CreateTwoPointRadial(
                                                   center1, (pts[1].fX - pts[0].fX) / 7,
                                                   center0, (pts[1].fX - pts[0].fX) / 2,
-                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
+                                                  data.fColors, data.fPos, data.fCount, tm, mapper,
+                                                  0, &localMatrix);
 }
 
 static SkShader* Make2Conical(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -86,11 +92,13 @@
     return SkGradientShader::CreateTwoPointConical(center1, radius1,
                                                    center0, radius0,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
-                               SkShader::TileMode tm, SkUnitMapper* mapper);
+                               SkShader::TileMode tm, SkUnitMapper* mapper,
+                               const SkMatrix& localMatrix);
 static const GradMaker gGradMakers[] = {
     MakeLinear, MakeRadial, MakeSweep, Make2Radial, Make2Conical
 };
@@ -125,15 +133,15 @@
         for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
             canvas->save();
             for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
-                SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
+                SkMatrix scale = SkMatrix::I();
 
                 if (i == 5) { // if the clamp case
-                    SkMatrix scale;
                     scale.setScale(0.5f, 0.5f);
                     scale.postTranslate(25.f, 25.f);
-                    shader->setLocalMatrix(scale);
                 }
 
+                SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL, scale);
+
                 paint.setShader(shader);
                 canvas->drawRect(r, paint);
                 shader->unref();
@@ -178,8 +186,6 @@
         for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
             canvas->save();
             for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
-                SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
-
                 // apply an increasing y perspective as we move to the right
                 SkMatrix perspective;
                 perspective.setIdentity();
@@ -188,7 +194,7 @@
                 perspective.setSkewX(SkScalarDiv(SkIntToScalar((unsigned) i+1),
                                      SkIntToScalar(10)));
 
-                shader->setLocalMatrix(perspective);
+                SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL, perspective);
 
                 paint.setShader(shader);
                 canvas->drawRect(r, paint);
diff --git a/gm/gradients_2pt_conical.cpp b/gm/gradients_2pt_conical.cpp
index 93bddb2..7f0467e 100644
--- a/gm/gradients_2pt_conical.cpp
+++ b/gm/gradients_2pt_conical.cpp
@@ -38,7 +38,8 @@
 };
 
 static SkShader* Make2ConicalOutside(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -47,11 +48,13 @@
     return SkGradientShader::CreateTwoPointConical(center0, radius0,
                                                    center1, radius1,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalOutsideFlip(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10);
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -60,89 +63,97 @@
     return SkGradientShader::CreateTwoPointConical(center1, radius1,
                                                    center0, radius0,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalInside(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                 SkScalarAve(pts[0].fY, pts[1].fY));
     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
-    return SkGradientShader::CreateTwoPointConical(
-                                                  center1, (pts[1].fX - pts[0].fX) / 7,
-                                                  center0, (pts[1].fX - pts[0].fX) / 2,
-                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
+    return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
+                                                   center0, (pts[1].fX - pts[0].fX) / 2,
+                                                   data.fColors, data.fPos, data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalInsideFlip(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                 SkScalarAve(pts[0].fY, pts[1].fY));
     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
-    return SkGradientShader::CreateTwoPointConical(
-                                                  center0, (pts[1].fX - pts[0].fX) / 2,
-                                                  center1, (pts[1].fX - pts[0].fX) / 7,
-                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
+    return SkGradientShader::CreateTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 2,
+                                                   center1, (pts[1].fX - pts[0].fX) / 7,
+                                                   data.fColors, data.fPos, data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalInsideCenter(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                 SkScalarAve(pts[0].fY, pts[1].fY));
     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
-    return SkGradientShader::CreateTwoPointConical(
-                                                  center0, (pts[1].fX - pts[0].fX) / 7,
-                                                  center0, (pts[1].fX - pts[0].fX) / 2,
-                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
+    return SkGradientShader::CreateTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 7,
+                                                   center0, (pts[1].fX - pts[0].fX) / 2,
+                                                   data.fColors, data.fPos, data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalZeroRad(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                 SkScalarAve(pts[0].fY, pts[1].fY));
     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
-    return SkGradientShader::CreateTwoPointConical(
-                                                  center1, 0.f,
-                                                  center0, (pts[1].fX - pts[0].fX) / 2,
-                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
+    return SkGradientShader::CreateTwoPointConical(center1, 0.f,
+                                                   center0, (pts[1].fX - pts[0].fX) / 2,
+                                                   data.fColors, data.fPos, data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalZeroRadFlip(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                 SkScalarAve(pts[0].fY, pts[1].fY));
     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
-    return SkGradientShader::CreateTwoPointConical(
-                                                  center1, (pts[1].fX - pts[0].fX) / 2,
-                                                  center0, 0.f,
-                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
+    return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 2,
+                                                   center0, 0.f,
+                                                   data.fColors, data.fPos, data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalZeroRadCenter(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                 SkScalarAve(pts[0].fY, pts[1].fY));
     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
-    return SkGradientShader::CreateTwoPointConical(
-                                                  center0, 0.f,
-                                                  center0, (pts[1].fX - pts[0].fX) / 2,
-                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
+    return SkGradientShader::CreateTwoPointConical(center0, 0.f,
+                                                   center0, (pts[1].fX - pts[0].fX) / 2,
+                                                   data.fColors, data.fPos, data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalZeroRadOutside(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = 0.f;
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -151,11 +162,13 @@
     return SkGradientShader::CreateTwoPointConical(center0, radius0,
                                                    center1, radius1,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalZeroRadFlipOutside(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = 0.f;
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -164,11 +177,13 @@
     return SkGradientShader::CreateTwoPointConical(center1, radius1,
                                                    center0, radius0,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalEdgeX(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 7);
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -178,11 +193,13 @@
     return SkGradientShader::CreateTwoPointConical(center0, radius0,
                                                    center1, radius1,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalEdgeY(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 7);
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -192,10 +209,12 @@
     return SkGradientShader::CreateTwoPointConical(center0, radius0,
                                                    center1, radius1,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 static SkShader* Make2ConicalZeroRadEdgeX(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = 0.f;
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -205,11 +224,13 @@
     return SkGradientShader::CreateTwoPointConical(center0, radius0,
                                                    center1, radius1,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalZeroRadEdgeY(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = 0.f;
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -219,11 +240,13 @@
     return SkGradientShader::CreateTwoPointConical(center0, radius0,
                                                    center1, radius1,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalTouchX(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 7);
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -233,11 +256,13 @@
     return SkGradientShader::CreateTwoPointConical(center0, radius0,
                                                    center1, radius1,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalTouchY(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 7);
     SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3);
@@ -247,24 +272,27 @@
     return SkGradientShader::CreateTwoPointConical(center0, radius0,
                                                    center1, radius1,
                                                    data.fColors, data.fPos,
-                                                   data.fCount, tm, mapper);
+                                                   data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 static SkShader* Make2ConicalInsideSmallRad(const SkPoint pts[2], const GradData& data,
-                             SkShader::TileMode tm, SkUnitMapper* mapper) {
+                             SkShader::TileMode tm, SkUnitMapper* mapper,
+                             const SkMatrix& localMatrix) {
     SkPoint center0, center1;
     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                 SkScalarAve(pts[0].fY, pts[1].fY));
     center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
-    return SkGradientShader::CreateTwoPointConical(
-                                                  center0, 0.0000000000000000001f,
-                                                  center0, (pts[1].fX - pts[0].fX) / 2,
-                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
+    return SkGradientShader::CreateTwoPointConical(center0, 0.0000000000000000001f,
+                                                   center0, (pts[1].fX - pts[0].fX) / 2,
+                                                   data.fColors, data.fPos, data.fCount, tm, mapper,
+                                                   0, &localMatrix);
 }
 
 typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
-                               SkShader::TileMode tm, SkUnitMapper* mapper);
+                               SkShader::TileMode tm, SkUnitMapper* mapper,
+                               const SkMatrix& localMatrix);
 
 static const GradMaker gGradMakersOutside[] = {
     Make2ConicalOutside, Make2ConicalOutsideFlip,
@@ -336,15 +364,14 @@
         for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
             canvas->save();
             for (int j = 0; j < count; j++) {
-                SkShader* shader = gradMaker[j](pts, gGradData[i], tm, NULL);
+                SkMatrix scale = SkMatrix::I();
 
                 if (i == 3) { // if the clamp case
-                    SkMatrix scale;
                     scale.setScale(0.5f, 0.5f);
                     scale.postTranslate(25.f, 25.f);
-                    shader->setLocalMatrix(scale);
                 }
 
+                SkShader* shader = gradMaker[j](pts, gGradData[i], tm, NULL, scale);
                 paint.setShader(shader);
                 canvas->drawRect(r, paint);
                 shader->unref();
diff --git a/gm/hairmodes.cpp b/gm/hairmodes.cpp
index 4aa999d..783c225 100644
--- a/gm/hairmodes.cpp
+++ b/gm/hairmodes.cpp
@@ -64,14 +64,12 @@
     *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
     *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = SkPackARGB32(0xFF, 0xCC, 0xCC, 0xCC);
 
-    SkShader* s = SkShader::CreateBitmapShader(bm,
-                                               SkShader::kRepeat_TileMode,
-                                               SkShader::kRepeat_TileMode);
-
     SkMatrix m;
     m.setScale(SkIntToScalar(6), SkIntToScalar(6));
-    s->setLocalMatrix(m);
-    return s;
+    return SkShader::CreateBitmapShader(bm,
+                                        SkShader::kRepeat_TileMode,
+                                        SkShader::kRepeat_TileMode,
+                                        &m);
 }
 
 namespace skiagm {
diff --git a/gm/mixedxfermodes.cpp b/gm/mixedxfermodes.cpp
index 4562325..f2d7fa3 100644
--- a/gm/mixedxfermodes.cpp
+++ b/gm/mixedxfermodes.cpp
@@ -86,13 +86,13 @@
             SkBitmap bitmap;
             bitmap.allocN32Pixels(2, 2);
             memcpy(bitmap.getPixels(), kCheckerPixelData, sizeof(kCheckerPixelData));
+            SkMatrix lm;
+            lm.setScale(SkIntToScalar(20), SkIntToScalar(20));
             fBG.reset(SkShader::CreateBitmapShader(bitmap,
                                                    SkShader::kRepeat_TileMode,
-                                                   SkShader::kRepeat_TileMode));
+                                                   SkShader::kRepeat_TileMode,
+                                                   &lm));
         }
-        SkMatrix lm;
-        lm.setScale(SkIntToScalar(20), SkIntToScalar(20));
-        fBG->setLocalMatrix(lm);
 
         SkPaint bgPaint;
         bgPaint.setShader(fBG.get());
diff --git a/gm/shaderbounds.cpp b/gm/shaderbounds.cpp
index ef9a7e9..2a52ead 100644
--- a/gm/shaderbounds.cpp
+++ b/gm/shaderbounds.cpp
@@ -9,7 +9,8 @@
 
 namespace skiagm {
 
-static SkShader* MakeLinear(SkScalar width, SkScalar height, bool alternate) {
+static SkShader* MakeLinear(SkScalar width, SkScalar height, bool alternate,
+                            const SkMatrix& localMatrix) {
   SkPoint pts[2] = { {0, 0}, {width, height}};
   SkColor colors[2] = {SK_ColorRED, SK_ColorGREEN};
   if (alternate) {
@@ -18,7 +19,7 @@
     colors[1] = SK_ColorYELLOW;
   }
   return SkGradientShader::CreateLinear(pts, colors, NULL, 2,
-                                        SkShader::kClamp_TileMode, NULL);
+                                        SkShader::kClamp_TileMode, NULL, 0, &localMatrix);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -26,7 +27,7 @@
 class ShaderBoundsGM : public GM {
 public:
     typedef SkShader* (*ShaderGenFunc)(SkScalar width, SkScalar height,
-                                       bool alternate);
+                                       bool alternate, const SkMatrix& localMatrix);
     ShaderBoundsGM(ShaderGenFunc maker, const SkString& name)
         : fShaderMaker(maker),
           fName(name) {
@@ -80,10 +81,9 @@
         }
         SkScalar shaderWidth = SkScalarDiv(SkIntToScalar(width), scale);
         SkScalar shaderHeight = SkScalarDiv(SkIntToScalar(height), scale);
-        SkShader* shader = fShaderMaker(shaderWidth, shaderHeight, background);
         SkMatrix shaderScale;
         shaderScale.setScale(scale, scale);
-        shader->setLocalMatrix(shaderScale);
+        SkShader* shader = fShaderMaker(shaderWidth, shaderHeight, background, shaderScale);
         return shader;
     }
 
diff --git a/gm/shadertext2.cpp b/gm/shadertext2.cpp
index f839161..e580d91 100644
--- a/gm/shadertext2.cpp
+++ b/gm/shadertext2.cpp
@@ -95,14 +95,10 @@
             makebm(&bmp, kPointSize / 2, kPointSize / 2);
         }
 
-        SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(bmp,
-                                                                   SkShader::kMirror_TileMode,
-                                                                   SkShader::kRepeat_TileMode));
         SkPaint fillPaint;
         fillPaint.setAntiAlias(true);
         fillPaint.setTextSize(SkIntToScalar(kPointSize));
         fillPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
-        fillPaint.setShader(shader);
 
         SkPaint outlinePaint;
         outlinePaint.setAntiAlias(true);
@@ -158,7 +154,10 @@
                 canvas->translate(0, kPadY / 2 + kPointSize);
                 columnH += kPadY / 2 + kPointSize;
                 for (int lm = 0; lm < localMatrices.count(); ++lm) {
-                    shader->setLocalMatrix(localMatrices[lm].fMatrix);
+                    paint.setShader(SkShader::CreateBitmapShader(bmp,
+                                                                 SkShader::kMirror_TileMode,
+                                                                 SkShader::kRepeat_TileMode,
+                                                                 &localMatrices[lm].fMatrix));
 
                     canvas->save();
                         canvas->concat(matrices[m].fMatrix);
diff --git a/gm/shadertext3.cpp b/gm/shadertext3.cpp
index a1c2d60..6ae3159 100644
--- a/gm/shadertext3.cpp
+++ b/gm/shadertext3.cpp
@@ -100,14 +100,15 @@
         int i = 0;
         for (size_t tm0 = 0; tm0 < SK_ARRAY_COUNT(kTileModes); ++tm0) {
             for (size_t tm1 = 0; tm1 < SK_ARRAY_COUNT(kTileModes); ++tm1) {
-                SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(fBmp,
-                                                                           kTileModes[tm0],
-                                                                           kTileModes[tm1]));
                 SkMatrix localM;
                 localM.setTranslate(5.f, 5.f);
                 localM.postRotate(20);
                 localM.postScale(1.15f, .85f);
-                shader->setLocalMatrix(localM);
+
+                SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(fBmp,
+                                                                           kTileModes[tm0],
+                                                                           kTileModes[tm1],
+                                                                           &localM));
 
                 SkPaint fillPaint;
                 fillPaint.setAntiAlias(true);
diff --git a/gm/xfermodes.cpp b/gm/xfermodes.cpp
index 24c48ee..16d6cbb 100644
--- a/gm/xfermodes.cpp
+++ b/gm/xfermodes.cpp
@@ -216,12 +216,12 @@
 
         const SkScalar w = SkIntToScalar(W);
         const SkScalar h = SkIntToScalar(H);
-        SkShader* s = SkShader::CreateBitmapShader(fBG,
-                                                   SkShader::kRepeat_TileMode,
-                                                   SkShader::kRepeat_TileMode);
         SkMatrix m;
         m.setScale(SkIntToScalar(6), SkIntToScalar(6));
-        s->setLocalMatrix(m);
+        SkShader* s = SkShader::CreateBitmapShader(fBG,
+                                                   SkShader::kRepeat_TileMode,
+                                                   SkShader::kRepeat_TileMode,
+                                                   &m);
 
         SkPaint labelP;
         labelP.setAntiAlias(true);
diff --git a/gm/xfermodes2.cpp b/gm/xfermodes2.cpp
index 1af59d2..2ccabc6 100644
--- a/gm/xfermodes2.cpp
+++ b/gm/xfermodes2.cpp
@@ -96,12 +96,12 @@
         bg.allocN32Pixels(2, 2, true);
         memcpy(bg.getPixels(), kCheckData, sizeof(kCheckData));
 
-        fBG.reset(SkShader::CreateBitmapShader(bg,
-                                               SkShader::kRepeat_TileMode,
-                                               SkShader::kRepeat_TileMode));
         SkMatrix lm;
         lm.setScale(SkIntToScalar(16), SkIntToScalar(16));
-        fBG->setLocalMatrix(lm);
+        fBG.reset(SkShader::CreateBitmapShader(bg,
+                                               SkShader::kRepeat_TileMode,
+                                               SkShader::kRepeat_TileMode,
+                                               &lm));
 
         SkBitmap dstBmp;
         dstBmp.allocN32Pixels(kSize, kSize);
diff --git a/gm/xfermodes3.cpp b/gm/xfermodes3.cpp
index 1863a3e..d5790d5 100644
--- a/gm/xfermodes3.cpp
+++ b/gm/xfermodes3.cpp
@@ -195,12 +195,12 @@
         SkAutoLockPixels bgAlp(bg);
         memcpy(bg.getPixels(), kCheckData, sizeof(kCheckData));
 
-        fBGShader.reset(SkShader::CreateBitmapShader(bg,
-                                                     SkShader::kRepeat_TileMode,
-                                                     SkShader::kRepeat_TileMode));
         SkMatrix lm;
         lm.setScale(SkIntToScalar(kCheckSize), SkIntToScalar(kCheckSize));
-        fBGShader->setLocalMatrix(lm);
+        fBGShader.reset(SkShader::CreateBitmapShader(bg,
+                                                     SkShader::kRepeat_TileMode,
+                                                     SkShader::kRepeat_TileMode,
+                                                     &lm));
 
         SkPaint bmpPaint;
         static const SkPoint kCenter = { SkIntToScalar(kSize) / 2, SkIntToScalar(kSize) / 2 };
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index cc2cc75..4af8f78 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -34,7 +34,7 @@
 public:
     SK_DECLARE_INST_COUNT(SkShader)
 
-    SkShader();
+    SkShader(const SkMatrix* localMatrix = NULL);
     virtual ~SkShader();
 
     /**
@@ -371,7 +371,8 @@
      *  @return     Returns a new shader object. Note: this function never returns null.
     */
     static SkShader* CreateBitmapShader(const SkBitmap& src,
-                                        TileMode tmx, TileMode tmy);
+                                        TileMode tmx, TileMode tmy,
+                                        const SkMatrix* localMatrix = NULL);
 
     /** Call this to create a new shader that will draw with the specified picture.
      *
diff --git a/include/effects/SkGradientShader.h b/include/effects/SkGradientShader.h
index ed0f1bf..871b34a 100644
--- a/include/effects/SkGradientShader.h
+++ b/include/effects/SkGradientShader.h
@@ -49,7 +49,8 @@
                                   const SkColor colors[], const SkScalar pos[], int count,
                                   SkShader::TileMode mode,
                                   SkUnitMapper* mapper = NULL,
-                                  uint32_t flags = 0);
+                                  uint32_t flags = 0,
+                                  const SkMatrix* localMatrix = NULL);
 
     /** Returns a shader that generates a radial gradient given the center and radius.
         <p />
@@ -72,7 +73,8 @@
                                   const SkColor colors[], const SkScalar pos[], int count,
                                   SkShader::TileMode mode,
                                   SkUnitMapper* mapper = NULL,
-                                  uint32_t flags = 0);
+                                  uint32_t flags = 0,
+                                  const SkMatrix* localMatrix = NULL);
 
     /** Returns a shader that generates a radial gradient given the start position, start radius, end position and end radius.
         <p />
@@ -102,7 +104,8 @@
                                           const SkScalar pos[], int count,
                                           SkShader::TileMode mode,
                                           SkUnitMapper* mapper = NULL,
-                                          uint32_t flags = 0);
+                                          uint32_t flags = 0,
+                                          const SkMatrix* localMatrix = NULL);
 
     /**
      *  Returns a shader that generates a conical gradient given two circles, or
@@ -118,7 +121,8 @@
                                            const SkScalar pos[], int count,
                                            SkShader::TileMode mode,
                                            SkUnitMapper* mapper = NULL,
-                                           uint32_t flags = 0);
+                                           uint32_t flags = 0,
+                                           const SkMatrix* localMatrix = NULL);
 
     /** Returns a shader that generates a sweep gradient given a center.
         <p />
@@ -139,7 +143,8 @@
     static SkShader* CreateSweep(SkScalar cx, SkScalar cy,
                                  const SkColor colors[], const SkScalar pos[],
                                  int count, SkUnitMapper* mapper = NULL,
-                                 uint32_t flags = 0);
+                                 uint32_t flags = 0,
+                                 const SkMatrix* localMatrix = NULL);
 
     SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
 };
diff --git a/samplecode/SampleAARectModes.cpp b/samplecode/SampleAARectModes.cpp
index bea0e28..f9972ae 100644
--- a/samplecode/SampleAARectModes.cpp
+++ b/samplecode/SampleAARectModes.cpp
@@ -68,14 +68,13 @@
     *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = SkPackARGB32(0xFF, 0xCC,
                                                              0xCC, 0xCC);
 
-    SkShader* s = SkShader::CreateBitmapShader(bm,
-                                               SkShader::kRepeat_TileMode,
-                                               SkShader::kRepeat_TileMode);
-
     SkMatrix m;
     m.setScale(SkIntToScalar(6), SkIntToScalar(6));
-    s->setLocalMatrix(m);
-    return s;
+
+    return SkShader::CreateBitmapShader(bm,
+                                        SkShader::kRepeat_TileMode,
+                                        SkShader::kRepeat_TileMode,
+                                        &m);
 }
 
 class AARectsModesView : public SampleView {
diff --git a/samplecode/SampleCamera.cpp b/samplecode/SampleCamera.cpp
index c700ee4..7660129 100644
--- a/samplecode/SampleCamera.cpp
+++ b/samplecode/SampleCamera.cpp
@@ -33,15 +33,15 @@
             str.printf("/skimages/elephant%d.jpeg", i);
             SkBitmap bm;
             if (SkImageDecoder::DecodeFile(str.c_str(), &bm)) {
-                SkShader* s = SkShader::CreateBitmapShader(bm,
-                                                           SkShader::kClamp_TileMode,
-                                                           SkShader::kClamp_TileMode);
-
                 SkRect src = { 0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()) };
                 SkRect dst = { -150, -150, 150, 150 };
                 SkMatrix matrix;
                 matrix.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
-                s->setLocalMatrix(matrix);
+
+                SkShader* s = SkShader::CreateBitmapShader(bm,
+                                                           SkShader::kClamp_TileMode,
+                                                           SkShader::kClamp_TileMode,
+                                                           &matrix);
                 *fShaders.append() = s;
             } else {
                 break;
diff --git a/samplecode/SampleColorFilter.cpp b/samplecode/SampleColorFilter.cpp
index 2dc2e42..fb5d427 100644
--- a/samplecode/SampleColorFilter.cpp
+++ b/samplecode/SampleColorFilter.cpp
@@ -92,13 +92,10 @@
     bm.lockPixels();
     *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = SkPreMultiplyColor(0xFFFFFFFF);
     *bm.getAddr32(0, 1) = *bm.getAddr32(1, 0) = SkPreMultiplyColor(0xFFCCCCCC);
-    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
-                                               SkShader::kRepeat_TileMode);
-
     SkMatrix m;
     m.setScale(12, 12);
-    s->setLocalMatrix(m);
-    return s;
+    return SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
+                                        SkShader::kRepeat_TileMode, &m);
 }
 
 static SkBitmap createBitmap(int n) {
diff --git a/samplecode/SampleDash.cpp b/samplecode/SampleDash.cpp
index 26d3694..e4fa79d 100644
--- a/samplecode/SampleDash.cpp
+++ b/samplecode/SampleDash.cpp
@@ -28,8 +28,7 @@
     matrix.setScale(SkIntToScalar(width), SK_Scalar1);
 
     SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
-                                               SkShader::kClamp_TileMode);
-    s->setLocalMatrix(matrix);
+                                               SkShader::kClamp_TileMode, &matrix);
 
     paint->setShader(s)->unref();
 }
diff --git a/samplecode/SampleFatBits.cpp b/samplecode/SampleFatBits.cpp
index 6900fae..9ea1d9e 100644
--- a/samplecode/SampleFatBits.cpp
+++ b/samplecode/SampleFatBits.cpp
@@ -43,13 +43,10 @@
     bm.lockPixels();
     *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = SkPreMultiplyColor(colors[0]);
     *bm.getAddr32(0, 1) = *bm.getAddr32(1, 0) = SkPreMultiplyColor(colors[1]);
-    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
-                                               SkShader::kRepeat_TileMode);
-
     SkMatrix m;
     m.setScale(12, 12);
-    s->setLocalMatrix(m);
-    return s;
+    return SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
+                                        SkShader::kRepeat_TileMode, &m);
 }
 
 class FatBits {
diff --git a/samplecode/SampleHairModes.cpp b/samplecode/SampleHairModes.cpp
index 4aa8e02..8788577 100644
--- a/samplecode/SampleHairModes.cpp
+++ b/samplecode/SampleHairModes.cpp
@@ -66,14 +66,13 @@
     *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
     *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = SkPackARGB32(0xFF, 0xCC, 0xCC, 0xCC);
 
-    SkShader* s = SkShader::CreateBitmapShader(bm,
-                                               SkShader::kRepeat_TileMode,
-                                               SkShader::kRepeat_TileMode);
-
     SkMatrix m;
     m.setScale(SkIntToScalar(6), SkIntToScalar(6));
-    s->setLocalMatrix(m);
-    return s;
+
+    return SkShader::CreateBitmapShader(bm,
+                                        SkShader::kRepeat_TileMode,
+                                        SkShader::kRepeat_TileMode,
+                                        &m);
 }
 
 class HairModesView : public SampleView {
diff --git a/samplecode/SampleLayers.cpp b/samplecode/SampleLayers.cpp
index 3ae5439..51f02a1 100644
--- a/samplecode/SampleLayers.cpp
+++ b/samplecode/SampleLayers.cpp
@@ -27,10 +27,11 @@
 #include "SkXfermode.h"
 #include "SkDrawFilter.h"
 
-static void make_paint(SkPaint* paint) {
+static void make_paint(SkPaint* paint, const SkMatrix& localMatrix) {
     SkColor colors[] = { 0, SK_ColorWHITE };
     SkPoint pts[] = { { 0, 0 }, { 0, SK_Scalar1*20 } };
-    SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
+    SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode,
+                                                 NULL, 0, &localMatrix);
 
     paint->setShader(s)->unref();
     paint->setXfermodeMode(SkXfermode::kDstIn_Mode);
@@ -104,19 +105,16 @@
     dump_layers("outside layer alpha", canvas);
 
     // now apply an effect
+    SkMatrix m;
+    m.setScale(SK_Scalar1, -SK_Scalar1);
+    m.postTranslate(0, SkIntToScalar(100));
 
     SkPaint paint;
-    make_paint(&paint);
+    make_paint(&paint, m);
     r.set(0, 0, SkIntToScalar(100), SkIntToScalar(20));
 //    SkDebugf("--------- draw top grad\n");
     canvas->drawRect(r, paint);
 
-    SkMatrix m;
-    SkShader* s = paint.getShader();
-    m.setScale(SK_Scalar1, -SK_Scalar1);
-    m.postTranslate(0, SkIntToScalar(100));
-    s->setLocalMatrix(m);
-
     r.fTop = SkIntToScalar(80);
     r.fBottom = SkIntToScalar(100);
 //    SkDebugf("--------- draw bot grad\n");
diff --git a/samplecode/SampleXfermodesBlur.cpp b/samplecode/SampleXfermodesBlur.cpp
index ea9561d..de75d05 100644
--- a/samplecode/SampleXfermodesBlur.cpp
+++ b/samplecode/SampleXfermodesBlur.cpp
@@ -151,12 +151,12 @@
 
         const SkScalar w = SkIntToScalar(W);
         const SkScalar h = SkIntToScalar(H);
-        SkShader* s = SkShader::CreateBitmapShader(fBG,
-                                                   SkShader::kRepeat_TileMode,
-                                                   SkShader::kRepeat_TileMode);
         SkMatrix m;
         m.setScale(SkIntToScalar(6), SkIntToScalar(6));
-        s->setLocalMatrix(m);
+        SkShader* s = SkShader::CreateBitmapShader(fBG,
+                                                   SkShader::kRepeat_TileMode,
+                                                   SkShader::kRepeat_TileMode,
+                                                   &m);
 
         SkPaint labelP;
         labelP.setAntiAlias(true);
diff --git a/src/animator/SkDrawGradient.cpp b/src/animator/SkDrawGradient.cpp
index 1b158f2..c115595 100644
--- a/src/animator/SkDrawGradient.cpp
+++ b/src/animator/SkDrawGradient.cpp
@@ -175,9 +175,9 @@
     if (addPrelude() == 0 || points.count() != 4)
         return NULL;
     SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(),
-        fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
+        fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode,
+        fUnitMapper, 0, getMatrix());
     SkAutoTDelete<SkShader> autoDel(shader);
-    addPostlude(shader);
     (void)autoDel.detach();
     return shader;
 }
@@ -210,9 +210,9 @@
     if (addPrelude() == 0)
         return NULL;
     SkShader* shader = SkGradientShader::CreateRadial(center,
-        radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
+        radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode,
+        fUnitMapper, 0, getMatrix());
     SkAutoTDelete<SkShader> autoDel(shader);
-    addPostlude(shader);
     (void)autoDel.detach();
     return shader;
 }
diff --git a/src/animator/SkDrawShader.cpp b/src/animator/SkDrawShader.cpp
index e3aa4da..f9f379b 100644
--- a/src/animator/SkDrawShader.cpp
+++ b/src/animator/SkDrawShader.cpp
@@ -36,9 +36,8 @@
     return false;
 }
 
-void SkDrawShader::addPostlude(SkShader* shader) {
-    if (matrix)
-        shader->setLocalMatrix(matrix->getMatrix());
+SkMatrix* SkDrawShader::getMatrix() {
+    return matrix ? &matrix->getMatrix() : NULL;
 }
 
 #if SK_USE_CONDENSED_INFO == 0
@@ -75,9 +74,9 @@
     // draw-time from the paint
     SkShader* shader  = SkShader::CreateBitmapShader(image->fBitmap,
                                                     (SkShader::TileMode) tileMode,
-                                                    (SkShader::TileMode) tileMode);
+                                                    (SkShader::TileMode) tileMode,
+                                                    getMatrix());
     SkAutoTDelete<SkShader> autoDel(shader);
-    addPostlude(shader);
     (void)autoDel.detach();
     return shader;
 }
diff --git a/src/animator/SkPaintPart.h b/src/animator/SkPaintPart.h
index a6154e5..6f33cb4 100644
--- a/src/animator/SkPaintPart.h
+++ b/src/animator/SkPaintPart.h
@@ -51,7 +51,7 @@
     virtual SkShader* getShader();
 protected:
     virtual bool add();
-    void addPostlude(SkShader* shader);
+    SkMatrix* getMatrix(); // returns NULL if matrix is NULL
     SkDrawMatrix* matrix;
     int /*SkShader::TileMode*/ tileMode;
 };
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index c2b633e..311e72f 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -381,11 +381,11 @@
     // construct a shader, so we can call drawRect with the dst
     SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
                                                SkShader::kClamp_TileMode,
-                                               SkShader::kClamp_TileMode);
+                                               SkShader::kClamp_TileMode,
+                                               &matrix);
     if (NULL == s) {
         return;
     }
-    s->setLocalMatrix(matrix);
 
     SkPaint paintWithShader(paint);
     paintWithShader.setStyle(SkPaint::kFill_Style);
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 5f5eb18..44bdc6d 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -31,8 +31,9 @@
     return false;
 }
 
-SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
-                                       TileMode tmx, TileMode tmy) {
+SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
+                                       const SkMatrix* localMatrix)
+        : INHERITED(localMatrix) {
     fRawBitmap = src;
     fTileModeX = (uint8_t)tmx;
     fTileModeY = (uint8_t)tmy;
@@ -347,7 +348,7 @@
 }
 
 SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
-        SkShader::TileMode tmy, SkTBlitterAllocator* allocator) {
+        SkShader::TileMode tmy, const SkMatrix* localMatrix, SkTBlitterAllocator* allocator) {
     SkShader* shader;
     SkColor color;
     if (src.isNull() || bitmapIsTooBig(src)) {
@@ -365,9 +366,9 @@
         }
     } else {
         if (NULL == allocator) {
-            shader = SkNEW_ARGS(SkBitmapProcShader, (src, tmx, tmy));
+            shader = SkNEW_ARGS(SkBitmapProcShader, (src, tmx, tmy, localMatrix));
         } else {
-            shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy);
+            shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy, localMatrix);
         }
     }
     return shader;
diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h
index e0c78b8..78b46ce 100644
--- a/src/core/SkBitmapProcShader.h
+++ b/src/core/SkBitmapProcShader.h
@@ -16,7 +16,8 @@
 
 class SkBitmapProcShader : public SkShader {
 public:
-    SkBitmapProcShader(const SkBitmap& src, TileMode tx, TileMode ty);
+    SkBitmapProcShader(const SkBitmap& src, TileMode tx, TileMode ty,
+                       const SkMatrix* localMatrix = NULL);
 
     // overrides from SkShader
     virtual bool isOpaque() const SK_OVERRIDE;
@@ -91,6 +92,6 @@
 // If alloc is non-NULL, it will be used to allocate the returned SkShader, and MUST outlive
 // the SkShader.
 SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode, SkShader::TileMode,
-                             SkTBlitterAllocator* alloc);
+                             const SkMatrix* localMatrix, SkTBlitterAllocator* alloc);
 
 #endif
diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp
index 77bc46f..2c27c9e 100644
--- a/src/core/SkComposeShader.cpp
+++ b/src/core/SkComposeShader.cpp
@@ -30,11 +30,11 @@
     INHERITED(buffer) {
     fShaderA = buffer.readShader();
     if (NULL == fShaderA) {
-        fShaderA = SkNEW_ARGS(SkColorShader, (0));
+        fShaderA = SkNEW_ARGS(SkColorShader, ((SkColor)0));
     }
     fShaderB = buffer.readShader();
     if (NULL == fShaderB) {
-        fShaderB = SkNEW_ARGS(SkColorShader, (0));
+        fShaderB = SkNEW_ARGS(SkColorShader, ((SkColor)0));
     }
     fMode = buffer.readXfermode();
 }
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 6ddd0d2..f9e06e5 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -72,11 +72,12 @@
  */
 class SkAutoBitmapShaderInstall : SkNoncopyable {
 public:
-    SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint)
+    SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint,
+                              const SkMatrix* localMatrix = NULL)
             : fPaint(paint) /* makes a copy of the paint */ {
         fPaint.setShader(CreateBitmapShader(src, SkShader::kClamp_TileMode,
                                             SkShader::kClamp_TileMode,
-                                            &fAllocator));
+                                            localMatrix, &fAllocator));
         // we deliberately left the shader with an owner-count of 2
         SkASSERT(2 == fPaint.getShader()->getRefCnt());
     }
@@ -1374,18 +1375,16 @@
         }
     }
 
-    SkAutoBitmapShaderInstall install(bitmap, paint);
-    const SkPaint& shaderPaint = install.paintWithShader();
-
     SkMatrix        matrix;
     SkRect          r;
 
     // get a scalar version of our rect
     r.set(bounds);
 
-    // tell the shader our offset
+    // create shader with offset
     matrix.setTranslate(r.fLeft, r.fTop);
-    shaderPaint.getShader()->setLocalMatrix(matrix);
+    SkAutoBitmapShaderInstall install(bitmap, paint, &matrix);
+    const SkPaint& shaderPaint = install.paintWithShader();
 
     SkDraw draw(*this);
     matrix.reset();
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp
index dc5c90b..466c5e1 100644
--- a/src/core/SkPictureShader.cpp
+++ b/src/core/SkPictureShader.cpp
@@ -91,13 +91,12 @@
         canvas.scale(tileScale.width(), tileScale.height());
         canvas.drawPicture(*fPicture);
 
-        fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy));
         fCachedTileScale = tileScale;
         fCachedLocalMatrix = this->getLocalMatrix();
 
         SkMatrix shaderMatrix = this->getLocalMatrix();
         shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
-        fCachedBitmapShader->setLocalMatrix(shaderMatrix);
+        fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix));
     }
 
     // Increment the ref counter inside the mutex to ensure the returned pointer is still valid.
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index b49dae8..4ddd291 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -15,8 +15,12 @@
 #include "SkShader.h"
 #include "SkWriteBuffer.h"
 
-SkShader::SkShader() {
-    fLocalMatrix.reset();
+SkShader::SkShader(const SkMatrix* localMatrix) {
+    if (localMatrix) {
+        fLocalMatrix = *localMatrix;
+    } else {
+        fLocalMatrix.reset();
+    }
 }
 
 SkShader::SkShader(SkReadBuffer& buffer)
@@ -180,9 +184,9 @@
     return NULL;
 }
 
-SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
-                                       TileMode tmx, TileMode tmy) {
-    return ::CreateBitmapShader(src, tmx, tmy, NULL);
+SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
+                                       const SkMatrix* localMatrix) {
+    return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL);
 }
 
 SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy) {
@@ -252,11 +256,8 @@
                                                       const SkMatrix& matrix)
     : INHERITED(shader, device, paint, matrix)
 {
-    SkColor color;
-    unsigned a;
-
-    color = shader.fColor;
-    a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(paint.getAlpha()));
+    SkColor color = shader.fColor;
+    unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(paint.getAlpha()));
 
     unsigned r = SkColorGetR(color);
     unsigned g = SkColorGetG(color);
diff --git a/src/core/SkSmallAllocator.h b/src/core/SkSmallAllocator.h
index 8d4b53a..018705f 100644
--- a/src/core/SkSmallAllocator.h
+++ b/src/core/SkSmallAllocator.h
@@ -96,6 +96,16 @@
         return static_cast<T*>(buf);
     }
 
+    template<typename T, typename A1, typename A2, typename A3, typename A4>
+    T* createT(const A1& a1, const A2& a2, const A3& a3, const A4& a4) {
+        void* buf = this->reserveT<T>();
+        if (NULL == buf) {
+            return NULL;
+        }
+        SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2, a3, a4));
+        return static_cast<T*>(buf);
+    }
+
     /*
      *  Reserve a specified amount of space (must be enough space for one T).
      *  The space will be in fStorage if there is room, or on the heap otherwise.
diff --git a/src/effects/SkTileImageFilter.cpp b/src/effects/SkTileImageFilter.cpp
index 5496f30..f3bad76 100644
--- a/src/effects/SkTileImageFilter.cpp
+++ b/src/effects/SkTileImageFilter.cpp
@@ -60,12 +60,12 @@
     SkPaint paint;
     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
 
-    SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
-                                  SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
     SkMatrix shaderMatrix;
     shaderMatrix.setTranslate(SkIntToScalar(srcOffset.fX),
                               SkIntToScalar(srcOffset.fY));
-    shader->setLocalMatrix(shaderMatrix);
+    SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
+                                  SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
+                                  &shaderMatrix));
     paint.setShader(shader);
     canvas.translate(-dstRect.fLeft, -dstRect.fTop);
     canvas.drawRect(dstRect, paint);
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index f4bde67..6d753a9 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -12,7 +12,9 @@
 #include "SkTwoPointConicalGradient.h"
 #include "SkSweepGradient.h"
 
-SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) {
+SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatrix* localMatrix)
+    : INHERITED(localMatrix)
+{
     SkASSERT(desc.fCount > 1);
 
     fMapper = desc.fMapper;
@@ -784,7 +786,8 @@
                                          const SkScalar pos[], int colorCount,
                                          SkShader::TileMode mode,
                                          SkUnitMapper* mapper,
-                                         uint32_t flags) {
+                                         uint32_t flags,
+                                         const SkMatrix* localMatrix) {
     if (NULL == pts || NULL == colors || colorCount < 1) {
         return NULL;
     }
@@ -792,7 +795,7 @@
 
     SkGradientShaderBase::Descriptor desc;
     desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
-    return SkNEW_ARGS(SkLinearGradient, (pts, desc));
+    return SkNEW_ARGS(SkLinearGradient, (pts, desc, localMatrix));
 }
 
 SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius,
@@ -800,7 +803,8 @@
                                          const SkScalar pos[], int colorCount,
                                          SkShader::TileMode mode,
                                          SkUnitMapper* mapper,
-                                         uint32_t flags) {
+                                         uint32_t flags,
+                                         const SkMatrix* localMatrix) {
     if (radius <= 0 || NULL == colors || colorCount < 1) {
         return NULL;
     }
@@ -808,7 +812,7 @@
 
     SkGradientShaderBase::Descriptor desc;
     desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
-    return SkNEW_ARGS(SkRadialGradient, (center, radius, desc));
+    return SkNEW_ARGS(SkRadialGradient, (center, radius, desc, localMatrix));
 }
 
 SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start,
@@ -820,7 +824,8 @@
                                                  int colorCount,
                                                  SkShader::TileMode mode,
                                                  SkUnitMapper* mapper,
-                                                 uint32_t flags) {
+                                                 uint32_t flags,
+                                                 const SkMatrix* localMatrix) {
     if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
         return NULL;
     }
@@ -829,7 +834,7 @@
     SkGradientShaderBase::Descriptor desc;
     desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
     return SkNEW_ARGS(SkTwoPointRadialGradient,
-                      (start, startRadius, end, endRadius, desc));
+                      (start, startRadius, end, endRadius, desc, localMatrix));
 }
 
 SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start,
@@ -841,7 +846,8 @@
                                                   int colorCount,
                                                   SkShader::TileMode mode,
                                                   SkUnitMapper* mapper,
-                                                  uint32_t flags) {
+                                                  uint32_t flags,
+                                                  const SkMatrix* localMatrix) {
     if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
         return NULL;
     }
@@ -858,7 +864,7 @@
     if (!flipGradient) {
         desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
         return SkNEW_ARGS(SkTwoPointConicalGradient,
-                          (start, startRadius, end, endRadius, flipGradient, desc));
+                          (start, startRadius, end, endRadius, flipGradient, desc, localMatrix));
     } else {
         SkAutoSTArray<8, SkColor> colorsNew(colorCount);
         SkAutoSTArray<8, SkScalar> posNew(colorCount);
@@ -876,7 +882,7 @@
         }
 
         return SkNEW_ARGS(SkTwoPointConicalGradient,
-                          (end, endRadius, start, startRadius, flipGradient, desc));
+                          (end, endRadius, start, startRadius, flipGradient, desc, localMatrix));
     }
 }
 
@@ -884,7 +890,8 @@
                                         const SkColor colors[],
                                         const SkScalar pos[],
                                         int colorCount, SkUnitMapper* mapper,
-                                        uint32_t flags) {
+                                        uint32_t flags,
+                                        const SkMatrix* localMatrix) {
     if (NULL == colors || colorCount < 1) {
         return NULL;
     }
@@ -892,7 +899,7 @@
 
     SkGradientShaderBase::Descriptor desc;
     desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper, flags);
-    return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc));
+    return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc, localMatrix));
 }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader)
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index 5dec665..c1e253f 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -99,7 +99,7 @@
     };
 
 public:
-    SkGradientShaderBase(const Descriptor& desc);
+    SkGradientShaderBase(const Descriptor& desc, const SkMatrix* localMatrix);
     virtual ~SkGradientShaderBase();
 
     // The cache is initialized on-demand when getCache16/32 is called.
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index e660d7c..70bbbf3 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -52,8 +52,9 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkLinearGradient::SkLinearGradient(const SkPoint pts[2], const Descriptor& desc)
-    : SkGradientShaderBase(desc)
+SkLinearGradient::SkLinearGradient(const SkPoint pts[2], const Descriptor& desc,
+                                   const SkMatrix* localMatrix)
+    : SkGradientShaderBase(desc, localMatrix)
     , fStart(pts[0])
     , fEnd(pts[1]) {
     pts_to_unit_matrix(pts, &fPtsToUnit);
diff --git a/src/effects/gradients/SkLinearGradient.h b/src/effects/gradients/SkLinearGradient.h
index 8d80667..699d76e 100644
--- a/src/effects/gradients/SkLinearGradient.h
+++ b/src/effects/gradients/SkLinearGradient.h
@@ -13,7 +13,7 @@
 
 class SkLinearGradient : public SkGradientShaderBase {
 public:
-    SkLinearGradient(const SkPoint pts[2], const Descriptor&);
+    SkLinearGradient(const SkPoint pts[2], const Descriptor&, const SkMatrix* localMatrix);
 
     virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&,
                                              void* storage) const SK_OVERRIDE;
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index bc2ea3b..f13d55c 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -146,8 +146,8 @@
 /////////////////////////////////////////////////////////////////////
 
 SkRadialGradient::SkRadialGradient(const SkPoint& center, SkScalar radius,
-                                   const Descriptor& desc)
-    : SkGradientShaderBase(desc),
+                                   const Descriptor& desc, const SkMatrix* localMatrix)
+    : SkGradientShaderBase(desc, localMatrix),
       fCenter(center),
       fRadius(radius)
 {
diff --git a/src/effects/gradients/SkRadialGradient.h b/src/effects/gradients/SkRadialGradient.h
index a3d04b1..7aafe2d 100644
--- a/src/effects/gradients/SkRadialGradient.h
+++ b/src/effects/gradients/SkRadialGradient.h
@@ -13,7 +13,8 @@
 
 class SkRadialGradient : public SkGradientShaderBase {
 public:
-    SkRadialGradient(const SkPoint& center, SkScalar radius, const Descriptor&);
+    SkRadialGradient(const SkPoint& center, SkScalar radius, const Descriptor&,
+                     const SkMatrix* localMatrix);
 
     virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&,
                                              void* storage) const SK_OVERRIDE;
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index 6dff1e7..a65631c 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -9,8 +9,8 @@
 #include "SkSweepGradient.h"
 
 SkSweepGradient::SkSweepGradient(SkScalar cx, SkScalar cy,
-                                 const Descriptor& desc)
-    : SkGradientShaderBase(desc)
+                                 const Descriptor& desc, const SkMatrix* localMatrix)
+    : SkGradientShaderBase(desc, localMatrix)
     , fCenter(SkPoint::Make(cx, cy))
 {
     fPtsToUnit.setTranslate(-cx, -cy);
diff --git a/src/effects/gradients/SkSweepGradient.h b/src/effects/gradients/SkSweepGradient.h
index 9998ed1..15c5b63 100644
--- a/src/effects/gradients/SkSweepGradient.h
+++ b/src/effects/gradients/SkSweepGradient.h
@@ -13,7 +13,8 @@
 
 class SkSweepGradient : public SkGradientShaderBase {
 public:
-    SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor&);
+    SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor&,
+                    const SkMatrix* localMatrix);
 
     virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&,
                                              void* storage) const SK_OVERRIDE;
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index b7aba82..9d1f8f1 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -197,8 +197,9 @@
 SkTwoPointConicalGradient::SkTwoPointConicalGradient(
         const SkPoint& start, SkScalar startRadius,
         const SkPoint& end, SkScalar endRadius,
-        bool flippedGrad, const Descriptor& desc)
-    : SkGradientShaderBase(desc),
+        bool flippedGrad, const Descriptor& desc,
+        const SkMatrix* localMatrix)
+    : SkGradientShaderBase(desc, localMatrix),
     fCenter1(start),
     fCenter2(end),
     fRadius1(startRadius),
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.h b/src/effects/gradients/SkTwoPointConicalGradient.h
index 80aa6fa..13ce3ea 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.h
+++ b/src/effects/gradients/SkTwoPointConicalGradient.h
@@ -44,7 +44,8 @@
 public:
     SkTwoPointConicalGradient(const SkPoint& start, SkScalar startRadius,
                               const SkPoint& end, SkScalar endRadius,
-                              bool flippedGrad, const Descriptor&);
+                              bool flippedGrad, const Descriptor&,
+                              const SkMatrix* localMatrix);
 
 
     virtual SkShader::Context* createContext(const SkBitmap&, const SkPaint&, const SkMatrix&,
diff --git a/src/effects/gradients/SkTwoPointRadialGradient.cpp b/src/effects/gradients/SkTwoPointRadialGradient.cpp
index a598c6e..41e577f 100644
--- a/src/effects/gradients/SkTwoPointRadialGradient.cpp
+++ b/src/effects/gradients/SkTwoPointRadialGradient.cpp
@@ -170,8 +170,8 @@
 SkTwoPointRadialGradient::SkTwoPointRadialGradient(
     const SkPoint& start, SkScalar startRadius,
     const SkPoint& end, SkScalar endRadius,
-    const Descriptor& desc)
-    : SkGradientShaderBase(desc),
+    const Descriptor& desc, const SkMatrix* localMatrix)
+    : SkGradientShaderBase(desc, localMatrix),
       fCenter1(start),
       fCenter2(end),
       fRadius1(startRadius),
diff --git a/src/effects/gradients/SkTwoPointRadialGradient.h b/src/effects/gradients/SkTwoPointRadialGradient.h
index 9ba89f2..1b387e6 100644
--- a/src/effects/gradients/SkTwoPointRadialGradient.h
+++ b/src/effects/gradients/SkTwoPointRadialGradient.h
@@ -15,7 +15,7 @@
 public:
     SkTwoPointRadialGradient(const SkPoint& start, SkScalar startRadius,
                               const SkPoint& end, SkScalar endRadius,
-                              const Descriptor&);
+                              const Descriptor&, const SkMatrix* localMatrix);
 
     virtual BitmapType asABitmap(SkBitmap* bitmap,
                                  SkMatrix* matrix,
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 53641dc..4af1610 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1202,8 +1202,7 @@
 
         SkPaint paintWithShader(paint);
         paintWithShader.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
-            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode))->unref();
-        paintWithShader.getShader()->setLocalMatrix(localM);
+            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &localM))->unref();
         SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight};
         this->drawRect(draw, dstRect, paintWithShader);
 
diff --git a/tests/DrawBitmapRectTest.cpp b/tests/DrawBitmapRectTest.cpp
index 9912643..e6cc781 100644
--- a/tests/DrawBitmapRectTest.cpp
+++ b/tests/DrawBitmapRectTest.cpp
@@ -197,8 +197,6 @@
     bm.allocN32Pixels(width, height);
     bm.eraseColor(SK_ColorRED);
 
-    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
-                                               SkShader::kRepeat_TileMode);
     matrix.setAll(0.0078740157f,
                   0,
                   SkIntToScalar(249),
@@ -206,7 +204,8 @@
                   0.0078740157f,
                   SkIntToScalar(239),
                   0, 0, SK_Scalar1);
-    s->setLocalMatrix(matrix);
+    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
+                                               SkShader::kRepeat_TileMode, &matrix);
 
     SkPaint paint;
     paint.setShader(s)->unref();