split SkPictureRecorder out of SkPicture

https://codereview.chromium.org/214953003/



git-svn-id: http://skia.googlecode.com/svn/trunk@14171 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index 50371d1..9b34b08 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -495,12 +495,13 @@
 static void DrawPictureTestStep(SkCanvas* canvas,
                                 skiatest::Reporter*,
                                 CanvasTestStep*) {
-    SkPicture* testPicture = SkNEW_ARGS(SkPicture, ());
-    SkAutoUnref aup(testPicture);
-    SkCanvas* testCanvas = testPicture->beginRecording(kWidth, kHeight);
+    SkPictureRecorder recorder;
+    SkCanvas* testCanvas = recorder.beginRecording(kWidth, kHeight);
     testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1));
     testCanvas->clipRect(kTestRect);
     testCanvas->drawRect(kTestRect, kTestPaint);
+    SkAutoTUnref<SkPicture> testPicture(recorder.endRecording());
+
     canvas->drawPicture(*testPicture);
 }
 TEST_STEP(DrawPicture, DrawPictureTestStep);
@@ -722,24 +723,23 @@
         // Verify that when a test step is executed twice, no extra resources
         // are flattened during the second execution
         testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat);
-        SkPicture referencePicture;
-        SkCanvas* referenceCanvas = referencePicture.beginRecording(kWidth,
-            kHeight, recordFlags);
+        SkPictureRecorder referenceRecorder;
+        SkCanvas* referenceCanvas = referenceRecorder.beginRecording(kWidth,
+                                                                     kHeight, recordFlags);
         testStep->draw(referenceCanvas, reporter);
-        SkPicture testPicture;
-        SkCanvas* testCanvas = testPicture.beginRecording(kWidth,
-            kHeight, recordFlags);
+
+        SkPictureRecorder testRecorder;
+        SkCanvas* testCanvas = testRecorder.beginRecording(kWidth,
+                                                           kHeight, recordFlags);
         testStep->draw(testCanvas, reporter);
         testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat);
         testStep->draw(testCanvas, reporter);
 
-        SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(
-            referenceCanvas);
-        SkPictureRecord* testRecord = static_cast<SkPictureRecord*>(
-            testCanvas);
+        SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(referenceCanvas);
+        SkPictureRecord* testRecord = static_cast<SkPictureRecord*>(testCanvas);
         testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat);
         AssertFlattenedObjectsEqual(referenceRecord, testRecord,
-            reporter, testStep);
+                                    reporter, testStep);
     }
 };
 
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index d2a5843..acc9bd5 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -276,8 +276,8 @@
 
     SkMatrix expectedMatrix = canvas.getTotalMatrix();
 
-    SkPicture picture;
-    SkCanvas* recordingCanvas = picture.beginRecording(100, 100,
+    SkPictureRecorder recorder;
+    SkCanvas* recordingCanvas = recorder.beginRecording(100, 100,
         SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
 
     SkPaint paint;
@@ -294,9 +294,9 @@
     recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
     recordingCanvas->restore(); // scale
     recordingCanvas->restore(); // saveLayer
-    picture.endRecording();
+    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
-    canvas.drawPicture(picture);
+    canvas.drawPicture(*picture);
 }
 
 static void test_huge_blur(SkBaseDevice* device, skiatest::Reporter* reporter) {
diff --git a/tests/LayerDrawLooperTest.cpp b/tests/LayerDrawLooperTest.cpp
index 1facb23..bc76a02 100644
--- a/tests/LayerDrawLooperTest.cpp
+++ b/tests/LayerDrawLooperTest.cpp
@@ -32,7 +32,7 @@
     virtual void drawRect(const SkDraw& draw, const SkRect& r,
                           const SkPaint& paint) SK_OVERRIDE {
         fLastMatrix = *draw.fMatrix;
-        INHERITED::drawRect(draw, r, paint);
+        this->INHERITED::drawRect(draw, r, paint);
     }
 
     SkMatrix fLastMatrix;
diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp
index b77beca..defb2e9 100644
--- a/tests/PictureTest.cpp
+++ b/tests/PictureTest.cpp
@@ -301,8 +301,8 @@
                                  SkTDArray<SkPixelRef*> analytic[],
                                  int count,
                                  DrawBitmapProc proc) {
-    SkPicture* pic = new SkPicture;
-    SkCanvas* canvas = pic->beginRecording(1000, 1000);
+    SkPictureRecorder recorder;
+    SkCanvas* canvas = recorder.beginRecording(1000, 1000);
     for (int i = 0; i < count; ++i) {
         analytic[i].rewind();
         canvas->save();
@@ -313,8 +313,7 @@
         proc(canvas, bm[i], bm[count+i], pos[i], &analytic[i]);
         canvas->restore();
     }
-    pic->endRecording();
-    return pic;
+    return recorder.endRecording();
 }
 
 static void rand_rect(SkRect* rect, SkRandom& rand, SkScalar W, SkScalar H) {
@@ -657,22 +656,22 @@
 // Ensure that deleting SkPicturePlayback does not assert. Asserts only fire in debug mode, so only
 // run in debug mode.
 static void test_deleting_empty_playback() {
-    SkPicture picture;
+    SkPictureRecorder recorder;
     // Creates an SkPictureRecord
-    picture.beginRecording(0, 0);
+    recorder.beginRecording(0, 0);
     // Turns that into an SkPicturePlayback
-    picture.endRecording();
+    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
     // Deletes the old SkPicturePlayback, and creates a new SkPictureRecord
-    picture.beginRecording(0, 0);
+    recorder.beginRecording(0, 0);
 }
 
 // Ensure that serializing an empty picture does not assert. Likewise only runs in debug mode.
 static void test_serializing_empty_picture() {
-    SkPicture picture;
-    picture.beginRecording(0, 0);
-    picture.endRecording();
+    SkPictureRecorder recorder;
+    recorder.beginRecording(0, 0);
+    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
     SkDynamicMemoryWStream stream;
-    picture.serialize(&stream);
+    picture->serialize(&stream);
 }
 #endif
 
@@ -712,66 +711,78 @@
     SkPaint paint;
     SkRect rect = SkRect::MakeLTRB(-10000000, -10000000, 10000000, 10000000);
 
-    SkPicture extra_save_picture;
-    extra_save_picture.beginRecording(100, 100);
-    extra_save_picture.getRecordingCanvas()->save();
-    extra_save_picture.getRecordingCanvas()->translate(10, 10);
-    extra_save_picture.getRecordingCanvas()->drawRect(rect, paint);
-    extra_save_picture.getRecordingCanvas()->save();
-    extra_save_picture.getRecordingCanvas()->translate(10, 10);
-    extra_save_picture.getRecordingCanvas()->drawRect(rect, paint);
+    SkPictureRecorder recorder;
 
-    testCanvas.drawPicture(extra_save_picture);
-    REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
+    {
+        // Create picture with 2 unbalanced saves
+        SkCanvas* canvas = recorder.beginRecording(100, 100);
+        canvas->save();
+        canvas->translate(10, 10);
+        canvas->drawRect(rect, paint);
+        canvas->save();
+        canvas->translate(10, 10);
+        canvas->drawRect(rect, paint);
+        SkAutoTUnref<SkPicture> extraSavePicture(recorder.endRecording());
+
+        testCanvas.drawPicture(*extraSavePicture);
+        REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
+    }
 
     set_canvas_to_save_count_4(&testCanvas);
 
-    SkPicture extra_restore_picture;
-    extra_restore_picture.beginRecording(100, 100);
-    extra_restore_picture.getRecordingCanvas()->save();
-    extra_restore_picture.getRecordingCanvas()->translate(10, 10);
-    extra_restore_picture.getRecordingCanvas()->drawRect(rect, paint);
-    extra_restore_picture.getRecordingCanvas()->save();
-    extra_restore_picture.getRecordingCanvas()->translate(10, 10);
-    extra_restore_picture.getRecordingCanvas()->drawRect(rect, paint);
-    extra_restore_picture.getRecordingCanvas()->restore();
-    extra_restore_picture.getRecordingCanvas()->restore();
-    extra_restore_picture.getRecordingCanvas()->restore();
-    extra_restore_picture.getRecordingCanvas()->restore();
+    {
+        // Create picture with 2 unbalanced restores
+        SkCanvas* canvas = recorder.beginRecording(100, 100);
+        canvas->save();
+        canvas->translate(10, 10);
+        canvas->drawRect(rect, paint);
+        canvas->save();
+        canvas->translate(10, 10);
+        canvas->drawRect(rect, paint);
+        canvas->restore();
+        canvas->restore();
+        canvas->restore();
+        canvas->restore();
+        SkAutoTUnref<SkPicture> extraRestorePicture(recorder.endRecording());
 
-    testCanvas.drawPicture(extra_save_picture);
-    REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
+        testCanvas.drawPicture(*extraRestorePicture);
+        REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
+    }
 
-    SkPicture no_save_picture;
-    extra_restore_picture.beginRecording(100, 100);
-    extra_restore_picture.getRecordingCanvas()->translate(10, 10);
-    extra_restore_picture.getRecordingCanvas()->drawRect(rect, paint);
+    set_canvas_to_save_count_4(&testCanvas);
 
-    testCanvas.drawPicture(extra_save_picture);
-    REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
-    REPORTER_ASSERT(reporter, testCanvas.getTotalMatrix().isIdentity());
+    {
+        SkCanvas* canvas = recorder.beginRecording(100, 100);
+        canvas->translate(10, 10);
+        canvas->drawRect(rect, paint);
+        SkAutoTUnref<SkPicture> noSavePicture(recorder.endRecording());
+
+        testCanvas.drawPicture(*noSavePicture);
+        REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
+        REPORTER_ASSERT(reporter, testCanvas.getTotalMatrix().isIdentity());
+    }
 }
 
 static void test_peephole() {
     SkRandom rand;
 
+    SkPictureRecorder recorder;
+
     for (int j = 0; j < 100; j++) {
         SkRandom rand2(rand); // remember the seed
 
-        SkPicture picture;
-        SkCanvas* canvas = picture.beginRecording(100, 100);
+        SkCanvas* canvas = recorder.beginRecording(100, 100);
 
         for (int i = 0; i < 1000; ++i) {
             rand_op(canvas, rand);
         }
-        picture.endRecording();
+        SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
         rand = rand2;
     }
 
     {
-        SkPicture picture;
-        SkCanvas* canvas = picture.beginRecording(100, 100);
+        SkCanvas* canvas = recorder.beginRecording(100, 100);
         SkRect rect = SkRect::MakeWH(50, 50);
 
         for (int i = 0; i < 100; ++i) {
@@ -781,7 +792,7 @@
             canvas->clipRect(rect);
             canvas->restore();
         }
-        picture.endRecording();
+        SkAutoTUnref<SkPicture> picture(recorder.endRecording());
     }
 }
 
@@ -793,13 +804,13 @@
     // fail.
     SkBitmap bm;
     bm.setConfig(SkImageInfo::MakeN32Premul(100, 100));
-    SkPicture picture;
-    SkCanvas* recordingCanvas = picture.beginRecording(100, 100);
+    SkPictureRecorder recorder;
+    SkCanvas* recordingCanvas = recorder.beginRecording(100, 100);
     recordingCanvas->drawBitmap(bm, 0, 0);
-    picture.endRecording();
+    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
     SkCanvas canvas;
-    canvas.drawPicture(picture);
+    canvas.drawPicture(*picture);
 }
 #endif
 
@@ -808,11 +819,13 @@
 }
 
 static SkData* serialized_picture_from_bitmap(const SkBitmap& bitmap) {
-    SkPicture picture;
-    SkCanvas* canvas = picture.beginRecording(bitmap.width(), bitmap.height());
+    SkPictureRecorder recorder;
+    SkCanvas* canvas = recorder.beginRecording(bitmap.width(), bitmap.height());
     canvas->drawBitmap(bitmap, 0, 0);
+    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
+
     SkDynamicMemoryWStream wStream;
-    picture.serialize(&wStream, &encode_bitmap_to_data);
+    picture->serialize(&wStream, &encode_bitmap_to_data);
     return wStream.copyToData();
 }
 
@@ -872,20 +885,11 @@
     // Before the fix, we used to crash accessing a null pointer when we
     // had a picture with no paints. This test passes by not crashing.
     {
-        SkPicture picture;
-        picture.beginRecording(1, 1);
-        picture.endRecording();
-        SkPicture* destPicture = picture.clone();
+        SkPictureRecorder recorder;
+        recorder.beginRecording(1, 1);
+        SkAutoTUnref<SkPicture> picture(recorder.endRecording());
+        SkAutoTUnref<SkPicture> destPicture(picture->clone());
         REPORTER_ASSERT(reporter, NULL != destPicture);
-        destPicture->unref();
-    }
-    {
-        // Test without call to endRecording
-        SkPicture picture;
-        picture.beginRecording(1, 1);
-        SkPicture* destPicture = picture.clone();
-        REPORTER_ASSERT(reporter, NULL != destPicture);
-        destPicture->unref();
     }
 }
 
@@ -897,11 +901,11 @@
 
     {
         // stock SkPicture
-        SkPicture picture;
-        picture.beginRecording(1, 1);
-        picture.endRecording();
+        SkPictureRecorder recorder;
+        recorder.beginRecording(1, 1);
+        SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
-        canvas.drawPicture(picture);
+        canvas.drawPicture(*picture);
     }
 
     {
@@ -911,29 +915,31 @@
         gridInfo.fOffset.setZero();
         gridInfo.fTileInterval.set(1, 1);
 
-        SkTileGridPicture picture(1, 1, gridInfo);
-        picture.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
-        picture.endRecording();
+        SkAutoTUnref<SkPictureFactory> factory(SkNEW_ARGS(SkTileGridPictureFactory, (gridInfo)));
+        SkPictureRecorder recorder(factory);
+        recorder.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
+        SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
-        canvas.drawPicture(picture);
+        canvas.drawPicture(*picture);
     }
 
     {
         // RTree
-        SkPicture picture;
-        picture.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
-        picture.endRecording();
+        SkPictureRecorder recorder;
+        recorder.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
+        SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
-        canvas.drawPicture(picture);
+        canvas.drawPicture(*picture);
     }
 
     {
         // quad tree
-        SkQuadTreePicture picture(SkIRect::MakeWH(1, 1));
-        picture.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
-        picture.endRecording();
+        SkAutoTUnref<SkPictureFactory> factory(SkNEW(SkQuadTreePictureFactory));
+        SkPictureRecorder recorder(factory);
+        recorder.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
+        SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
-        canvas.drawPicture(picture);
+        canvas.drawPicture(*picture);
     }
 }
 
@@ -954,11 +960,11 @@
     SkPath path2;
     path2.addOval(rect3);
     SkIRect clipBounds;
+    SkPictureRecorder recorder;
     // Minimalist test set for 100% code coverage of
     // SkPictureRecord::updateClipConservativelyUsingBounds
     {
-        SkPicture picture;
-        SkCanvas* canvas = picture.beginRecording(10, 10,
+        SkCanvas* canvas = recorder.beginRecording(10, 10,
             SkPicture::kUsePathBoundsForClip_RecordingFlag);
         canvas->clipPath(invPath, SkRegion::kIntersect_Op);
         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
@@ -969,8 +975,7 @@
         REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
     }
     {
-        SkPicture picture;
-        SkCanvas* canvas = picture.beginRecording(10, 10,
+        SkCanvas* canvas = recorder.beginRecording(10, 10,
             SkPicture::kUsePathBoundsForClip_RecordingFlag);
         canvas->clipPath(path, SkRegion::kIntersect_Op);
         canvas->clipPath(invPath, SkRegion::kIntersect_Op);
@@ -982,8 +987,7 @@
         REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
     }
     {
-        SkPicture picture;
-        SkCanvas* canvas = picture.beginRecording(10, 10,
+        SkCanvas* canvas = recorder.beginRecording(10, 10,
             SkPicture::kUsePathBoundsForClip_RecordingFlag);
         canvas->clipPath(path, SkRegion::kIntersect_Op);
         canvas->clipPath(invPath, SkRegion::kUnion_Op);
@@ -995,8 +999,7 @@
         REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
     }
     {
-        SkPicture picture;
-        SkCanvas* canvas = picture.beginRecording(10, 10,
+        SkCanvas* canvas = recorder.beginRecording(10, 10,
             SkPicture::kUsePathBoundsForClip_RecordingFlag);
         canvas->clipPath(path, SkRegion::kDifference_Op);
         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
@@ -1007,8 +1010,7 @@
         REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
     }
     {
-        SkPicture picture;
-        SkCanvas* canvas = picture.beginRecording(10, 10,
+        SkCanvas* canvas = recorder.beginRecording(10, 10,
             SkPicture::kUsePathBoundsForClip_RecordingFlag);
         canvas->clipPath(path, SkRegion::kReverseDifference_Op);
         bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
@@ -1022,8 +1024,7 @@
         REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
     }
     {
-        SkPicture picture;
-        SkCanvas* canvas = picture.beginRecording(10, 10,
+        SkCanvas* canvas = recorder.beginRecording(10, 10,
             SkPicture::kUsePathBoundsForClip_RecordingFlag);
         canvas->clipPath(path, SkRegion::kIntersect_Op);
         canvas->clipPath(path2, SkRegion::kXOR_Op);
@@ -1081,8 +1082,8 @@
 };
 
 static void test_clip_expansion(skiatest::Reporter* reporter) {
-    SkPicture picture;
-    SkCanvas* canvas = picture.beginRecording(10, 10, 0);
+    SkPictureRecorder recorder;
+    SkCanvas* canvas = recorder.beginRecording(10, 10, 0);
 
     canvas->clipRect(SkRect::MakeEmpty(), SkRegion::kReplace_Op);
     // The following expanding clip should not be skipped.
@@ -1091,9 +1092,10 @@
     SkPaint p;
     p.setColor(SK_ColorBLUE);
     canvas->drawPaint(p);
+    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
     ClipCountingCanvas testCanvas(10, 10);
-    picture.draw(&testCanvas);
+    picture->draw(&testCanvas);
 
     // Both clips should be present on playback.
     REPORTER_ASSERT(reporter, testCanvas.getClipCount() == 2);
@@ -1103,95 +1105,87 @@
     SkBitmap bm;
     make_bm(&bm, 10, 10, SK_ColorRED, true);
 
-    SkCanvas* canvas;
+    SkPictureRecorder recorder;
 
-    SkPicture childPlain;
-    childPlain.beginRecording(10, 10);
-    childPlain.endRecording();
-    REPORTER_ASSERT(reporter, !childPlain.willPlayBackBitmaps()); // 0
+    recorder.beginRecording(10, 10);
+    SkAutoTUnref<SkPicture> childPlain(recorder.endRecording());
+    REPORTER_ASSERT(reporter, !childPlain->willPlayBackBitmaps()); // 0
 
-    SkPicture childWithBitmap;
-    childWithBitmap.beginRecording(10, 10)->drawBitmap(bm, 0, 0);
-    childWithBitmap.endRecording();
-    REPORTER_ASSERT(reporter, childWithBitmap.willPlayBackBitmaps()); // 1
+    recorder.beginRecording(10, 10)->drawBitmap(bm, 0, 0);
+    SkAutoTUnref<SkPicture> childWithBitmap(recorder.endRecording());
+    REPORTER_ASSERT(reporter, childWithBitmap->willPlayBackBitmaps()); // 1
 
-    SkPicture parentPP;
-    canvas = parentPP.beginRecording(10, 10);
-    canvas->drawPicture(childPlain);
-    parentPP.endRecording();
-    REPORTER_ASSERT(reporter, !parentPP.willPlayBackBitmaps()); // 0
-
-    SkPicture parentPWB;
-    canvas = parentPWB.beginRecording(10, 10);
-    canvas->drawPicture(childWithBitmap);
-    parentPWB.endRecording();
-    REPORTER_ASSERT(reporter, parentPWB.willPlayBackBitmaps()); // 1
-
-    SkPicture parentWBP;
-    canvas = parentWBP.beginRecording(10, 10);
-    canvas->drawBitmap(bm, 0, 0);
-    canvas->drawPicture(childPlain);
-    parentWBP.endRecording();
-    REPORTER_ASSERT(reporter, parentWBP.willPlayBackBitmaps()); // 1
-
-    SkPicture parentWBWB;
-    canvas = parentWBWB.beginRecording(10, 10);
-    canvas->drawBitmap(bm, 0, 0);
-    canvas->drawPicture(childWithBitmap);
-    parentWBWB.endRecording();
-    REPORTER_ASSERT(reporter, parentWBWB.willPlayBackBitmaps()); // 2
+    {
+        SkCanvas* canvas = recorder.beginRecording(10, 10);
+        canvas->drawPicture(*childPlain);
+        SkAutoTUnref<SkPicture> parentPP(recorder.endRecording());
+        REPORTER_ASSERT(reporter, !parentPP->willPlayBackBitmaps()); // 0
+    }
+    {
+        SkCanvas* canvas = recorder.beginRecording(10, 10);
+        canvas->drawPicture(*childWithBitmap);
+        SkAutoTUnref<SkPicture> parentPWB(recorder.endRecording());
+        REPORTER_ASSERT(reporter, parentPWB->willPlayBackBitmaps()); // 1
+    }
+    {
+        SkCanvas* canvas = recorder.beginRecording(10, 10);
+        canvas->drawBitmap(bm, 0, 0);
+        canvas->drawPicture(*childPlain);
+        SkAutoTUnref<SkPicture> parentWBP(recorder.endRecording());
+        REPORTER_ASSERT(reporter, parentWBP->willPlayBackBitmaps()); // 1
+    }
+    {
+        SkCanvas* canvas = recorder.beginRecording(10, 10);
+        canvas->drawBitmap(bm, 0, 0);
+        canvas->drawPicture(*childWithBitmap);
+        SkAutoTUnref<SkPicture> parentWBWB(recorder.endRecording());
+        REPORTER_ASSERT(reporter, parentWBWB->willPlayBackBitmaps()); // 2
+    }
 }
 
 static void test_gen_id(skiatest::Reporter* reporter) {
 
-    SkPicture hasData, empty, midRecord;
+    SkPicture empty;
 
-    uint32_t beforeID = hasData.uniqueID();
-    REPORTER_ASSERT(reporter, SK_InvalidGenID != beforeID);
+    // Empty pictures should still have a valid ID
+    REPORTER_ASSERT(reporter, empty.uniqueID() != SK_InvalidGenID);
 
-    // all 3 pictures should have different ids
-    REPORTER_ASSERT(reporter, beforeID != empty.uniqueID());
-    REPORTER_ASSERT(reporter, beforeID != midRecord.uniqueID());
-    REPORTER_ASSERT(reporter, empty.uniqueID() != midRecord.uniqueID());
+    SkPictureRecorder recorder;
 
-    hasData.beginRecording(1, 1);
-    // gen ID should be invalid mid-record
-    REPORTER_ASSERT(reporter, SK_InvalidGenID == hasData.uniqueID());
-    hasData.endRecording();
-    // picture should get a new (non-zero) id after recording
-    REPORTER_ASSERT(reporter, hasData.uniqueID() != beforeID);
-    REPORTER_ASSERT(reporter, hasData.uniqueID() != SK_InvalidGenID);
+    SkCanvas* canvas = recorder.beginRecording(1, 1);
+    canvas->drawARGB(255, 255, 255, 255);
+    SkAutoTUnref<SkPicture> hasData(recorder.endRecording());
+    // picture should have a non-zero id after recording
+    REPORTER_ASSERT(reporter, hasData->uniqueID() != SK_InvalidGenID);
 
-    midRecord.beginRecording(1, 1);
-    REPORTER_ASSERT(reporter, SK_InvalidGenID == midRecord.uniqueID());
+    // both pictures should have different ids
+    REPORTER_ASSERT(reporter, hasData->uniqueID() != empty.uniqueID());
 
     // test out copy constructor
-    SkPicture copyWithData(hasData);
-    REPORTER_ASSERT(reporter, hasData.uniqueID() == copyWithData.uniqueID());
+    SkPicture copyWithData(*hasData);
+    REPORTER_ASSERT(reporter, hasData->uniqueID() == copyWithData.uniqueID());
 
     SkPicture emptyCopy(empty);
     REPORTER_ASSERT(reporter, empty.uniqueID() != emptyCopy.uniqueID());
 
-    SkPicture copyMidRecord(midRecord);
-    REPORTER_ASSERT(reporter, midRecord.uniqueID() != copyMidRecord.uniqueID());
-    REPORTER_ASSERT(reporter, copyMidRecord.uniqueID() != SK_InvalidGenID);
-
     // test out swap
-    beforeID = copyMidRecord.uniqueID();
-    copyWithData.swap(copyMidRecord);
-    REPORTER_ASSERT(reporter, copyWithData.uniqueID() == beforeID);
-    REPORTER_ASSERT(reporter, copyMidRecord.uniqueID() == hasData.uniqueID());
+    {
+        SkPicture swapWithData;
+        uint32_t beforeID1 = swapWithData.uniqueID();
+        uint32_t beforeID2 = copyWithData.uniqueID();
+        swapWithData.swap(copyWithData);
+        REPORTER_ASSERT(reporter, copyWithData.uniqueID() == beforeID1);
+        REPORTER_ASSERT(reporter, swapWithData.uniqueID() == beforeID2);
+    }
 
     // test out clone
-    SkAutoTUnref<SkPicture> cloneWithData(hasData.clone());
-    REPORTER_ASSERT(reporter, hasData.uniqueID() == cloneWithData->uniqueID());
+    {
+        SkAutoTUnref<SkPicture> cloneWithData(hasData->clone());
+        REPORTER_ASSERT(reporter, hasData->uniqueID() == cloneWithData->uniqueID());
 
-    SkAutoTUnref<SkPicture> emptyClone(empty.clone());
-    REPORTER_ASSERT(reporter, empty.uniqueID() != emptyClone->uniqueID());
-
-    SkAutoTUnref<SkPicture> cloneMidRecord(midRecord.clone());
-    REPORTER_ASSERT(reporter, midRecord.uniqueID() != cloneMidRecord->uniqueID());
-    REPORTER_ASSERT(reporter, cloneMidRecord->uniqueID() != SK_InvalidGenID);
+        SkAutoTUnref<SkPicture> emptyClone(empty.clone());
+        REPORTER_ASSERT(reporter, empty.uniqueID() != emptyClone->uniqueID());
+    }
 }
 
 DEF_TEST(Picture, reporter) {
@@ -1235,9 +1229,9 @@
 }
 
 DEF_TEST(Picture_EmptyBitmap, r) {
-    SkPicture picture;
-    test_draw_bitmaps(picture.beginRecording(10, 10));
-    picture.endRecording();
+    SkPictureRecorder recorder;
+    test_draw_bitmaps(recorder.beginRecording(10, 10));
+    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 }
 
 DEF_TEST(Canvas_EmptyBitmap, r) {
diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp
index a039e55..1c57aaf 100644
--- a/tests/SerializationTest.cpp
+++ b/tests/SerializationTest.cpp
@@ -369,11 +369,10 @@
 
     // Test simple SkPicture serialization
     {
-        SkPicture* pict = new SkPicture;
-        SkAutoUnref aur(pict);
-        bool didDraw = drawSomething(pict->beginRecording(kBitmapSize, kBitmapSize));
+        SkPictureRecorder recorder;
+        bool didDraw = drawSomething(recorder.beginRecording(kBitmapSize, kBitmapSize));
         REPORTER_ASSERT(reporter, didDraw);
-        pict->endRecording();
+        SkAutoTUnref<SkPicture> pict(recorder.endRecording());
 
         // Serialize picture
         SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag);
diff --git a/tests/TileGridTest.cpp b/tests/TileGridTest.cpp
index f23324a..25425fa 100644
--- a/tests/TileGridTest.cpp
+++ b/tests/TileGridTest.cpp
@@ -56,16 +56,17 @@
     info.fMargin.setEmpty();
     info.fOffset.setZero();
     info.fTileInterval.set(10, 10);
-    SkTileGridPicture picture(20, 20, info);
     SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
                                     SkIntToScalar(8), SkIntToScalar(8));
     SkRect rect2 = SkRect::MakeXYWH(SkIntToScalar(11), SkIntToScalar(11),
                                     SkIntToScalar(1), SkIntToScalar(1));
-    SkCanvas* canvas = picture.beginRecording(20, 20, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
+    SkAutoTUnref<SkPictureFactory> factory(SkNEW_ARGS(SkTileGridPictureFactory, (info)));
+    SkPictureRecorder recorder(factory);
+    SkCanvas* canvas = recorder.beginRecording(20, 20, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
     SkPaint paint;
     canvas->drawRect(rect1, paint);
     canvas->drawRect(rect2, paint);
-    picture.endRecording();
+    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
     SkBitmap store;
     store.allocN32Pixels(1, 1);
@@ -73,14 +74,14 @@
     // Test parts of top-left tile
     {
         MockCanvas mockCanvas(store);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
     }
     {
         MockCanvas mockCanvas(store);
         mockCanvas.translate(-7.99f, -7.99f);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
     }
@@ -88,7 +89,7 @@
     {
         MockCanvas mockCanvas(store);
         mockCanvas.translate(-9.5f, -9.5f);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 2 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
         REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[1]);
@@ -97,7 +98,7 @@
     {
         MockCanvas mockCanvas(store);
         mockCanvas.translate(-16.0f, -16.0f);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
     }
@@ -105,28 +106,28 @@
     {
         MockCanvas mockCanvas(store);
         mockCanvas.translate(2.0f, 0.0f);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
     }
     {
         MockCanvas mockCanvas(store);
         mockCanvas.translate(0.0f, 2.0f);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
     }
     {
         MockCanvas mockCanvas(store);
         mockCanvas.translate(-22.0f, -16.0f);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
     }
     {
         MockCanvas mockCanvas(store);
         mockCanvas.translate(-16.0f, -22.0f);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
     }
@@ -138,7 +139,6 @@
     info.fMargin.set(1, 1);
     info.fOffset.set(-1, -1);
     info.fTileInterval.set(8, 8);
-    SkTileGridPicture picture(20, 20, info);
 
     // rect landing entirely in top left tile
     SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
@@ -149,12 +149,14 @@
     // rect landing entirely in bottomright tile
     SkRect rect3 = SkRect::MakeXYWH(SkIntToScalar(19), SkIntToScalar(19),
                                     SkIntToScalar(1), SkIntToScalar(1));
-    SkCanvas* canvas = picture.beginRecording(20, 20, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
+    SkAutoTUnref<SkPictureFactory> factory(SkNEW_ARGS(SkTileGridPictureFactory, (info)));
+    SkPictureRecorder recorder(factory);
+    SkCanvas* canvas = recorder.beginRecording(20, 20, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
     SkPaint paint;
     canvas->drawRect(rect1, paint);
     canvas->drawRect(rect2, paint);
     canvas->drawRect(rect3, paint);
-    picture.endRecording();
+    SkAutoTUnref<SkPicture> picture(recorder.endRecording());
 
     SkBitmap tileBitmap;
     tileBitmap.allocN32Pixels(10, 10);
@@ -167,14 +169,14 @@
         // The offset should cancel the top and left borders of the top left tile
         // So a look-up at interval 0-10 should be grid aligned,
         MockCanvas mockCanvas(tileBitmap);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
     }
     {
         // Encroaching border by one pixel
         MockCanvas mockCanvas(moreThanATileBitmap);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 2 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
         REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[1]);
@@ -185,14 +187,14 @@
         // with middle tile.
         MockCanvas mockCanvas(tileBitmap);
         mockCanvas.translate(SkIntToScalar(-8), SkIntToScalar(-8));
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
     }
     {
         MockCanvas mockCanvas(tileBitmap);
         mockCanvas.translate(-7.9f, -7.9f);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 2 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
         REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[1]);
@@ -200,7 +202,7 @@
     {
         MockCanvas mockCanvas(tileBitmap);
         mockCanvas.translate(-8.1f, -8.1f);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         REPORTER_ASSERT(reporter, 2 == mockCanvas.fRects.count());
         REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
         REPORTER_ASSERT(reporter, rect3 == mockCanvas.fRects[1]);
@@ -211,7 +213,7 @@
         // adjusted region, sitting right on top of the tile boundary.
         MockCanvas mockCanvas(tinyBitmap);
         mockCanvas.translate(-8.0f, -8.0f);
-        picture.draw(&mockCanvas);
+        picture->draw(&mockCanvas);
         // This test passes by not asserting. We do not validate the rects recorded
         // because the result is numerically unstable (floating point equality).
         // The content of any one of the four tiles of the tilegrid would be a valid