option to return drawable from recording

patch from issue 747033005 at patchset 80001 (http://crrev.com/747033005#ps80001)

BUG=skia:

Review URL: https://codereview.chromium.org/732653004
diff --git a/src/core/SkCanvasDrawable.cpp b/src/core/SkCanvasDrawable.cpp
index e0120f0..99a4996 100644
--- a/src/core/SkCanvasDrawable.cpp
+++ b/src/core/SkCanvasDrawable.cpp
@@ -41,8 +41,8 @@
     }
 }
 
-SkPicture* SkCanvasDrawable::newPictureSnapshot(SkBBHFactory* bbhFactory, uint32_t recordFlags) {
-    return this->onNewPictureSnapshot(bbhFactory, recordFlags);
+SkPicture* SkCanvasDrawable::newPictureSnapshot() {
+    return this->onNewPictureSnapshot();
 }
 
 uint32_t SkCanvasDrawable::getGenerationID() {
@@ -64,11 +64,11 @@
 
 #include "SkPictureRecorder.h"
 
-SkPicture* SkCanvasDrawable::onNewPictureSnapshot(SkBBHFactory* bbhFactory, uint32_t recordFlags) {
+SkPicture* SkCanvasDrawable::onNewPictureSnapshot() {
     SkPictureRecorder recorder;
 
     const SkRect bounds = this->getBounds();
-    SkCanvas* canvas = recorder.beginRecording(bounds, bbhFactory, recordFlags);
+    SkCanvas* canvas = recorder.beginRecording(bounds, NULL, 0);
     this->draw(canvas);
     if (false) {
         draw_bbox(canvas, bounds);
diff --git a/src/core/SkCanvasDrawable.h b/src/core/SkCanvasDrawable.h
index f189f2d..bc5b4fd 100644
--- a/src/core/SkCanvasDrawable.h
+++ b/src/core/SkCanvasDrawable.h
@@ -10,8 +10,8 @@
 
 #include "SkRefCnt.h"
 
-class SkBBHFactory;
 class SkCanvas;
+class SkPicture;
 struct SkRect;
 
 /**
@@ -32,10 +32,7 @@
      */
     void draw(SkCanvas*);
 
-    SkPicture* newPictureSnapshot(SkBBHFactory* bbhFactory, uint32_t recordFlags);
-    SkPicture* newPictureSnapshot() {
-        return this->newPictureSnapshot(NULL, 0);
-    }
+    SkPicture* newPictureSnapshot();
 
     /**
      *  Return a unique value for this instance. If two calls to this return the same value,
@@ -63,7 +60,7 @@
 protected:
     virtual SkRect onGetBounds() = 0;
     virtual void onDraw(SkCanvas*) = 0;
-    virtual SkPicture* onNewPictureSnapshot(SkBBHFactory*, uint32_t recordFlags);
+    virtual SkPicture* onNewPictureSnapshot();
 
 private:
     int32_t fGenerationID;
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
index b4c3063..3e006c1 100644
--- a/src/core/SkPicture.cpp
+++ b/src/core/SkPicture.cpp
@@ -319,7 +319,7 @@
     (void)canvas->getClipBounds(&clipBounds);
     const bool useBBH = !clipBounds.contains(this->cullRect());
 
-    SkRecordDraw(*fRecord, canvas, this->drawablePicts(), this->drawableCount(),
+    SkRecordDraw(*fRecord, canvas, this->drawablePicts(), NULL, this->drawableCount(),
                  useBBH ? fBBH.get() : NULL, callback);
 }
 
@@ -474,7 +474,7 @@
                                    SkPicture const* const drawablePicts[], int drawableCount) {
     SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.height()), 0/*flags*/);
     rec.beginRecording();
-        SkRecordDraw(src, &rec, drawablePicts, drawableCount, NULL/*bbh*/, NULL/*callback*/);
+        SkRecordDraw(src, &rec, drawablePicts, NULL, drawableCount, NULL/*bbh*/, NULL/*callback*/);
     rec.endRecording();
     return SkNEW_ARGS(SkPictureData, (rec, info, false/*deep copy ops?*/));
 }
@@ -526,8 +526,8 @@
                      SkBBoxHierarchy* bbh)
     : fUniqueID(next_picture_generation_id())
     , fCullRect(cullRect)
-    , fRecord(record)
+    , fRecord(SkRef(record))
     , fBBH(SkSafeRef(bbh))
-    , fDrawablePicts(drawablePicts)
+    , fDrawablePicts(drawablePicts)     // take ownership
     , fAnalysis(*fRecord)
 {}
diff --git a/src/core/SkPictureRecorder.cpp b/src/core/SkPictureRecorder.cpp
index 3262938..d64390c 100644
--- a/src/core/SkPictureRecorder.cpp
+++ b/src/core/SkPictureRecorder.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "SkCanvasDrawable.h"
 #include "SkData.h"
 #include "SkLayerInfo.h"
 #include "SkPictureRecorder.h"
@@ -14,7 +15,7 @@
 #include "SkRecordOpts.h"
 #include "SkTypes.h"
 
-SkPictureRecorder::SkPictureRecorder() {}
+SkPictureRecorder::SkPictureRecorder() : fBBHFactory(NULL) {}
 
 SkPictureRecorder::~SkPictureRecorder() {}
 
@@ -22,6 +23,7 @@
                                             SkBBHFactory* bbhFactory /* = NULL */,
                                             uint32_t recordFlags /* = 0 */) {
     fCullRect = cullRect;
+    fBBHFactory = bbhFactory;
     fFlags = recordFlags;
 
     if (bbhFactory) {
@@ -38,7 +40,7 @@
     return fRecorder.get();
 }
 
-SkPicture* SkPictureRecorder::endRecording() {
+SkPicture* SkPictureRecorder::endRecordingAsPicture() {
     // TODO: delay as much of this work until just before first playback?
     SkRecordOptimize(fRecord);
 
@@ -50,26 +52,23 @@
         saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key)));
     }
 
+    SkCanvasDrawableList* drawableList = fRecorder->getDrawableList();
+    SkPicture::SnapshotArray* pictList = drawableList ? drawableList->newDrawableSnapshot() : NULL;
+
     if (fBBH.get()) {
         if (saveLayerData) {
-            SkRecordComputeLayers(fCullRect, *fRecord, fBBH.get(), saveLayerData);
+            SkRecordComputeLayers(fCullRect, *fRecord, pictList, fBBH.get(), saveLayerData);
         } else {
             SkRecordFillBounds(fCullRect, *fRecord, fBBH.get());
         }
     }
 
-    // TODO: we should remember these from our caller
-    SkBBHFactory* factory = NULL;
-    uint32_t recordFlags = 0;
-    SkAutoTDelete<SkPicture::SnapshotArray> drawablePicts(
-            fRecorder->newDrawableSnapshot(factory, recordFlags));
-    SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullRect, fRecord.detach(),
-                                             drawablePicts.detach(), fBBH.get()));
+    SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullRect, fRecord, pictList, fBBH));
 
     if (saveLayerData) {
         pict->EXPERIMENTAL_addAccelData(saveLayerData);
     }
-
+    
     return pict;
 }
 
@@ -79,5 +78,86 @@
     }
 
     int drawableCount = 0;
-    SkRecordDraw(*fRecord, canvas, NULL, drawableCount, NULL/*bbh*/, NULL/*callback*/);
+    SkCanvasDrawable* const* drawables = NULL;
+    SkCanvasDrawableList* drawableList = fRecorder->getDrawableList();
+    if (drawableList) {
+        drawableCount = drawableList->count();
+        drawables = drawableList->begin();
+    }
+    SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, NULL/*bbh*/, NULL/*callback*/);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkRecordedDrawable : public SkCanvasDrawable {
+    SkAutoTUnref<SkRecord>              fRecord;
+    SkAutoTUnref<SkBBoxHierarchy>       fBBH;
+    SkAutoTDelete<SkCanvasDrawableList> fDrawableList;
+    const SkRect                        fBounds;
+    const bool                          fDoSaveLayerInfo;
+
+public:
+    SkRecordedDrawable(SkRecord* record, SkBBoxHierarchy* bbh, SkCanvasDrawableList* drawableList,
+                       const SkRect& bounds, bool doSaveLayerInfo)
+        : fRecord(SkRef(record))
+        , fBBH(SkSafeRef(bbh))
+        , fDrawableList(drawableList)   // we take ownership
+        , fBounds(bounds)
+        , fDoSaveLayerInfo(doSaveLayerInfo)
+    {}
+
+protected:
+    SkRect onGetBounds() SK_OVERRIDE { return fBounds; }
+
+    void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+        SkCanvasDrawable* const* drawables = NULL;
+        int drawableCount = 0;
+        if (fDrawableList) {
+            drawables = fDrawableList->begin();
+            drawableCount = fDrawableList->count();
+        }
+        SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, fBBH, NULL/*callback*/);
+    }
+
+    SkPicture* onNewPictureSnapshot() SK_OVERRIDE {
+        SkPicture::SnapshotArray* pictList = NULL;
+        if (fDrawableList) {
+            // TODO: should we plumb-down the BBHFactory and recordFlags from our host
+            //       PictureRecorder?
+            pictList = fDrawableList->newDrawableSnapshot();
+        }
+
+        SkAutoTUnref<SkLayerInfo> saveLayerData;
+
+        if (fBBH && fDoSaveLayerInfo) {
+            SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
+
+            saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key)));
+
+            SkBBoxHierarchy* bbh = NULL;    // we've already computed fBBH (received in constructor)
+            // TODO: update saveLayer info computation to reuse the already computed
+            // bounds in 'fBBH'
+            SkRecordComputeLayers(fBounds, *fRecord, pictList, bbh, saveLayerData);
+        }
+
+        SkPicture* pict = SkNEW_ARGS(SkPicture, (fBounds, fRecord, pictList, fBBH));
+
+        if (saveLayerData) {
+            pict->EXPERIMENTAL_addAccelData(saveLayerData);
+        }
+        return pict;
+    }
+};
+
+SkCanvasDrawable* SkPictureRecorder::EXPERIMENTAL_endRecordingAsDrawable() {
+    // TODO: delay as much of this work until just before first playback?
+    SkRecordOptimize(fRecord);
+
+    if (fBBH.get()) {
+        SkRecordFillBounds(fCullRect, *fRecord, fBBH.get());
+    }
+
+    return SkNEW_ARGS(SkRecordedDrawable, (fRecord, fBBH, fRecorder->detachDrawableList(),
+                                           fCullRect,
+                                           SkToBool(fFlags & kComputeSaveLayerInfo_RecordFlag)));
 }
diff --git a/src/core/SkRecord.h b/src/core/SkRecord.h
index 403110d..8179b06 100644
--- a/src/core/SkRecord.h
+++ b/src/core/SkRecord.h
@@ -25,7 +25,7 @@
 // only with SkRecords::* structs defined in SkRecords.h.  Your compiler will helpfully yell if you
 // get this wrong.
 
-class SkRecord : SkNoncopyable {
+class SkRecord : public SkNVRefCnt<SkRecord> {
     enum {
         kFirstReserveCount = 64 / sizeof(void*),
     };
@@ -240,6 +240,6 @@
     // Strangely the order of these fields matters.  If the unsigneds don't go first we're 56 bytes.
     // tomhudson and mtklein have no idea why.
 };
-SK_COMPILE_ASSERT(sizeof(SkRecord) <= 48, SkRecordSize);
+SK_COMPILE_ASSERT(sizeof(SkRecord) <= 56, SkRecordSize);
 
 #endif//SkRecord_DEFINED
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 7e35d8a..5e1fe7f 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -11,7 +11,9 @@
 
 void SkRecordDraw(const SkRecord& record,
                   SkCanvas* canvas,
-                  SkPicture const* const drawablePicts[], int drawableCount,
+                  SkPicture const* const drawablePicts[],
+                  SkCanvasDrawable* const drawables[],
+                  int drawableCount,
                   const SkBBoxHierarchy* bbh,
                   SkDrawPictureCallback* callback) {
     SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
@@ -32,7 +34,7 @@
         SkTDArray<unsigned> ops;
         bbh->search(query, &ops);
 
-        SkRecords::Draw draw(canvas, drawablePicts, drawableCount);
+        SkRecords::Draw draw(canvas, drawablePicts, drawables, drawableCount);
         for (int i = 0; i < ops.count(); i++) {
             if (callback && callback->abortDrawing()) {
                 return;
@@ -44,7 +46,7 @@
         }
     } else {
         // Draw all ops.
-        SkRecords::Draw draw(canvas, drawablePicts, drawableCount);
+        SkRecords::Draw draw(canvas, drawablePicts, drawables, drawableCount);
         for (unsigned i = 0; i < record.count(); i++) {
             if (callback && callback->abortDrawing()) {
                 return;
@@ -133,7 +135,12 @@
 template <> void Draw::draw(const DrawDrawable& r) {
     SkASSERT(r.index >= 0);
     SkASSERT(r.index < fDrawableCount);
-    fCanvas->drawPicture(fDrawablePicts[r.index]);
+    if (fDrawables) {
+        SkASSERT(NULL == fDrawablePicts);
+        fCanvas->EXPERIMENTAL_drawDrawable(fDrawables[r.index]);
+    } else {
+        fCanvas->drawPicture(fDrawablePicts[r.index]);
+    }
 }
 
 // This is an SkRecord visitor that fills an SkBBoxHierarchy.
@@ -159,7 +166,8 @@
     FillBounds(const SkRect& cullRect, const SkRecord& record)
         : fNumRecords(record.count())
         , fCullRect(cullRect)
-        , fBounds(record.count()) {
+        , fBounds(record.count())
+    {
         // Calculate bounds for all ops.  This won't go quite in order, so we'll need
         // to store the bounds separately then feed them in to the BBH later in order.
         fCTM = &SkMatrix::I();
@@ -591,11 +599,13 @@
 // SkRecord visitor to gather saveLayer/restore information.
 class CollectLayers : SkNoncopyable {
 public:
-    CollectLayers(const SkRect& cullRect, const SkRecord& record, SkLayerInfo* accelData)
+    CollectLayers(const SkRect& cullRect, const SkRecord& record,
+                  const SkPicture::SnapshotArray* pictList, SkLayerInfo* accelData)
         : fSaveLayersInStack(0)
         , fAccelData(accelData)
-        , fFillBounds(cullRect, record) {
-    }
+        , fPictList(pictList)
+        , fFillBounds(cullRect, record)
+    {}
 
     void setCurrentOp(unsigned currentOp) { fFillBounds.setCurrentOp(currentOp); }
 
@@ -638,13 +648,13 @@
     void trackSaveLayers(const SaveLayer& sl) { this->pushSaveLayerInfo(true, sl.paint); }
     void trackSaveLayers(const Restore& r) { this->popSaveLayerInfo(); }
 
-    void trackSaveLayers(const DrawPicture& dp) {
+    void trackSaveLayersForPicture(const SkPicture* picture, const SkPaint* paint) {
         // For sub-pictures, we wrap their layer information within the parent
         // picture's rendering hierarchy
         SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
 
         const SkLayerInfo* childData =
-            static_cast<const SkLayerInfo*>(dp.picture->EXPERIMENTAL_getAccelData(key));
+            static_cast<const SkLayerInfo*>(picture->EXPERIMENTAL_getAccelData(key));
         if (!childData) {
             // If the child layer hasn't been generated with saveLayer data we
             // assume the worst (i.e., that it does contain layers which nest
@@ -658,7 +668,7 @@
         for (int i = 0; i < childData->numBlocks(); ++i) {
             const SkLayerInfo::BlockInfo& src = childData->block(i);
 
-            FillBounds::Bounds newBound = fFillBounds.adjustAndMap(src.fBounds, dp.paint);
+            FillBounds::Bounds newBound = fFillBounds.adjustAndMap(src.fBounds, paint);
             if (newBound.isEmpty()) {
                 continue;
             }
@@ -669,7 +679,7 @@
 
             // If src.fPicture is NULL the layer is in dp.picture; otherwise
             // it belongs to a sub-picture.
-            dst.fPicture = src.fPicture ? src.fPicture : static_cast<const SkPicture*>(dp.picture);
+            dst.fPicture = src.fPicture ? src.fPicture : picture;
             dst.fPicture->ref();
             dst.fBounds = newBound;
             dst.fLocalMat = src.fLocalMat;
@@ -685,6 +695,17 @@
         }
     }
 
+    void trackSaveLayers(const DrawPicture& dp) {
+        this->trackSaveLayersForPicture(dp.picture, dp.paint);
+    }
+
+    void trackSaveLayers(const DrawDrawable& dp) {
+        SkASSERT(fPictList);
+        SkASSERT(dp.index >= 0 && dp.index < fPictList->count());
+        const SkPaint* paint = NULL;    // drawables don't get a side-car paint
+        this->trackSaveLayersForPicture(fPictList->begin()[dp.index], paint);
+    }
+
     // Inform all the saveLayers already on the stack that they now have a
     // nested saveLayer inside them
     void updateStackForSaveLayer() {
@@ -743,6 +764,7 @@
     int                   fSaveLayersInStack;
     SkTDArray<SaveLayerInfo> fSaveLayerStack;
     SkLayerInfo*          fAccelData;
+    const SkPicture::SnapshotArray* fPictList;
 
     SkRecords::FillBounds fFillBounds;
 };
@@ -761,8 +783,9 @@
 }
 
 void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record,
-                           SkBBoxHierarchy* bbh, SkLayerInfo* data) {
-    SkRecords::CollectLayers visitor(cullRect, record, data);
+                           const SkPicture::SnapshotArray* pictList, SkBBoxHierarchy* bbh,
+                           SkLayerInfo* data) {
+    SkRecords::CollectLayers visitor(cullRect, record, pictList, data);
 
     for (unsigned curOp = 0; curOp < record.count(); curOp++) {
         visitor.setCurrentOp(curOp);
diff --git a/src/core/SkRecordDraw.h b/src/core/SkRecordDraw.h
index 8ea1bbd..e95123b 100644
--- a/src/core/SkRecordDraw.h
+++ b/src/core/SkRecordDraw.h
@@ -14,16 +14,19 @@
 #include "SkMatrix.h"
 #include "SkRecord.h"
 
+class SkCanvasDrawable;
 class SkLayerInfo;
 
 // Fill a BBH to be used by SkRecordDraw to accelerate playback.
 void SkRecordFillBounds(const SkRect& cullRect, const SkRecord&, SkBBoxHierarchy*);
 
 void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record,
+                           const SkPicture::SnapshotArray*,
                            SkBBoxHierarchy* bbh, SkLayerInfo* data);
 
 // Draw an SkRecord into an SkCanvas.  A convenience wrapper around SkRecords::Draw.
-void SkRecordDraw(const SkRecord&, SkCanvas*, SkPicture const* const drawablePicts[], int drawableCount,
+void SkRecordDraw(const SkRecord&, SkCanvas*, SkPicture const* const drawablePicts[],
+                  SkCanvasDrawable* const drawables[], int drawableCount,
                   const SkBBoxHierarchy*, SkDrawPictureCallback*);
 
 // Draw a portion of an SkRecord into an SkCanvas while replacing clears with drawRects.
@@ -41,11 +44,13 @@
 // This is an SkRecord visitor that will draw that SkRecord to an SkCanvas.
 class Draw : SkNoncopyable {
 public:
-    explicit Draw(SkCanvas* canvas, SkPicture const* const drawablePicts[], int drawableCount,
+    explicit Draw(SkCanvas* canvas, SkPicture const* const drawablePicts[],
+                  SkCanvasDrawable* const drawables[], int drawableCount,
                   const SkMatrix* initialCTM = NULL)
         : fInitialCTM(initialCTM ? *initialCTM : canvas->getTotalMatrix())
         , fCanvas(canvas)
         , fDrawablePicts(drawablePicts)
+        , fDrawables(drawables)
         , fDrawableCount(drawableCount)
     {}
 
@@ -67,6 +72,7 @@
     const SkMatrix fInitialCTM;
     SkCanvas* fCanvas;
     SkPicture const* const* fDrawablePicts;
+    SkCanvasDrawable* const* fDrawables;
     int fDrawableCount;
 };
 
@@ -75,7 +81,8 @@
 public:
     PartialDraw(SkCanvas* canvas, SkPicture const* const drawablePicts[], int drawableCount,
                 const SkRect& clearRect, const SkMatrix& initialCTM)
-        : INHERITED(canvas, drawablePicts, drawableCount, &initialCTM), fClearRect(clearRect) {}
+        : INHERITED(canvas, drawablePicts, NULL, drawableCount, &initialCTM), fClearRect(clearRect)
+    {}
 
     // Same as Draw for all ops except Clear.
     template <typename T> void operator()(const T& r) {
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 22d742f..3548851 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -9,6 +9,28 @@
 #include "SkPatchUtils.h"
 #include "SkPicture.h"
 
+SkCanvasDrawableList::~SkCanvasDrawableList() {
+    fArray.unrefAll();
+}
+
+SkPicture::SnapshotArray* SkCanvasDrawableList::newDrawableSnapshot() {
+    const int count = fArray.count();
+    if (0 == count) {
+        return NULL;
+    }
+    SkAutoTMalloc<const SkPicture*> pics(count);
+    for (int i = 0; i < count; ++i) {
+        pics[i] = fArray[i]->newPictureSnapshot();
+    }
+    return SkNEW_ARGS(SkPicture::SnapshotArray, (pics.detach(), count));
+}
+
+void SkCanvasDrawableList::append(SkCanvasDrawable* drawable) {
+    *fArray.append() = SkRef(drawable);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
 SkRecorder::SkRecorder(SkRecord* record, int width, int height)
     : SkCanvas(SkIRect::MakeWH(width, height), SkCanvas::kConservativeRasterClip_InitFlag)
     , fRecord(record)
@@ -19,29 +41,11 @@
     , fRecord(record)
     , fSaveLayerCount(0) {}
 
-SkRecorder::~SkRecorder() {
-    fDrawableList.unrefAll();
-}
-
 void SkRecorder::forgetRecord() {
-    fDrawableList.unrefAll();
-    fDrawableList.reset();
+    fDrawableList.reset(NULL);
     fRecord = NULL;
 }
 
-SkPicture::SnapshotArray* SkRecorder::newDrawableSnapshot(SkBBHFactory* factory,
-                                                          uint32_t recordFlags) {
-    const int count = fDrawableList.count();
-    if (0 == count) {
-        return NULL;
-    }
-    SkAutoTMalloc<const SkPicture*> pics(count);
-    for (int i = 0; i < count; ++i) {
-        pics[i] = fDrawableList[i]->newPictureSnapshot(factory, recordFlags);
-    }
-    return SkNEW_ARGS(SkPicture::SnapshotArray, (pics.detach(), count));
-}
-
 // To make appending to fRecord a little less verbose.
 #define APPEND(T, ...) \
         SkNEW_PLACEMENT_ARGS(fRecord->append<SkRecords::T>(), SkRecords::T, (__VA_ARGS__))
@@ -146,8 +150,11 @@
 }
 
 void SkRecorder::onDrawDrawable(SkCanvasDrawable* drawable) {
-    *fDrawableList.append() = SkRef(drawable);
-    APPEND(DrawDrawable, drawable->getBounds(), fDrawableList.count() - 1);
+    if (!fDrawableList) {
+        fDrawableList.reset(SkNEW(SkCanvasDrawableList));
+    }
+    fDrawableList->append(drawable);
+    APPEND(DrawDrawable, drawable->getBounds(), fDrawableList->count() - 1);
 }
 
 void SkRecorder::drawPath(const SkPath& path, const SkPaint& paint) {
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index b532c89..be67ddd 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -13,6 +13,24 @@
 #include "SkRecords.h"
 #include "SkTDArray.h"
 
+class SkBBHFactory;
+
+class SkCanvasDrawableList : SkNoncopyable {
+public:
+    ~SkCanvasDrawableList();
+
+    int count() const { return fArray.count(); }
+    SkCanvasDrawable* const* begin() const { return fArray.begin(); }
+
+    void append(SkCanvasDrawable* drawable);
+
+    // Return a new or ref'd array of pictures that were snapped from our drawables.
+    SkPicture::SnapshotArray* newDrawableSnapshot();
+
+private:
+    SkTDArray<SkCanvasDrawable*> fArray;
+};
+
 // SkRecorder provides an SkCanvas interface for recording into an SkRecord.
 
 class SkRecorder : public SkCanvas {
@@ -20,10 +38,9 @@
     // Does not take ownership of the SkRecord.
     SkRecorder(SkRecord*, int width, int height);   // legacy version
     SkRecorder(SkRecord*, const SkRect& bounds);
-    virtual ~SkRecorder() SK_OVERRIDE;
 
-    // Return a new or ref'd array of pictures that were snapped from our drawables.
-    SkPicture::SnapshotArray* newDrawableSnapshot(SkBBHFactory*, uint32_t recordFlags);
+    SkCanvasDrawableList* getDrawableList() const { return fDrawableList.get(); }
+    SkCanvasDrawableList* detachDrawableList() { return fDrawableList.detach(); }
 
     // Make SkRecorder forget entirely about its SkRecord*; all calls to SkRecorder will fail.
     void forgetRecord();
@@ -145,7 +162,7 @@
 
     int fSaveLayerCount;
     SkTDArray<SkBool8> fSaveIsSaveLayer;
-    SkTDArray<SkCanvasDrawable*> fDrawableList;
+    SkAutoTDelete<SkCanvasDrawableList> fDrawableList;
 };
 
 #endif//SkRecorder_DEFINED