diff options
author | Stan Iliev <stani@google.com> | 2016-12-12 17:39:55 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2016-12-12 23:24:31 +0000 |
commit | 5f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2fe (patch) | |
tree | 935c5f0922e389c84644d19fdb0fe6110cc334fc /src | |
parent | 966bb348a5bdeec44252ede4cb73ba907af2d92b (diff) |
Add a method in SkCanvas to set "hard" clip bounds.
Add SkCanvas::setBoundRect, which sets the max clip rectangle,
which can be replaced by clipRect, clipRRect and clipPath.
BUG=skia:
Change-Id: Ie39eb1715214971576e7a1dda760c6997a7e0208
Reviewed-on: https://skia-review.googlesource.com/5359
Commit-Queue: Stan Iliev <stani@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkCanvas.cpp | 14 | ||||
-rw-r--r-- | src/core/SkClipStack.cpp | 14 | ||||
-rw-r--r-- | src/core/SkRasterClip.cpp | 17 | ||||
-rw-r--r-- | src/core/SkRasterClip.h | 24 |
4 files changed, 64 insertions, 5 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 6a825b5402..cb76051add 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -668,6 +668,7 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { fMCRec = (MCRec*)fMCStack.push_back(); new (fMCRec) MCRec(fConservativeRasterClip); + fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect); fIsScaleTranslate = true; SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); @@ -1539,6 +1540,19 @@ void SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeSty fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); } +void SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) { + fClipRestrictionRect = rect; + fClipStack->setDeviceClipRestriction(fClipRestrictionRect); + if (!fClipRestrictionRect.isEmpty()) { + this->checkForDeferredSave(); + AutoValidateClip avc(this); + fClipStack->clipDevRect(fClipRestrictionRect, kIntersect_SkClipOp); + fMCRec->fRasterClip.op(fClipRestrictionRect, SkRegion::kIntersect_Op); + fDeviceCMDirty = true; + fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); + } +} + void SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) { this->checkForDeferredSave(); ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; diff --git a/src/core/SkClipStack.cpp b/src/core/SkClipStack.cpp index c7d5359760..bc8c5c5d62 100644 --- a/src/core/SkClipStack.cpp +++ b/src/core/SkClipStack.cpp @@ -734,6 +734,10 @@ void SkClipStack::clipRRect(const SkRRect& rrect, const SkMatrix& matrix, SkClip if (rrect.transform(matrix, &transformedRRect)) { Element element(fSaveCount, transformedRRect, op, doAA); this->pushElement(element); + if (this->hasClipRestriction(op)) { + Element element(fSaveCount, fClipRestrictionRect, kIntersect_SkClipOp, false); + this->pushElement(element); + } return; } SkPath path; @@ -747,6 +751,11 @@ void SkClipStack::clipRect(const SkRect& rect, const SkMatrix& matrix, SkClipOp if (matrix.rectStaysRect()) { SkRect devRect; matrix.mapRect(&devRect, rect); + if (this->hasClipRestriction(op)) { + if (!devRect.intersect(fClipRestrictionRect)) { + devRect.setEmpty(); + } + } Element element(fSaveCount, devRect, op, doAA); this->pushElement(element); return; @@ -761,9 +770,12 @@ void SkClipStack::clipPath(const SkPath& path, const SkMatrix& matrix, SkClipOp bool doAA) { SkPath devPath; path.transform(matrix, &devPath); - Element element(fSaveCount, devPath, op, doAA); this->pushElement(element); + if (this->hasClipRestriction(op)) { + Element element(fSaveCount, fClipRestrictionRect, kIntersect_SkClipOp, false); + this->pushElement(element); + } } void SkClipStack::clipEmpty() { diff --git a/src/core/SkRasterClip.cpp b/src/core/SkRasterClip.cpp index 1090c66f34..a9e043f84f 100644 --- a/src/core/SkRasterClip.cpp +++ b/src/core/SkRasterClip.cpp @@ -21,6 +21,7 @@ SkRasterClip::SkRasterClip(const SkRasterClip& src) { fIsEmpty = src.isEmpty(); fIsRect = src.isRect(); + fClipRestrictionRect = src.fClipRestrictionRect; SkDEBUGCODE(this->validate();) } @@ -185,8 +186,10 @@ bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) return this->updateCacheAndReturnNonEmpty(); } -bool SkRasterClip::op(const SkRRect& rrect, const SkMatrix& matrix, const SkIRect& bounds, +bool SkRasterClip::op(const SkRRect& rrect, const SkMatrix& matrix, const SkIRect& devBounds, SkRegion::Op op, bool doAA) { + SkIRect bounds(devBounds); + this->applyClipRestriction(op, &bounds); if (fForceConservativeRects) { return this->op(rrect.getBounds(), matrix, bounds, op, doAA); } @@ -197,9 +200,11 @@ bool SkRasterClip::op(const SkRRect& rrect, const SkMatrix& matrix, const SkIRec return this->op(path, matrix, bounds, op, doAA); } -bool SkRasterClip::op(const SkPath& path, const SkMatrix& matrix, const SkIRect& bounds, +bool SkRasterClip::op(const SkPath& path, const SkMatrix& matrix, const SkIRect& devBounds, SkRegion::Op op, bool doAA) { AUTO_RASTERCLIP_VALIDATE(*this); + SkIRect bounds(devBounds); + this->applyClipRestriction(op, &bounds); if (fForceConservativeRects) { SkIRect ir; @@ -321,12 +326,14 @@ static bool nearly_integral(SkScalar x) { return x - SkScalarFloorToScalar(x) < domain; } -bool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, const SkIRect& bounds, +bool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, const SkIRect& devBounds, SkRegion::Op op, bool doAA) { 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: @@ -346,7 +353,7 @@ bool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, const SkI SkPath path; path.addRect(localRect); path.setIsVolatile(true); - return this->op(path, matrix, bounds, op, doAA); + return this->op(path, matrix, devBounds, op, doAA); } matrix.mapRect(&devRect, localRect); @@ -363,11 +370,13 @@ bool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, const SkI if (fIsBW && !doAA) { SkIRect ir; devRect.round(&ir); + this->applyClipRestriction(op, &ir); (void)fBW.op(ir, op); } else { if (fIsBW) { this->convertToAA(); } + this->applyClipRestriction(op, &devRect); (void)fAA.op(devRect, op, doAA); } return this->updateCacheAndReturnNonEmpty(); diff --git a/src/core/SkRasterClip.h b/src/core/SkRasterClip.h index 4b462479c3..4b19f6a1a8 100644 --- a/src/core/SkRasterClip.h +++ b/src/core/SkRasterClip.h @@ -94,6 +94,10 @@ public: void validate() const {} #endif + void setDeviceClipRestriction(const SkIRect* rect) { + fClipRestrictionRect = rect; + } + private: SkRegion fBW; SkAAClip fAA; @@ -102,6 +106,7 @@ private: // these 2 are caches based on querying the right obj based on fIsBW bool fIsEmpty; bool fIsRect; + const SkIRect* fClipRestrictionRect = nullptr; bool computeIsEmpty() const { return fIsBW ? fBW.isEmpty() : fAA.isEmpty(); @@ -131,6 +136,25 @@ private: bool setPath(const SkPath& path, const SkIRect& clip, bool doAA); bool op(const SkRasterClip&, SkRegion::Op); bool setConservativeRect(const SkRect& r, const SkIRect& clipR, bool isInverse); + + inline void applyClipRestriction(SkRegion::Op op, SkIRect* bounds) { + if (op >= SkRegion::kUnion_Op && fClipRestrictionRect + && !fClipRestrictionRect->isEmpty()) { + if (!bounds->intersect(*fClipRestrictionRect)) { + bounds->setEmpty(); + } + } + } + + inline void applyClipRestriction(SkRegion::Op op, SkRect* bounds) { + if (op >= SkRegion::kUnion_Op && fClipRestrictionRect + && !fClipRestrictionRect->isEmpty()) { + auto fClipRestrictionRect2 = SkRect::MakeFromIRect(*fClipRestrictionRect); + if (!bounds->intersect(fClipRestrictionRect2)) { + bounds->setEmpty(); + } + } + } }; class SkAutoRasterClipValidate : SkNoncopyable { |