Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(432)

Unified Diff: src/pathops/SkOpCoincidence.cpp

Issue 1394503003: fix some pathops bugs found in 1M skps (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: init to avoid warning Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/pathops/SkOpCoincidence.h ('k') | src/pathops/SkOpContour.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkOpCoincidence.cpp
diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp
index fb2de5ac60029e8df2f5e7e3488029add621b714..a22cfc6deb23307857316cf15a3a9189bbd13b79 100755
--- a/src/pathops/SkOpCoincidence.cpp
+++ b/src/pathops/SkOpCoincidence.cpp
@@ -51,6 +51,8 @@ void SkOpCoincidence::add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* o
coinRec->fOppPtTStart = oppPtTStart;
coinRec->fOppPtTEnd = oppPtTEnd;
coinRec->fFlipped = flipped;
+ SkDEBUGCODE(coinRec->fID = fDebugState->nextCoinID());
+
this->fHead = coinRec;
}
@@ -65,7 +67,7 @@ static void t_range(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, d
*coinTe = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * eRatio;
}
-void SkOpCoincidence::addExpanded(SkChunkAlloc* allocator
+bool SkOpCoincidence::addExpanded(SkChunkAlloc* allocator
PATH_OPS_DEBUG_VALIDATE_PARAMS(SkOpGlobalState* globalState)) {
#if DEBUG_VALIDATE
globalState->setPhase(SkOpGlobalState::kIntersecting);
@@ -92,7 +94,9 @@ void SkOpCoincidence::addExpanded(SkChunkAlloc* allocator
double startPart = (test->t() - startPtT->fT) / startRange;
double oStartRange = coin->fOppPtTEnd->fT - oStartPtT->fT;
double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange;
- SkASSERT(startPart != oStartPart);
+ if (startPart == oStartPart) {
+ return false;
+ }
SkOpPtT* newPt;
if (startPart < oStartPart) {
double newT = oStartPtT->fT + oStartRange * startPart;
@@ -112,7 +116,7 @@ void SkOpCoincidence::addExpanded(SkChunkAlloc* allocator
if (test != end) {
test = test->upCast()->next();
}
- if (oStart != oEnd) {
+ if (oTest != oEnd) {
oTest = coin->fFlipped ? oTest->prev() : oTest->upCast()->next();
}
}
@@ -120,9 +124,10 @@ void SkOpCoincidence::addExpanded(SkChunkAlloc* allocator
#if DEBUG_VALIDATE
globalState->setPhase(SkOpGlobalState::kWalking);
#endif
+ return true;
}
-void SkOpCoincidence::addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over1s,
+bool SkOpCoincidence::addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over1s,
SkOpPtT* over1e, SkChunkAlloc* allocator) {
SkCoincidentSpans* check = this->fTop;
do {
@@ -132,7 +137,7 @@ void SkOpCoincidence::addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over
|| !fDebugState->debugRunFail());
SkASSERT(check->fOppPtTEnd->span() == outer->fOppPtTEnd->span()
|| !fDebugState->debugRunFail());
- return;
+ return false;
}
if (check->fCoinPtTStart->span() == outer->fCoinPtTStart->span()
&& check->fOppPtTStart->span() == over1s->span()) {
@@ -140,13 +145,14 @@ void SkOpCoincidence::addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over
|| !fDebugState->debugRunFail());
SkASSERT(check->fOppPtTEnd->span() == over1e->span()
|| !fDebugState->debugRunFail());
- return;
+ return false;
}
} while ((check = check->fNext));
this->add(outer->fCoinPtTStart, outer->fCoinPtTEnd, over1s, over1e, allocator);
#if 0
// FIXME: up to four flavors could be added -- do we need only one?
#endif
+ return true;
}
bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e,
@@ -184,7 +190,7 @@ bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e,
+ (int) between(check->fOppPtTStart->fT, oTe, check->fOppPtTEnd->fT);
// SkASSERT(tweenCount == 0 || tweenCount == 4);
if (tweenCount) {
- return true;
+ return false;
}
} while ((check = check->fNext));
if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) {
@@ -196,9 +202,7 @@ bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e,
}
SkOpPtT* cs = coinSeg->addMissing(coinTs, oppSeg, allocator);
SkOpPtT* ce = coinSeg->addMissing(coinTe, oppSeg, allocator);
- if (cs == ce) {
- return false;
- }
+ SkASSERT(cs != ce);
SkOpPtT* os = oppSeg->addMissing(oppTs, coinSeg, allocator);
SkOpPtT* oe = oppSeg->addMissing(oppTe, coinSeg, allocator);
SkASSERT(os != oe);
@@ -215,13 +219,13 @@ bool SkOpCoincidence::addMissing(SkChunkAlloc* allocator) {
if (!outer) {
return true;
}
- bool result;
+ bool added = false;
fTop = outer;
fHead = nullptr;
do {
// addifmissing can modify the list that this is walking
- // maybe save head so that walker can iterate over old data unperturbed
- // and addifmissing can add to head freely then add saved head in the end
+ // save head so that walker can iterate over old data unperturbed
+ // addifmissing adds to head freely then add saved head in the end
const SkOpSegment* outerCoin = outer->fCoinPtTStart->segment();
SkASSERT(outerCoin == outer->fCoinPtTEnd->segment());
const SkOpSegment* outerOpp = outer->fOppPtTStart->segment();
@@ -236,43 +240,31 @@ bool SkOpCoincidence::addMissing(SkChunkAlloc* allocator) {
if (outerCoin == innerCoin
&& this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd,
inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) {
- if (!this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd,
+ added |= this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd,
inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE,
outer->fOppPtTStart, outer->fOppPtTEnd,
- inner->fOppPtTStart, inner->fOppPtTEnd, allocator)) {
- result = false;
- goto returnResult;
- }
+ inner->fOppPtTStart, inner->fOppPtTEnd, allocator);
} else if (outerCoin == innerOpp
&& this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd,
inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) {
- if (!this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd,
+ added |= this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd,
inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE,
outer->fOppPtTStart, outer->fOppPtTEnd,
- inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator)) {
- result = false;
- goto returnResult;
- }
+ inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator);
} else if (outerOpp == innerCoin
&& this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd,
inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) {
- if (!this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd,
+ added |= this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd,
inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE,
outer->fCoinPtTStart, outer->fCoinPtTEnd,
- inner->fOppPtTStart, inner->fOppPtTEnd, allocator)) {
- result = false;
- goto returnResult;
- }
+ inner->fOppPtTStart, inner->fOppPtTEnd, allocator);
} else if (outerOpp == innerOpp
&& this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd,
inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) {
- if (!this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd,
+ added |= this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd,
inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE,
outer->fCoinPtTStart, outer->fCoinPtTEnd,
- inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator)) {
- result = false;
- goto returnResult;
- }
+ inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator);
} else if (outerCoin != innerCoin) {
// check to see if outer span overlaps the inner span
// look for inner segment in pt-t list
@@ -283,21 +275,24 @@ bool SkOpCoincidence::addMissing(SkChunkAlloc* allocator) {
if (testS && testS->fT >= inner->fCoinPtTStart->fT
&& testE && testE->fT <= inner->fCoinPtTEnd->fT
&& this->testForCoincidence(outer, testS, testE)) {
- this->addIfMissing(outer, testS, testE, allocator);
+ added |= this->addIfMissing(outer, testS, testE, allocator);
} else {
testS = inner->fCoinPtTStart->contains(outerCoin);
testE = inner->fCoinPtTEnd->contains(outerCoin);
if (testS && testS->fT >= outer->fCoinPtTStart->fT
&& testE && testE->fT <= outer->fCoinPtTEnd->fT
&& this->testForCoincidence(inner, testS, testE)) {
- this->addIfMissing(inner, testS, testE, allocator);
+ added |= this->addIfMissing(inner, testS, testE, allocator);
}
}
}
+#if 0 && DEBUG_COINCIDENCE
+ SkString miss;
+ miss.printf("addMissing inner=%d outer=%d", inner->debugID(), outer->debugID());
+ DEBUG_COINCIDENCE_HEALTH(fDebugState->contourHead(), miss.c_str());
+#endif
}
} while ((outer = outer->fNext));
- result = true;
-returnResult:
SkCoincidentSpans** headPtr = &fHead;
while (*headPtr) {
SkCoincidentSpans** headNext = &(*headPtr)->fNext;
@@ -307,7 +302,7 @@ returnResult:
headPtr = headNext;
}
*headPtr = fTop;
- return result;
+ return added;
}
void SkOpCoincidence::addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegment* seg2,
@@ -340,9 +335,9 @@ void SkOpCoincidence::addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegm
this->add(s1, e1, s2, e2, allocator);
}
-bool SkOpCoincidence::contains(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart,
- SkOpPtT* oppPtTEnd, bool flipped) {
- SkCoincidentSpans* coin = fHead;
+bool SkOpCoincidence::contains(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd,
+ const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, bool flipped) const {
+ const SkCoincidentSpans* coin = fHead;
if (!coin) {
return false;
}
@@ -454,6 +449,9 @@ bool SkOpCoincidence::apply() {
if (next == end) {
break;
}
+ if (!next->upCastable()) {
+ return false;
+ }
start = next->upCast();
// if the opposite ran out too soon, just reuse the last span
if (!oNext || !oNext->upCastable()) {
@@ -662,8 +660,8 @@ bool SkOpCoincidence::overlap(const SkOpPtT* coin1s, const SkOpPtT* coin1e,
return *overS < *overE;
}
-bool SkOpCoincidence::testForCoincidence(const SkCoincidentSpans* outer, SkOpPtT* testS,
- SkOpPtT* testE) const {
+bool SkOpCoincidence::testForCoincidence(const SkCoincidentSpans* outer, const SkOpPtT* testS,
+ const SkOpPtT* testE) const {
return testS->segment()->testForCoincidence(testS, testE, testS->span(),
testE->span(), outer->fCoinPtTStart->segment(), 120000); // FIXME: replace with tuned
}
« no previous file with comments | « src/pathops/SkOpCoincidence.h ('k') | src/pathops/SkOpContour.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698