Merge "Fix persistent Canvas clip handling"
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index a8f8134..6d3dfac 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -240,11 +240,15 @@
     return count;
 }
 
+// The SkiaCanvas::restore operation layers on the capability to preserve
+// either (or both) the matrix and/or clip state after a SkCanvas::restore
+// operation. It does this by explicitly saving off the clip & matrix state
+// when requested and playing it back after the SkCanvas::restore.
 void SkiaCanvas::restore() {
     const SaveRec* rec = (NULL == mSaveStack.get())
             ? NULL
             : static_cast<SaveRec*>(mSaveStack->back());
-    int currentSaveCount = mCanvas->getSaveCount() - 1;
+    int currentSaveCount = mCanvas->getSaveCount();
     SkASSERT(NULL == rec || currentSaveCount >= rec->saveCount);
 
     if (NULL == rec || rec->saveCount != currentSaveCount) {
@@ -262,8 +266,9 @@
     }
 
     SkTArray<SkClipStack::Element> savedClips;
+    int topClipStackFrame = mCanvas->getClipStack()->getSaveCount();
     if (preserveClip) {
-        saveClipsForFrame(savedClips, currentSaveCount);
+        saveClipsForFrame(savedClips, topClipStackFrame);
     }
 
     mCanvas->restore();
@@ -272,7 +277,11 @@
         mCanvas->setMatrix(savedMatrix);
     }
 
-    if (preserveClip && !savedClips.empty()) {
+    if (preserveClip && !savedClips.empty() &&
+        topClipStackFrame != mCanvas->getClipStack()->getSaveCount()) {
+        // Only reapply the saved clips if the top clip stack frame was actually
+        // popped by restore().  If it wasn't, it means it doesn't belong to the
+        // restored canvas frame (SkCanvas lazy save/restore kicked in).
         applyClips(savedClips);
     }
 
@@ -322,21 +331,23 @@
     }
 
     SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back());
-    // Store the save counter in the SkClipStack domain.
-    // (0-based, equal to the number of save ops on the stack).
-    rec->saveCount = mCanvas->getSaveCount() - 1;
+    rec->saveCount = mCanvas->getSaveCount();
     rec->saveFlags = flags;
 }
 
-void SkiaCanvas::saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount) {
+void SkiaCanvas::saveClipsForFrame(SkTArray<SkClipStack::Element>& clips,
+                                   int saveCountToBackup) {
+    // Each SkClipStack::Element stores the index of the canvas save
+    // with which it is associated. Backup only those Elements that
+    // are associated with 'saveCountToBackup'
     SkClipStack::Iter clipIterator(*mCanvas->getClipStack(),
                                    SkClipStack::Iter::kTop_IterStart);
-    while (const SkClipStack::Element* elem = clipIterator.next()) {
-        if (elem->getSaveCount() < frameSaveCount) {
-            // done with the current frame.
+    while (const SkClipStack::Element* elem = clipIterator.prev()) {
+        if (elem->getSaveCount() < saveCountToBackup) {
+            // done with the target save count.
             break;
         }
-        SkASSERT(elem->getSaveCount() == frameSaveCount);
+        SkASSERT(elem->getSaveCount() == saveCountToBackup);
         clips.push_back(*elem);
     }
 }