Store SkRRects in SkClipStack

BUG=skia:2181
R=robertphillips@google.com

Author: bsalomon@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13465 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkClipStack.h b/include/core/SkClipStack.h
index 0d6cfb2..0896db4 100644
--- a/include/core/SkClipStack.h
+++ b/include/core/SkClipStack.h
@@ -11,6 +11,7 @@
 #include "SkDeque.h"
 #include "SkPath.h"
 #include "SkRect.h"
+#include "SkRRect.h"
 #include "SkRegion.h"
 #include "SkTDArray.h"
 
@@ -41,6 +42,8 @@
             kEmpty_Type,
             //!< This element combines a rect with the current clip using a set operation
             kRect_Type,
+            //!< This element combines a round-rect with the current clip using a set operation
+            kRRect_Type,
             //!< This element combines a path with the current clip using a set operation
             kPath_Type,
         };
@@ -54,46 +57,35 @@
             this->initRect(0, rect, op, doAA);
         }
 
+        Element(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+            this->initRRect(0, rrect, op, doAA);
+        }
+
         Element(const SkPath& path, SkRegion::Op op, bool doAA) {
             this->initPath(0, path, op, doAA);
         }
 
-        bool operator== (const Element& element) const {
-            if (this == &element) {
-                return true;
-            }
-            if (fOp != element.fOp ||
-                fType != element.fType ||
-                fDoAA != element.fDoAA ||
-                fSaveCount != element.fSaveCount) {
-                return false;
-            }
-            switch (fType) {
-                case kPath_Type:
-                    return fPath == element.fPath;
-                case kRect_Type:
-                    return fRect == element.fRect;
-                case kEmpty_Type:
-                    return true;
-                default:
-                    SkDEBUGFAIL("Unexpected type.");
-                    return false;
-            }
-        }
+        bool operator== (const Element& element) const;
         bool operator!= (const Element& element) const { return !(*this == element); }
 
         //!< Call to get the type of the clip element.
         Type getType() const { return fType; }
 
         //!< Call if getType() is kPath to get the path.
-        const SkPath& getPath() const { return fPath; }
+        const SkPath& getPath() const { SkASSERT(kPath_Type == fType); return fPath; }
+
+        //!< Call if getType() is kRRect to get the round-rect.
+        const SkRRect& getRRect() const { SkASSERT(kRRect_Type == fType); return fRRect; }
 
         //!< Call if getType() is kRect to get the rect.
-        const SkRect& getRect() const { return fRect; }
+        const SkRect& getRect() const { SkASSERT(kRect_Type == fType); return fRect; }
 
         //!< Call if getType() is not kEmpty to get the set operation used to combine this element.
         SkRegion::Op getOp() const { return fOp; }
 
+        //!< Call to get the element as a path, regardless of its type.
+        void asPath(SkPath* path) const;
+
         /** If getType() is not kEmpty this indicates whether the clip shape should be anti-aliased
             when it is rasterized. */
         bool isAA() const { return fDoAA; }
@@ -120,6 +112,8 @@
             switch (fType) {
                 case kRect_Type:
                     return fRect;
+                case kRRect_Type:
+                    return fRRect.getBounds();
                 case kPath_Type:
                     return fPath.getBounds();
                 case kEmpty_Type:
@@ -138,6 +132,8 @@
             switch (fType) {
                 case kRect_Type:
                     return fRect.contains(rect);
+                case kRRect_Type:
+                    return fRRect.contains(rect);
                 case kPath_Type:
                     return fPath.conservativelyContainsRect(rect);
                 case kEmpty_Type:
@@ -160,6 +156,7 @@
 
         SkPath          fPath;
         SkRect          fRect;
+        SkRRect         fRRect;
         int             fSaveCount; // save count of stack when this element was added.
         SkRegion::Op    fOp;
         Type            fType;
@@ -189,6 +186,10 @@
             this->setEmpty();
         }
 
+        Element(int saveCount, const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+            this->initRRect(saveCount, rrect, op, doAA);
+        }
+
         Element(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) {
             this->initRect(saveCount, rect, op, doAA);
         }
@@ -215,20 +216,29 @@
             this->initCommon(saveCount, op, doAA);
         }
 
-        void initPath(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) {
-            fPath = path;
-            fType = kPath_Type;
+        void initRRect(int saveCount, const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+            if (rrect.isRect()) {
+                fRect = rrect.getBounds();
+                fType = kRect_Type;
+            } else {
+                fRRect = rrect;
+                fType = kRRect_Type;
+            }
             this->initCommon(saveCount, op, doAA);
         }
 
+        void initPath(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA);
+
         void setEmpty() {
             fType = kEmpty_Type;
             fFiniteBound.setEmpty();
             fFiniteBoundType = kNormal_BoundsType;
             fIsIntersectionOfRects = false;
             fRect.setEmpty();
+            fRRect.setEmpty();
             fPath.reset();
             fGenID = kEmptyGenID;
+            SkDEBUGCODE(this->checkEmpty();)
         }
 
         // All Element methods below are only used within SkClipStack.cpp
@@ -305,6 +315,7 @@
         this->clipDevRect(r, op, false);
     }
     void clipDevRect(const SkRect&, SkRegion::Op, bool doAA);
+    void clipDevRRect(const SkRRect&, SkRegion::Op, bool doAA);
     void clipDevPath(const SkPath&, SkRegion::Op, bool doAA);
     // An optimized version of clipDevRect(emptyRect, kIntersect, ...)
     void clipEmpty();
@@ -428,6 +439,11 @@
     static int32_t     gGenID;
 
     /**
+     * Helper for clipDevPath, etc.
+     */
+    void pushElement(const Element& element);
+
+    /**
      * Restore the stack back to the specified save count.
      */
     void restoreTo(int saveCount);