Index: src/core/SkCanvas.cpp |
=================================================================== |
--- src/core/SkCanvas.cpp (revision 13577) |
+++ src/core/SkCanvas.cpp (working copy) |
@@ -1147,6 +1147,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()) { |
@@ -1167,7 +1173,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 |
@@ -1177,8 +1185,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 |
@@ -1187,12 +1195,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; |
@@ -1205,60 +1213,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()) { |
@@ -1279,7 +1308,9 @@ |
fDeviceCMDirty = true; |
fCachedLocalClipBoundsDirty = true; |
- doAA &= fAllowSoftClip; |
+ if (!fAllowSoftClip) { |
+ edgeStyle = kHard_ClipEdgeStyle; |
+ } |
SkPath devPath; |
path.transform(*fMCRec->fMatrix, &devPath); |
@@ -1295,7 +1326,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(); |
@@ -1319,15 +1350,17 @@ |
// 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, |
+void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op, |
bool inverseFilled) { |
// This is for updating the clip conservatively using only bounds |
// information. |
@@ -1351,7 +1384,7 @@ |
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); |
+ return; |
case SkRegion::kUnion_Op: |
case SkRegion::kReplace_Op: |
case SkRegion::kReverseDifference_Op: |
@@ -1367,10 +1400,9 @@ |
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::clipRect(deviceBounds, SkRegion::kReplace_Op, false); |
this->SkCanvas::restore(); //pop the matrix, but keep the clip |
- return result; |
+ return; |
} |
default: |
SkASSERT(0); // unhandled op? |
@@ -1381,27 +1413,34 @@ |
case SkRegion::kIntersect_Op: |
case SkRegion::kUnion_Op: |
case SkRegion::kReplace_Op: |
- return this->SkCanvas::clipRect(bounds, op, false); |
+ this->SkCanvas::clipRect(bounds, op, false); |
+ return; |
case SkRegion::kDifference_Op: |
// Difference can only shrink the current clip. |
// Leaving clip unchanged conservatively fullfills the contract. |
- return this->getClipDeviceBounds(NULL); |
+ return; |
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::clipRect(bounds, SkRegion::kReplace_Op, false); |
+ return; |
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::clipRect(bounds, SkRegion::kUnion_Op, false); |
+ return; |
default: |
SkASSERT(0); // unhandled op? |
} |
} |
- return true; |
} |
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; |
@@ -1411,7 +1450,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 |
@@ -1441,11 +1480,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; |
} |
} |