Revert "Add SkClipStack::replaceClip() separate from deprecated clip op"
This reverts commit 68587ae274
.
Reason for revert: breaking path clipping tests in Android?
Original change's description:
> Add SkClipStack::replaceClip() separate from deprecated clip op
>
> The replaceClip functionality was added to allow Android to move off of
> generalized expanding clips. At the time, SkClipStack simply used the
> kReplace_SkClipOp to handle it. In order to remove those expanding ops,
> SkClipStack will need a proper implementation of replaceClip().
>
> The clip elements have an additional field to mark if
> it's a replace (and it's op will be kIntersect). Adds a temporary
> getRegionOp() function to unify elements that use this field vs.
> elements that use the deprecated clip op (i.e. if they were deserialized
> from an SKP that recorded an expanding op).
>
> Clients of SkClipOp that checked for replace ops use the new function
> instead of referring to the enum value directly.
>
> Bug: skia:10209
> Change-Id: I1c16c87fadb2becfe181db717c05e240ac87fd34
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/436158
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> Reviewed-by: Robert Phillips <robertphillips@google.com>
> Reviewed-by: Chris Dalton <csmartdalton@google.com>
TBR=robertphillips@google.com,brianosman@google.com,csmartdalton@google.com,michaelludwig@google.com,skcq-be@skia-corp.google.com.iam.gserviceaccount.com
Change-Id: If3f99a7d2f2df99c2b99d431d494ca28da66b1d8
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:10209
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/436956
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
b942d4b436
commit
8ba1e71a1f
@ -46,7 +46,6 @@ SkClipStack::Element::Element(const Element& that) {
|
||||
fOp = that.fOp;
|
||||
fDeviceSpaceType = that.fDeviceSpaceType;
|
||||
fDoAA = that.fDoAA;
|
||||
fIsReplace = that.fIsReplace;
|
||||
fFiniteBoundType = that.fFiniteBoundType;
|
||||
fFiniteBound = that.fFiniteBound;
|
||||
fIsIntersectionOfRects = that.fIsIntersectionOfRects;
|
||||
@ -67,8 +66,7 @@ bool SkClipStack::Element::operator== (const Element& element) const {
|
||||
return true;
|
||||
}
|
||||
if (fOp != element.fOp || fDeviceSpaceType != element.fDeviceSpaceType ||
|
||||
fDoAA != element.fDoAA || fIsReplace != element.fIsReplace ||
|
||||
fSaveCount != element.fSaveCount) {
|
||||
fDoAA != element.fDoAA || fSaveCount != element.fSaveCount) {
|
||||
return false;
|
||||
}
|
||||
switch (fDeviceSpaceType) {
|
||||
@ -175,7 +173,6 @@ void SkClipStack::Element::initCommon(int saveCount, SkClipOp op, bool doAA) {
|
||||
fSaveCount = saveCount;
|
||||
fOp = op;
|
||||
fDoAA = doAA;
|
||||
fIsReplace = false;
|
||||
// A default of inside-out and empty bounds means the bounds are effectively void as it
|
||||
// indicates that nothing is known to be outside the clip.
|
||||
fFiniteBoundType = kInsideOut_BoundsType;
|
||||
@ -252,13 +249,6 @@ void SkClipStack::Element::initShader(int saveCount, sk_sp<SkShader> shader) {
|
||||
this->initCommon(saveCount, SkClipOp::kIntersect, false);
|
||||
}
|
||||
|
||||
void SkClipStack::Element::initReplaceRect(int saveCount, const SkRect& rect, bool doAA) {
|
||||
fDeviceSpaceRRect.setRect(rect);
|
||||
fDeviceSpaceType = DeviceSpaceType::kRect;
|
||||
this->initCommon(saveCount, SkClipOp::kIntersect, doAA);
|
||||
fIsReplace = true;
|
||||
}
|
||||
|
||||
void SkClipStack::Element::asDeviceSpacePath(SkPath* path) const {
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kEmpty:
|
||||
@ -307,14 +297,14 @@ void SkClipStack::Element::checkEmpty() const {
|
||||
|
||||
bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkClipOp op) const {
|
||||
if (DeviceSpaceType::kEmpty == fDeviceSpaceType &&
|
||||
(SkClipOp::kDifference == op || SkClipOp::kIntersect == op)) {
|
||||
(kDifference_SkClipOp == op || kIntersect_SkClipOp == op)) {
|
||||
return true;
|
||||
}
|
||||
// Only clips within the same save/restore frame (as captured by
|
||||
// the save count) can be merged
|
||||
return fSaveCount == saveCount &&
|
||||
SkClipOp::kIntersect == op &&
|
||||
(SkClipOp::kIntersect == fOp || this->isReplaceOp());
|
||||
kIntersect_SkClipOp == op &&
|
||||
(kIntersect_SkClipOp == fOp || kReplace_SkClipOp == fOp);
|
||||
}
|
||||
|
||||
bool SkClipStack::Element::rectRectIntersectAllowed(const SkRect& newR, bool newAA) const {
|
||||
@ -528,9 +518,8 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
|
||||
fFiniteBound = this->getDeviceSpaceRect();
|
||||
fFiniteBoundType = kNormal_BoundsType;
|
||||
|
||||
if (this->isReplaceOp() ||
|
||||
(SkClipOp::kIntersect == fOp && nullptr == prior) ||
|
||||
(SkClipOp::kIntersect == fOp && prior->fIsIntersectionOfRects &&
|
||||
if (kReplace_SkClipOp == fOp || (kIntersect_SkClipOp == fOp && nullptr == prior) ||
|
||||
(kIntersect_SkClipOp == fOp && prior->fIsIntersectionOfRects &&
|
||||
prior->rectRectIntersectAllowed(this->getDeviceSpaceRect(), fDoAA))) {
|
||||
fIsIntersectionOfRects = true;
|
||||
}
|
||||
@ -589,29 +578,32 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
|
||||
kPrev_Cur_FillCombo == combination);
|
||||
|
||||
// Now integrate with clip with the prior clips
|
||||
if (!this->isReplaceOp()) {
|
||||
switch (fOp) {
|
||||
case SkClipOp::kDifference:
|
||||
this->combineBoundsDiff(combination, prevFinite);
|
||||
break;
|
||||
case kXOR_SkClipOp:
|
||||
this->combineBoundsXOR(combination, prevFinite);
|
||||
break;
|
||||
case kUnion_SkClipOp:
|
||||
this->combineBoundsUnion(combination, prevFinite);
|
||||
break;
|
||||
case SkClipOp::kIntersect:
|
||||
this->combineBoundsIntersection(combination, prevFinite);
|
||||
break;
|
||||
case kReverseDifference_SkClipOp:
|
||||
this->combineBoundsRevDiff(combination, prevFinite);
|
||||
break;
|
||||
default:
|
||||
SkDebugf("SkClipOp error\n");
|
||||
SkASSERT(0);
|
||||
break;
|
||||
}
|
||||
} // else Replace just ignores everything prior and should already have filled in bounds.
|
||||
switch (fOp) {
|
||||
case kDifference_SkClipOp:
|
||||
this->combineBoundsDiff(combination, prevFinite);
|
||||
break;
|
||||
case kXOR_SkClipOp:
|
||||
this->combineBoundsXOR(combination, prevFinite);
|
||||
break;
|
||||
case kUnion_SkClipOp:
|
||||
this->combineBoundsUnion(combination, prevFinite);
|
||||
break;
|
||||
case kIntersect_SkClipOp:
|
||||
this->combineBoundsIntersection(combination, prevFinite);
|
||||
break;
|
||||
case kReverseDifference_SkClipOp:
|
||||
this->combineBoundsRevDiff(combination, prevFinite);
|
||||
break;
|
||||
case kReplace_SkClipOp:
|
||||
// Replace just ignores everything prior
|
||||
// The current clip's bound information is already filled in
|
||||
// so nothing to do
|
||||
break;
|
||||
default:
|
||||
SkDebugf("SkClipOp error\n");
|
||||
SkASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This constant determines how many Element's are allocated together as a block in
|
||||
@ -750,13 +742,12 @@ void SkClipStack::getBounds(SkRect* canvFiniteBound,
|
||||
}
|
||||
|
||||
bool SkClipStack::internalQuickContains(const SkRect& rect) const {
|
||||
|
||||
Iter iter(*this, Iter::kTop_IterStart);
|
||||
const Element* element = iter.prev();
|
||||
while (element != nullptr) {
|
||||
// TODO: Once expanding ops are removed, this condition is equiv. to op == kDifference.
|
||||
if (SkClipOp::kIntersect != element->getOp() && !element->isReplaceOp()) {
|
||||
if (kIntersect_SkClipOp != element->getOp() && kReplace_SkClipOp != element->getOp())
|
||||
return false;
|
||||
}
|
||||
if (element->isInverseFilled()) {
|
||||
// Part of 'rect' could be trimmed off by the inverse-filled clip element
|
||||
if (SkRect::Intersects(element->getBounds(), rect)) {
|
||||
@ -767,7 +758,7 @@ bool SkClipStack::internalQuickContains(const SkRect& rect) const {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (element->isReplaceOp()) {
|
||||
if (kReplace_SkClipOp == element->getOp()) {
|
||||
break;
|
||||
}
|
||||
element = iter.prev();
|
||||
@ -776,13 +767,12 @@ bool SkClipStack::internalQuickContains(const SkRect& rect) const {
|
||||
}
|
||||
|
||||
bool SkClipStack::internalQuickContains(const SkRRect& rrect) const {
|
||||
|
||||
Iter iter(*this, Iter::kTop_IterStart);
|
||||
const Element* element = iter.prev();
|
||||
while (element != nullptr) {
|
||||
// TODO: Once expanding ops are removed, this condition is equiv. to op == kDifference.
|
||||
if (SkClipOp::kIntersect != element->getOp() && !element->isReplaceOp()) {
|
||||
if (kIntersect_SkClipOp != element->getOp() && kReplace_SkClipOp != element->getOp())
|
||||
return false;
|
||||
}
|
||||
if (element->isInverseFilled()) {
|
||||
// Part of 'rrect' could be trimmed off by the inverse-filled clip element
|
||||
if (SkRect::Intersects(element->getBounds(), rrect.getBounds())) {
|
||||
@ -793,7 +783,7 @@ bool SkClipStack::internalQuickContains(const SkRRect& rrect) const {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (element->isReplaceOp()) {
|
||||
if (kReplace_SkClipOp == element->getOp()) {
|
||||
break;
|
||||
}
|
||||
element = iter.prev();
|
||||
@ -807,10 +797,7 @@ void SkClipStack::pushElement(const Element& element) {
|
||||
Element* prior = (Element*) iter.prev();
|
||||
|
||||
if (prior) {
|
||||
if (element.isReplaceOp()) {
|
||||
this->restoreTo(fSaveCount - 1);
|
||||
prior = (Element*) fDeque.back();
|
||||
} else if (prior->canBeIntersectedInPlace(fSaveCount, element.getOp())) {
|
||||
if (prior->canBeIntersectedInPlace(fSaveCount, element.getOp())) {
|
||||
switch (prior->fDeviceSpaceType) {
|
||||
case Element::DeviceSpaceType::kEmpty:
|
||||
SkDEBUGCODE(prior->checkEmpty();)
|
||||
@ -851,27 +838,32 @@ void SkClipStack::pushElement(const Element& element) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (kReplace_SkClipOp == element.getOp()) {
|
||||
this->restoreTo(fSaveCount - 1);
|
||||
prior = (Element*) fDeque.back();
|
||||
}
|
||||
}
|
||||
Element* newElement = new (fDeque.push_back()) Element(element);
|
||||
newElement->updateBoundAndGenID(prior);
|
||||
}
|
||||
|
||||
void SkClipStack::clipRRect(const SkRRect& rrect, const SkMatrix& matrix, SkClipOp op, bool doAA) {
|
||||
void SkClipStack::clipRRect(const SkRRect& rrect, const SkMatrix& matrix, SkClipOp op,
|
||||
bool doAA) {
|
||||
Element element(fSaveCount, rrect, matrix, op, doAA);
|
||||
this->pushElement(element);
|
||||
if (this->hasClipRestriction(op)) {
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), SkClipOp::kIntersect,
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), kIntersect_SkClipOp,
|
||||
false);
|
||||
this->pushElement(restriction);
|
||||
}
|
||||
}
|
||||
|
||||
void SkClipStack::clipRect(const SkRect& rect, const SkMatrix& matrix, SkClipOp op, bool doAA) {
|
||||
void SkClipStack::clipRect(const SkRect& rect, const SkMatrix& matrix, SkClipOp op,
|
||||
bool doAA) {
|
||||
Element element(fSaveCount, rect, matrix, op, doAA);
|
||||
this->pushElement(element);
|
||||
if (this->hasClipRestriction(op)) {
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), SkClipOp::kIntersect,
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), kIntersect_SkClipOp,
|
||||
false);
|
||||
this->pushElement(restriction);
|
||||
}
|
||||
@ -882,7 +874,7 @@ void SkClipStack::clipPath(const SkPath& path, const SkMatrix& matrix, SkClipOp
|
||||
Element element(fSaveCount, path, matrix, op, doAA);
|
||||
this->pushElement(element);
|
||||
if (this->hasClipRestriction(op)) {
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), SkClipOp::kIntersect,
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), kIntersect_SkClipOp,
|
||||
false);
|
||||
this->pushElement(restriction);
|
||||
}
|
||||
@ -896,21 +888,10 @@ void SkClipStack::clipShader(sk_sp<SkShader> shader) {
|
||||
SkASSERT(fClipRestrictionRect.isEmpty());
|
||||
}
|
||||
|
||||
void SkClipStack::replaceClip(const SkRect& rect, bool doAA) {
|
||||
Element element(fSaveCount, rect, doAA);
|
||||
this->pushElement(element);
|
||||
// A replace is always affected by the clip restriction
|
||||
if (!fClipRestrictionRect.isEmpty()) {
|
||||
Element restriction(fSaveCount, fClipRestrictionRect, SkMatrix::I(), SkClipOp::kIntersect,
|
||||
false);
|
||||
this->pushElement(restriction);
|
||||
}
|
||||
}
|
||||
|
||||
void SkClipStack::clipEmpty() {
|
||||
Element* element = (Element*) fDeque.back();
|
||||
|
||||
if (element && element->canBeIntersectedInPlace(fSaveCount, SkClipOp::kIntersect)) {
|
||||
if (element && element->canBeIntersectedInPlace(fSaveCount, kIntersect_SkClipOp)) {
|
||||
element->setEmpty();
|
||||
}
|
||||
new (fDeque.push_back()) Element(fSaveCount);
|
||||
@ -937,6 +918,7 @@ const SkClipStack::Element* SkClipStack::Iter::prev() {
|
||||
}
|
||||
|
||||
const SkClipStack::Element* SkClipStack::Iter::skipToTopmost(SkClipOp op) {
|
||||
|
||||
if (nullptr == fStack) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -1025,13 +1007,13 @@ bool SkClipStack::isRRect(const SkRect& bounds, SkRRect* rrect, bool* aa) const
|
||||
back->getDeviceSpaceType() != SkClipStack::Element::DeviceSpaceType::kRRect) {
|
||||
return false;
|
||||
}
|
||||
if (back->isReplaceOp()) {
|
||||
if (back->getOp() == kReplace_SkClipOp) {
|
||||
*rrect = back->asDeviceSpaceRRect();
|
||||
*aa = back->isAA();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (back->getOp() == SkClipOp::kIntersect) {
|
||||
if (back->getOp() == kIntersect_SkClipOp) {
|
||||
SkRect backBounds;
|
||||
if (!backBounds.intersect(bounds, back->asDeviceSpaceRRect().rect())) {
|
||||
return false;
|
||||
@ -1046,12 +1028,12 @@ bool SkClipStack::isRRect(const SkRect& bounds, SkRRect* rrect, bool* aa) const
|
||||
SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart);
|
||||
SkAssertResult(static_cast<const Element*>(iter.prev()) == back);
|
||||
while (const Element* prior = (const Element*)iter.prev()) {
|
||||
// TODO: Once expanding clip ops are removed, this is equiv. to op == kDifference
|
||||
if ((prior->getOp() != SkClipOp::kIntersect && !prior->isReplaceOp()) ||
|
||||
if ((prior->getOp() != kIntersect_SkClipOp &&
|
||||
prior->getOp() != kReplace_SkClipOp) ||
|
||||
!prior->contains(backBounds)) {
|
||||
return false;
|
||||
}
|
||||
if (prior->isReplaceOp()) {
|
||||
if (prior->getOp() == kReplace_SkClipOp) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1121,9 +1103,8 @@ void SkClipStack::Element::dump() const {
|
||||
static_assert(5 == static_cast<int>(kReplace_SkClipOp), "enum mismatch");
|
||||
static_assert(SK_ARRAY_COUNT(kOpStrings) == SkRegion::kOpCnt, "enum mismatch");
|
||||
|
||||
const char* opName = this->isReplaceOp() ? "replace" : kOpStrings[static_cast<int>(fOp)];
|
||||
SkDebugf("Type: %s, Op: %s, AA: %s, Save Count: %d\n", kTypeStrings[(int)fDeviceSpaceType],
|
||||
opName, (fDoAA ? "yes" : "no"), fSaveCount);
|
||||
kOpStrings[static_cast<int>(fOp)], (fDoAA ? "yes" : "no"), fSaveCount);
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kEmpty:
|
||||
SkDebugf("\n");
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
static const int kTypeCnt = (int)DeviceSpaceType::kLastType + 1;
|
||||
|
||||
Element() {
|
||||
this->initCommon(0, SkClipOp::kIntersect, false);
|
||||
this->initCommon(0, kReplace_SkClipOp, false);
|
||||
this->setEmpty();
|
||||
}
|
||||
|
||||
@ -90,10 +90,6 @@ public:
|
||||
this->initShader(0, std::move(shader));
|
||||
}
|
||||
|
||||
Element(const SkRect& rect, bool doAA) {
|
||||
this->initReplaceRect(0, rect, doAA);
|
||||
}
|
||||
|
||||
~Element();
|
||||
|
||||
bool operator== (const Element& element) const;
|
||||
@ -135,12 +131,6 @@ public:
|
||||
//!< Call if getDeviceSpaceType() is not kEmpty to get the set operation used to combine
|
||||
//!< this element.
|
||||
SkClipOp getOp() const { return fOp; }
|
||||
// Augments getOps()'s behavior by requiring a clip reset before the op is applied.
|
||||
bool isReplaceOp() const { return fIsReplace || fOp == kReplace_SkClipOp; }
|
||||
|
||||
SkRegion::Op getRegionOp() const {
|
||||
return this->isReplaceOp() ? SkRegion::kReplace_Op : (SkRegion::Op) this->getOp();
|
||||
}
|
||||
|
||||
//!< Call to get the element as a path, regardless of its type.
|
||||
void asDeviceSpacePath(SkPath* path) const;
|
||||
@ -160,12 +150,6 @@ public:
|
||||
|
||||
//!< Sets the set operation represented by the element.
|
||||
void setOp(SkClipOp op) { fOp = op; }
|
||||
// TODO: This is only used by GrReducedClip, which will be deletable soon, so then this
|
||||
// can also be cleaned up.
|
||||
void setReplaceOp() {
|
||||
fOp = SkClipOp::kIntersect;
|
||||
fIsReplace = true;
|
||||
}
|
||||
|
||||
/** The GenID can be used by clip stack clients to cache representations of the clip. The
|
||||
ID corresponds to the set of clip elements up to and including this element within the
|
||||
@ -231,7 +215,6 @@ public:
|
||||
SkClipOp fOp;
|
||||
DeviceSpaceType fDeviceSpaceType;
|
||||
bool fDoAA;
|
||||
bool fIsReplace;
|
||||
|
||||
/* fFiniteBoundType and fFiniteBound are used to incrementally update the clip stack's
|
||||
bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound represents the
|
||||
@ -256,7 +239,7 @@ public:
|
||||
mutable SkTArray<GrUniqueKey> fKeysToInvalidate;
|
||||
#endif
|
||||
Element(int saveCount) {
|
||||
this->initCommon(saveCount, SkClipOp::kIntersect, false);
|
||||
this->initCommon(saveCount, kReplace_SkClipOp, false);
|
||||
this->setEmpty();
|
||||
}
|
||||
|
||||
@ -276,17 +259,12 @@ public:
|
||||
this->initShader(saveCount, std::move(shader));
|
||||
}
|
||||
|
||||
Element(int saveCount, const SkRect& rect, bool doAA) {
|
||||
this->initReplaceRect(saveCount, rect, doAA);
|
||||
}
|
||||
|
||||
void initCommon(int saveCount, SkClipOp op, bool doAA);
|
||||
void initRect(int saveCount, const SkRect&, const SkMatrix&, SkClipOp, bool doAA);
|
||||
void initRRect(int saveCount, const SkRRect&, const SkMatrix&, SkClipOp, bool doAA);
|
||||
void initPath(int saveCount, const SkPath&, const SkMatrix&, SkClipOp, bool doAA);
|
||||
void initAsPath(int saveCount, const SkPath&, const SkMatrix&, SkClipOp, bool doAA);
|
||||
void initShader(int saveCount, sk_sp<SkShader>);
|
||||
void initReplaceRect(int saveCount, const SkRect&, bool doAA);
|
||||
|
||||
void setEmpty();
|
||||
|
||||
@ -395,8 +373,6 @@ public:
|
||||
fClipRestrictionRect = SkRect::Make(rect);
|
||||
}
|
||||
|
||||
void replaceClip(const SkRect& devRect, bool doAA);
|
||||
|
||||
/**
|
||||
* isWideOpen returns true if the clip state corresponds to the infinite
|
||||
* plane (i.e., draws are not limited at all)
|
||||
|
@ -53,8 +53,10 @@ void SkClipStackDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) {
|
||||
}
|
||||
|
||||
void SkClipStackDevice::onReplaceClip(const SkIRect& rect) {
|
||||
SkRect deviceRect = SkMatrixPriv::MapRect(this->globalToDevice(), SkRect::Make(rect));
|
||||
fClipStack.replaceClip(deviceRect, /*doAA=*/false);
|
||||
// FIXME When the deprecated clip ops are completely removed, SkClipStack will need to be
|
||||
// updated to have a better way of tracking replacement.
|
||||
fClipStack.clipRect(SkRect::Make(rect), this->globalToDevice().asM33(),
|
||||
kReplace_SkClipOp, false);
|
||||
}
|
||||
|
||||
void SkClipStackDevice::onSetDeviceClipRestriction(SkIRect* clipRestriction) {
|
||||
|
@ -338,7 +338,7 @@ static void draw_clip_elements_to_mask_helper(GrSWMaskHelper& helper, const Elem
|
||||
SkClipOp op = element->getOp();
|
||||
GrAA aa = GrAA(element->isAA());
|
||||
|
||||
if (SkClipOp::kIntersect == op || kReverseDifference_SkClipOp == op) {
|
||||
if (kIntersect_SkClipOp == op || kReverseDifference_SkClipOp == op) {
|
||||
// Intersect and reverse difference require modifying pixels outside of the geometry
|
||||
// that is being "drawn". In both cases we erase all the pixels outside of the geometry
|
||||
// but leave the pixels inside the geometry alone. For reverse difference we invert all
|
||||
|
@ -122,11 +122,10 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds
|
||||
ClipResult::kNotClipped == this->addAnalyticRect(fAAClipRect, Invert::kNo, GrAA::kYes)) {
|
||||
if (fMaskElements.isEmpty()) {
|
||||
// Use a replace since it is faster than intersect.
|
||||
fMaskElements.addToHead(fAAClipRect, true /*doAA*/);
|
||||
fMaskElements.addToHead(fAAClipRect, SkMatrix::I(), kReplace_SkClipOp, true /*doAA*/);
|
||||
fInitialState = InitialState::kAllOut;
|
||||
} else {
|
||||
fMaskElements.addToTail(fAAClipRect, SkMatrix::I(), SkClipOp::kIntersect,
|
||||
true /*doAA*/);
|
||||
fMaskElements.addToTail(fAAClipRect, SkMatrix::I(), kIntersect_SkClipOp, true /*doAA*/);
|
||||
}
|
||||
fMaskRequiresAA = true;
|
||||
fMaskGenID = fAAClipRectGenID;
|
||||
@ -190,193 +189,194 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
bool skippable = false;
|
||||
bool isFlip = false; // does this op just flip the in/out state of every point in the bounds
|
||||
|
||||
if (element->isReplaceOp()) {
|
||||
// Replace will always terminate our walk. We will either begin the forward walk
|
||||
// at the replace op or detect here than the shape is either completely inside
|
||||
// or completely outside the bounds. In this latter case it can be skipped by
|
||||
// setting the correct value for initialTriState.
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipOutsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
switch (element->getOp()) {
|
||||
case kDifference_SkClipOp:
|
||||
// check if the shape subtracted either contains the entire bounds (and makes
|
||||
// the clip empty) or is outside the bounds and therefore can be skipped.
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipInsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
}
|
||||
skippable = (ClipResult::kClipped == result);
|
||||
}
|
||||
if (ClipResult::kClipped == result) {
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipOutsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
}
|
||||
skippable = (ClipResult::kClipped == result);
|
||||
}
|
||||
}
|
||||
if (!skippable) {
|
||||
emsmallens = true;
|
||||
}
|
||||
break;
|
||||
case kIntersect_SkClipOp:
|
||||
// check if the shape intersected contains the entire bounds and therefore can
|
||||
// be skipped or it is outside the entire bounds and therefore makes the clip
|
||||
// empty.
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipOutsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
}
|
||||
skippable = (ClipResult::kClipped == result);
|
||||
}
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipInsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
}
|
||||
skippable = (ClipResult::kClipped == result);
|
||||
}
|
||||
}
|
||||
if (!skippable) {
|
||||
emsmallens = true;
|
||||
}
|
||||
break;
|
||||
case kUnion_SkClipOp:
|
||||
// If the union-ed shape contains the entire bounds then after this element
|
||||
// the bounds is entirely inside the clip. If the union-ed shape is outside the
|
||||
// bounds then this op can be skipped.
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
skippable = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipInsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
}
|
||||
if (ClipResult::kClipped == result) {
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
skippable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!skippable) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
embiggens = emsmallens = true;
|
||||
}
|
||||
} else if (element->getOp() == SkClipOp::kDifference) {
|
||||
// check if the shape subtracted either contains the entire bounds (and makes
|
||||
// the clip empty) or is outside the bounds and therefore can be skipped.
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipInsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
}
|
||||
skippable = (ClipResult::kClipped == result);
|
||||
if (!skippable) {
|
||||
embiggens = true;
|
||||
}
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipOutsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
break;
|
||||
case kXOR_SkClipOp:
|
||||
// If the bounds is entirely inside the shape being xor-ed then the effect is
|
||||
// to flip the inside/outside state of every point in the bounds. We may be
|
||||
// able to take advantage of this in the forward pass. If the xor-ed shape
|
||||
// doesn't intersect the bounds then it can be skipped.
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
isFlip = true;
|
||||
}
|
||||
skippable = (ClipResult::kClipped == result);
|
||||
}
|
||||
}
|
||||
if (!skippable) {
|
||||
emsmallens = true;
|
||||
}
|
||||
} else if (element->getOp() == SkClipOp::kIntersect) {
|
||||
// check if the shape intersected contains the entire bounds and therefore can
|
||||
// be skipped or it is outside the entire bounds and therefore makes the clip
|
||||
// empty.
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipOutsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
isFlip = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
skippable = true;
|
||||
}
|
||||
skippable = (ClipResult::kClipped == result);
|
||||
}
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipInsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
if (!skippable) {
|
||||
emsmallens = embiggens = true;
|
||||
}
|
||||
break;
|
||||
case kReverseDifference_SkClipOp:
|
||||
// When the bounds is entirely within the rev-diff shape then this behaves like xor
|
||||
// and reverses every point inside the bounds. If the shape is completely outside
|
||||
// the bounds then we know after this element is applied that the bounds will be
|
||||
// all outside the current clip.B
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
isFlip = true;
|
||||
}
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
isFlip = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
}
|
||||
skippable = (ClipResult::kClipped == result);
|
||||
}
|
||||
}
|
||||
if (!skippable) {
|
||||
emsmallens = true;
|
||||
}
|
||||
} else {
|
||||
// TODO: These are just expanding clip ops and are slated for imminent removal.
|
||||
switch (element->getOp()) {
|
||||
case kUnion_SkClipOp:
|
||||
// If the union-ed shape contains the entire bounds then after this element
|
||||
// the bounds is entirely inside the clip. If the union-ed shape is outside the
|
||||
// bounds then this op can be skipped.
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
if (!skippable) {
|
||||
emsmallens = embiggens = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case kReplace_SkClipOp:
|
||||
// Replace will always terminate our walk. We will either begin the forward walk
|
||||
// at the replace op or detect here than the shape is either completely inside
|
||||
// or completely outside the bounds. In this latter case it can be skipped by
|
||||
// setting the correct value for initialTriState.
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipOutsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
}
|
||||
if (ClipResult::kClipped == result) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
skippable = true;
|
||||
}
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
}
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (!embiggens) {
|
||||
ClipResult result = this->clipInsideElement(element);
|
||||
if (ClipResult::kMadeEmpty == result) {
|
||||
return;
|
||||
}
|
||||
if (ClipResult::kClipped == result) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
skippable = true;
|
||||
}
|
||||
}
|
||||
if (!skippable) {
|
||||
embiggens = true;
|
||||
}
|
||||
break;
|
||||
case kXOR_SkClipOp:
|
||||
// If the bounds is entirely inside the shape being xor-ed then the effect is
|
||||
// to flip the inside/outside state of every point in the bounds. We may be
|
||||
// able to take advantage of this in the forward pass. If the xor-ed shape
|
||||
// doesn't intersect the bounds then it can be skipped.
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
isFlip = true;
|
||||
}
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
isFlip = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
skippable = true;
|
||||
}
|
||||
}
|
||||
if (!skippable) {
|
||||
emsmallens = embiggens = true;
|
||||
}
|
||||
break;
|
||||
case kReverseDifference_SkClipOp:
|
||||
// When the bounds is entirely within the rev-diff shape then this behaves like
|
||||
// xor and reverses every point inside the bounds. If the shape is completely
|
||||
// outside the bounds then we know after this element is applied that the bounds
|
||||
// will be all outside the current clip.B
|
||||
if (element->isInverseFilled()) {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
isFlip = true;
|
||||
}
|
||||
} else {
|
||||
if (element->contains(relaxedQueryBounds)) {
|
||||
isFlip = true;
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
}
|
||||
}
|
||||
if (!skippable) {
|
||||
emsmallens = embiggens = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SkDEBUGFAIL("Unexpected op.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!skippable) {
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
embiggens = emsmallens = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SkDEBUGFAIL("Unexpected op.");
|
||||
break;
|
||||
}
|
||||
if (!skippable) {
|
||||
if (fMaskElements.isEmpty()) {
|
||||
@ -398,11 +398,11 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
// Intersecting an inverse shape is the same as differencing the non-inverse shape.
|
||||
// Replacing with an inverse shape is the same as setting initialState=kAllIn and
|
||||
// differencing the non-inverse shape.
|
||||
bool isReplace = newElement->isReplaceOp();
|
||||
bool isReplace = kReplace_SkClipOp == newElement->getOp();
|
||||
if (newElement->isInverseFilled() &&
|
||||
(SkClipOp::kIntersect == newElement->getOp() || isReplace)) {
|
||||
(kIntersect_SkClipOp == newElement->getOp() || isReplace)) {
|
||||
newElement->invertShapeFillType();
|
||||
newElement->setOp(SkClipOp::kDifference);
|
||||
newElement->setOp(kDifference_SkClipOp);
|
||||
if (isReplace) {
|
||||
SkASSERT(InitialTriState::kAllOut == initialTriState);
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
@ -420,60 +420,60 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
Element* element = fMaskElements.headIter().get();
|
||||
while (element) {
|
||||
bool skippable = false;
|
||||
// Only check non-replace ops since we would have skipped the replace on backwards walk
|
||||
// if we could have.
|
||||
if (!element->isReplaceOp()) {
|
||||
switch (element->getOp()) {
|
||||
case SkClipOp::kDifference:
|
||||
// subtracting from the empty set yields the empty set.
|
||||
skippable = InitialTriState::kAllOut == initialTriState;
|
||||
break;
|
||||
case SkClipOp::kIntersect:
|
||||
// intersecting with the empty set yields the empty set
|
||||
if (InitialTriState::kAllOut == initialTriState) {
|
||||
skippable = true;
|
||||
switch (element->getOp()) {
|
||||
case kDifference_SkClipOp:
|
||||
// subtracting from the empty set yields the empty set.
|
||||
skippable = InitialTriState::kAllOut == initialTriState;
|
||||
break;
|
||||
case kIntersect_SkClipOp:
|
||||
// intersecting with the empty set yields the empty set
|
||||
if (InitialTriState::kAllOut == initialTriState) {
|
||||
skippable = true;
|
||||
} else {
|
||||
// We can clear to zero and then simply draw the clip element.
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
element->setOp(kReplace_SkClipOp);
|
||||
}
|
||||
break;
|
||||
case kUnion_SkClipOp:
|
||||
if (InitialTriState::kAllIn == initialTriState) {
|
||||
// unioning the infinite plane with anything is a no-op.
|
||||
skippable = true;
|
||||
} else {
|
||||
// unioning the empty set with a shape is the shape.
|
||||
element->setOp(kReplace_SkClipOp);
|
||||
}
|
||||
break;
|
||||
case kXOR_SkClipOp:
|
||||
if (InitialTriState::kAllOut == initialTriState) {
|
||||
// xor could be changed to diff in the kAllIn case, not sure it's a win.
|
||||
element->setOp(kReplace_SkClipOp);
|
||||
}
|
||||
break;
|
||||
case kReverseDifference_SkClipOp:
|
||||
if (InitialTriState::kAllIn == initialTriState) {
|
||||
// subtracting the whole plane will yield the empty set.
|
||||
skippable = true;
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
} else {
|
||||
// this picks up flips inserted in the backwards pass.
|
||||
skippable = element->isInverseFilled() ?
|
||||
GrClip::IsOutsideClip(element->getBounds(), queryBounds) :
|
||||
element->contains(relaxedQueryBounds);
|
||||
if (skippable) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
} else {
|
||||
// We can clear to zero and then simply draw the clip element.
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
element->setReplaceOp();
|
||||
element->setOp(kReplace_SkClipOp);
|
||||
}
|
||||
break;
|
||||
case kUnion_SkClipOp:
|
||||
if (InitialTriState::kAllIn == initialTriState) {
|
||||
// unioning the infinite plane with anything is a no-op.
|
||||
skippable = true;
|
||||
} else {
|
||||
// unioning the empty set with a shape is the shape.
|
||||
element->setReplaceOp();
|
||||
}
|
||||
break;
|
||||
case kXOR_SkClipOp:
|
||||
if (InitialTriState::kAllOut == initialTriState) {
|
||||
// xor could be changed to diff in the kAllIn case, not sure it's a win.
|
||||
element->setReplaceOp();
|
||||
}
|
||||
break;
|
||||
case kReverseDifference_SkClipOp:
|
||||
if (InitialTriState::kAllIn == initialTriState) {
|
||||
// subtracting the whole plane will yield the empty set.
|
||||
skippable = true;
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
} else {
|
||||
// this picks up flips inserted in the backwards pass.
|
||||
skippable = element->isInverseFilled() ?
|
||||
GrClip::IsOutsideClip(element->getBounds(), queryBounds) :
|
||||
element->contains(relaxedQueryBounds);
|
||||
if (skippable) {
|
||||
initialTriState = InitialTriState::kAllIn;
|
||||
} else {
|
||||
element->setReplaceOp();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SkDEBUGFAIL("Unexpected op.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kReplace_SkClipOp:
|
||||
skippable = false; // we would have skipped it in the backwards walk if we
|
||||
// could've.
|
||||
break;
|
||||
default:
|
||||
SkDEBUGFAIL("Unexpected op.");
|
||||
break;
|
||||
}
|
||||
if (!skippable) {
|
||||
break;
|
||||
@ -720,7 +720,7 @@ static bool stencil_element(skgpu::v1::SurfaceDrawContext* sdc,
|
||||
break;
|
||||
case SkClipStack::Element::DeviceSpaceType::kRect: {
|
||||
GrPaint paint;
|
||||
paint.setCoverageSetOpXPFactory(element->getRegionOp(),
|
||||
paint.setCoverageSetOpXPFactory((SkRegion::Op)element->getOp(),
|
||||
element->isInverseFilled());
|
||||
sdc->stencilRect(&clip, ss, std::move(paint), aa, viewMatrix,
|
||||
element->getDeviceSpaceRect());
|
||||
@ -733,7 +733,7 @@ static bool stencil_element(skgpu::v1::SurfaceDrawContext* sdc,
|
||||
path.toggleInverseFillType();
|
||||
}
|
||||
|
||||
return sdc->drawAndStencilPath(&clip, ss, element->getRegionOp(),
|
||||
return sdc->drawAndStencilPath(&clip, ss, (SkRegion::Op)element->getOp(),
|
||||
element->isInverseFilled(), aa, viewMatrix, path);
|
||||
}
|
||||
}
|
||||
@ -799,7 +799,7 @@ bool GrReducedClip::drawAlphaClipMask(skgpu::v1::SurfaceDrawContext* sdc) const
|
||||
// walk through each clip element and perform its set op
|
||||
for (ElementList::Iter iter(fMaskElements); iter.get(); iter.next()) {
|
||||
const Element* element = iter.get();
|
||||
SkRegion::Op op = element->getRegionOp();
|
||||
SkRegion::Op op = (SkRegion::Op)element->getOp();
|
||||
GrAA aa = GrAA(element->isAA());
|
||||
bool invert = element->isInverseFilled();
|
||||
if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
|
||||
@ -861,7 +861,7 @@ bool GrReducedClip::drawStencilClipMask(GrRecordingContext* rContext,
|
||||
// walk through each clip element and perform its set op with the existing clip.
|
||||
for (ElementList::Iter iter(fMaskElements); iter.get(); iter.next()) {
|
||||
const Element* element = iter.get();
|
||||
SkRegion::Op op = element->getRegionOp();
|
||||
SkRegion::Op op = (SkRegion::Op)element->getOp();
|
||||
GrAA aa = element->isAA() ? GrAA::kYes : GrAA::kNo;
|
||||
|
||||
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
|
@ -39,26 +39,30 @@ static bool is_rect(const SkClipStack& clipStack, const SkRect& bounds, SkRect*
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (element->isReplaceOp()) {
|
||||
currentClip = rect_intersect(bounds, elementRect);
|
||||
} else if (element->getOp() == SkClipOp::kIntersect) {
|
||||
currentClip = rect_intersect(currentClip, elementRect);
|
||||
} else {
|
||||
return false;
|
||||
switch (element->getOp()) {
|
||||
case kReplace_SkClipOp:
|
||||
currentClip = rect_intersect(bounds, elementRect);
|
||||
break;
|
||||
case SkClipOp::kIntersect:
|
||||
currentClip = rect_intersect(currentClip, elementRect);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*dst = currentClip;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: When there's no expanding clip ops, this function may not be necessary anymore.
|
||||
static bool is_complex_clip(const SkClipStack& stack) {
|
||||
SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
|
||||
while (const SkClipStack::Element* element = iter.next()) {
|
||||
if (element->isReplaceOp() ||
|
||||
(element->getOp() != SkClipOp::kDifference &&
|
||||
element->getOp() != SkClipOp::kIntersect)) {
|
||||
return true;
|
||||
switch (element->getOp()) {
|
||||
case SkClipOp::kDifference:
|
||||
case SkClipOp::kIntersect:
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -238,3 +242,4 @@ void SkPDFGraphicStackState::drainStack() {
|
||||
}
|
||||
SkASSERT(fStackDepth == 0);
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,8 @@ void SkClipStack_AsPath(const SkClipStack& cs, SkPath* path) {
|
||||
}
|
||||
|
||||
SkClipOp elementOp = element->getOp();
|
||||
if (element->isReplaceOp()) {
|
||||
if (elementOp == kReplace_SkClipOp) {
|
||||
*path = operand;
|
||||
// TODO: Once expanding clip ops are removed, we can switch the iterator to be top
|
||||
// to bottom, which allows us to break here on encountering a replace op.
|
||||
} else {
|
||||
Op(*path, operand, (SkPathOp)elementOp, path);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "include/core/SkMatrix.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "src/core/SkClipOpPriv.h"
|
||||
#include "src/core/SkClipStack.h"
|
||||
#include "src/gpu/GrClipStackClip.h"
|
||||
#include "tests/Test.h"
|
||||
@ -31,7 +32,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrClipBounds, reporter, ctxInfo) {
|
||||
// create a clip stack that will (trivially) reduce to a single rect that
|
||||
// is larger than the screen
|
||||
SkClipStack stack;
|
||||
stack.replaceRect(clipRect);
|
||||
stack.clipRect(clipRect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
|
||||
bool isIntersectionOfRects = true;
|
||||
SkRect devStackBounds;
|
||||
|
@ -58,15 +58,15 @@ static void test_assign_and_comparison(skiatest::Reporter* reporter) {
|
||||
p.lineTo(7, 8);
|
||||
p.lineTo(5, 9);
|
||||
p.close();
|
||||
s.clipPath(p, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
s.clipPath(p, SkMatrix::I(), kIntersect_SkClipOp, doAA);
|
||||
|
||||
s.save();
|
||||
REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
|
||||
|
||||
SkRect r = SkRect::MakeLTRB(1, 2, 3, 4);
|
||||
s.clipRect(r, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
s.clipRect(r, SkMatrix::I(), kIntersect_SkClipOp, doAA);
|
||||
r = SkRect::MakeLTRB(10, 11, 12, 13);
|
||||
s.clipRect(r, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
s.clipRect(r, SkMatrix::I(), kIntersect_SkClipOp, doAA);
|
||||
|
||||
s.save();
|
||||
REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
|
||||
@ -96,7 +96,7 @@ static void test_assign_and_comparison(skiatest::Reporter* reporter) {
|
||||
s.save();
|
||||
REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
|
||||
r = SkRect::MakeLTRB(14, 15, 16, 17);
|
||||
s.clipRect(r, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
s.clipRect(r, SkMatrix::I(), kIntersect_SkClipOp, doAA);
|
||||
REPORTER_ASSERT(reporter, s != copy);
|
||||
|
||||
// Test that version constructed with rect-path rather than a rect is still considered equal.
|
||||
@ -136,7 +136,7 @@ static void test_assign_and_comparison(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
|
||||
|
||||
p.addRect(r);
|
||||
s.clipPath(p, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
s.clipPath(p, SkMatrix::I(), kIntersect_SkClipOp, doAA);
|
||||
REPORTER_ASSERT(reporter, s != copy);
|
||||
}
|
||||
|
||||
@ -249,8 +249,8 @@ static void test_bounds(skiatest::Reporter* reporter,
|
||||
};
|
||||
|
||||
static const SkClipOp gOps[] = {
|
||||
SkClipOp::kIntersect,
|
||||
SkClipOp::kDifference,
|
||||
kIntersect_SkClipOp,
|
||||
kDifference_SkClipOp,
|
||||
kUnion_SkClipOp,
|
||||
kXOR_SkClipOp,
|
||||
kReverseDifference_SkClipOp
|
||||
@ -294,15 +294,15 @@ static void test_bounds(skiatest::Reporter* reporter,
|
||||
SkDEBUGFAIL("Don't call this with kEmpty or kShader.");
|
||||
break;
|
||||
case SkClipStack::Element::DeviceSpaceType::kRect:
|
||||
stack.clipRect(rectA, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(rectA, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(rectB, SkMatrix::I(), gOps[op], false);
|
||||
break;
|
||||
case SkClipStack::Element::DeviceSpaceType::kRRect:
|
||||
stack.clipRRect(rrectA, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRRect(rrectA, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRRect(rrectB, SkMatrix::I(), gOps[op], false);
|
||||
break;
|
||||
case SkClipStack::Element::DeviceSpaceType::kPath:
|
||||
stack.clipPath(pathA, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(pathA, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(pathB, SkMatrix::I(), gOps[op], false);
|
||||
break;
|
||||
}
|
||||
@ -315,7 +315,7 @@ static void test_bounds(skiatest::Reporter* reporter,
|
||||
|
||||
if (SkClipStack::Element::DeviceSpaceType::kRect == primType) {
|
||||
REPORTER_ASSERT(reporter, isIntersectionOfRects ==
|
||||
(gOps[op] == SkClipOp::kIntersect));
|
||||
(gOps[op] == kIntersect_SkClipOp));
|
||||
} else {
|
||||
REPORTER_ASSERT(reporter, !isIntersectionOfRects);
|
||||
}
|
||||
@ -363,7 +363,7 @@ static void test_isWideOpen(skiatest::Reporter* reporter) {
|
||||
clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
|
||||
clipB.setFillType(SkPathFillType::kInverseEvenOdd);
|
||||
|
||||
stack.clipPath(clipA, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(clipA, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.clipPath(clipB, SkMatrix::I(), kUnion_SkClipOp, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, stack.isWideOpen());
|
||||
@ -387,7 +387,7 @@ static void test_isWideOpen(skiatest::Reporter* reporter) {
|
||||
SkRect emptyRect;
|
||||
emptyRect.setEmpty();
|
||||
|
||||
stack.clipRect(emptyRect, SkMatrix::I(), SkClipOp::kDifference, false);
|
||||
stack.clipRect(emptyRect, SkMatrix::I(), kDifference_SkClipOp, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, stack.isWideOpen());
|
||||
REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmostGenID());
|
||||
@ -399,7 +399,7 @@ static void test_isWideOpen(skiatest::Reporter* reporter) {
|
||||
|
||||
stack.save();
|
||||
|
||||
stack.clipRect(rectA, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(rectA, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, !stack.isWideOpen());
|
||||
REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID != stack.getTopmostGenID());
|
||||
@ -432,7 +432,7 @@ static void test_rect_inverse_fill(skiatest::Reporter* reporter) {
|
||||
path.addRect(rect);
|
||||
path.toggleInverseFillType();
|
||||
SkClipStack stack;
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
|
||||
SkRect bounds;
|
||||
SkClipStack::BoundsType boundsType;
|
||||
@ -454,9 +454,9 @@ static void test_rect_replace(skiatest::Reporter* reporter) {
|
||||
{
|
||||
SkClipStack stack;
|
||||
REPORTER_ASSERT(reporter, 0 == count(stack));
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
}
|
||||
|
||||
@ -465,9 +465,9 @@ static void test_rect_replace(skiatest::Reporter* reporter) {
|
||||
{
|
||||
SkClipStack stack;
|
||||
REPORTER_ASSERT(reporter, 0 == count(stack));
|
||||
stack.replaceClip(rect, true);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.replaceClip(rect, true);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
}
|
||||
|
||||
@ -476,23 +476,23 @@ static void test_rect_replace(skiatest::Reporter* reporter) {
|
||||
{
|
||||
SkClipStack stack;
|
||||
REPORTER_ASSERT(reporter, 0 == count(stack));
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.replaceClip(rect, true);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
}
|
||||
|
||||
// Make sure replace clip rects don't collapse too much.
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect2, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.clipRect(rect2, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
stack.save();
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
stack.getBounds(&bound, &type, &isIntersectionOfRects);
|
||||
REPORTER_ASSERT(reporter, bound == rect);
|
||||
@ -500,16 +500,16 @@ static void test_rect_replace(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
stack.save();
|
||||
stack.replaceClip(rect, false);
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
stack.restore();
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
stack.save();
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect2, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.replaceClip(rect, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
stack.clipRect(rect2, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
stack.restore();
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
@ -518,35 +518,27 @@ static void test_rect_replace(skiatest::Reporter* reporter) {
|
||||
|
||||
// Simplified path-based version of test_rect_replace.
|
||||
static void test_path_replace(skiatest::Reporter* reporter) {
|
||||
auto replacePath = [](SkClipStack* stack, const SkPath& path, bool doAA) {
|
||||
const SkRect wideOpen = SkRect::MakeLTRB(-1000, -1000, 1000, 1000);
|
||||
stack->replaceClip(wideOpen, false);
|
||||
stack->clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, doAA);
|
||||
};
|
||||
SkRect rect = SkRect::MakeWH(100, 100);
|
||||
SkPath path;
|
||||
path.addCircle(50, 50, 50);
|
||||
|
||||
// Emulating replace operations with more complex geometry is not atomic, it's a replace
|
||||
// with a wide-open rect and then an intersection with the complex geometry. The replace can
|
||||
// combine with prior elements, but the subsequent intersect cannot be combined so the stack
|
||||
// continues to grow.
|
||||
// Replace operation doesn't grow the stack.
|
||||
{
|
||||
SkClipStack stack;
|
||||
REPORTER_ASSERT(reporter, 0 == count(stack));
|
||||
replacePath(&stack, path, false);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
replacePath(&stack, path, false);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
stack.clipPath(path, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.clipPath(path, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
}
|
||||
|
||||
// Replacing rect with path.
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.replaceClip(rect, true);
|
||||
stack.clipRect(rect, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
stack.clipPath(path, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
replacePath(&stack, path, true);
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
}
|
||||
}
|
||||
|
||||
@ -567,8 +559,10 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// all bw overlapping - should merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
@ -580,8 +574,10 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// all aa overlapping - should merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
@ -593,8 +589,10 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// mixed overlapping - should _not_ merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
|
||||
stack.clipRect(overlapLeft, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
|
||||
stack.clipRect(overlapRight, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
|
||||
@ -606,8 +604,10 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// mixed nested (bw inside aa) - should merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), kReplace_SkClipOp, true);
|
||||
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
@ -619,8 +619,10 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// mixed nested (aa inside bw) - should merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
|
||||
REPORTER_ASSERT(reporter, 1 == count(stack));
|
||||
|
||||
@ -632,8 +634,10 @@ static void test_rect_merging(skiatest::Reporter* reporter) {
|
||||
// reverse nested (aa inside bw) - should _not_ merge
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
|
||||
stack.clipRect(nestedChild, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
|
||||
stack.clipRect(nestedParent, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
|
||||
REPORTER_ASSERT(reporter, 2 == count(stack));
|
||||
|
||||
@ -661,32 +665,32 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), SkClipOp::kDifference, false);
|
||||
// return false because quickContains currently does not care for kDifference
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), kDifference_SkClipOp, false);
|
||||
// return false because quickContains currently does not care for kDifference_SkClipOp
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
// Replace Op tests
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.replaceClip(outsideRect, false);
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(insideRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(insideRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.save(); // To prevent in-place substitution by replace OP
|
||||
stack.replaceClip(outsideRect, false);
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
stack.restore();
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.save(); // To prevent in-place substitution by replace OP
|
||||
stack.replaceClip(insideRect, false);
|
||||
stack.clipRect(insideRect, SkMatrix::I(), kReplace_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
stack.restore();
|
||||
}
|
||||
@ -694,59 +698,59 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
// Verify proper traversal of multi-element clip
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(insideRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(insideRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
// Use a path for second clip to prevent in-place intersection
|
||||
stack.clipPath(outsideCircle, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(outsideCircle, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
// Intersect Op tests with rectangles
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(outsideRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(insideRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(insideRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(intersectingRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(intersectingRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipRect(nonIntersectingRect, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect(nonIntersectingRect, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
// Intersect Op tests with circle paths
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipPath(outsideCircle, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(outsideCircle, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipPath(insideCircle, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(insideCircle, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipPath(intersectingCircle, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(intersectingCircle, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.clipPath(nonIntersectingCircle, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(nonIntersectingCircle, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -756,7 +760,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkPath path;
|
||||
path.addRect(outsideRect);
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -765,7 +769,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkPath path;
|
||||
path.addRect(insideRect);
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -774,7 +778,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkPath path;
|
||||
path.addRect(intersectingRect);
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -783,7 +787,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkPath path;
|
||||
path.addRect(nonIntersectingRect);
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -792,7 +796,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
SkPath path = outsideCircle;
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -800,7 +804,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
SkPath path = insideCircle;
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -808,7 +812,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
SkPath path = intersectingCircle;
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
|
||||
}
|
||||
|
||||
@ -816,7 +820,7 @@ static void test_quickContains(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
SkPath path = nonIntersectingCircle;
|
||||
path.toggleInverseFillType();
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipPath(path, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
|
||||
}
|
||||
}
|
||||
@ -839,18 +843,18 @@ static void set_region_to_stack(const SkClipStack& stack, const SkIRect& bounds,
|
||||
break;
|
||||
}
|
||||
|
||||
region->op(elemRegion, element->getRegionOp());
|
||||
region->op(elemRegion, (SkRegion::Op)element->getOp());
|
||||
}
|
||||
}
|
||||
|
||||
static void test_invfill_diff_bug(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
stack.clipRect({10, 10, 20, 20}, SkMatrix::I(), SkClipOp::kIntersect, false);
|
||||
stack.clipRect({10, 10, 20, 20}, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
|
||||
SkPath path;
|
||||
path.addRect({30, 10, 40, 20});
|
||||
path.setFillType(SkPathFillType::kInverseWinding);
|
||||
stack.clipPath(path, SkMatrix::I(), SkClipOp::kDifference, false);
|
||||
stack.clipPath(path, SkMatrix::I(), kDifference_SkClipOp, false);
|
||||
|
||||
REPORTER_ASSERT(reporter, SkClipStack::kEmptyGenID == stack.getTopmostGenID());
|
||||
|
||||
@ -936,10 +940,6 @@ static void add_shader(const SkRect& rect, bool invert, SkClipOp op, SkClipStack
|
||||
}
|
||||
|
||||
static void add_elem_to_stack(const SkClipStack::Element& element, SkClipStack* stack) {
|
||||
if (element.isReplaceOp()) {
|
||||
const SkRect resetBounds = SkRect::MakeLTRB(-10000.f, -10000.f, 10000.f, 10000.f);
|
||||
stack->replaceClip(resetBounds, element.isAA());
|
||||
}
|
||||
switch (element.getDeviceSpaceType()) {
|
||||
case SkClipStack::Element::DeviceSpaceType::kRect:
|
||||
stack->clipRect(element.getDeviceSpaceRect(), SkMatrix::I(), element.getOp(),
|
||||
@ -983,13 +983,19 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter, bool enableCli
|
||||
static const SkScalar kMaxElemSizeFrac = SK_Scalar1;
|
||||
|
||||
static const SkClipOp kOps[] = {
|
||||
SkClipOp::kDifference,
|
||||
SkClipOp::kIntersect,
|
||||
kDifference_SkClipOp,
|
||||
kIntersect_SkClipOp,
|
||||
kUnion_SkClipOp,
|
||||
kXOR_SkClipOp,
|
||||
kReverseDifference_SkClipOp,
|
||||
kReplace_SkClipOp,
|
||||
};
|
||||
|
||||
// Replace operations short-circuit the optimizer. We want to make sure that we test this code
|
||||
// path a little bit but we don't want it to prevent us from testing many longer traversals in
|
||||
// the optimizer.
|
||||
static const int kReplaceDiv = 4 * kMaxElemsPerTest;
|
||||
|
||||
// We want to test inverse fills. However, they are quite rare in practice so don't over do it.
|
||||
static const SkScalar kFractionInverted = SK_Scalar1 / kMaxElemsPerTest;
|
||||
|
||||
@ -1013,9 +1019,15 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter, bool enableCli
|
||||
int numElems = r.nextRangeU(kMinElemsPerTest, kMaxElemsPerTest);
|
||||
bool doAA = r.nextBiasedBool(kFractionAntialiased);
|
||||
for (int e = 0; e < numElems; ++e) {
|
||||
size_t opLimit = enableClipShader ? ((size_t) SkClipOp::kIntersect + 1)
|
||||
size_t opLimit = enableClipShader ? ((size_t) kIntersect_SkClipOp + 1)
|
||||
: SK_ARRAY_COUNT(kOps);
|
||||
SkClipOp op = kOps[r.nextULessThan(opLimit)];
|
||||
if (op == kReplace_SkClipOp) {
|
||||
if (r.nextU() % kReplaceDiv) {
|
||||
--e;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// saves can change the clip stack behavior when an element is added.
|
||||
bool doSave = r.nextBool();
|
||||
@ -1098,8 +1110,8 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter, bool enableCli
|
||||
SkIRect scissor = reduced->hasScissor() ? reduced->scissor() : kIBounds;
|
||||
|
||||
// GrReducedClipStack assumes that the final result is clipped to the returned bounds
|
||||
reducedStack.clipDevRect(scissor, SkClipOp::kIntersect);
|
||||
stack.clipDevRect(scissor, SkClipOp::kIntersect);
|
||||
reducedStack.clipDevRect(scissor, kIntersect_SkClipOp);
|
||||
stack.clipDevRect(scissor, kIntersect_SkClipOp);
|
||||
|
||||
// convert both the original stack and reduced stack to SkRegions and see if they're equal
|
||||
SkRegion region;
|
||||
@ -1123,8 +1135,10 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter, bool enableCli
|
||||
static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) {
|
||||
{
|
||||
SkClipStack stack;
|
||||
stack.replaceClip(SkRect::MakeXYWH(0, 0, 100, 100), true);
|
||||
stack.replaceClip(SkRect::MakeXYWH(0, 0, 50.3f, 50.3f), true);
|
||||
stack.clipRect(SkRect::MakeXYWH(0, 0, 100, 100), SkMatrix::I(), kReplace_SkClipOp,
|
||||
true);
|
||||
stack.clipRect(SkRect::MakeXYWH(0, 0, SkScalar(50.3), SkScalar(50.3)), SkMatrix::I(),
|
||||
kReplace_SkClipOp, true);
|
||||
SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100);
|
||||
|
||||
sk_sp<GrDirectContext> context = GrDirectContext::MakeMock(nullptr);
|
||||
@ -1148,7 +1162,8 @@ static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) {
|
||||
// A B
|
||||
// C D
|
||||
|
||||
stack.replaceClip(SkRect::MakeXYWH(0, 0, 25.3f, 25.3f), true);
|
||||
stack.clipRect(SkRect::MakeXYWH(0, 0, SkScalar(25.3), SkScalar(25.3)), SkMatrix::I(),
|
||||
kReplace_SkClipOp, true);
|
||||
uint32_t genIDA = stack.getTopmostGenID();
|
||||
stack.clipRect(SkRect::MakeXYWH(50, 0, SkScalar(25.3), SkScalar(25.3)), SkMatrix::I(),
|
||||
kUnion_SkClipOp, true);
|
||||
@ -1235,10 +1250,11 @@ static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_reduced_clip_stack_no_aa_crash(skiatest::Reporter* reporter) {
|
||||
SkClipStack stack;
|
||||
stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 100, 100), SkClipOp::kIntersect);
|
||||
stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 50, 50), SkClipOp::kIntersect);
|
||||
stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 100, 100), kReplace_SkClipOp);
|
||||
stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 50, 50), kReplace_SkClipOp);
|
||||
SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100);
|
||||
|
||||
sk_sp<GrDirectContext> context = GrDirectContext::MakeMock(nullptr);
|
||||
@ -1343,7 +1359,7 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) {
|
||||
// Pixel-aligned rect (iior=true).
|
||||
name.printf("Pixel-aligned rect test, iter %i", i);
|
||||
SkClipStack stack;
|
||||
stack.clipRect(alignedRect, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(alignedRect, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
test_aa_query(reporter, name, stack, m, {IL, IT, IR, IB}, ClipMethod::kIgnoreClip);
|
||||
test_aa_query(reporter, name, stack, m, {IL, IT-1, IR, IT}, ClipMethod::kSkipDraw);
|
||||
test_aa_query(reporter, name, stack, m, {IL, IT-2, IR, IB}, ClipMethod::kScissor);
|
||||
@ -1351,7 +1367,7 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) {
|
||||
// Rect (iior=true).
|
||||
name.printf("Rect test, iter %i", i);
|
||||
stack.reset();
|
||||
stack.clipRect(rect, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(rect, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
test_aa_query(reporter, name, stack, m, {L, T, R, B}, ClipMethod::kIgnoreClip);
|
||||
test_aa_query(reporter, name, stack, m, {L-.1f, T, L, B}, ClipMethod::kSkipDraw);
|
||||
test_aa_query(reporter, name, stack, m, {L-.1f, T, L+.1f, B}, ClipMethod::kAAElements, 1);
|
||||
@ -1359,7 +1375,7 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) {
|
||||
// Difference rect (iior=false, inside-out bounds).
|
||||
name.printf("Difference rect test, iter %i", i);
|
||||
stack.reset();
|
||||
stack.clipRect(rect, SkMatrix::I(), SkClipOp::kDifference, true);
|
||||
stack.clipRect(rect, SkMatrix::I(), kDifference_SkClipOp, true);
|
||||
test_aa_query(reporter, name, stack, m, {L, T, R, B}, ClipMethod::kSkipDraw);
|
||||
test_aa_query(reporter, name, stack, m, {L, T-.1f, R, T}, ClipMethod::kIgnoreClip);
|
||||
test_aa_query(reporter, name, stack, m, {L, T-.1f, R, T+.1f}, ClipMethod::kAAElements, 1);
|
||||
@ -1367,7 +1383,7 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) {
|
||||
// Complex clip (iior=false, normal bounds).
|
||||
name.printf("Complex clip test, iter %i", i);
|
||||
stack.reset();
|
||||
stack.clipRect(rect, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(rect, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
stack.clipRect(innerRect, SkMatrix::I(), kXOR_SkClipOp, true);
|
||||
test_aa_query(reporter, name, stack, m, {l, t, r, b}, ClipMethod::kSkipDraw);
|
||||
test_aa_query(reporter, name, stack, m, {r-.1f, t, R, b}, ClipMethod::kAAElements, 1);
|
||||
@ -1379,7 +1395,7 @@ static void test_reduced_clip_stack_aa(skiatest::Reporter* reporter) {
|
||||
// Complex clip where outer rect is pixel aligned (iior=false, normal bounds).
|
||||
name.printf("Aligned Complex clip test, iter %i", i);
|
||||
stack.reset();
|
||||
stack.clipRect(alignedRect, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
stack.clipRect(alignedRect, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
stack.clipRect(innerRect, SkMatrix::I(), kXOR_SkClipOp, true);
|
||||
test_aa_query(reporter, name, stack, m, {l, t, r, b}, ClipMethod::kSkipDraw);
|
||||
test_aa_query(reporter, name, stack, m, {l, b-.1f, r, IB}, ClipMethod::kAAElements, 1);
|
||||
@ -1411,7 +1427,7 @@ static void test_tiny_query_bounds_assertion_bug(skiatest::Reporter* reporter) {
|
||||
const SkRect clipBounds = SkRect::MakeXYWH(1.5f, 100, 1000, 1000);
|
||||
|
||||
SkClipStack rectStack;
|
||||
rectStack.clipRect(clipBounds, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
rectStack.clipRect(clipBounds, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
|
||||
SkPath clipPath;
|
||||
clipPath.moveTo(clipBounds.left(), clipBounds.top());
|
||||
@ -1420,7 +1436,7 @@ static void test_tiny_query_bounds_assertion_bug(skiatest::Reporter* reporter) {
|
||||
clipPath.quadTo(clipBounds.left(), clipBounds.bottom(),
|
||||
clipBounds.left(), clipBounds.top());
|
||||
SkClipStack pathStack;
|
||||
pathStack.clipPath(clipPath, SkMatrix::I(), SkClipOp::kIntersect, true);
|
||||
pathStack.clipPath(clipPath, SkMatrix::I(), kIntersect_SkClipOp, true);
|
||||
|
||||
sk_sp<GrDirectContext> context = GrDirectContext::MakeMock(nullptr);
|
||||
const GrCaps* caps = context->priv().caps();
|
||||
@ -1489,7 +1505,7 @@ DEF_TEST(ClipStack, reporter) {
|
||||
{ 0, 0, 75, 75 }
|
||||
};
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) {
|
||||
stack.clipDevRect(gRects[i], SkClipOp::kIntersect);
|
||||
stack.clipDevRect(gRects[i], kIntersect_SkClipOp);
|
||||
}
|
||||
|
||||
// all of the above rects should have been intersected, leaving only 1 rect
|
||||
@ -1501,7 +1517,7 @@ DEF_TEST(ClipStack, reporter) {
|
||||
REPORTER_ASSERT(reporter, element);
|
||||
REPORTER_ASSERT(reporter,
|
||||
SkClipStack::Element::DeviceSpaceType::kRect == element->getDeviceSpaceType());
|
||||
REPORTER_ASSERT(reporter, SkClipOp::kIntersect == element->getOp());
|
||||
REPORTER_ASSERT(reporter, kIntersect_SkClipOp == element->getOp());
|
||||
REPORTER_ASSERT(reporter, element->getDeviceSpaceRect() == answer);
|
||||
// now check that we only had one in our iterator
|
||||
REPORTER_ASSERT(reporter, !iter.next());
|
||||
|
Loading…
Reference in New Issue
Block a user