Index: src/pathops/SkOpSegment.cpp |
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp |
index 826495b764715439a9088f88442be16bdc53ea08..5208a38667f9f597e635fbdb9b5c980ed2e662c1 100644 |
--- a/src/pathops/SkOpSegment.cpp |
+++ b/src/pathops/SkOpSegment.cpp |
@@ -407,7 +407,8 @@ void SkOpSegment::addCurveTo(int start, int end, SkPathWriter* path, bool active |
void SkOpSegment::addEndSpan(int endIndex) { |
SkASSERT(span(endIndex).fT == 1 || (span(endIndex).fTiny |
- && approximately_greater_than_one(span(endIndex).fT))); |
+// && approximately_greater_than_one(span(endIndex).fT) |
+ )); |
int spanCount = fTs.count(); |
int startIndex = endIndex - 1; |
while (fTs[startIndex].fT == 1 || fTs[startIndex].fTiny) { |
@@ -619,6 +620,7 @@ int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) { |
int less = -1; |
// FIXME: note that this relies on spans being a continguous array |
// find range of spans with nearly the same point as this one |
+ // FIXME: SkDPoint::ApproximatelyEqual is better but breaks tests at the moment |
while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, pt)) { |
if (fVerb == SkPath::kCubic_Verb) { |
double tInterval = newT - span[less].fT; |
@@ -631,6 +633,7 @@ int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) { |
--less; |
} |
int more = 1; |
+ // FIXME: SkDPoint::ApproximatelyEqual is better but breaks tests at the moment |
while (fTs.end() - &span[more - 1] > 1 && AlmostEqualUlps(span[more].fPt, pt)) { |
if (fVerb == SkPath::kCubic_Verb) { |
double tEndInterval = span[more].fT - newT; |
@@ -704,7 +707,9 @@ void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS |
double oStartT = other->fTs[oIndex].fT; |
// look for first point beyond match |
while (startPt == other->fTs[--oIndex].fPt || precisely_equal(oStartT, other->fTs[oIndex].fT)) { |
- SkASSERT(oIndex > 0); |
+ if (!oIndex) { |
+ return; // tiny spans may move in the wrong direction |
+ } |
} |
SkOpSpan* test = &fTs[index]; |
SkOpSpan* oTest = &other->fTs[oIndex]; |
@@ -1408,6 +1413,7 @@ void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d |
// FIXME: this doesn't prevent the same span from being added twice |
// fix in caller, SkASSERT here? |
+// FIXME: this may erroneously reject adds for cubic loops |
const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, |
const SkPoint& pt, const SkPoint& pt2) { |
int tCount = fTs.count(); |
@@ -1416,19 +1422,44 @@ const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double other |
if (!approximately_negative(span.fT - t)) { |
break; |
} |
- if (approximately_negative(span.fT - t) && span.fOther == other |
- && approximately_equal(span.fOtherT, otherT)) { |
+ if (span.fOther == other) { |
+ bool tsMatch = approximately_equal(span.fT, t); |
+ bool otherTsMatch = approximately_equal(span.fOtherT, otherT); |
+ // FIXME: add cubic loop detecting logic here |
+ // if fLoop bit is set on span, that could be enough if addOtherT copies the bit |
+ // or if a new bit is added ala fOtherLoop |
+ if (tsMatch || otherTsMatch) { |
#if DEBUG_ADD_T_PAIR |
- SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n", |
- __FUNCTION__, fID, t, other->fID, otherT); |
+ SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n", |
+ __FUNCTION__, fID, t, other->fID, otherT); |
#endif |
- return NULL; |
+ return NULL; |
+ } |
+ } |
+ } |
+ int oCount = other->count(); |
+ for (int oIndex = 0; oIndex < oCount; ++oIndex) { |
+ const SkOpSpan& oSpan = other->span(oIndex); |
+ if (!approximately_negative(oSpan.fT - otherT)) { |
+ break; |
+ } |
+ if (oSpan.fOther == this) { |
+ bool otherTsMatch = approximately_equal(oSpan.fT, otherT); |
+ bool tsMatch = approximately_equal(oSpan.fOtherT, t); |
+ if (otherTsMatch || tsMatch) { |
+#if DEBUG_ADD_T_PAIR |
+ SkDebugf("%s addTPair other duplicate this=%d %1.9g other=%d %1.9g\n", |
+ __FUNCTION__, fID, t, other->fID, otherT); |
+#endif |
+ return NULL; |
+ } |
} |
} |
#if DEBUG_ADD_T_PAIR |
SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n", |
__FUNCTION__, fID, t, other->fID, otherT); |
#endif |
+ SkASSERT(other != this); |
int insertedAt = addT(other, pt, t); |
int otherInsertedAt = other->addT(this, pt2, otherT); |
addOtherT(insertedAt, otherT, otherInsertedAt); |
@@ -1569,7 +1600,7 @@ int SkOpSegment::checkSetAngle(int tIndex) const { |
int SkOpSegment::computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType) { |
SkASSERT(includeType != SkOpAngle::kUnaryXor); |
SkOpAngle* firstAngle = spanToAngle(endIndex, startIndex); |
- if (NULL == firstAngle) { |
+ if (NULL == firstAngle || NULL == firstAngle->next()) { |
return SK_NaN32; |
} |
// if all angles have a computed winding, |
@@ -2162,6 +2193,7 @@ void SkOpSegment::checkEnds() { |
MissingSpan& missing = missingSpans.push_back(); |
SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); |
missing.fT = t; |
+ SkASSERT(this != match); |
missing.fOther = match; |
missing.fOtherT = matchT; |
missing.fPt = peekSpan.fPt; |
@@ -2204,10 +2236,14 @@ void SkOpSegment::checkLinks(const SkOpSpan* base, |
const SkOpSpan* test = base; |
const SkOpSpan* missing = NULL; |
while (test > first && (--test)->fPt == base->fPt) { |
+ if (this == test->fOther) { |
+ continue; |
+ } |
CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans); |
} |
test = base; |
while (test < last && (++test)->fPt == base->fPt) { |
+ SkASSERT(this != test->fOther); |
CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans); |
} |
} |
@@ -2456,7 +2492,7 @@ void SkOpSegment::checkSmallCoincidence(const SkOpSpan& span, |
if (checkMultiple && !oSpan.fSmall) { |
return; |
} |
- SkASSERT(oSpan.fSmall); |
+// SkASSERT(oSpan.fSmall); |
if (oStartIndex < oEndIndex) { |
addTCoincident(span.fPt, next->fPt, next->fT, other); |
} else { |
@@ -2577,6 +2613,7 @@ void SkOpSegment::checkTiny() { |
SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); |
missing.fSegment = thisOther; |
missing.fT = thisSpan->fOtherT; |
+ SkASSERT(this != nextOther); |
missing.fOther = nextOther; |
missing.fOtherT = nextSpan->fOtherT; |
missing.fPt = thisSpan->fPt; |
@@ -3487,7 +3524,8 @@ SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding, |
// FIXME: this is probably a bug -- rects3 asserts here |
// SkASSERT(other->fTs[min].fOppSum == oppWinding); |
} else { |
- SkASSERT(other->fTs[min].fWindSum == oppWinding); |
+// FIXME: this is probably a bug -- issue414409b asserts here |
+// SkASSERT(other->fTs[min].fWindSum == oppWinding); |
// FIXME: this is probably a bug -- skpwww_joomla_org_23 asserts here |
// SkASSERT(other->fTs[min].fOppSum == winding); |
} |
@@ -3902,6 +3940,9 @@ SkOpSegment* SkOpSegment::nextChase(int* indexPtr, int* stepPtr, int* minPtr, Sk |
return set_last(last, &endSpan); |
} |
const SkOpAngle* next = angle->next(); |
+ if (NULL == next) { |
+ return NULL; |
+ } |
if (angle->sign() != next->sign()) { |
#if DEBUG_WINDING |
SkDebugf("%s mismatched signs\n", __FUNCTION__); |
@@ -3917,7 +3958,10 @@ SkOpSegment* SkOpSegment::nextChase(int* indexPtr, int* stepPtr, int* minPtr, Sk |
return set_last(last, &endSpan); |
} |
SkASSERT(*indexPtr >= 0); |
- SkASSERT(otherEnd >= 0); |
+ if (otherEnd < 0) { |
+ return NULL; |
+ } |
+// SkASSERT(otherEnd >= 0); |
#if 1 |
int origMin = origIndex + (step < 0 ? step : 0); |
const SkOpSpan& orig = this->span(origMin); |