Ensure playing back a picture always balances saves and restores

This "fixes" the legacy interface's possible creation of pictures with unbalanced save/restores.

The Android dox will need to be updated once/if this lands.

R=reed@google.com, scroggo@google.com

Author: robertphillips@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@14772 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index f2356bd..87cd941 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -859,7 +859,8 @@
 
     // Record this, so we can concat w/ it if we encounter a setMatrix()
     SkMatrix initialMatrix = canvas.getTotalMatrix();
-    int originalSaveCount = canvas.getSaveCount();
+
+    SkAutoCanvasRestore acr(&canvas, false);
 
 #ifdef SK_BUILD_FOR_ANDROID
     fAbortCurrentPlayback = false;
@@ -871,7 +872,6 @@
 
     while (!reader.eof()) {
         if (callback && callback->abortDrawing()) {
-            canvas.restoreToCount(originalSaveCount);
             return;
         }
 #ifdef SK_BUILD_FOR_ANDROID
diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp
index 226280a..8467d6a 100644
--- a/tests/PictureTest.cpp
+++ b/tests/PictureTest.cpp
@@ -975,6 +975,48 @@
         REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
         REPORTER_ASSERT(reporter, testCanvas.getTotalMatrix().isIdentity());
     }
+
+#if defined(SK_SUPPORT_LEGACY_PICTURE_CAN_RECORD) && \
+    defined(SK_SUPPORT_LEGACY_DERIVED_PICTURE_CLASSES)
+    set_canvas_to_save_count_4(&testCanvas);
+
+    // Due to "fake" endRecording, the old SkPicture recording interface
+    // allowed unbalanced saves/restores to leak out. This sub-test checks
+    // that the situation has been remedied.
+    {
+        SkPicture p;
+
+        SkCanvas* canvas = p.beginRecording(100, 100);
+        for (int i = 0; i < 4; ++i) {
+           canvas->save();
+        }
+        SkRect r = SkRect::MakeWH(50, 50);
+        SkPaint paint;
+        canvas->drawRect(r, paint);
+
+        // Copying a mid-recording picture could result in unbalanced saves/restores
+        SkPicture p2(p);
+
+        testCanvas.drawPicture(p2);
+        REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
+        set_canvas_to_save_count_4(&testCanvas);
+
+        // Cloning a mid-recording picture could result in unbalanced saves/restores
+        SkAutoTUnref<SkPicture> p3(p.clone());
+        testCanvas.drawPicture(*p3);
+        REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
+        set_canvas_to_save_count_4(&testCanvas);
+
+        // Serializing a mid-recording picture could result in unbalanced saves/restores
+        SkDynamicMemoryWStream wStream;
+        p.serialize(&wStream);
+        SkAutoDataUnref data(wStream.copyToData());
+        SkMemoryStream stream(data);
+        SkAutoTUnref<SkPicture> p4(SkPicture::CreateFromStream(&stream, NULL));
+        testCanvas.drawPicture(*p4);
+        REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
+    }
+#endif
 }
 
 static void test_peephole() {