Index: src/core/SkCanvas.cpp |
=================================================================== |
--- src/core/SkCanvas.cpp (revision 13622) |
+++ src/core/SkCanvas.cpp (working copy) |
@@ -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; |
} |