fix pathops unsortable angles
Pathops determines which edges are kept and discarded
by sorting intersections counterclockwise. An edge
may be unsortable if it is too close to a neighbor to
clearly be on its left or right.
If a pair of lines is unsortable, they are probably
nearly coincident, but just far enough apart to escape
the coincident test.
The current code correctly marks the lines as unsortable,
but returned a guess at the sorting order anyway. Instead,
preserve the unsorted-ness (unsorted mess?) and let
the decision of what to keep defer til later.
This triggered a couple of asserts that needed rewriting
or disabling, but fixes the bug in question and does not
regress the extended tests in debug or release.
Also, fix a debugging routine that bit-rotted.
TBR=reed@google.com
Bug: skia:8228
Change-Id: Ifab90c65837ed9656bb572c385fcc5c916348778
Reviewed-on: https://skia-review.googlesource.com/149620
Commit-Queue: Cary Clark <caryclark@skia.org>
Auto-Submit: Cary Clark <caryclark@skia.org>
Reviewed-by: Cary Clark <caryclark@skia.org>
diff --git a/src/pathops/SkOpAngle.cpp b/src/pathops/SkOpAngle.cpp
index 9decb27..ae2b793 100644
--- a/src/pathops/SkOpAngle.cpp
+++ b/src/pathops/SkOpAngle.cpp
@@ -120,22 +120,22 @@
*/
lrOrder = lrGap > 20 ? 0 : lrGap > 11 ? -1 : 1;
} else {
- lrOrder = (int) lh->orderable(rh);
- if (!ltrOverlap) {
+ lrOrder = lh->orderable(rh);
+ if (!ltrOverlap && lrOrder >= 0) {
return COMPARE_RESULT(5, !lrOrder);
}
}
int ltOrder;
- SkASSERT((lh->fSectorMask & fSectorMask) || (rh->fSectorMask & fSectorMask));
+ SkASSERT((lh->fSectorMask & fSectorMask) || (rh->fSectorMask & fSectorMask) || -1 == lrOrder);
if (lh->fSectorMask & fSectorMask) {
- ltOrder = (int) lh->orderable(this);
+ ltOrder = lh->orderable(this);
} else {
int ltGap = (fSectorStart - lh->fSectorStart + 32) & 0x1f;
ltOrder = ltGap > 20 ? 0 : ltGap > 11 ? -1 : 1;
}
int trOrder;
if (rh->fSectorMask & fSectorMask) {
- trOrder = (int) this->orderable(rh);
+ trOrder = this->orderable(rh);
} else {
int trGap = (rh->fSectorStart - fSectorStart + 32) & 0x1f;
trOrder = trGap > 20 ? 0 : trGap > 11 ? -1 : 1;
@@ -145,7 +145,7 @@
if (lrOrder >= 0 && ltOrder >= 0 && trOrder >= 0) {
return COMPARE_RESULT(7, lrOrder ? (ltOrder & trOrder) : (ltOrder | trOrder));
}
- SkASSERT(lrOrder >= 0 || ltOrder >= 0 || trOrder >= 0);
+// SkASSERT(lrOrder >= 0 || ltOrder >= 0 || trOrder >= 0);
// There's not enough information to sort. Get the pairs of angles in opposite planes.
// If an order is < 0, the pair is already in an opposite plane. Check the remaining pairs.
// FIXME : once all variants are understood, rewrite this more simply
@@ -862,7 +862,7 @@
return startSpan >= 8;
}
-bool SkOpAngle::orderable(SkOpAngle* rh) {
+int SkOpAngle::orderable(SkOpAngle* rh) {
int result;
if (!fPart.isCurve()) {
if (!rh->fPart.isCurve()) {
@@ -874,12 +874,12 @@
double rx_y = rightX * leftY;
if (x_ry == rx_y) {
if (leftX * rightX < 0 || leftY * rightY < 0) {
- return true; // exactly 180 degrees apart
+ return 1; // exactly 180 degrees apart
}
goto unorderable;
}
SkASSERT(x_ry != rx_y); // indicates an undetected coincidence -- worth finding earlier
- return x_ry < rx_y;
+ return x_ry < rx_y ? 1 : 0;
}
if ((result = this->allOnOneSide(rh)) >= 0) {
return result;
@@ -889,7 +889,7 @@
}
} else if (!rh->fPart.isCurve()) {
if ((result = rh->allOnOneSide(this)) >= 0) {
- return !result;
+ return result ? 0 : 1;
}
if (rh->fUnorderable || approximately_zero(fSide)) {
goto unorderable;
@@ -897,11 +897,11 @@
} else if ((result = this->convexHullOverlaps(rh)) >= 0) {
return result;
}
- return this->endsIntersect(rh);
+ return this->endsIntersect(rh) ? 1 : 0;
unorderable:
fUnorderable = true;
rh->fUnorderable = true;
- return true;
+ return -1;
}
// OPTIMIZE: if this shows up in a profile, add a previous pointer
diff --git a/src/pathops/SkOpAngle.h b/src/pathops/SkOpAngle.h
index 3d7a895..eb77757 100644
--- a/src/pathops/SkOpAngle.h
+++ b/src/pathops/SkOpAngle.h
@@ -112,7 +112,7 @@
double midT() const;
bool midToSide(const SkOpAngle* rh, bool* inside) const;
bool oppositePlanes(const SkOpAngle* rh) const;
- bool orderable(SkOpAngle* rh); // false == this < rh ; true == this > rh
+ int orderable(SkOpAngle* rh); // false == this < rh ; true == this > rh; -1 == unorderable
void setSector();
void setSpans();
bool tangentsDiverge(const SkOpAngle* rh, double s0xt0);
diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp
index 8010ab7..b7174da 100644
--- a/src/pathops/SkPathOpsDebug.cpp
+++ b/src/pathops/SkPathOpsDebug.cpp
@@ -100,7 +100,7 @@
}
SpanGlitch* recordCommon(GlitchType type) {
- SpanGlitch* glitch = fGlitches.push_back();
+ SpanGlitch* glitch = fGlitches.push();
glitch->fBase = nullptr;
glitch->fSuspect = nullptr;
glitch->fSegment = nullptr;