Builder class for SkLayerRasterizer.

Provide builder class to make SkLayerRasterizer immutable. We have to keep the
addLayer() methods for now because they are used in Chrome. They will be removed
once this changed has been rolled into Chrome.
An added benefit of this is that this class can only be allocated on the heap.

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

Author: dominikg@chromium.org

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13590 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/texteffects.cpp b/gm/texteffects.cpp
index cf9ec5a..eb7accb 100644
--- a/gm/texteffects.cpp
+++ b/gm/texteffects.cpp
@@ -12,85 +12,85 @@
 #include "SkWriteBuffer.h"
 #include "SkLayerRasterizer.h"
 
-static void r0(SkLayerRasterizer* rast, SkPaint& p) {
+static void r0(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
     p.setMaskFilter(SkBlurMaskFilter::Create(SkBlurMaskFilter::kNormal_BlurStyle,
                               SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3))))->unref();
-    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
+    rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
 
     p.setMaskFilter(NULL);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setAlpha(0x11);
     p.setStyle(SkPaint::kFill_Style);
     p.setXfermodeMode(SkXfermode::kSrc_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r1(SkLayerRasterizer* rast, SkPaint& p) {
-    rast->addLayer(p);
+static void r1(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
+    rastBuilder->addLayer(p);
 
     p.setAlpha(0x40);
     p.setXfermodeMode(SkXfermode::kSrc_Mode);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*2);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r2(SkLayerRasterizer* rast, SkPaint& p) {
+static void r2(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
     p.setStyle(SkPaint::kStrokeAndFill_Style);
     p.setStrokeWidth(SK_Scalar1*4);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*3/2);
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r3(SkLayerRasterizer* rast, SkPaint& p) {
+static void r3(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*3);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setAlpha(0x20);
     p.setStyle(SkPaint::kFill_Style);
     p.setXfermodeMode(SkXfermode::kSrc_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r4(SkLayerRasterizer* rast, SkPaint& p) {
+static void r4(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
     p.setAlpha(0x60);
-    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
+    rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
 
     p.setAlpha(0xFF);
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
+    rastBuilder->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
 
     p.setXfermode(NULL);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
 #include "SkDiscretePathEffect.h"
 
-static void r5(SkLayerRasterizer* rast, SkPaint& p) {
-    rast->addLayer(p);
+static void r5(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
+    rastBuilder->addLayer(p);
 
     p.setPathEffect(SkDiscretePathEffect::Create(SK_Scalar1*4, SK_Scalar1*3))->unref();
     p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r6(SkLayerRasterizer* rast, SkPaint& p) {
-    rast->addLayer(p);
+static void r6(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
+    rastBuilder->addLayer(p);
 
     p.setAntiAlias(false);
-    SkLayerRasterizer* rast2 = new SkLayerRasterizer;
-    r5(rast2, p);
-    p.setRasterizer(rast2)->unref();
+    SkLayerRasterizer::Builder rastBuilder2;
+    r5(&rastBuilder2, p);
+    p.setRasterizer(rastBuilder2.detachRasterizer())->unref();
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
 #include "Sk2DPathEffect.h"
@@ -101,49 +101,49 @@
     return SkPath2DPathEffect::Create(matrix, path);
 }
 
-static void r7(SkLayerRasterizer* rast, SkPaint& p) {
+static void r7(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
     SkMatrix    lattice;
     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
     p.setPathEffect(MakeDotEffect(SK_Scalar1*4, lattice))->unref();
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r8(SkLayerRasterizer* rast, SkPaint& p) {
-    rast->addLayer(p);
+static void r8(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
+    rastBuilder->addLayer(p);
 
     SkMatrix    lattice;
     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
     p.setPathEffect(MakeDotEffect(SK_Scalar1*2, lattice))->unref();
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setPathEffect(NULL);
     p.setXfermode(NULL);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r9(SkLayerRasterizer* rast, SkPaint& p) {
-    rast->addLayer(p);
+static void r9(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
+    rastBuilder->addLayer(p);
 
     SkMatrix    lattice;
     lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
     lattice.postRotate(SkIntToScalar(30), 0, 0);
     p.setPathEffect(SkLine2DPathEffect::Create(SK_Scalar1*2, lattice))->unref();
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setPathEffect(NULL);
     p.setXfermode(NULL);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
+typedef void (*raster_proc)(SkLayerRasterizer::Builder*, SkPaint&);
 
 static const raster_proc gRastProcs[] = {
     r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
@@ -156,11 +156,11 @@
     if (proc)
     {
         SkPaint p;
-        SkLayerRasterizer*  rast = new SkLayerRasterizer;
+        SkLayerRasterizer::Builder rastBuilder;
 
         p.setAntiAlias(true);
-        proc(rast, p);
-        paint->setRasterizer(rast)->unref();
+        proc(&rastBuilder, p);
+        paint->setRasterizer(rastBuilder.detachRasterizer())->unref();
     }
 
 #if 0
diff --git a/include/core/SkRasterizer.h b/include/core/SkRasterizer.h
index d916b23..d6e514c 100644
--- a/include/core/SkRasterizer.h
+++ b/include/core/SkRasterizer.h
@@ -22,8 +22,6 @@
 public:
     SK_DECLARE_INST_COUNT(SkRasterizer)
 
-    SkRasterizer() {}
-
     /** Turn the path into a mask, respecting the specified local->device matrix.
     */
     bool rasterize(const SkPath& path, const SkMatrix& matrix,
@@ -33,6 +31,7 @@
     SK_DEFINE_FLATTENABLE_TYPE(SkRasterizer)
 
 protected:
+    SkRasterizer() {}
     SkRasterizer(SkReadBuffer& buffer) : INHERITED(buffer) {}
 
     virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix,
diff --git a/include/effects/SkLayerRasterizer.h b/include/effects/SkLayerRasterizer.h
index be81a2b..fdfb179 100644
--- a/include/effects/SkLayerRasterizer.h
+++ b/include/effects/SkLayerRasterizer.h
@@ -18,9 +18,36 @@
 
 class SK_API SkLayerRasterizer : public SkRasterizer {
 public:
-            SkLayerRasterizer();
     virtual ~SkLayerRasterizer();
 
+    class SK_API Builder {
+    public:
+        Builder();
+        ~Builder();
+
+        void addLayer(const SkPaint& paint) {
+            this->addLayer(paint, 0, 0);
+        }
+
+        /**
+          *  Add a new layer (above any previous layers) to the rasterizer.
+          *  The layer will extract those fields that affect the mask from
+          *  the specified paint, but will not retain a reference to the paint
+          *  object itself, so it may be reused without danger of side-effects.
+          */
+        void addLayer(const SkPaint& paint, SkScalar dx, SkScalar dy);
+
+        /**
+          *  Pass queue of layers on to newly created layer rasterizer and return it. The builder
+          *  cannot be used any more after calling this function.
+          */
+        SkLayerRasterizer* detachRasterizer();
+
+    private:
+        SkDeque* fLayers;
+    };
+
+#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API
     void addLayer(const SkPaint& paint) {
         this->addLayer(paint, 0, 0);
     }
@@ -31,10 +58,12 @@
         object itself, so it may be reused without danger of side-effects.
     */
     void addLayer(const SkPaint& paint, SkScalar dx, SkScalar dy);
+#endif
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLayerRasterizer)
 
 protected:
+    SkLayerRasterizer(SkDeque* layers);
     SkLayerRasterizer(SkReadBuffer&);
     virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
 
@@ -43,8 +72,19 @@
                              const SkIRect* clipBounds,
                              SkMask* mask, SkMask::CreateMode mode) const;
 
+#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API
+public:
+#endif
+    SkLayerRasterizer();
+
 private:
-    SkDeque fLayers;
+#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API
+    SkDeque* fLayers;
+#else
+    const SkDeque* const fLayers;
+#endif
+
+    static SkDeque* ReadLayers(SkReadBuffer& buffer);
 
     typedef SkRasterizer INHERITED;
 };
diff --git a/samplecode/ClockFaceView.cpp b/samplecode/ClockFaceView.cpp
index ed0bce9..a887cc6 100644
--- a/samplecode/ClockFaceView.cpp
+++ b/samplecode/ClockFaceView.cpp
@@ -133,15 +133,15 @@
     return new Dot2DPathEffect(rad, lattice, pts);
 }
 
-static void r7(SkLayerRasterizer* rast, SkPaint& p, SkScalar interp) {
+static void r7(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p, SkScalar interp) {
     p.setPathEffect(makepe(SkScalarToFloat(interp), NULL))->unref();
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 #if 0
     p.setPathEffect(new InverseFillPE())->unref();
     p.setXfermodeMode(SkXfermode::kSrcIn_Mode);
     p.setXfermodeMode(SkXfermode::kClear_Mode);
     p.setAlpha((1 - interp) * 255);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 #endif
 }
 
@@ -152,11 +152,11 @@
 static void apply_shader(SkPaint* paint, float scale)
 {
     SkPaint p;
-    SkLayerRasterizer*  rast = new SkLayerRasterizer;
+    SkLayerRasterizer::Builder rastBuilder;
 
     p.setAntiAlias(true);
-    r7(rast, p, scale);
-    paint->setRasterizer(rast)->unref();
+    r7(&rastBuilder, p, scale);
+    paint->setRasterizer(rastBuilder.detachRasterizer())->unref();
 
     paint->setColor(SK_ColorBLUE);
 }
diff --git a/samplecode/SampleAll.cpp b/samplecode/SampleAll.cpp
index eb988f1..e0058c4 100644
--- a/samplecode/SampleAll.cpp
+++ b/samplecode/SampleAll.cpp
@@ -80,84 +80,84 @@
 
 ///////////////////////////////////////////////////////////
 
-static void r0(SkLayerRasterizer* rast, SkPaint& p) {
+static void r0(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
     p.setMaskFilter(SkBlurMaskFilter::Create(SkBlurMaskFilter::kNormal_BlurStyle,
                                              SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3)),
                                              SkBlurMaskFilter::kNone_BlurFlag))->unref();
-    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
+    rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
 
     p.setMaskFilter(NULL);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setAlpha(0x11);
     p.setStyle(SkPaint::kFill_Style);
     p.setXfermodeMode(SkXfermode::kSrc_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r1(SkLayerRasterizer* rast, SkPaint& p) {
-    rast->addLayer(p);
+static void r1(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
+    rastBuilder->addLayer(p);
 
     p.setAlpha(0x40);
     p.setXfermodeMode(SkXfermode::kSrc_Mode);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*2);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r2(SkLayerRasterizer* rast, SkPaint& p) {
+static void r2(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
     p.setStyle(SkPaint::kStrokeAndFill_Style);
     p.setStrokeWidth(SK_Scalar1*4);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*3/2);
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r3(SkLayerRasterizer* rast, SkPaint& p) {
+static void r3(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*3);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setAlpha(0x20);
     p.setStyle(SkPaint::kFill_Style);
     p.setXfermodeMode(SkXfermode::kSrc_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r4(SkLayerRasterizer* rast, SkPaint& p) {
+static void r4(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
     p.setAlpha(0x60);
-    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
+    rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
 
     p.setAlpha(0xFF);
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
+    rastBuilder->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
 
     p.setXfermode(NULL);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r5(SkLayerRasterizer* rast, SkPaint& p) {
-    rast->addLayer(p);
+static void r5(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
+    rastBuilder->addLayer(p);
 
     p.setPathEffect(SkDiscretePathEffect::Create(SK_Scalar1*4, SK_Scalar1*3))->unref();
     p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r6(SkLayerRasterizer* rast, SkPaint& p) {
-    rast->addLayer(p);
+static void r6(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
+    rastBuilder->addLayer(p);
 
     p.setAntiAlias(false);
-    SkLayerRasterizer* rast2 = new SkLayerRasterizer;
-    r5(rast2, p);
-    p.setRasterizer(rast2)->unref();
+    SkLayerRasterizer::Builder rastBuilder2;
+    r5(&rastBuilder2, p);
+    p.setRasterizer(rastBuilder2.detachRasterizer())->unref();
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
 class Dot2DPathEffect : public Sk2DPathEffect {
@@ -186,49 +186,49 @@
     typedef Sk2DPathEffect INHERITED;
 };
 
-static void r7(SkLayerRasterizer* rast, SkPaint& p) {
+static void r7(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
     SkMatrix    lattice;
     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
     p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*4, lattice))->unref();
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r8(SkLayerRasterizer* rast, SkPaint& p) {
-    rast->addLayer(p);
+static void r8(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
+    rastBuilder->addLayer(p);
 
     SkMatrix    lattice;
     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
     p.setPathEffect(new Dot2DPathEffect(SK_Scalar1*2, lattice))->unref();
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setPathEffect(NULL);
     p.setXfermode(NULL);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r9(SkLayerRasterizer* rast, SkPaint& p) {
-    rast->addLayer(p);
+static void r9(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) {
+    rastBuilder->addLayer(p);
 
     SkMatrix    lattice;
     lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
     lattice.postRotate(SkIntToScalar(30), 0, 0);
     p.setPathEffect(SkLine2DPathEffect::Create(SK_Scalar1*2, lattice))->unref();
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setPathEffect(NULL);
     p.setXfermode(NULL);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
+typedef void (*raster_proc)(SkLayerRasterizer::Builder*, SkPaint&);
 
 static const raster_proc gRastProcs[] = {
     r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
@@ -248,11 +248,11 @@
     raster_proc proc = gRastProcs[index];
     if (proc) {
         SkPaint p;
-        SkLayerRasterizer*  rast = new SkLayerRasterizer;
+        SkLayerRasterizer::Builder rastBuilder;
 
         p.setAntiAlias(true);
-        proc(rast, p);
-        paint->setRasterizer(rast)->unref();
+        proc(&rastBuilder, p);
+        paint->setRasterizer(rastBuilder.detachRasterizer())->unref();
     }
 
 #if 1
diff --git a/samplecode/SamplePathEffects.cpp b/samplecode/SamplePathEffects.cpp
index 2a1a49b..9af0abb 100644
--- a/samplecode/SamplePathEffects.cpp
+++ b/samplecode/SamplePathEffects.cpp
@@ -74,9 +74,9 @@
 #include "SkColorFilter.h"
 #include "SkLayerRasterizer.h"
 
-class testrast : public SkLayerRasterizer {
+class TestRastBuilder : public SkLayerRasterizer::Builder {
 public:
-    testrast() {
+    TestRastBuilder() {
         SkPaint paint;
         paint.setAntiAlias(true);
 
@@ -177,7 +177,8 @@
 
         paint.setARGB(0xFF, 0, 0, 0);
         paint.setPathEffect(make_warp_pe())->unref();
-        paint.setRasterizer(new testrast)->unref();
+        TestRastBuilder testRastBuilder;
+        paint.setRasterizer(testRastBuilder.detachRasterizer())->unref();
         canvas->drawPath(fPath, paint);
     }
 
diff --git a/samplecode/SampleSlides.cpp b/samplecode/SampleSlides.cpp
index 914283a..ece9684 100644
--- a/samplecode/SampleSlides.cpp
+++ b/samplecode/SampleSlides.cpp
@@ -476,92 +476,92 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static void r0(SkLayerRasterizer* rast, SkPaint& p)
+static void r0(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p)
 {
     p.setMaskFilter(SkBlurMaskFilter::Create(SkBlurMaskFilter::kNormal_BlurStyle,
                                              SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3))))->unref();
-    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
+    rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
 
     p.setMaskFilter(NULL);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setAlpha(0x11);
     p.setStyle(SkPaint::kFill_Style);
     p.setXfermodeMode(SkXfermode::kSrc_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r1(SkLayerRasterizer* rast, SkPaint& p)
+static void r1(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p)
 {
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setAlpha(0x40);
     p.setXfermodeMode(SkXfermode::kSrc_Mode);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*2);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r2(SkLayerRasterizer* rast, SkPaint& p)
+static void r2(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p)
 {
     p.setStyle(SkPaint::kStrokeAndFill_Style);
     p.setStrokeWidth(SK_Scalar1*4);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*3/2);
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r3(SkLayerRasterizer* rast, SkPaint& p)
+static void r3(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p)
 {
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1*3);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setAlpha(0x20);
     p.setStyle(SkPaint::kFill_Style);
     p.setXfermodeMode(SkXfermode::kSrc_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r4(SkLayerRasterizer* rast, SkPaint& p)
+static void r4(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p)
 {
     p.setAlpha(0x60);
-    rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
+    rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3));
 
     p.setAlpha(0xFF);
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
+    rastBuilder->addLayer(p, SK_Scalar1*3/2, SK_Scalar1*3/2);
 
     p.setXfermode(NULL);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
 #include "SkDiscretePathEffect.h"
 
-static void r5(SkLayerRasterizer* rast, SkPaint& p)
+static void r5(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p)
 {
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setPathEffect(SkDiscretePathEffect::Create(SK_Scalar1*4, SK_Scalar1*3))->unref();
     p.setXfermodeMode(SkXfermode::kSrcOut_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r6(SkLayerRasterizer* rast, SkPaint& p)
+static void r6(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p)
 {
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setAntiAlias(false);
-    SkLayerRasterizer* rast2 = new SkLayerRasterizer;
-    r5(rast2, p);
-    p.setRasterizer(rast2)->unref();
+    SkLayerRasterizer::Builder rastBuilder2;
+    r5(&rastBuilder2, p);
+    p.setRasterizer(rastBuilder2.detachRasterizer())->unref();
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
 #include "Sk2DPathEffect.h"
@@ -572,52 +572,52 @@
     return SkPath2DPathEffect::Create(matrix, path);
 }
 
-static void r7(SkLayerRasterizer* rast, SkPaint& p)
+static void r7(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p)
 {
     SkMatrix    lattice;
     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
     p.setPathEffect(MakeDotEffect(SK_Scalar1*4, lattice))->unref();
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r8(SkLayerRasterizer* rast, SkPaint& p)
+static void r8(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p)
 {
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     SkMatrix    lattice;
     lattice.setScale(SK_Scalar1*6, SK_Scalar1*6, 0, 0);
     lattice.postSkew(SK_Scalar1/3, 0, 0, 0);
     p.setPathEffect(MakeDotEffect(SK_Scalar1*2, lattice))->unref();
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setPathEffect(NULL);
     p.setXfermode(NULL);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-static void r9(SkLayerRasterizer* rast, SkPaint& p)
+static void r9(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p)
 {
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     SkMatrix    lattice;
     lattice.setScale(SK_Scalar1, SK_Scalar1*6, 0, 0);
     lattice.postRotate(SkIntToScalar(30), 0, 0);
     p.setPathEffect(SkLine2DPathEffect::Create(SK_Scalar1*2, lattice))->unref();
     p.setXfermodeMode(SkXfermode::kClear_Mode);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 
     p.setPathEffect(NULL);
     p.setXfermode(NULL);
     p.setStyle(SkPaint::kStroke_Style);
     p.setStrokeWidth(SK_Scalar1);
-    rast->addLayer(p);
+    rastBuilder->addLayer(p);
 }
 
-typedef void (*raster_proc)(SkLayerRasterizer*, SkPaint&);
+typedef void (*raster_proc)(SkLayerRasterizer::Builder*, SkPaint&);
 
 static const raster_proc gRastProcs[] = {
     r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
@@ -626,11 +626,11 @@
 static void apply_shader(SkPaint* paint, int index) {
     raster_proc proc = gRastProcs[index];
     SkPaint p;
-    SkLayerRasterizer*  rast = new SkLayerRasterizer;
+    SkLayerRasterizer::Builder rastBuilder;
 
     p.setAntiAlias(true);
-    proc(rast, p);
-    paint->setRasterizer(rast)->unref();
+    proc(&rastBuilder, p);
+    paint->setRasterizer(rastBuilder.detachRasterizer())->unref();
     paint->setColor(SK_ColorBLUE);
 }
 
diff --git a/src/effects/SkLayerRasterizer.cpp b/src/effects/SkLayerRasterizer.cpp
index a10d758..e35c5e8 100644
--- a/src/effects/SkLayerRasterizer.cpp
+++ b/src/effects/SkLayerRasterizer.cpp
@@ -25,25 +25,36 @@
     SkVector    fOffset;
 };
 
-SkLayerRasterizer::SkLayerRasterizer() : fLayers(sizeof(SkLayerRasterizer_Rec))
+SkLayerRasterizer::SkLayerRasterizer()
+    : fLayers(SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec))))
+{
+}
+
+SkLayerRasterizer::SkLayerRasterizer(SkDeque* layers) : fLayers(layers)
 {
 }
 
 SkLayerRasterizer::~SkLayerRasterizer() {
-    SkDeque::F2BIter        iter(fLayers);
+    SkASSERT(fLayers);
+    SkDeque::F2BIter        iter(*fLayers);
     SkLayerRasterizer_Rec*  rec;
 
     while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL)
         rec->fPaint.~SkPaint();
+
+    SkDELETE(fLayers);
 }
 
+#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API
 void SkLayerRasterizer::addLayer(const SkPaint& paint, SkScalar dx,
                                  SkScalar dy) {
-    SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
+    SkASSERT(fLayers);
+    SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers->push_back();
 
     SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (paint));
     rec->fOffset.set(dx, dy);
 }
+#endif
 
 static bool compute_bounds(const SkDeque& layers, const SkPath& path,
                            const SkMatrix& matrix,
@@ -89,12 +100,13 @@
 bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
                                     const SkIRect* clipBounds,
                                     SkMask* mask, SkMask::CreateMode mode) const {
-    if (fLayers.empty()) {
+    SkASSERT(fLayers);
+    if (fLayers->empty()) {
         return false;
     }
 
     if (SkMask::kJustRenderImage_CreateMode != mode) {
-        if (!compute_bounds(fLayers, path, matrix, clipBounds, &mask->fBounds))
+        if (!compute_bounds(*fLayers, path, matrix, clipBounds, &mask->fBounds))
             return false;
     }
 
@@ -131,7 +143,7 @@
         // we set the matrixproc in the loop, as the matrix changes each time (potentially)
         draw.fBounder   = NULL;
 
-        SkDeque::F2BIter        iter(fLayers);
+        SkDeque::F2BIter        iter(*fLayers);
         SkLayerRasterizer_Rec*  rec;
 
         while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) {
@@ -144,24 +156,29 @@
 }
 
 SkLayerRasterizer::SkLayerRasterizer(SkReadBuffer& buffer)
-    : SkRasterizer(buffer), fLayers(sizeof(SkLayerRasterizer_Rec)) {
+    : SkRasterizer(buffer), fLayers(ReadLayers(buffer)) {}
+
+SkDeque* SkLayerRasterizer::ReadLayers(SkReadBuffer& buffer) {
     int count = buffer.readInt();
 
+    SkDeque* layers = SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec)));
     for (int i = 0; i < count; i++) {
-        SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
+        SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)layers->push_back();
 
         SkNEW_PLACEMENT(&rec->fPaint, SkPaint);
         buffer.readPaint(&rec->fPaint);
         buffer.readPoint(&rec->fOffset);
     }
+    return layers;
 }
 
 void SkLayerRasterizer::flatten(SkWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
 
-    buffer.writeInt(fLayers.count());
+    SkASSERT(fLayers);
+    buffer.writeInt(fLayers->count());
 
-    SkDeque::F2BIter                iter(fLayers);
+    SkDeque::F2BIter                iter(*fLayers);
     const SkLayerRasterizer_Rec*    rec;
 
     while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) {
@@ -169,3 +186,28 @@
         buffer.writePoint(rec->fOffset);
     }
 }
+
+SkLayerRasterizer::Builder::Builder()
+        : fLayers(SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec))))
+{
+}
+
+SkLayerRasterizer::Builder::~Builder()
+{
+    SkDELETE(fLayers);
+}
+
+void SkLayerRasterizer::Builder::addLayer(const SkPaint& paint, SkScalar dx,
+                                          SkScalar dy) {
+    SkASSERT(fLayers);
+    SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers->push_back();
+
+    SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (paint));
+    rec->fOffset.set(dx, dy);
+}
+
+SkLayerRasterizer* SkLayerRasterizer::Builder::detachRasterizer() {
+    SkLayerRasterizer* rasterizer = SkNEW_ARGS(SkLayerRasterizer, (fLayers));
+    fLayers = NULL;
+    return rasterizer;
+}