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