Rename methods and enum on SkClipStack::Element to indicate "device space"
Change-Id: I83056843b530f76590f755f97e3d0a5a58f371fa Reviewed-on: https://skia-review.googlesource.com/39402 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
f9810666bd
commit
f3b46e5193
@ -79,17 +79,17 @@ void WindowRectanglesGM::onCoverClipStack(const SkClipStack& stack, SkCanvas* ca
|
||||
for (const SkClipStack::Element* element = iter.next(); element; element = iter.next()) {
|
||||
SkClipOp op = element->getOp();
|
||||
bool isAA = element->isAA();
|
||||
switch (element->getType()) {
|
||||
case SkClipStack::Element::kPath_Type:
|
||||
canvas->clipPath(element->getPath(), op, isAA);
|
||||
switch (element->getDeviceSpaceType()) {
|
||||
case SkClipStack::Element::DeviceSpaceType::kPath:
|
||||
canvas->clipPath(element->getDeviceSpacePath(), op, isAA);
|
||||
break;
|
||||
case SkClipStack::Element::kRRect_Type:
|
||||
canvas->clipRRect(element->getRRect(), op, isAA);
|
||||
case SkClipStack::Element::DeviceSpaceType::kRRect:
|
||||
canvas->clipRRect(element->getDeviceSpaceRRect(), op, isAA);
|
||||
break;
|
||||
case SkClipStack::Element::kRect_Type:
|
||||
canvas->clipRect(element->getRect(), op, isAA);
|
||||
case SkClipStack::Element::DeviceSpaceType::kRect:
|
||||
canvas->clipRect(element->getDeviceSpaceRect(), op, isAA);
|
||||
break;
|
||||
case SkClipStack::Element::kEmpty_Type:
|
||||
case SkClipStack::Element::DeviceSpaceType::kEmpty:
|
||||
canvas->clipRect({ 0, 0, 0, 0 }, kIntersect_SkClipOp, false);
|
||||
break;
|
||||
}
|
||||
|
@ -20,24 +20,24 @@ static const int32_t kFirstUnreservedGenID = 3;
|
||||
int32_t SkClipStack::gGenID = kFirstUnreservedGenID;
|
||||
|
||||
SkClipStack::Element::Element(const Element& that) {
|
||||
switch (that.getType()) {
|
||||
case kEmpty_Type:
|
||||
fRRect.setEmpty();
|
||||
fPath.reset();
|
||||
switch (that.getDeviceSpaceType()) {
|
||||
case DeviceSpaceType::kEmpty:
|
||||
fDeviceSpaceRRect.setEmpty();
|
||||
fDeviceSpacePath.reset();
|
||||
break;
|
||||
case kRect_Type: // Rect uses rrect
|
||||
case kRRect_Type:
|
||||
fPath.reset();
|
||||
fRRect = that.fRRect;
|
||||
case DeviceSpaceType::kRect: // Rect uses rrect
|
||||
case DeviceSpaceType::kRRect:
|
||||
fDeviceSpacePath.reset();
|
||||
fDeviceSpaceRRect = that.fDeviceSpaceRRect;
|
||||
break;
|
||||
case kPath_Type:
|
||||
fPath.set(that.getPath());
|
||||
case DeviceSpaceType::kPath:
|
||||
fDeviceSpacePath.set(that.getDeviceSpacePath());
|
||||
break;
|
||||
}
|
||||
|
||||
fSaveCount = that.fSaveCount;
|
||||
fOp = that.fOp;
|
||||
fType = that.fType;
|
||||
fDeviceSpaceType = that.fDeviceSpaceType;
|
||||
fDoAA = that.fDoAA;
|
||||
fFiniteBoundType = that.fFiniteBoundType;
|
||||
fFiniteBound = that.fFiniteBound;
|
||||
@ -49,20 +49,18 @@ bool SkClipStack::Element::operator== (const Element& element) const {
|
||||
if (this == &element) {
|
||||
return true;
|
||||
}
|
||||
if (fOp != element.fOp ||
|
||||
fType != element.fType ||
|
||||
fDoAA != element.fDoAA ||
|
||||
fSaveCount != element.fSaveCount) {
|
||||
if (fOp != element.fOp || fDeviceSpaceType != element.fDeviceSpaceType ||
|
||||
fDoAA != element.fDoAA || fSaveCount != element.fSaveCount) {
|
||||
return false;
|
||||
}
|
||||
switch (fType) {
|
||||
case kPath_Type:
|
||||
return this->getPath() == element.getPath();
|
||||
case kRRect_Type:
|
||||
return fRRect == element.fRRect;
|
||||
case kRect_Type:
|
||||
return this->getRect() == element.getRect();
|
||||
case kEmpty_Type:
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kPath:
|
||||
return this->getDeviceSpacePath() == element.getDeviceSpacePath();
|
||||
case DeviceSpaceType::kRRect:
|
||||
return fDeviceSpaceRRect == element.fDeviceSpaceRRect;
|
||||
case DeviceSpaceType::kRect:
|
||||
return this->getDeviceSpaceRect() == element.getDeviceSpaceRect();
|
||||
case DeviceSpaceType::kEmpty:
|
||||
return true;
|
||||
default:
|
||||
SkDEBUGFAIL("Unexpected type.");
|
||||
@ -72,13 +70,13 @@ bool SkClipStack::Element::operator== (const Element& element) const {
|
||||
|
||||
const SkRect& SkClipStack::Element::getBounds() const {
|
||||
static const SkRect kEmpty = {0, 0, 0, 0};
|
||||
switch (fType) {
|
||||
case kRect_Type: // fallthrough
|
||||
case kRRect_Type:
|
||||
return fRRect.getBounds();
|
||||
case kPath_Type:
|
||||
return fPath.get()->getBounds();
|
||||
case kEmpty_Type:
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kRect: // fallthrough
|
||||
case DeviceSpaceType::kRRect:
|
||||
return fDeviceSpaceRRect.getBounds();
|
||||
case DeviceSpaceType::kPath:
|
||||
return fDeviceSpacePath.get()->getBounds();
|
||||
case DeviceSpaceType::kEmpty:
|
||||
return kEmpty;
|
||||
default:
|
||||
SkDEBUGFAIL("Unexpected type.");
|
||||
@ -87,14 +85,14 @@ const SkRect& SkClipStack::Element::getBounds() const {
|
||||
}
|
||||
|
||||
bool SkClipStack::Element::contains(const SkRect& rect) const {
|
||||
switch (fType) {
|
||||
case kRect_Type:
|
||||
return this->getRect().contains(rect);
|
||||
case kRRect_Type:
|
||||
return fRRect.contains(rect);
|
||||
case kPath_Type:
|
||||
return fPath.get()->conservativelyContainsRect(rect);
|
||||
case kEmpty_Type:
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kRect:
|
||||
return this->getDeviceSpaceRect().contains(rect);
|
||||
case DeviceSpaceType::kRRect:
|
||||
return fDeviceSpaceRRect.contains(rect);
|
||||
case DeviceSpaceType::kPath:
|
||||
return fDeviceSpacePath.get()->conservativelyContainsRect(rect);
|
||||
case DeviceSpaceType::kEmpty:
|
||||
return false;
|
||||
default:
|
||||
SkDEBUGFAIL("Unexpected type.");
|
||||
@ -103,15 +101,15 @@ bool SkClipStack::Element::contains(const SkRect& rect) const {
|
||||
}
|
||||
|
||||
bool SkClipStack::Element::contains(const SkRRect& rrect) const {
|
||||
switch (fType) {
|
||||
case kRect_Type:
|
||||
return this->getRect().contains(rrect.getBounds());
|
||||
case kRRect_Type:
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kRect:
|
||||
return this->getDeviceSpaceRect().contains(rrect.getBounds());
|
||||
case DeviceSpaceType::kRRect:
|
||||
// We don't currently have a generalized rrect-rrect containment.
|
||||
return fRRect.contains(rrect.getBounds()) || rrect == fRRect;
|
||||
case kPath_Type:
|
||||
return fPath.get()->conservativelyContainsRect(rrect.getBounds());
|
||||
case kEmpty_Type:
|
||||
return fDeviceSpaceRRect.contains(rrect.getBounds()) || rrect == fDeviceSpaceRRect;
|
||||
case DeviceSpaceType::kPath:
|
||||
return fDeviceSpacePath.get()->conservativelyContainsRect(rrect.getBounds());
|
||||
case DeviceSpaceType::kEmpty:
|
||||
return false;
|
||||
default:
|
||||
SkDEBUGFAIL("Unexpected type.");
|
||||
@ -120,23 +118,23 @@ bool SkClipStack::Element::contains(const SkRRect& rrect) const {
|
||||
}
|
||||
|
||||
void SkClipStack::Element::invertShapeFillType() {
|
||||
switch (fType) {
|
||||
case kRect_Type:
|
||||
fPath.init();
|
||||
fPath.get()->addRect(this->getRect());
|
||||
fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType);
|
||||
fType = kPath_Type;
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kRect:
|
||||
fDeviceSpacePath.init();
|
||||
fDeviceSpacePath.get()->addRect(this->getDeviceSpaceRect());
|
||||
fDeviceSpacePath.get()->setFillType(SkPath::kInverseEvenOdd_FillType);
|
||||
fDeviceSpaceType = DeviceSpaceType::kPath;
|
||||
break;
|
||||
case kRRect_Type:
|
||||
fPath.init();
|
||||
fPath.get()->addRRect(fRRect);
|
||||
fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType);
|
||||
fType = kPath_Type;
|
||||
case DeviceSpaceType::kRRect:
|
||||
fDeviceSpacePath.init();
|
||||
fDeviceSpacePath.get()->addRRect(fDeviceSpaceRRect);
|
||||
fDeviceSpacePath.get()->setFillType(SkPath::kInverseEvenOdd_FillType);
|
||||
fDeviceSpaceType = DeviceSpaceType::kPath;
|
||||
break;
|
||||
case kPath_Type:
|
||||
fPath.get()->toggleInverseFillType();
|
||||
case DeviceSpaceType::kPath:
|
||||
fDeviceSpacePath.get()->toggleInverseFillType();
|
||||
break;
|
||||
case kEmpty_Type:
|
||||
case DeviceSpaceType::kEmpty:
|
||||
// Should this set to an empty, inverse filled path?
|
||||
break;
|
||||
}
|
||||
@ -159,8 +157,8 @@ void SkClipStack::Element::initRect(int saveCount, const SkRect& rect, const SkM
|
||||
if (m.rectStaysRect()) {
|
||||
SkRect devRect;
|
||||
m.mapRect(&devRect, rect);
|
||||
fRRect.setRect(devRect);
|
||||
fType = kRect_Type;
|
||||
fDeviceSpaceRRect.setRect(devRect);
|
||||
fDeviceSpaceType = DeviceSpaceType::kRect;
|
||||
this->initCommon(saveCount, op, doAA);
|
||||
return;
|
||||
}
|
||||
@ -172,12 +170,12 @@ void SkClipStack::Element::initRect(int saveCount, const SkRect& rect, const SkM
|
||||
|
||||
void SkClipStack::Element::initRRect(int saveCount, const SkRRect& rrect, const SkMatrix& m,
|
||||
SkClipOp op, bool doAA) {
|
||||
if (rrect.transform(m, &fRRect)) {
|
||||
SkRRect::Type type = fRRect.getType();
|
||||
if (rrect.transform(m, &fDeviceSpaceRRect)) {
|
||||
SkRRect::Type type = fDeviceSpaceRRect.getType();
|
||||
if (SkRRect::kRect_Type == type || SkRRect::kEmpty_Type == type) {
|
||||
fType = kRect_Type;
|
||||
fDeviceSpaceType = DeviceSpaceType::kRect;
|
||||
} else {
|
||||
fType = kRRect_Type;
|
||||
fDeviceSpaceType = DeviceSpaceType::kRRect;
|
||||
}
|
||||
this->initCommon(saveCount, op, doAA);
|
||||
return;
|
||||
@ -209,42 +207,42 @@ void SkClipStack::Element::initPath(int saveCount, const SkPath& path, const SkM
|
||||
|
||||
void SkClipStack::Element::initAsPath(int saveCount, const SkPath& path, const SkMatrix& m,
|
||||
SkClipOp op, bool doAA) {
|
||||
path.transform(m, fPath.init());
|
||||
fPath.get()->setIsVolatile(true);
|
||||
fType = kPath_Type;
|
||||
path.transform(m, fDeviceSpacePath.init());
|
||||
fDeviceSpacePath.get()->setIsVolatile(true);
|
||||
fDeviceSpaceType = DeviceSpaceType::kPath;
|
||||
this->initCommon(saveCount, op, doAA);
|
||||
}
|
||||
|
||||
void SkClipStack::Element::asPath(SkPath* path) const {
|
||||
switch (fType) {
|
||||
case kEmpty_Type:
|
||||
void SkClipStack::Element::asDeviceSpacePath(SkPath* path) const {
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kEmpty:
|
||||
path->reset();
|
||||
path->setIsVolatile(true);
|
||||
break;
|
||||
case kRect_Type:
|
||||
case DeviceSpaceType::kRect:
|
||||
path->reset();
|
||||
path->addRect(this->getRect());
|
||||
path->addRect(this->getDeviceSpaceRect());
|
||||
path->setIsVolatile(true);
|
||||
break;
|
||||
case kRRect_Type:
|
||||
case DeviceSpaceType::kRRect:
|
||||
path->reset();
|
||||
path->addRRect(fRRect);
|
||||
path->addRRect(fDeviceSpaceRRect);
|
||||
path->setIsVolatile(true);
|
||||
break;
|
||||
case kPath_Type:
|
||||
*path = *fPath.get();
|
||||
case DeviceSpaceType::kPath:
|
||||
*path = *fDeviceSpacePath.get();
|
||||
break;
|
||||
}
|
||||
path->setIsVolatile(true);
|
||||
}
|
||||
|
||||
void SkClipStack::Element::setEmpty() {
|
||||
fType = kEmpty_Type;
|
||||
fDeviceSpaceType = DeviceSpaceType::kEmpty;
|
||||
fFiniteBound.setEmpty();
|
||||
fFiniteBoundType = kNormal_BoundsType;
|
||||
fIsIntersectionOfRects = false;
|
||||
fRRect.setEmpty();
|
||||
fPath.reset();
|
||||
fDeviceSpaceRRect.setEmpty();
|
||||
fDeviceSpacePath.reset();
|
||||
fGenID = kEmptyGenID;
|
||||
SkDEBUGCODE(this->checkEmpty();)
|
||||
}
|
||||
@ -254,12 +252,12 @@ void SkClipStack::Element::checkEmpty() const {
|
||||
SkASSERT(kNormal_BoundsType == fFiniteBoundType);
|
||||
SkASSERT(!fIsIntersectionOfRects);
|
||||
SkASSERT(kEmptyGenID == fGenID);
|
||||
SkASSERT(fRRect.isEmpty());
|
||||
SkASSERT(!fPath.isValid());
|
||||
SkASSERT(fDeviceSpaceRRect.isEmpty());
|
||||
SkASSERT(!fDeviceSpacePath.isValid());
|
||||
}
|
||||
|
||||
bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkClipOp op) const {
|
||||
if (kEmpty_Type == fType &&
|
||||
if (DeviceSpaceType::kEmpty == fDeviceSpaceType &&
|
||||
(kDifference_SkClipOp == op || kIntersect_SkClipOp == op)) {
|
||||
return true;
|
||||
}
|
||||
@ -271,19 +269,19 @@ bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkClipOp op) c
|
||||
}
|
||||
|
||||
bool SkClipStack::Element::rectRectIntersectAllowed(const SkRect& newR, bool newAA) const {
|
||||
SkASSERT(kRect_Type == fType);
|
||||
SkASSERT(DeviceSpaceType::kRect == fDeviceSpaceType);
|
||||
|
||||
if (fDoAA == newAA) {
|
||||
// if the AA setting is the same there is no issue
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!SkRect::Intersects(this->getRect(), newR)) {
|
||||
if (!SkRect::Intersects(this->getDeviceSpaceRect(), newR)) {
|
||||
// The calling code will correctly set the result to the empty clip
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this->getRect().contains(newR)) {
|
||||
if (this->getDeviceSpaceRect().contains(newR)) {
|
||||
// if the new rect carves out a portion of the old one there is no
|
||||
// issue
|
||||
return true;
|
||||
@ -476,32 +474,31 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
|
||||
// First, optimistically update the current Element's bound information
|
||||
// with the current clip's bound
|
||||
fIsIntersectionOfRects = false;
|
||||
switch (fType) {
|
||||
case kRect_Type:
|
||||
fFiniteBound = this->getRect();
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kRect:
|
||||
fFiniteBound = this->getDeviceSpaceRect();
|
||||
fFiniteBoundType = kNormal_BoundsType;
|
||||
|
||||
if (kReplace_SkClipOp == fOp ||
|
||||
(kIntersect_SkClipOp == fOp && nullptr == prior) ||
|
||||
if (kReplace_SkClipOp == fOp || (kIntersect_SkClipOp == fOp && nullptr == prior) ||
|
||||
(kIntersect_SkClipOp == fOp && prior->fIsIntersectionOfRects &&
|
||||
prior->rectRectIntersectAllowed(this->getRect(), fDoAA))) {
|
||||
prior->rectRectIntersectAllowed(this->getDeviceSpaceRect(), fDoAA))) {
|
||||
fIsIntersectionOfRects = true;
|
||||
}
|
||||
break;
|
||||
case kRRect_Type:
|
||||
fFiniteBound = fRRect.getBounds();
|
||||
case DeviceSpaceType::kRRect:
|
||||
fFiniteBound = fDeviceSpaceRRect.getBounds();
|
||||
fFiniteBoundType = kNormal_BoundsType;
|
||||
break;
|
||||
case kPath_Type:
|
||||
fFiniteBound = fPath.get()->getBounds();
|
||||
case DeviceSpaceType::kPath:
|
||||
fFiniteBound = fDeviceSpacePath.get()->getBounds();
|
||||
|
||||
if (fPath.get()->isInverseFillType()) {
|
||||
if (fDeviceSpacePath.get()->isInverseFillType()) {
|
||||
fFiniteBoundType = kInsideOut_BoundsType;
|
||||
} else {
|
||||
fFiniteBoundType = kNormal_BoundsType;
|
||||
}
|
||||
break;
|
||||
case kEmpty_Type:
|
||||
case DeviceSpaceType::kEmpty:
|
||||
SkDEBUGFAIL("We shouldn't get here with an empty element.");
|
||||
break;
|
||||
}
|
||||
@ -763,8 +760,8 @@ bool SkClipStack::asPath(SkPath *path) const {
|
||||
SkClipStack::Iter iter(*this, SkClipStack::Iter::kBottom_IterStart);
|
||||
while (const SkClipStack::Element* element = iter.next()) {
|
||||
SkPath operand;
|
||||
if (element->getType() != SkClipStack::Element::kEmpty_Type) {
|
||||
element->asPath(&operand);
|
||||
if (element->getDeviceSpaceType() != SkClipStack::Element::DeviceSpaceType::kEmpty) {
|
||||
element->asDeviceSpacePath(&operand);
|
||||
}
|
||||
|
||||
SkClipOp elementOp = element->getOp();
|
||||
@ -790,20 +787,22 @@ void SkClipStack::pushElement(const Element& element) {
|
||||
|
||||
if (prior) {
|
||||
if (prior->canBeIntersectedInPlace(fSaveCount, element.getOp())) {
|
||||
switch (prior->fType) {
|
||||
case Element::kEmpty_Type:
|
||||
switch (prior->fDeviceSpaceType) {
|
||||
case Element::DeviceSpaceType::kEmpty:
|
||||
SkDEBUGCODE(prior->checkEmpty();)
|
||||
return;
|
||||
case Element::kRect_Type:
|
||||
if (Element::kRect_Type == element.getType()) {
|
||||
if (prior->rectRectIntersectAllowed(element.getRect(), element.isAA())) {
|
||||
case Element::DeviceSpaceType::kRect:
|
||||
if (Element::DeviceSpaceType::kRect == element.getDeviceSpaceType()) {
|
||||
if (prior->rectRectIntersectAllowed(element.getDeviceSpaceRect(),
|
||||
element.isAA())) {
|
||||
SkRect isectRect;
|
||||
if (!isectRect.intersect(prior->getRect(), element.getRect())) {
|
||||
if (!isectRect.intersect(prior->getDeviceSpaceRect(),
|
||||
element.getDeviceSpaceRect())) {
|
||||
prior->setEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
prior->fRRect.setRect(isectRect);
|
||||
prior->fDeviceSpaceRRect.setRect(isectRect);
|
||||
prior->fDoAA = element.isAA();
|
||||
Element* priorPrior = (Element*) iter.prev();
|
||||
prior->updateBoundAndGenID(priorPrior);
|
||||
@ -971,19 +970,19 @@ bool SkClipStack::isRRect(const SkRect& bounds, SkRRect* rrect, bool* aa) const
|
||||
return false;
|
||||
}
|
||||
const Element* back = static_cast<const Element*>(fDeque.back());
|
||||
if (back->getType() != SkClipStack::Element::kRect_Type &&
|
||||
back->getType() != SkClipStack::Element::kRRect_Type) {
|
||||
if (back->getDeviceSpaceType() != SkClipStack::Element::DeviceSpaceType::kRect &&
|
||||
back->getDeviceSpaceType() != SkClipStack::Element::DeviceSpaceType::kRRect) {
|
||||
return false;
|
||||
}
|
||||
if (back->getOp() == kReplace_SkClipOp) {
|
||||
*rrect = back->asRRect();
|
||||
*rrect = back->asDeviceSpaceRRect();
|
||||
*aa = back->isAA();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (back->getOp() == kIntersect_SkClipOp) {
|
||||
SkRect backBounds;
|
||||
if (!backBounds.intersect(bounds, back->asRRect().rect())) {
|
||||
if (!backBounds.intersect(bounds, back->asDeviceSpaceRRect().rect())) {
|
||||
return false;
|
||||
}
|
||||
if (cnt > 1) {
|
||||
@ -1000,7 +999,7 @@ bool SkClipStack::isRRect(const SkRect& bounds, SkRRect* rrect, bool* aa) const
|
||||
}
|
||||
}
|
||||
}
|
||||
*rrect = back->asRRect();
|
||||
*rrect = back->asDeviceSpaceRRect();
|
||||
*aa = back->isAA();
|
||||
return true;
|
||||
}
|
||||
@ -1036,11 +1035,11 @@ void SkClipStack::Element::dump() const {
|
||||
"rrect",
|
||||
"path"
|
||||
};
|
||||
static_assert(0 == kEmpty_Type, "type_str");
|
||||
static_assert(1 == kRect_Type, "type_str");
|
||||
static_assert(2 == kRRect_Type, "type_str");
|
||||
static_assert(3 == kPath_Type, "type_str");
|
||||
static_assert(SK_ARRAY_COUNT(kTypeStrings) == kTypeCnt, "type_str");
|
||||
static_assert(0 == static_cast<int>(DeviceSpaceType::kEmpty), "enum mismatch");
|
||||
static_assert(1 == static_cast<int>(DeviceSpaceType::kRect), "enum mismatch");
|
||||
static_assert(2 == static_cast<int>(DeviceSpaceType::kRRect), "enum mismatch");
|
||||
static_assert(3 == static_cast<int>(DeviceSpaceType::kPath), "enum mismatch");
|
||||
static_assert(SK_ARRAY_COUNT(kTypeStrings) == kTypeCnt, "enum mismatch");
|
||||
|
||||
static const char* kOpStrings[] = {
|
||||
"difference",
|
||||
@ -1050,30 +1049,30 @@ void SkClipStack::Element::dump() const {
|
||||
"reverse-difference",
|
||||
"replace",
|
||||
};
|
||||
static_assert(0 == static_cast<int>(kDifference_SkClipOp), "op_str");
|
||||
static_assert(1 == static_cast<int>(kIntersect_SkClipOp), "op_str");
|
||||
static_assert(2 == static_cast<int>(kUnion_SkClipOp), "op_str");
|
||||
static_assert(3 == static_cast<int>(kXOR_SkClipOp), "op_str");
|
||||
static_assert(4 == static_cast<int>(kReverseDifference_SkClipOp), "op_str");
|
||||
static_assert(5 == static_cast<int>(kReplace_SkClipOp), "op_str");
|
||||
static_assert(SK_ARRAY_COUNT(kOpStrings) == SkRegion::kOpCnt, "op_str");
|
||||
static_assert(0 == static_cast<int>(kDifference_SkClipOp), "enum mismatch");
|
||||
static_assert(1 == static_cast<int>(kIntersect_SkClipOp), "enum mismatch");
|
||||
static_assert(2 == static_cast<int>(kUnion_SkClipOp), "enum mismatch");
|
||||
static_assert(3 == static_cast<int>(kXOR_SkClipOp), "enum mismatch");
|
||||
static_assert(4 == static_cast<int>(kReverseDifference_SkClipOp), "enum mismatch");
|
||||
static_assert(5 == static_cast<int>(kReplace_SkClipOp), "enum mismatch");
|
||||
static_assert(SK_ARRAY_COUNT(kOpStrings) == SkRegion::kOpCnt, "enum mismatch");
|
||||
|
||||
SkDebugf("Type: %s, Op: %s, AA: %s, Save Count: %d\n", kTypeStrings[fType],
|
||||
SkDebugf("Type: %s, Op: %s, AA: %s, Save Count: %d\n", kTypeStrings[(int)fDeviceSpaceType],
|
||||
kOpStrings[static_cast<int>(fOp)], (fDoAA ? "yes" : "no"), fSaveCount);
|
||||
switch (fType) {
|
||||
case kEmpty_Type:
|
||||
switch (fDeviceSpaceType) {
|
||||
case DeviceSpaceType::kEmpty:
|
||||
SkDebugf("\n");
|
||||
break;
|
||||
case kRect_Type:
|
||||
this->getRect().dump();
|
||||
case DeviceSpaceType::kRect:
|
||||
this->getDeviceSpaceRect().dump();
|
||||
SkDebugf("\n");
|
||||
break;
|
||||
case kRRect_Type:
|
||||
this->getRRect().dump();
|
||||
case DeviceSpaceType::kRRect:
|
||||
this->getDeviceSpaceRRect().dump();
|
||||
SkDebugf("\n");
|
||||
break;
|
||||
case kPath_Type:
|
||||
this->getPath().dump(nullptr, true, false);
|
||||
case DeviceSpaceType::kPath:
|
||||
this->getDeviceSpacePath().dump(nullptr, true, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -41,21 +41,26 @@ public:
|
||||
kInsideOut_BoundsType
|
||||
};
|
||||
|
||||
/**
|
||||
* An element of the clip stack. It represents a shape combined with the prevoius clip using a
|
||||
* set operator. Each element can be antialiased or not.
|
||||
*/
|
||||
class Element {
|
||||
public:
|
||||
enum Type {
|
||||
/** This indicates the shape type of the clip element in device space. */
|
||||
enum class DeviceSpaceType {
|
||||
//!< This element makes the clip empty (regardless of previous elements).
|
||||
kEmpty_Type,
|
||||
//!< This element combines a rect with the current clip using a set operation
|
||||
kRect_Type,
|
||||
//!< This element combines a round-rect with the current clip using a set operation
|
||||
kRRect_Type,
|
||||
//!< This element combines a path with the current clip using a set operation
|
||||
kPath_Type,
|
||||
kEmpty,
|
||||
//!< This element combines a device space rect with the current clip.
|
||||
kRect,
|
||||
//!< This element combines a device space round-rect with the current clip.
|
||||
kRRect,
|
||||
//!< This element combines a device space path with the current clip.
|
||||
kPath,
|
||||
|
||||
kLastType = kPath_Type
|
||||
kLastType = kPath
|
||||
};
|
||||
static const int kTypeCnt = kLastType + 1;
|
||||
static const int kTypeCnt = (int)DeviceSpaceType::kLastType + 1;
|
||||
|
||||
Element() {
|
||||
this->initCommon(0, kReplace_SkClipOp, false);
|
||||
@ -88,31 +93,42 @@ public:
|
||||
bool operator!= (const Element& element) const { return !(*this == element); }
|
||||
|
||||
//!< Call to get the type of the clip element.
|
||||
Type getType() const { return fType; }
|
||||
DeviceSpaceType getDeviceSpaceType() const { return fDeviceSpaceType; }
|
||||
|
||||
//!< Call to get the save count associated with this clip element.
|
||||
int getSaveCount() const { return fSaveCount; }
|
||||
|
||||
//!< Call if getType() is kPath to get the path.
|
||||
const SkPath& getPath() const { SkASSERT(kPath_Type == fType); return *fPath.get(); }
|
||||
|
||||
//!< Call if getType() is kRRect to get the round-rect.
|
||||
const SkRRect& getRRect() const { SkASSERT(kRRect_Type == fType); return fRRect; }
|
||||
|
||||
//!< Call if getType() is kRect to get the rect.
|
||||
const SkRect& getRect() const {
|
||||
SkASSERT(kRect_Type == fType && (fRRect.isRect() || fRRect.isEmpty()));
|
||||
return fRRect.getBounds();
|
||||
//!< Call if getDeviceSpaceType() is kPath to get the path.
|
||||
const SkPath& getDeviceSpacePath() const {
|
||||
SkASSERT(DeviceSpaceType::kPath == fDeviceSpaceType);
|
||||
return *fDeviceSpacePath.get();
|
||||
}
|
||||
|
||||
//!< Call if getType() is not kEmpty to get the set operation used to combine this element.
|
||||
//!< Call if getDeviceSpaceType() is kRRect to get the round-rect.
|
||||
const SkRRect& getDeviceSpaceRRect() const {
|
||||
SkASSERT(DeviceSpaceType::kRRect == fDeviceSpaceType);
|
||||
return fDeviceSpaceRRect;
|
||||
}
|
||||
|
||||
//!< Call if getDeviceSpaceType() is kRect to get the rect.
|
||||
const SkRect& getDeviceSpaceRect() const {
|
||||
SkASSERT(DeviceSpaceType::kRect == fDeviceSpaceType &&
|
||||
(fDeviceSpaceRRect.isRect() || fDeviceSpaceRRect.isEmpty()));
|
||||
return fDeviceSpaceRRect.getBounds();
|
||||
}
|
||||
|
||||
//!< Call if getDeviceSpaceType() is not kEmpty to get the set operation used to combine
|
||||
//!< this element.
|
||||
SkClipOp getOp() const { return fOp; }
|
||||
|
||||
//!< Call to get the element as a path, regardless of its type.
|
||||
void asPath(SkPath* path) const;
|
||||
void asDeviceSpacePath(SkPath* path) const;
|
||||
|
||||
//!< Call if getType() is not kPath to get the element as a round rect.
|
||||
const SkRRect& asRRect() const { SkASSERT(kPath_Type != fType); return fRRect; }
|
||||
const SkRRect& asDeviceSpaceRRect() const {
|
||||
SkASSERT(DeviceSpaceType::kPath != fDeviceSpaceType);
|
||||
return fDeviceSpaceRRect;
|
||||
}
|
||||
|
||||
/** If getType() is not kEmpty this indicates whether the clip shape should be anti-aliased
|
||||
when it is rasterized. */
|
||||
@ -148,7 +164,8 @@ public:
|
||||
* Is the clip shape inverse filled.
|
||||
*/
|
||||
bool isInverseFilled() const {
|
||||
return kPath_Type == fType && fPath.get()->isInverseFillType();
|
||||
return DeviceSpaceType::kPath == fDeviceSpaceType &&
|
||||
fDeviceSpacePath.get()->isInverseFillType();
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
@ -173,11 +190,11 @@ public:
|
||||
private:
|
||||
friend class SkClipStack;
|
||||
|
||||
SkTLazy<SkPath> fPath;
|
||||
SkRRect fRRect;
|
||||
SkTLazy<SkPath> fDeviceSpacePath;
|
||||
SkRRect fDeviceSpaceRRect;
|
||||
int fSaveCount; // save count of stack when this element was added.
|
||||
SkClipOp fOp;
|
||||
Type fType;
|
||||
DeviceSpaceType fDeviceSpaceType;
|
||||
bool fDoAA;
|
||||
|
||||
/* fFiniteBoundType and fFiniteBound are used to incrementally update the clip stack's
|
||||
|
@ -90,7 +90,7 @@ bool GrClipStackClip::PathNeedsSWRenderer(GrContext* context,
|
||||
const Element* element,
|
||||
GrPathRenderer** prOut,
|
||||
bool needsStencil) {
|
||||
if (Element::kRect_Type == element->getType()) {
|
||||
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
// rects can always be drawn directly w/o using the software path
|
||||
// TODO: skip rrects once we're drawing them directly.
|
||||
if (prOut) {
|
||||
@ -99,11 +99,11 @@ bool GrClipStackClip::PathNeedsSWRenderer(GrContext* context,
|
||||
return false;
|
||||
} else {
|
||||
// We shouldn't get here with an empty clip element.
|
||||
SkASSERT(Element::kEmpty_Type != element->getType());
|
||||
SkASSERT(Element::DeviceSpaceType::kEmpty != element->getDeviceSpaceType());
|
||||
|
||||
// the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer
|
||||
SkPath path;
|
||||
element->asPath(&path);
|
||||
element->asDeviceSpacePath(&path);
|
||||
if (path.isInverseFillType()) {
|
||||
path.toggleInverseFillType();
|
||||
}
|
||||
@ -213,16 +213,19 @@ static bool get_analytic_clip_processor(const ElementList& elements,
|
||||
invert ? kInverseFillBW_GrProcessorEdgeType : kFillBW_GrProcessorEdgeType;
|
||||
}
|
||||
|
||||
switch (iter.get()->getType()) {
|
||||
case SkClipStack::Element::kPath_Type:
|
||||
fps.emplace_back(GrConvexPolyEffect::Make(edgeType, iter.get()->getPath()));
|
||||
switch (iter.get()->getDeviceSpaceType()) {
|
||||
case SkClipStack::Element::DeviceSpaceType::kPath:
|
||||
fps.emplace_back(
|
||||
GrConvexPolyEffect::Make(edgeType, iter.get()->getDeviceSpacePath()));
|
||||
break;
|
||||
case SkClipStack::Element::kRRect_Type: {
|
||||
fps.emplace_back(GrRRectEffect::Make(edgeType, iter.get()->getRRect()));
|
||||
case SkClipStack::Element::DeviceSpaceType::kRRect: {
|
||||
fps.emplace_back(
|
||||
GrRRectEffect::Make(edgeType, iter.get()->getDeviceSpaceRRect()));
|
||||
break;
|
||||
}
|
||||
case SkClipStack::Element::kRect_Type: {
|
||||
fps.emplace_back(GrConvexPolyEffect::Make(edgeType, iter.get()->getRect()));
|
||||
case SkClipStack::Element::DeviceSpaceType::kRect: {
|
||||
fps.emplace_back(
|
||||
GrConvexPolyEffect::Make(edgeType, iter.get()->getDeviceSpaceRect()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -462,7 +465,7 @@ sk_sp<GrTextureProxy> GrClipStackClip::createSoftwareClipMask(
|
||||
helper.drawRect(temp, SkRegion::kXOR_Op, GrAA::kNo, 0xFF);
|
||||
}
|
||||
SkPath clipPath;
|
||||
element->asPath(&clipPath);
|
||||
element->asDeviceSpacePath(&clipPath);
|
||||
clipPath.toggleInverseFillType();
|
||||
GrShape shape(clipPath, GrStyle::SimpleFill());
|
||||
helper.drawShape(shape, SkRegion::kReplace_Op, aa, 0x00);
|
||||
@ -471,11 +474,11 @@ sk_sp<GrTextureProxy> GrClipStackClip::createSoftwareClipMask(
|
||||
|
||||
// The other ops (union, xor, diff) only affect pixels inside
|
||||
// the geometry so they can just be drawn normally
|
||||
if (Element::kRect_Type == element->getType()) {
|
||||
helper.drawRect(element->getRect(), (SkRegion::Op)op, aa, 0xFF);
|
||||
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
helper.drawRect(element->getDeviceSpaceRect(), (SkRegion::Op)op, aa, 0xFF);
|
||||
} else {
|
||||
SkPath path;
|
||||
element->asPath(&path);
|
||||
element->asDeviceSpacePath(&path);
|
||||
GrShape shape(path, GrStyle::SimpleFill());
|
||||
helper.drawShape(shape, (SkRegion::Op)op, aa, 0xFF);
|
||||
}
|
||||
|
@ -171,8 +171,9 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
} else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
|
||||
skippable = true;
|
||||
} else if (fWindowRects.count() < maxWindowRectangles && !embiggens &&
|
||||
!element->isAA() && Element::kRect_Type == element->getType()) {
|
||||
this->addWindowRectangle(element->getRect(), false);
|
||||
!element->isAA() &&
|
||||
Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
this->addWindowRectangle(element->getDeviceSpaceRect(), false);
|
||||
skippable = true;
|
||||
}
|
||||
}
|
||||
@ -198,11 +199,11 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (!embiggens && !element->isAA() &&
|
||||
Element::kRect_Type == element->getType()) {
|
||||
Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
// fIBounds and queryBounds have already acccounted for this element via
|
||||
// clip stack bounds; here we just apply the non-aa rounding effect.
|
||||
SkIRect nonaaRect;
|
||||
element->getRect().round(&nonaaRect);
|
||||
element->getDeviceSpaceRect().round(&nonaaRect);
|
||||
if (!this->intersectIBounds(nonaaRect)) {
|
||||
return;
|
||||
}
|
||||
@ -304,11 +305,11 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
|
||||
initialTriState = InitialTriState::kAllOut;
|
||||
skippable = true;
|
||||
} else if (!embiggens && !element->isAA() &&
|
||||
Element::kRect_Type == element->getType()) {
|
||||
Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
// fIBounds and queryBounds have already acccounted for this element via
|
||||
// clip stack bounds; here we just apply the non-aa rounding effect.
|
||||
SkIRect nonaaRect;
|
||||
element->getRect().round(&nonaaRect);
|
||||
element->getDeviceSpaceRect().round(&nonaaRect);
|
||||
if (!this->intersectIBounds(nonaaRect)) {
|
||||
return;
|
||||
}
|
||||
@ -458,18 +459,18 @@ void GrReducedClip::addInteriorWindowRectangles(int maxWindowRectangles) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Element::kRect_Type == element->getType()) {
|
||||
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
SkASSERT(element->isAA());
|
||||
this->addWindowRectangle(element->getRect(), true);
|
||||
this->addWindowRectangle(element->getDeviceSpaceRect(), true);
|
||||
if (fWindowRects.count() >= maxWindowRectangles) {
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Element::kRRect_Type == element->getType()) {
|
||||
if (Element::DeviceSpaceType::kRRect == element->getDeviceSpaceType()) {
|
||||
// For round rects we add two overlapping windows in the shape of a plus.
|
||||
const SkRRect& clipRRect = element->getRRect();
|
||||
const SkRRect& clipRRect = element->getDeviceSpaceRRect();
|
||||
SkVector insetTL = clipRRect.radii(SkRRect::kUpperLeft_Corner);
|
||||
SkVector insetBR = clipRRect.radii(SkRRect::kLowerRight_Corner);
|
||||
if (SkRRect::kComplex_Type == clipRRect.getType()) {
|
||||
@ -538,19 +539,18 @@ static bool stencil_element(GrRenderTargetContext* rtc,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkClipStack::Element* element) {
|
||||
GrAA aa = GrBoolToAA(element->isAA());
|
||||
switch (element->getType()) {
|
||||
case Element::kEmpty_Type:
|
||||
switch (element->getDeviceSpaceType()) {
|
||||
case Element::DeviceSpaceType::kEmpty:
|
||||
SkDEBUGFAIL("Should never get here with an empty element.");
|
||||
break;
|
||||
case Element::kRect_Type:
|
||||
return rtc->priv().drawAndStencilRect(clip, ss,
|
||||
(SkRegion::Op)element->getOp(),
|
||||
case Element::DeviceSpaceType::kRect:
|
||||
return rtc->priv().drawAndStencilRect(clip, ss, (SkRegion::Op)element->getOp(),
|
||||
element->isInverseFilled(), aa, viewMatrix,
|
||||
element->getRect());
|
||||
element->getDeviceSpaceRect());
|
||||
break;
|
||||
default: {
|
||||
SkPath path;
|
||||
element->asPath(&path);
|
||||
element->asDeviceSpacePath(&path);
|
||||
if (path.isInverseFillType()) {
|
||||
path.toggleInverseFillType();
|
||||
}
|
||||
@ -571,16 +571,16 @@ static void draw_element(GrRenderTargetContext* rtc,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkClipStack::Element* element) {
|
||||
// TODO: Draw rrects directly here.
|
||||
switch (element->getType()) {
|
||||
case Element::kEmpty_Type:
|
||||
switch (element->getDeviceSpaceType()) {
|
||||
case Element::DeviceSpaceType::kEmpty:
|
||||
SkDEBUGFAIL("Should never get here with an empty element.");
|
||||
break;
|
||||
case Element::kRect_Type:
|
||||
rtc->drawRect(clip, std::move(paint), aa, viewMatrix, element->getRect());
|
||||
case Element::DeviceSpaceType::kRect:
|
||||
rtc->drawRect(clip, std::move(paint), aa, viewMatrix, element->getDeviceSpaceRect());
|
||||
break;
|
||||
default: {
|
||||
SkPath path;
|
||||
element->asPath(&path);
|
||||
element->asDeviceSpacePath(&path);
|
||||
if (path.isInverseFillType()) {
|
||||
path.toggleInverseFillType();
|
||||
}
|
||||
@ -730,11 +730,11 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context,
|
||||
|
||||
GrPathRenderer* pr = nullptr;
|
||||
SkPath clipPath;
|
||||
if (Element::kRect_Type == element->getType()) {
|
||||
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport;
|
||||
fillInverted = false;
|
||||
} else {
|
||||
element->asPath(&clipPath);
|
||||
element->asDeviceSpacePath(&clipPath);
|
||||
fillInverted = clipPath.isInverseFillType();
|
||||
if (fillInverted) {
|
||||
clipPath.toggleInverseFillType();
|
||||
@ -777,9 +777,10 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context,
|
||||
GrUserStencilOp::kIncMaybeClamp,
|
||||
0xffff>()
|
||||
);
|
||||
if (Element::kRect_Type == element->getType()) {
|
||||
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
renderTargetContext->priv().stencilRect(stencilClip.fixedClip(), &kDrawToStencil,
|
||||
aaType, SkMatrix::I(), element->getRect());
|
||||
aaType, SkMatrix::I(),
|
||||
element->getDeviceSpaceRect());
|
||||
} else {
|
||||
if (!clipPath.isEmpty()) {
|
||||
GrShape shape(clipPath, GrStyle::SimpleFill());
|
||||
@ -815,9 +816,10 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context,
|
||||
// element directly or a bounding rect of the entire clip.
|
||||
for (GrUserStencilSettings const* const* pass = stencilPasses; *pass; ++pass) {
|
||||
if (drawDirectToClip) {
|
||||
if (Element::kRect_Type == element->getType()) {
|
||||
if (Element::DeviceSpaceType::kRect == element->getDeviceSpaceType()) {
|
||||
renderTargetContext->priv().stencilRect(stencilClip, *pass, aaType,
|
||||
SkMatrix::I(), element->getRect());
|
||||
SkMatrix::I(),
|
||||
element->getDeviceSpaceRect());
|
||||
} else {
|
||||
GrShape shape(clipPath, GrStyle::SimpleFill());
|
||||
GrPaint paint;
|
||||
|
@ -301,12 +301,12 @@ static bool get_clip_stack_path(const SkMatrix& transform,
|
||||
iter.reset(clipStack, SkClipStack::Iter::kBottom_IterStart);
|
||||
for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
|
||||
SkPath entryPath;
|
||||
if (SkClipStack::Element::kEmpty_Type == clipEntry->getType()) {
|
||||
if (SkClipStack::Element::DeviceSpaceType::kEmpty == clipEntry->getDeviceSpaceType()) {
|
||||
outClipPath->reset();
|
||||
outClipPath->setFillType(SkPath::kInverseWinding_FillType);
|
||||
continue;
|
||||
} else {
|
||||
clipEntry->asPath(&entryPath);
|
||||
clipEntry->asDeviceSpacePath(&entryPath);
|
||||
}
|
||||
entryPath.transform(transform);
|
||||
if (!apply_clip(clipEntry->getOp(), *outClipPath, entryPath, outClipPath)) {
|
||||
|
@ -158,8 +158,9 @@ static void test_iterators(skiatest::Reporter* reporter) {
|
||||
int i;
|
||||
|
||||
for (i = 0, element = iter.next(); element; ++i, element = iter.next()) {
|
||||
REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
|
||||
REPORTER_ASSERT(reporter, element->getRect() == gRects[i]);
|
||||
REPORTER_ASSERT(reporter, SkClipStack::Element::DeviceSpaceType::kRect ==
|
||||
element->getDeviceSpaceType());
|
||||
REPORTER_ASSERT(reporter, element->getDeviceSpaceRect() == gRects[i]);
|
||||
}
|
||||
|
||||
SkASSERT(i == 4);
|
||||
@ -173,8 +174,9 @@ static void test_iterators(skiatest::Reporter* reporter) {
|
||||
int i;
|
||||
|
||||
for (i = 3, element = iter.prev(); element; --i, element = iter.prev()) {
|
||||
REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
|
||||
REPORTER_ASSERT(reporter, element->getRect() == gRects[i]);
|
||||
REPORTER_ASSERT(reporter, SkClipStack::Element::DeviceSpaceType::kRect ==
|
||||
element->getDeviceSpaceType());
|
||||
REPORTER_ASSERT(reporter, element->getDeviceSpaceRect() == gRects[i]);
|
||||
}
|
||||
|
||||
SkASSERT(i == -1);
|
||||
@ -187,13 +189,15 @@ static void test_iterators(skiatest::Reporter* reporter) {
|
||||
SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
|
||||
|
||||
element = iter.skipToTopmost(kUnion_SkClipOp);
|
||||
REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
|
||||
REPORTER_ASSERT(reporter, element->getRect() == gRects[3]);
|
||||
REPORTER_ASSERT(reporter, SkClipStack::Element::DeviceSpaceType::kRect ==
|
||||
element->getDeviceSpaceType());
|
||||
REPORTER_ASSERT(reporter, element->getDeviceSpaceRect() == gRects[3]);
|
||||
}
|
||||
}
|
||||
|
||||
// Exercise the SkClipStack's getConservativeBounds computation
|
||||
static void test_bounds(skiatest::Reporter* reporter, SkClipStack::Element::Type primType) {
|
||||
static void test_bounds(skiatest::Reporter* reporter,
|
||||
SkClipStack::Element::DeviceSpaceType primType) {
|
||||
static const int gNumCases = 20;
|
||||
static const SkRect gAnswerRectsBW[gNumCases] = {
|
||||
// A op B
|
||||
@ -252,7 +256,7 @@ static void test_bounds(skiatest::Reporter* reporter, SkClipStack::Element::Type
|
||||
bool isIntersectionOfRects = false;
|
||||
|
||||
int testCase = 0;
|
||||
int numBitTests = SkClipStack::Element::kPath_Type == primType ? 4 : 1;
|
||||
int numBitTests = SkClipStack::Element::DeviceSpaceType::kPath == primType ? 4 : 1;
|
||||
for (int invBits = 0; invBits < numBitTests; ++invBits) {
|
||||
for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
|
||||
|
||||
@ -266,18 +270,18 @@ static void test_bounds(skiatest::Reporter* reporter, SkClipStack::Element::Type
|
||||
SkPath::kEvenOdd_FillType);
|
||||
|
||||
switch (primType) {
|
||||
case SkClipStack::Element::kEmpty_Type:
|
||||
case SkClipStack::Element::DeviceSpaceType::kEmpty:
|
||||
SkDEBUGFAIL("Don't call this with kEmpty.");
|
||||
break;
|
||||
case SkClipStack::Element::kRect_Type:
|
||||
case SkClipStack::Element::DeviceSpaceType::kRect:
|
||||
stack.clipRect(rectA, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRect(rectB, SkMatrix::I(), gOps[op], false);
|
||||
break;
|
||||
case SkClipStack::Element::kRRect_Type:
|
||||
case SkClipStack::Element::DeviceSpaceType::kRRect:
|
||||
stack.clipRRect(rrectA, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipRRect(rrectB, SkMatrix::I(), gOps[op], false);
|
||||
break;
|
||||
case SkClipStack::Element::kPath_Type:
|
||||
case SkClipStack::Element::DeviceSpaceType::kPath:
|
||||
stack.clipPath(pathA, SkMatrix::I(), kIntersect_SkClipOp, false);
|
||||
stack.clipPath(pathB, SkMatrix::I(), gOps[op], false);
|
||||
break;
|
||||
@ -289,7 +293,7 @@ static void test_bounds(skiatest::Reporter* reporter, SkClipStack::Element::Type
|
||||
stack.getConservativeBounds(0, 0, 100, 100, &devClipBound,
|
||||
&isIntersectionOfRects);
|
||||
|
||||
if (SkClipStack::Element::kRect_Type == primType) {
|
||||
if (SkClipStack::Element::DeviceSpaceType::kRect == primType) {
|
||||
REPORTER_ASSERT(reporter, isIntersectionOfRects ==
|
||||
(gOps[op] == kIntersect_SkClipOp));
|
||||
} else {
|
||||
@ -810,12 +814,12 @@ static void set_region_to_stack(const SkClipStack& stack, const SkIRect& bounds,
|
||||
SkRegion boundsRgn(bounds);
|
||||
SkPath path;
|
||||
|
||||
switch (element->getType()) {
|
||||
case SkClipStack::Element::kEmpty_Type:
|
||||
switch (element->getDeviceSpaceType()) {
|
||||
case SkClipStack::Element::DeviceSpaceType::kEmpty:
|
||||
elemRegion.setEmpty();
|
||||
break;
|
||||
default:
|
||||
element->asPath(&path);
|
||||
element->asDeviceSpacePath(&path);
|
||||
elemRegion.setPath(path, boundsRgn);
|
||||
break;
|
||||
}
|
||||
@ -899,17 +903,20 @@ static void add_oval(const SkRect& rect, bool invert, SkClipOp op, SkClipStack*
|
||||
};
|
||||
|
||||
static void add_elem_to_stack(const SkClipStack::Element& element, SkClipStack* stack) {
|
||||
switch (element.getType()) {
|
||||
case SkClipStack::Element::kRect_Type:
|
||||
stack->clipRect(element.getRect(), SkMatrix::I(), element.getOp(), element.isAA());
|
||||
switch (element.getDeviceSpaceType()) {
|
||||
case SkClipStack::Element::DeviceSpaceType::kRect:
|
||||
stack->clipRect(element.getDeviceSpaceRect(), SkMatrix::I(), element.getOp(),
|
||||
element.isAA());
|
||||
break;
|
||||
case SkClipStack::Element::kRRect_Type:
|
||||
stack->clipRRect(element.getRRect(), SkMatrix::I(), element.getOp(), element.isAA());
|
||||
case SkClipStack::Element::DeviceSpaceType::kRRect:
|
||||
stack->clipRRect(element.getDeviceSpaceRRect(), SkMatrix::I(), element.getOp(),
|
||||
element.isAA());
|
||||
break;
|
||||
case SkClipStack::Element::kPath_Type:
|
||||
stack->clipPath(element.getPath(), SkMatrix::I(), element.getOp(), element.isAA());
|
||||
case SkClipStack::Element::DeviceSpaceType::kPath:
|
||||
stack->clipPath(element.getDeviceSpacePath(), SkMatrix::I(), element.getOp(),
|
||||
element.isAA());
|
||||
break;
|
||||
case SkClipStack::Element::kEmpty_Type:
|
||||
case SkClipStack::Element::DeviceSpaceType::kEmpty:
|
||||
SkDEBUGFAIL("Why did the reducer produce an explicit empty.");
|
||||
stack->clipEmpty();
|
||||
break;
|
||||
@ -1413,9 +1420,10 @@ DEF_TEST(ClipStack, reporter) {
|
||||
answer.iset(25, 25, 75, 75);
|
||||
|
||||
REPORTER_ASSERT(reporter, element);
|
||||
REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
|
||||
REPORTER_ASSERT(reporter,
|
||||
SkClipStack::Element::DeviceSpaceType::kRect == element->getDeviceSpaceType());
|
||||
REPORTER_ASSERT(reporter, kIntersect_SkClipOp == element->getOp());
|
||||
REPORTER_ASSERT(reporter, element->getRect() == answer);
|
||||
REPORTER_ASSERT(reporter, element->getDeviceSpaceRect() == answer);
|
||||
// now check that we only had one in our iterator
|
||||
REPORTER_ASSERT(reporter, !iter.next());
|
||||
|
||||
@ -1425,9 +1433,9 @@ DEF_TEST(ClipStack, reporter) {
|
||||
|
||||
test_assign_and_comparison(reporter);
|
||||
test_iterators(reporter);
|
||||
test_bounds(reporter, SkClipStack::Element::kRect_Type);
|
||||
test_bounds(reporter, SkClipStack::Element::kRRect_Type);
|
||||
test_bounds(reporter, SkClipStack::Element::kPath_Type);
|
||||
test_bounds(reporter, SkClipStack::Element::DeviceSpaceType::kRect);
|
||||
test_bounds(reporter, SkClipStack::Element::DeviceSpaceType::kRRect);
|
||||
test_bounds(reporter, SkClipStack::Element::DeviceSpaceType::kPath);
|
||||
test_isWideOpen(reporter);
|
||||
test_rect_merging(reporter);
|
||||
test_rect_replace(reporter);
|
||||
|
@ -251,10 +251,10 @@ void SkDebugCanvas::drawTo(SkCanvas* originalCanvas, int index, int m) {
|
||||
const SkClipStack::Element* element;
|
||||
SkPath devPath;
|
||||
while ((element = iter.next())) {
|
||||
SkClipStack::Element::Type type = element->getType();
|
||||
SkClipStack::Element::DeviceSpaceType type = element->getDeviceSpaceType();
|
||||
SkPath operand;
|
||||
if (type != SkClipStack::Element::kEmpty_Type) {
|
||||
element->asPath(&operand);
|
||||
if (type != SkClipStack::Element::DeviceSpaceType::kEmpty) {
|
||||
element->asDeviceSpacePath(&operand);
|
||||
}
|
||||
SkClipOp elementOp = element->getOp();
|
||||
this->addClipStackData(devPath, operand, elementOp);
|
||||
|
Loading…
Reference in New Issue
Block a user