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

Unified Diff: src/pathops/SkOpSegment.cpp

Issue 1140813002: deal more consistently with unsortable edges (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix linux warning Created 5 years, 7 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/SkOpSegment.h ('k') | src/pathops/SkOpSpan.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkOpSegment.cpp
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp
index de813cb7c9c3ba022b1b6f4331124d462109f1b4..01417d6b8f492257c8bca934e1a55dc756320a5a 100644
--- a/src/pathops/SkOpSegment.cpp
+++ b/src/pathops/SkOpSegment.cpp
@@ -43,18 +43,18 @@ static const bool gActiveEdge[kXOR_SkPathOp + 1][2][2][2][2] = {
#undef T
SkOpAngle* SkOpSegment::activeAngle(SkOpSpanBase* start, SkOpSpanBase** startPtr,
- SkOpSpanBase** endPtr, bool* done, bool* sortable) {
- if (SkOpAngle* result = activeAngleInner(start, startPtr, endPtr, done, sortable)) {
+ SkOpSpanBase** endPtr, bool* done) {
+ if (SkOpAngle* result = activeAngleInner(start, startPtr, endPtr, done)) {
return result;
}
- if (SkOpAngle* result = activeAngleOther(start, startPtr, endPtr, done, sortable)) {
+ if (SkOpAngle* result = activeAngleOther(start, startPtr, endPtr, done)) {
return result;
}
return NULL;
}
SkOpAngle* SkOpSegment::activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** startPtr,
- SkOpSpanBase** endPtr, bool* done, bool* sortable) {
+ SkOpSpanBase** endPtr, bool* done) {
SkOpSpan* upSpan = start->upCastable();
if (upSpan) {
if (upSpan->windValue() || upSpan->oppValue()) {
@@ -95,11 +95,11 @@ SkOpAngle* SkOpSegment::activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** sta
}
SkOpAngle* SkOpSegment::activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** startPtr,
- SkOpSpanBase** endPtr, bool* done, bool* sortable) {
+ SkOpSpanBase** endPtr, bool* done) {
SkOpPtT* oPtT = start->ptT()->next();
SkOpSegment* other = oPtT->segment();
SkOpSpanBase* oSpan = oPtT->span();
- return other->activeAngleInner(oSpan, startPtr, endPtr, done, sortable);
+ return other->activeAngleInner(oSpan, startPtr, endPtr, done);
}
bool SkOpSegment::activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask, int xorSuMask,
@@ -311,6 +311,14 @@ void SkOpSegment::align() {
if (!span->aligned()) {
span->alignEnd(1, fPts[SkPathOpsVerbToPoints(fVerb)]);
}
+ if (this->collapsed()) {
+ SkOpSpan* span = &fHead;
+ do {
+ span->setWindValue(0);
+ span->setOppValue(0);
+ this->markDone(span);
+ } while ((span = span->next()->upCastable()));
+ }
debugValidate();
}
@@ -363,6 +371,10 @@ void SkOpSegment::checkAngleCoin(SkOpCoincidence* coincidences, SkChunkAlloc* al
} while ((base = span->next()));
}
+bool SkOpSegment::collapsed() const {
+ return fVerb == SkPath::kLine_Verb && fHead.pt() == fTail.pt();
+}
+
void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
SkOpAngle::IncludeType includeType) {
SkOpSegment* baseSegment = baseAngle->segment();
@@ -1078,7 +1090,7 @@ SkOpSegment* SkOpSegment::nextChase(SkOpSpanBase** startPtr, int* stepPtr, SkOpS
return other;
}
-static void clear_visited(SkOpSpan* span) {
+static void clear_visited(SkOpSpanBase* span) {
// reset visited flag back to false
do {
SkOpPtT* ptT = span->ptT(), * stopPtT = ptT;
@@ -1086,7 +1098,7 @@ static void clear_visited(SkOpSpan* span) {
SkOpSegment* opp = ptT->segment();
opp->resetVisited();
}
- } while ((span = span->next()->upCastable()));
+ } while (!span->final() && (span = span->upCast()->next()));
}
// look for pairs of undetected coincident curves
@@ -1098,50 +1110,59 @@ void SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc
if (this->verb() != SkPath::kLine_Verb) {
return;
}
+ if (this->done()) {
+ return;
+ }
SkOpSpan* prior = NULL;
- SkOpSpan* span = &fHead;
+ SkOpSpanBase* spanBase = &fHead;
do {
- SkOpPtT* ptT = span->ptT(), * spanStopPtT = ptT;
- SkASSERT(ptT->span() == span);
+ SkOpPtT* ptT = spanBase->ptT(), * spanStopPtT = ptT;
+ SkASSERT(ptT->span() == spanBase);
while ((ptT = ptT->next()) != spanStopPtT) {
SkOpSegment* opp = ptT->span()->segment();
- if (!opp->setVisited()) {
+ if (opp->verb() == SkPath::kLine_Verb) {
continue;
}
- if (opp->verb() == SkPath::kLine_Verb) {
+ if (opp->done()) {
continue;
}
- if (span->containsCoincidence(opp)) { // FIXME: this assumes that if the opposite
- // segment is coincident then no more coincidence
- // needs to be detected. This may not be true.
+ // when opp is encounted the 1st time, continue; on 2nd encounter, look for coincidence
+ if (!opp->visited()) {
continue;
}
- if (span->containsCoinEnd(opp)) {
+ if (spanBase == &fHead) {
continue;
- }
- // if already visited and visited again, check for coin
- if (span == &fHead) {
+ }
+ SkOpSpan* span = spanBase->upCastable();
+ // FIXME?: this assumes that if the opposite segment is coincident then no more
+ // coincidence needs to be detected. This may not be true.
+ if (span && span->containsCoincidence(opp)) {
continue;
}
+ if (spanBase->containsCoinEnd(opp)) {
+ continue;
+ }
SkOpPtT* priorPtT = NULL, * priorStopPtT;
// find prior span containing opp segment
SkOpSegment* priorOpp = NULL;
- prior = span;
- while (!priorOpp && (prior = prior->prev())) {
- priorStopPtT = priorPtT = prior->ptT();
+ SkOpSpan* priorTest = spanBase->prev();
+ while (!priorOpp && priorTest) {
+ priorStopPtT = priorPtT = priorTest->ptT();
while ((priorPtT = priorPtT->next()) != priorStopPtT) {
SkOpSegment* segment = priorPtT->span()->segment();
if (segment == opp) {
+ prior = priorTest;
priorOpp = opp;
break;
}
}
+ priorTest = priorTest->prev();
}
if (!priorOpp) {
continue;
}
SkOpPtT* oppStart = prior->ptT();
- SkOpPtT* oppEnd = span->ptT();
+ SkOpPtT* oppEnd = spanBase->ptT();
bool swapped = priorPtT->fT > ptT->fT;
if (swapped) {
SkTSwap(priorPtT, ptT);
@@ -1154,7 +1175,7 @@ void SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc
}
{
// average t, find mid pt
- double midT = (prior->t() + span->t()) / 2;
+ double midT = (prior->t() + spanBase->t()) / 2;
SkPoint midPt = this->ptAtT(midT);
coincident = true;
// if the mid pt is not near either end pt, project perpendicular through opp seg
@@ -1182,9 +1203,10 @@ void SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc
}
if (coincident) {
// mark coincidence
- coincidences->add(priorPtT, ptT, oppStart, oppEnd, allocator);
+ if (!coincidences->extend(priorPtT, ptT, oppStart, oppEnd)) {
+ coincidences->add(priorPtT, ptT, oppStart, oppEnd, allocator);
+ }
clear_visited(&fHead);
- missingCoincidence(coincidences, allocator);
return;
}
swapBack:
@@ -1192,7 +1214,7 @@ void SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc
SkTSwap(priorPtT, ptT);
}
}
- } while ((span = span->next()->upCastable()));
+ } while ((spanBase = spanBase->final() ? NULL : spanBase->upCast()->next()));
clear_visited(&fHead);
}
@@ -1610,13 +1632,7 @@ int SkOpSegment::updateWinding(SkOpSpanBase* start, SkOpSpanBase* end) {
SkOpSpan* lesser = start->starter(end);
int winding = lesser->windSum();
if (winding == SK_MinS32) {
- SkOpGlobalState* globals = this->globalState();
- SkOpContour* contourHead = globals->contourHead();
- int windTry = 0;
- while (!lesser->sortableTop(contourHead) && ++windTry < SkOpGlobalState::kMaxWindingTries) {
- ;
- }
- winding = lesser->windSum();
+ winding = lesser->computeWindSum();
}
if (winding == SK_MinS32) {
return winding;
« no previous file with comments | « src/pathops/SkOpSegment.h ('k') | src/pathops/SkOpSpan.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698