replace getTotalClipStack() with replayClips()+ClipVisitor
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 13 Apr 2012 13:50:27 +0000 (13:50 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 13 Apr 2012 13:50:27 +0000 (13:50 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@3670 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkCanvas.h
src/core/SkCanvas.cpp
tests/CanvasTest.cpp

index a09a592..25cc94a 100644 (file)
@@ -886,13 +886,20 @@ public:
      */
     const SkRegion& getTotalClip() const;
 
+    void setExternalMatrix(const SkMatrix* = NULL);
+
+    class ClipVisitor {
+    public:
+        virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
+        virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
+    };
+
     /**
-     *  Return the current clipstack. This mirrors the result in getTotalClip()
-     *  but is represented as a stack of geometric clips + region-ops.
+     *  Replays the clip operations, back to front, that have been applied to
+     *  the canvas, calling the appropriate method on the visitor for each
+     *  clip. All clips have already been transformed into device space.
      */
-    const SkClipStack& getTotalClipStack() const;
-
-    void setExternalMatrix(const SkMatrix* = NULL);
+    void replayClips(ClipVisitor*) const;
 
     ///////////////////////////////////////////////////////////////////////////
 
index c415a10..56ac2da 100644 (file)
@@ -218,7 +218,7 @@ public:
         fCanvas = canvas;
         canvas->updateDeviceCMCache();
 
-        fClipStack = &canvas->getTotalClipStack();
+        fClipStack = &canvas->fClipStack;
         fBounder = canvas->getBounder();
         fCurrLayer = canvas->fMCRec->fTopLayer;
         fSkipEmptyClips = skipEmptyClips;
@@ -1210,6 +1210,22 @@ void SkCanvas::validateClip() const {
 }
 #endif
 
+void SkCanvas::replayClips(ClipVisitor* visitor) const {
+    SkClipStack::B2FIter                iter(fClipStack);
+    const SkClipStack::B2FIter::Clip*   clip;
+
+    SkRect empty = {};
+    while ((clip = iter.next()) != NULL) {
+        if (clip->fPath) {
+            visitor->clipPath(*clip->fPath, clip->fOp, clip->fDoAA);
+        } else if (clip->fRect) {
+            visitor->clipRect(*clip->fRect, clip->fOp, clip->fDoAA);
+        } else {
+            visitor->clipRect(empty, SkRegion::kIntersect_Op, false);
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 void SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const {
@@ -1342,10 +1358,6 @@ const SkRegion& SkCanvas::getTotalClip() const {
     return fMCRec->fRasterClip->forceGetBW();
 }
 
-const SkClipStack& SkCanvas::getTotalClipStack() const {
-    return fClipStack;
-}
-
 void SkCanvas::setExternalMatrix(const SkMatrix* matrix) {
     if (NULL == matrix || matrix->isIdentity()) {
         if (fUseExternalMatrix) {
index 65a3494..b008a57 100644 (file)
 #include "SkTDArray.h"
 #include "Test.h"
 
+class Canvas2CanvasClipVisitor : public SkCanvas::ClipVisitor {
+public:
+    Canvas2CanvasClipVisitor(SkCanvas* target) : fTarget(target) {}
+
+    virtual void clipRect(const SkRect& r, SkRegion::Op op, bool aa) {
+        fTarget->clipRect(r, op, aa);
+    }
+    virtual void clipPath(const SkPath& p, SkRegion::Op op, bool aa) {
+        fTarget->clipPath(p, op, aa);
+    }
+
+private:
+    SkCanvas* fTarget;
+};
+
+static void test_clipVisitor(skiatest::Reporter* reporter, SkCanvas* canvas) {
+    SkISize size = canvas->getDeviceSize();
+    
+    SkBitmap bm;
+    bm.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
+    SkCanvas c(bm);
+
+    Canvas2CanvasClipVisitor visitor(&c);
+    canvas->replayClips(&visitor);
+
+    REPORTER_ASSERT(reporter, c.getTotalClip() == canvas->getTotalClip());
+}
+
 static const int kWidth = 2;
 static const int kHeight = 2;
 // Maximum stream length for picture serialization
@@ -436,8 +464,6 @@ static void AssertCanvasStatesEqual(skiatest::Reporter* reporter,
         canvas2->getClipType(), testStep->assertMessage());
     REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalClip() ==
         canvas2->getTotalClip(), testStep->assertMessage());
-    REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalClipStack() ==
-        canvas2->getTotalClipStack(), testStep->assertMessage());
 
     // The following test code is commented out because the test fails when
     // the canvas is an SkPictureRecord or SkDeferredCanvas