add clipstack to canvas. not used yet, but will be for devices (e.g. gpu) that
want to see how the clip was built



git-svn-id: http://skia.googlecode.com/svn/trunk@824 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 046c692..88b012d 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -528,6 +528,7 @@
         while ((rec = (MCRec*)iter.next()) != NULL) {
             (void)rec->fRegion->setEmpty();
         }
+        fClipStack.reset();
     } else {
         // compute our total bounds for all devices
         SkIRect bounds;
@@ -539,6 +540,7 @@
         while ((rec = (MCRec*)iter.next()) != NULL) {
             (void)rec->fRegion->op(bounds, SkRegion::kIntersect_Op);
         }
+        fClipStack.clipDevRect(bounds, SkRegion::kIntersect_Op);
     }
     return device;
 }
@@ -648,6 +650,9 @@
     newTop->fNext = fMCRec;
     fMCRec = newTop;
 
+    fClipStack.save();
+    SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
+
     return saveCount;
 }
 
@@ -729,6 +734,7 @@
         ir = clipBounds;
     }
 
+    fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op);
     // early exit if the clip is now empty
     if (bounds_affects_clip(flags) &&
         !fMCRec->fRegion->op(ir, SkRegion::kIntersect_Op)) {
@@ -775,6 +781,7 @@
     fLocalBoundsCompareTypeDirty = true;
     fLocalBoundsCompareTypeDirtyBW = true;
 
+    fClipStack.restore();
 	// reserve our layer (if any)
     DeviceCM* layer = fMCRec->fLayer;   // may be null
     // now detach it from fMCRec so we can pop(). Gets freed after its drawn
@@ -798,6 +805,8 @@
         }
         SkDELETE(layer);
 	}
+
+    SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
 }
 
 int SkCanvas::getSaveCount() const {
@@ -910,7 +919,33 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
+#ifdef SK_DEBUG
+void SkCanvas::validateClip() const {
+    const SkRegion& rgn = this->getTotalClip();
+    const SkDevice* device = this->getDevice();
+    SkIRect ir;
+    ir.set(0, 0, device->width(), device->height());
+    SkRegion clipRgn(ir);
+
+    SkClipStack::B2FIter                iter(fClipStack);
+    const SkClipStack::B2FIter::Clip*   clip;
+    while ((clip = iter.next()) != NULL) {
+        if (clip->fPath) {
+            clipRgn.setPath(*clip->fPath, clipRgn);
+        } else if (clip->fRect) {
+            clip->fRect->round(&ir);
+            clipRgn.op(ir, clip->fOp);
+        } else {
+            break;
+        }
+    }
+    SkASSERT(rgn == clipRgn);
+}
+#endif
+
 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
+    AutoValidateClip avc(this);
+
     fDeviceCMDirty = true;
     fLocalBoundsCompareTypeDirty = true;
     fLocalBoundsCompareTypeDirtyBW = true;
@@ -924,6 +959,7 @@
         SkIRect     ir;
 
         fMCRec->fMatrix->mapRect(&r, rect);
+        fClipStack.clipDevRect(r, op);
         r.round(&ir);
         return fMCRec->fRegion->op(ir, op);
     } else {
@@ -939,6 +975,8 @@
 }
 
 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) {
+    AutoValidateClip avc(this);
+
     fDeviceCMDirty = true;
     fLocalBoundsCompareTypeDirty = true;
     fLocalBoundsCompareTypeDirtyBW = true;
@@ -946,6 +984,9 @@
     SkPath devPath;
     path.transform(*fMCRec->fMatrix, &devPath);
 
+    // if we called path.swap() we could avoid a deep copy of this path
+    fClipStack.clipDevPath(devPath, op);
+
     if (SkRegion::kIntersect_Op == op) {
         return fMCRec->fRegion->setPath(devPath, *fMCRec->fRegion);
     } else {
@@ -964,13 +1005,21 @@
 }
 
 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
+    AutoValidateClip avc(this);
+
     fDeviceCMDirty = true;
     fLocalBoundsCompareTypeDirty = true;
     fLocalBoundsCompareTypeDirtyBW = true;
 
+    // todo: signal fClipStack that we have a region, and therefore (I guess)
+    // we have to ignore it, and use the region directly?
+    fClipStack.clipDevRect(rgn.getBounds());
+
     return fMCRec->fRegion->op(rgn, op);
 }
 
+///////////////////////////////////////////////////////////////////////////////
+
 void SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const {
     SkRect r;
     SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType :