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() {