Added ctor to SkClipStack and isEmpty method

http://codereview.appspot.com/6444048/



git-svn-id: http://skia.googlecode.com/svn/trunk@4787 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkClipStack.h b/include/core/SkClipStack.h
index 71b68ce..60ed9ed 100644
--- a/include/core/SkClipStack.h
+++ b/include/core/SkClipStack.h
@@ -24,6 +24,7 @@
 public:
     SkClipStack();
     SkClipStack(const SkClipStack& b);
+    explicit SkClipStack(const SkRect& r);
     ~SkClipStack();
 
     SkClipStack& operator=(const SkClipStack& b);
@@ -68,6 +69,12 @@
     void clipDevRect(const SkRect&, SkRegion::Op, bool doAA);
     void clipDevPath(const SkPath&, SkRegion::Op, bool doAA);
 
+    /**
+     * isWideOpen returns true if the clip state corresponds to the infinite 
+     * plane (i.e., draws are not limited at all)
+     */
+    bool isWideOpen() const;
+
 private:
     struct Rec;
 
diff --git a/src/core/SkClipStack.cpp b/src/core/SkClipStack.cpp
index 7857bdf..673981b 100644
--- a/src/core/SkClipStack.cpp
+++ b/src/core/SkClipStack.cpp
@@ -375,6 +375,12 @@
     *this = b;
 }
 
+SkClipStack::SkClipStack(const SkRect& r) : fDeque(sizeof(Rec)) {
+    if (!r.isEmpty()) {
+        this->clipDevRect(r, SkRegion::kReplace_Op, false);
+    }
+}
+
 SkClipStack::~SkClipStack() {
     reset();
 }
@@ -545,6 +551,16 @@
     ((Rec*) fDeque.back())->updateBound(rec);
 }
 
+bool SkClipStack::isWideOpen() const { 
+    if (0 == fDeque.count()) {
+        return true;
+    }
+    
+    const Rec* back = (const Rec*) fDeque.back();
+    return kInsideOut_BoundsType == back->fFiniteBoundType &&
+           back->fFiniteBound.isEmpty();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 SkClipStack::Iter::Iter() : fStack(NULL) {
diff --git a/tests/ClipStackTest.cpp b/tests/ClipStackTest.cpp
index 02fa8cf..160c544 100644
--- a/tests/ClipStackTest.cpp
+++ b/tests/ClipStackTest.cpp
@@ -260,6 +260,8 @@
                 stack.clipDevPath(clipB, gOps[op], false);
             }
 
+            REPORTER_ASSERT(reporter, !stack.isWideOpen());
+
             stack.getConservativeBounds(0, 0, 100, 100, &bound,
                                         &isIntersectionOfRects);
 
@@ -279,6 +281,77 @@
     }
 }
 
+// Test out 'isWideOpen' entry point
+static void test_isWideOpen(skiatest::Reporter* reporter) {
+
+    SkRect rectA, rectB;
+
+    rectA.iset(10, 10, 40, 40);
+    rectB.iset(50, 50, 80, 80);
+
+    // Stack should initially be wide open
+    {
+        SkClipStack stack;
+
+        REPORTER_ASSERT(reporter, stack.isWideOpen());
+    }
+
+    // Test out case where the user specifies a union that includes everything
+    {
+        SkClipStack stack;
+
+        SkPath clipA, clipB;
+
+        clipA.addRoundRect(rectA, SkIntToScalar(5), SkIntToScalar(5));
+        clipA.setFillType(SkPath::kInverseEvenOdd_FillType);
+
+        clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
+        clipB.setFillType(SkPath::kInverseEvenOdd_FillType);
+
+        stack.clipDevPath(clipA, SkRegion::kReplace_Op, false);
+        stack.clipDevPath(clipB, SkRegion::kUnion_Op, false);
+
+        REPORTER_ASSERT(reporter, stack.isWideOpen());
+    }
+
+    // Test out union w/ a wide open clip
+    {
+        SkClipStack stack;
+
+        stack.clipDevRect(rectA, SkRegion::kUnion_Op, false);
+
+        REPORTER_ASSERT(reporter, stack.isWideOpen());
+    }
+
+    // Test out empty difference from a wide open clip
+    {
+        SkClipStack stack;
+
+        SkRect emptyRect;
+        emptyRect.setEmpty();
+
+        stack.clipDevRect(emptyRect, SkRegion::kDifference_Op, false);
+
+        REPORTER_ASSERT(reporter, stack.isWideOpen());
+    }
+
+    // Test out return to wide open
+    {
+        SkClipStack stack;
+
+        stack.save();
+
+        stack.clipDevRect(rectA, SkRegion::kReplace_Op, false);
+
+        REPORTER_ASSERT(reporter, !stack.isWideOpen());
+
+        stack.restore();
+
+        REPORTER_ASSERT(reporter, stack.isWideOpen());
+    }
+}
+
+
 static void TestClipStack(skiatest::Reporter* reporter) {
     SkClipStack stack;
 
@@ -317,6 +390,7 @@
     test_iterators(reporter);
     test_bounds(reporter, true);
     test_bounds(reporter, false);
+    test_isWideOpen(reporter);
 }
 
 #include "TestClassDef.h"