diff options
author | Cary Clark <caryclark@google.com> | 2017-03-03 20:27:13 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-03-03 20:27:22 +0000 |
commit | baf06bc89a0ee2ac4033281e7310f6c727faab79 (patch) | |
tree | 13aca9c2e88a457a91f2d0dcf0f3418411ea63fc /src/core/SkRasterClip.cpp | |
parent | 94fc0fe016bbfeb097c829df513673d4fcbb38b3 (diff) |
Revert "Revert[2] "Remove SkDraw from device-draw methods, and enable device-centric clipping."""
This reverts commit cfaa63237b152ae216f1351207bce3ea9808814c.
Reason for revert: speculative revert to fix Google3
Original change's description:
> Revert[2] "Remove SkDraw from device-draw methods, and enable device-centric clipping.""
>
> passes new (augmented) CanvasClipType unittest
> fixed rasterclipstack::setnewsize
>
> This reverts commit ea5e676a7b75600edcde3912886486004ccd7626.
>
> BUG=skia:
>
> Change-Id: I004653e0f4d01454662f8516fccab0046486f273
> Reviewed-on: https://skia-review.googlesource.com/9185
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Mike Reed <reed@google.com>
>
TBR=bsalomon@google.com,reed@google.com,reviews@skia.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:
Change-Id: Ibd7ee6383999f008eb6ee59c1c3f1c06a86044ea
Reviewed-on: https://skia-review.googlesource.com/9230
Reviewed-by: Cary Clark <caryclark@google.com>
Commit-Queue: Cary Clark <caryclark@google.com>
Diffstat (limited to 'src/core/SkRasterClip.cpp')
-rw-r--r-- | src/core/SkRasterClip.cpp | 226 |
1 files changed, 106 insertions, 120 deletions
diff --git a/src/core/SkRasterClip.cpp b/src/core/SkRasterClip.cpp index f43d14e483..a9e043f84f 100644 --- a/src/core/SkRasterClip.cpp +++ b/src/core/SkRasterClip.cpp @@ -8,125 +8,10 @@ #include "SkRasterClip.h" #include "SkPath.h" -enum MutateResult { - kDoNothing_MutateResult, - kReplaceClippedAgainstGlobalBounds_MutateResult, - kContinue_MutateResult, -}; - -static MutateResult mutate_conservative_op(SkRegion::Op* op, bool inverseFilled) { - if (inverseFilled) { - switch (*op) { - case SkRegion::kIntersect_Op: - case SkRegion::kDifference_Op: - // These ops can only shrink the current clip. So leaving - // the clip unchanged conservatively respects the contract. - return kDoNothing_MutateResult; - case SkRegion::kUnion_Op: - case SkRegion::kReplace_Op: - case SkRegion::kReverseDifference_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. - *op = SkRegion::kReplace_Op; - return kReplaceClippedAgainstGlobalBounds_MutateResult; - } - } - } else { - // Not inverse filled - switch (*op) { - case SkRegion::kIntersect_Op: - case SkRegion::kUnion_Op: - case SkRegion::kReplace_Op: - return kContinue_MutateResult; - case SkRegion::kDifference_Op: - // Difference can only shrink the current clip. - // Leaving clip unchanged conservatively fullfills the contract. - return kDoNothing_MutateResult; - case SkRegion::kReverseDifference_Op: - // To reverse, we swap in the bounds with a replace op. - // As with difference, leave it unchanged. - *op = SkRegion::kReplace_Op; - return kContinue_MutateResult; - 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)) - *op = SkRegion::kUnion_Op; - return kContinue_MutateResult; - } - } - SkFAIL("should not get here"); - return kDoNothing_MutateResult; -} - -void SkConservativeClip::op(const SkRect& localRect, const SkMatrix& ctm, const SkIRect& devBounds, - SkRegion::Op op, bool doAA) { - SkRect devRect; - - SkIRect bounds(devBounds); - this->applyClipRestriction(op, &bounds); - SkIRect ir; - switch (mutate_conservative_op(&op, false)) { - case kDoNothing_MutateResult: - return; - case kReplaceClippedAgainstGlobalBounds_MutateResult: - ir = bounds; - break; - case kContinue_MutateResult: - ctm.mapRect(&devRect, localRect); - ir = doAA ? devRect.roundOut() : devRect.round(); - break; - } - this->op(ir, op); -} - -void SkConservativeClip::op(const SkRRect& rrect, const SkMatrix& ctm, const SkIRect& devBounds, - SkRegion::Op op, bool doAA) { - SkIRect bounds(devBounds); - this->applyClipRestriction(op, &bounds); - this->op(rrect.getBounds(), ctm, bounds, op, doAA); -} - -void SkConservativeClip::op(const SkPath& path, const SkMatrix& ctm, const SkIRect& devBounds, - SkRegion::Op op, bool doAA) { - SkIRect bounds(devBounds); - this->applyClipRestriction(op, &bounds); - - SkIRect ir; - switch (mutate_conservative_op(&op, path.isInverseFillType())) { - case kDoNothing_MutateResult: - return; - case kReplaceClippedAgainstGlobalBounds_MutateResult: - ir = bounds; - break; - case kContinue_MutateResult: { - SkRect bounds = path.getBounds(); - ctm.mapRect(&bounds); - ir = bounds.roundOut(); - break; - } - } - return this->op(ir, op); -} - -void SkConservativeClip::op(const SkRegion& rgn, SkRegion::Op op) { - this->op(rgn.getBounds(), op); -} - -void SkConservativeClip::op(const SkIRect& devRect, SkRegion::Op op) { - // This may still create a complex region (which we would then take the bounds - // Perhaps we should inline the op-logic directly to never create the rgn... - SkRegion result; - result.op(SkRegion(fBounds), SkRegion(devRect), op); - fBounds = result.getBounds(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - SkRasterClip::SkRasterClip(const SkRasterClip& src) { AUTO_RASTERCLIP_VALIDATE(src); + fForceConservativeRects = src.fForceConservativeRects; fIsBW = src.fIsBW; if (fIsBW) { fBW = src.fBW; @@ -141,20 +26,23 @@ SkRasterClip::SkRasterClip(const SkRasterClip& src) { } SkRasterClip::SkRasterClip(const SkRegion& rgn) : fBW(rgn) { + fForceConservativeRects = false; fIsBW = true; fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute fIsRect = !fIsEmpty; SkDEBUGCODE(this->validate();) } -SkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) { +SkRasterClip::SkRasterClip(const SkIRect& bounds, bool forceConservativeRects) : fBW(bounds) { + fForceConservativeRects = forceConservativeRects; fIsBW = true; fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute fIsRect = !fIsEmpty; SkDEBUGCODE(this->validate();) } -SkRasterClip::SkRasterClip() { +SkRasterClip::SkRasterClip(bool forceConservativeRects) { + fForceConservativeRects = forceConservativeRects; fIsBW = true; fIsEmpty = true; fIsRect = false; @@ -166,6 +54,8 @@ SkRasterClip::~SkRasterClip() { } bool SkRasterClip::operator==(const SkRasterClip& other) const { + // This impl doesn't care if fForceConservativeRects is the same in both, only the current state + if (fIsBW != other.fIsBW) { return false; } @@ -224,9 +114,65 @@ bool SkRasterClip::setConservativeRect(const SkRect& r, const SkIRect& clipR, bo ///////////////////////////////////////////////////////////////////////////////////// +enum MutateResult { + kDoNothing_MutateResult, + kReplaceClippedAgainstGlobalBounds_MutateResult, + kContinue_MutateResult, +}; + +static MutateResult mutate_conservative_op(SkRegion::Op* op, bool inverseFilled) { + if (inverseFilled) { + switch (*op) { + case SkRegion::kIntersect_Op: + case SkRegion::kDifference_Op: + // These ops can only shrink the current clip. So leaving + // the clip unchanged conservatively respects the contract. + return kDoNothing_MutateResult; + case SkRegion::kUnion_Op: + case SkRegion::kReplace_Op: + case SkRegion::kReverseDifference_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. + *op = SkRegion::kReplace_Op; + return kReplaceClippedAgainstGlobalBounds_MutateResult; + } + } + } else { + // Not inverse filled + switch (*op) { + case SkRegion::kIntersect_Op: + case SkRegion::kUnion_Op: + case SkRegion::kReplace_Op: + return kContinue_MutateResult; + case SkRegion::kDifference_Op: + // Difference can only shrink the current clip. + // Leaving clip unchanged conservatively fullfills the contract. + return kDoNothing_MutateResult; + case SkRegion::kReverseDifference_Op: + // To reverse, we swap in the bounds with a replace op. + // As with difference, leave it unchanged. + *op = SkRegion::kReplace_Op; + return kContinue_MutateResult; + 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)) + *op = SkRegion::kUnion_Op; + return kContinue_MutateResult; + } + } + SkFAIL("should not get here"); + return kDoNothing_MutateResult; +} + bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) { AUTO_RASTERCLIP_VALIDATE(*this); + if (fForceConservativeRects) { + return this->setConservativeRect(path.getBounds(), clip.getBounds(), path.isInverseFillType()); + } + if (this->isBW() && !doAA) { (void)fBW.setPath(path, clip); } else { @@ -244,6 +190,9 @@ bool SkRasterClip::op(const SkRRect& rrect, const SkMatrix& matrix, const SkIRec SkRegion::Op op, bool doAA) { SkIRect bounds(devBounds); this->applyClipRestriction(op, &bounds); + if (fForceConservativeRects) { + return this->op(rrect.getBounds(), matrix, bounds, op, doAA); + } SkPath path; path.addRRect(rrect); @@ -257,6 +206,24 @@ bool SkRasterClip::op(const SkPath& path, const SkMatrix& matrix, const SkIRect& SkIRect bounds(devBounds); this->applyClipRestriction(op, &bounds); + if (fForceConservativeRects) { + SkIRect ir; + switch (mutate_conservative_op(&op, path.isInverseFillType())) { + case kDoNothing_MutateResult: + return !this->isEmpty(); + case kReplaceClippedAgainstGlobalBounds_MutateResult: + ir = bounds; + break; + case kContinue_MutateResult: { + SkRect bounds = path.getBounds(); + matrix.mapRect(&bounds); + ir = bounds.roundOut(); + break; + } + } + return this->op(ir, op); + } + // base is used to limit the size (and therefore memory allocation) of the // region that results from scan converting devPath. SkRegion base; @@ -279,7 +246,7 @@ bool SkRasterClip::op(const SkPath& path, const SkMatrix& matrix, const SkIRect& return this->setPath(devPath, this->bwRgn(), doAA); } else { base.setRect(this->getBounds()); - SkRasterClip clip; + SkRasterClip clip(fForceConservativeRects); clip.setPath(devPath, base, doAA); return this->op(clip, op); } @@ -289,7 +256,7 @@ bool SkRasterClip::op(const SkPath& path, const SkMatrix& matrix, const SkIRect& if (SkRegion::kReplace_Op == op) { return this->setPath(devPath, base, doAA); } else { - SkRasterClip clip; + SkRasterClip clip(fForceConservativeRects); clip.setPath(devPath, base, doAA); return this->op(clip, op); } @@ -364,6 +331,23 @@ bool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, const SkI AUTO_RASTERCLIP_VALIDATE(*this); SkRect devRect; + if (fForceConservativeRects) { + SkIRect bounds(devBounds); + this->applyClipRestriction(op, &bounds); + SkIRect ir; + switch (mutate_conservative_op(&op, false)) { + case kDoNothing_MutateResult: + return !this->isEmpty(); + case kReplaceClippedAgainstGlobalBounds_MutateResult: + ir = bounds; + break; + case kContinue_MutateResult: + matrix.mapRect(&devRect, localRect); + ir = devRect.roundOut(); + break; + } + return this->op(ir, op); + } const bool isScaleTrans = matrix.isScaleTranslate(); if (!isScaleTrans) { SkPath path; @@ -443,6 +427,8 @@ const SkRegion& SkRasterClip::forceGetBW() { void SkRasterClip::convertToAA() { AUTO_RASTERCLIP_VALIDATE(*this); + SkASSERT(!fForceConservativeRects); + SkASSERT(fIsBW); fAA.setRegion(fBW); fIsBW = false; |