| 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;
|
| }
|
| }
|
|
|