add new onClip* methods to SkCanvas

https://codereview.chromium.org/183453002/



git-svn-id: http://skia.googlecode.com/svn/trunk@13627 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index bc14974..96d16fc 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1166,6 +1166,12 @@
 //////////////////////////////////////////////////////////////////////////////
 
 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
+    this->onClipRect(rect, op, edgeStyle);
+    return !this->isClipEmpty();
+}
+
+void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
 #ifdef SK_ENABLE_CLIP_QUICKREJECT
     if (SkRegion::kIntersect_Op == op) {
         if (fMCRec->fRasterClip->isEmpty()) {
@@ -1186,7 +1192,9 @@
 
     fDeviceCMDirty = true;
     fCachedLocalClipBoundsDirty = true;
-    doAA &= fAllowSoftClip;
+    if (!fAllowSoftClip) {
+        edgeStyle = kHard_ClipEdgeStyle;
+    }
 
     if (fMCRec->fMatrix->rectStaysRect()) {
         // for these simpler matrices, we can stay a rect even after applying
@@ -1196,8 +1204,8 @@
         SkRect      r;
 
         fMCRec->fMatrix->mapRect(&r, rect);
-        fClipStack.clipDevRect(r, op, doAA);
-        return fMCRec->fRasterClip->op(r, op, doAA);
+        fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
+        fMCRec->fRasterClip->op(r, op, kSoft_ClipEdgeStyle == edgeStyle);
     } else {
         // since we're rotated or some such thing, we convert the rect to a path
         // and clip against that, since it can handle any matrix. However, to
@@ -1206,12 +1214,12 @@
         SkPath  path;
 
         path.addRect(rect);
-        return this->SkCanvas::clipPath(path, op, doAA);
+        this->SkCanvas::onClipPath(path, op, edgeStyle);
     }
 }
 
-static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip,
-                           const SkPath& devPath, SkRegion::Op op, bool doAA) {
+static void clip_path_helper(const SkCanvas* canvas, SkRasterClip* currClip,
+                             const SkPath& devPath, SkRegion::Op op, bool doAA) {
     // base is used to limit the size (and therefore memory allocation) of the
     // region that results from scan converting devPath.
     SkRegion base;
@@ -1224,60 +1232,81 @@
             // FIXME: we should also be able to do this when currClip->isBW(),
             // but relaxing the test above triggers GM asserts in
             // SkRgnBuilder::blitH(). We need to investigate what's going on.
-            return currClip->setPath(devPath, currClip->bwRgn(), doAA);
+            currClip->setPath(devPath, currClip->bwRgn(), doAA);
         } else {
             base.setRect(currClip->getBounds());
             SkRasterClip clip;
             clip.setPath(devPath, base, doAA);
-            return currClip->op(clip, op);
+            currClip->op(clip, op);
         }
     } else {
         const SkBaseDevice* device = canvas->getDevice();
         if (!device) {
-            return currClip->setEmpty();
+            currClip->setEmpty();
+            return;
         }
 
         base.setRect(0, 0, device->width(), device->height());
 
         if (SkRegion::kReplace_Op == op) {
-            return currClip->setPath(devPath, base, doAA);
+            currClip->setPath(devPath, base, doAA);
         } else {
             SkRasterClip clip;
             clip.setPath(devPath, base, doAA);
-            return currClip->op(clip, op);
+            currClip->op(clip, op);
         }
     }
 }
 
 bool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
     if (rrect.isRect()) {
-        // call the non-virtual version
-        return this->SkCanvas::clipRect(rrect.getBounds(), op, doAA);
+        this->onClipRect(rrect.getBounds(), op, edgeStyle);
+    } else {
+        this->onClipRRect(rrect, op, edgeStyle);
     }
+    return !this->isClipEmpty();
+}
 
+void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
     SkRRect transformedRRect;
     if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) {
         AutoValidateClip avc(this);
 
         fDeviceCMDirty = true;
         fCachedLocalClipBoundsDirty = true;
-        doAA &= fAllowSoftClip;
+        if (!fAllowSoftClip) {
+            edgeStyle = kHard_ClipEdgeStyle;
+        }
 
-        fClipStack.clipDevRRect(transformedRRect, op, doAA);
+        fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
 
         SkPath devPath;
         devPath.addRRect(transformedRRect);
 
-        return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA);
+        clip_path_helper(this, fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
+        return;
     }
 
     SkPath path;
     path.addRRect(rrect);
     // call the non-virtual version
-    return this->SkCanvas::clipPath(path, op, doAA);
+    this->SkCanvas::onClipPath(path, op, edgeStyle);
 }
 
 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
+    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
+    SkRect r;
+    if (!path.isInverseFillType() && path.isRect(&r)) {
+        this->onClipRect(r, op, edgeStyle);
+    } else {
+        this->onClipPath(path, op, edgeStyle);
+    }
+
+    return !this->isClipEmpty();
+}
+
+void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
 #ifdef SK_ENABLE_CLIP_QUICKREJECT
     if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
         if (fMCRec->fRasterClip->isEmpty()) {
@@ -1298,7 +1327,9 @@
 
     fDeviceCMDirty = true;
     fCachedLocalClipBoundsDirty = true;
-    doAA &= fAllowSoftClip;
+    if (!fAllowSoftClip) {
+        edgeStyle = kHard_ClipEdgeStyle;
+    }
 
     SkPath devPath;
     path.transform(*fMCRec->fMatrix, &devPath);
@@ -1314,7 +1345,7 @@
     }
 
     // if we called path.swap() we could avoid a deep copy of this path
-    fClipStack.clipDevPath(devPath, op, doAA);
+    fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
 
     if (fAllowSimplifyClip) {
         devPath.reset();
@@ -1338,12 +1369,14 @@
             // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
             // perhaps we need an API change to avoid this sort of mixed-signals about
             // clipping.
-            doAA |= element->isAA();
+            if (element->isAA()) {
+                edgeStyle = kSoft_ClipEdgeStyle;
+            }
         }
         op = SkRegion::kReplace_Op;
     }
 
-    return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA);
+    clip_path_helper(this, fMCRec->fRasterClip, devPath, op, edgeStyle);
 }
 
 bool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op,
@@ -1369,13 +1402,12 @@
             case SkRegion::kIntersect_Op:
             case SkRegion::kDifference_Op:
                 // These ops can only shrink the current clip. So leaving
-                // the clip unchanges conservatively respects the contract.
-                return this->getClipDeviceBounds(NULL);
+                // the clip unchanged conservatively respects the contract.
+                break;
             case SkRegion::kUnion_Op:
             case SkRegion::kReplace_Op:
             case SkRegion::kReverseDifference_Op:
-            case SkRegion::kXOR_Op:
-                {
+            case SkRegion::kXOR_Op: {
                     // These ops can grow the current clip up to the extents of
                     // the input clip, which is inverse filled, so we just set
                     // the current clip to the device bounds.
@@ -1386,11 +1418,11 @@
                     this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag);
                     // set the clip in device space
                     this->SkCanvas::setMatrix(SkMatrix::I());
-                    bool result = this->SkCanvas::clipRect(deviceBounds,
-                        SkRegion::kReplace_Op, false);
+                    this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_Op, 
+                                               kHard_ClipEdgeStyle);
                     this->SkCanvas::restore(); //pop the matrix, but keep the clip
-                    return result;
-                }
+                    break;
+            }
             default:
                 SkASSERT(0); // unhandled op?
         }
@@ -1400,27 +1432,36 @@
             case SkRegion::kIntersect_Op:
             case SkRegion::kUnion_Op:
             case SkRegion::kReplace_Op:
-                return this->SkCanvas::clipRect(bounds, op, false);
+                this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle);
+                break;
             case SkRegion::kDifference_Op:
                 // Difference can only shrink the current clip.
                 // Leaving clip unchanged conservatively fullfills the contract.
-                return this->getClipDeviceBounds(NULL);
+                break;
             case SkRegion::kReverseDifference_Op:
                 // To reverse, we swap in the bounds with a replace op.
                 // As with difference, leave it unchanged.
-                return this->SkCanvas::clipRect(bounds, SkRegion::kReplace_Op, false);
+                this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
+                break;
             case SkRegion::kXOR_Op:
                 // Be conservative, based on (A XOR B) always included in (A union B),
                 // which is always included in (bounds(A) union bounds(B))
-                return this->SkCanvas::clipRect(bounds, SkRegion::kUnion_Op, false);
+                this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_ClipEdgeStyle);
+                break;
             default:
                 SkASSERT(0); // unhandled op?
         }
     }
-    return true;
+
+    return !this->isClipEmpty();
 }
 
 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
+    this->onClipRegion(rgn, op);
+    return !this->isClipEmpty();
+}
+
+void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
     AutoValidateClip avc(this);
 
     fDeviceCMDirty = true;
@@ -1430,7 +1471,7 @@
     // we have to ignore it, and use the region directly?
     fClipStack.clipDevRect(rgn.getBounds(), op);
 
-    return fMCRec->fRasterClip->op(rgn, op);
+    fMCRec->fRasterClip->op(rgn, op);
 }
 
 #ifdef SK_DEBUG
@@ -1460,11 +1501,7 @@
             default: {
                 SkPath path;
                 element->asPath(&path);
-                clipPathHelper(this,
-                               &tmpClip,
-                               path,
-                               element->getOp(),
-                               element->isAA());
+                clip_path_helper(this, &tmpClip, path, element->getOp(), element->isAA());
                 break;
             }
         }
@@ -1543,7 +1580,7 @@
 
 bool SkCanvas::getClipBounds(SkRect* bounds) const {
     SkIRect ibounds;
-    if (!getClipDeviceBounds(&ibounds)) {
+    if (!this->getClipDeviceBounds(&ibounds)) {
         return false;
     }
 
@@ -1588,8 +1625,12 @@
 }
 
 SkCanvas::ClipType SkCanvas::getClipType() const {
-    if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType;
-    if (fMCRec->fRasterClip->isRect()) return kRect_ClipType;
+    if (fMCRec->fRasterClip->isEmpty()) {
+        return kEmpty_ClipType;
+    }
+    if (fMCRec->fRasterClip->isRect()) {
+        return kRect_ClipType;
+    }
     return kComplex_ClipType;
 }