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/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;
+}