aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/SkCanvas.cpp14
-rw-r--r--src/core/SkClipStack.cpp14
-rw-r--r--src/core/SkRasterClip.cpp17
-rw-r--r--src/core/SkRasterClip.h24
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 {