diff options
author | 2016-12-16 17:17:25 -0500 | |
---|---|---|
committer | 2016-12-16 22:47:00 +0000 | |
commit | ab2d73b06fe6c518be1d399a79c9cc39db21abb6 (patch) | |
tree | b0a7c6a51acbaeb6aaca55361a838daabd506003 /src | |
parent | ee1c73fc1b8a616ac79572759b02435698171fbf (diff) |
rework xor to be more like winding
Pathops is very well exercised with winding paths,
but less so with xor (even odd) paths.
Rewrite the xor main loop to look like the winding
one to take advantage of the latter's bug fixes.
TBR=reed@google.com
BUG=skia:6041
Change-Id: Ied8d522254a327b1817b54f0abbf4414f5fab7da
Reviewed-on: https://skia-review.googlesource.com/6228
Reviewed-by: Cary Clark <caryclark@google.com>
Commit-Queue: Cary Clark <caryclark@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/pathops/SkOpCoincidence.cpp | 2 | ||||
-rw-r--r-- | src/pathops/SkOpContour.cpp | 16 | ||||
-rw-r--r-- | src/pathops/SkOpContour.h | 2 | ||||
-rw-r--r-- | src/pathops/SkOpSegment.cpp | 14 | ||||
-rw-r--r-- | src/pathops/SkOpSegment.h | 2 | ||||
-rw-r--r-- | src/pathops/SkPathOpsCommon.cpp | 11 | ||||
-rw-r--r-- | src/pathops/SkPathOpsCommon.h | 3 | ||||
-rw-r--r-- | src/pathops/SkPathOpsSimplify.cpp | 30 |
8 files changed, 39 insertions, 41 deletions
diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp index 1dd34ada93..9f841114d5 100644 --- a/src/pathops/SkOpCoincidence.cpp +++ b/src/pathops/SkOpCoincidence.cpp @@ -162,7 +162,7 @@ bool SkCoincidentSpans::ordered(bool* result) const { do { const SkOpPtT* opp = next->contains(oppSeg); if (!opp) { - SkOPOBJASSERT(start, 0); // may assert if coincident span isn't fully processed +// SkOPOBJASSERT(start, 0); // may assert if coincident span isn't fully processed return false; } if ((oppLastT > opp->fT) != flipped) { diff --git a/src/pathops/SkOpContour.cpp b/src/pathops/SkOpContour.cpp index 98467c558c..62380ab4fa 100644 --- a/src/pathops/SkOpContour.cpp +++ b/src/pathops/SkOpContour.cpp @@ -31,15 +31,19 @@ void SkOpContour::toReversePath(SkPathWriter* path) const { path->assemble(); } -SkOpSegment* SkOpContour::undoneSegment(SkOpSpanBase** startPtr, SkOpSpanBase** endPtr) { - SkOpSegment* segment = &fHead; +SkOpSpan* SkOpContour::undoneSpan() { + SkOpSegment* testSegment = &fHead; + bool allDone = true; do { - if (segment->done()) { + if (testSegment->done()) { continue; } - segment->undoneSpan(startPtr, endPtr); - return segment; - } while ((segment = segment->next())); + allDone = false; + return testSegment->undoneSpan(); + } while ((testSegment = testSegment->next())); + if (allDone) { + fDone = true; + } return nullptr; } diff --git a/src/pathops/SkOpContour.h b/src/pathops/SkOpContour.h index 8596002a2c..03230e1e90 100644 --- a/src/pathops/SkOpContour.h +++ b/src/pathops/SkOpContour.h @@ -368,7 +368,7 @@ public: void toReversePath(SkPathWriter* path) const; void toPath(SkPathWriter* path) const; - SkOpSegment* undoneSegment(SkOpSpanBase** startPtr, SkOpSpanBase** endPtr); + SkOpSpan* undoneSpan(); protected: SkOpGlobalState* fState; diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp index 95f4a983f2..58c71af437 100644 --- a/src/pathops/SkOpSegment.cpp +++ b/src/pathops/SkOpSegment.cpp @@ -1619,16 +1619,16 @@ bool SkOpSegment::testForCoincidence(const SkOpPtT* priorPtT, const SkOpPtT* ptT return coincident; } -void SkOpSegment::undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end) { - SkOpSpan* span = this->head(); +SkOpSpan* SkOpSegment::undoneSpan() { + SkOpSpan* span = &fHead; + SkOpSpanBase* next; do { + next = span->next(); if (!span->done()) { - break; + return span; } - } while ((span = span->next()->upCastable())); - SkASSERT(span); - *start = span; - *end = span->next(); + } while (!next->final() && (span = next->upCast())); + return nullptr; } int SkOpSegment::updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const { diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h index 116a630813..17c8a8f67e 100644 --- a/src/pathops/SkOpSegment.h +++ b/src/pathops/SkOpSegment.h @@ -398,7 +398,7 @@ public: bool testForCoincidence(const SkOpPtT* priorPtT, const SkOpPtT* ptT, const SkOpSpanBase* prior, const SkOpSpanBase* spanBase, const SkOpSegment* opp) const; - void undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end); + SkOpSpan* undoneSpan(); int updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const; int updateOppWinding(const SkOpAngle* angle) const; int updateOppWindingReverse(const SkOpAngle* angle) const; diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp index 7387249904..59bab0f6bd 100644 --- a/src/pathops/SkPathOpsCommon.cpp +++ b/src/pathops/SkPathOpsCommon.cpp @@ -85,12 +85,13 @@ const SkOpAngle* AngleWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* windi return angle; } -SkOpSegment* FindUndone(SkOpContourHead* contourList, SkOpSpanBase** startPtr, - SkOpSpanBase** endPtr) { - SkOpSegment* result; - SkOpContour* contour = contourList; +SkOpSpan* FindUndone(SkOpContourHead* contourHead) { + SkOpContour* contour = contourHead; do { - result = contour->undoneSegment(startPtr, endPtr); + if (contour->done()) { + continue; + } + SkOpSpan* result = contour->undoneSpan(); if (result) { return result; } diff --git a/src/pathops/SkPathOpsCommon.h b/src/pathops/SkPathOpsCommon.h index beffb8522c..679a486930 100644 --- a/src/pathops/SkPathOpsCommon.h +++ b/src/pathops/SkPathOpsCommon.h @@ -19,8 +19,7 @@ const SkOpAngle* AngleWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* windi SkOpSegment* FindChase(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** startPtr, SkOpSpanBase** endPtr); SkOpSpan* FindSortableTop(SkOpContourHead* ); -SkOpSegment* FindUndone(SkOpContourHead* , SkOpSpanBase** startPtr, - SkOpSpanBase** endPtr); +SkOpSpan* FindUndone(SkOpContourHead* ); bool FixWinding(SkPath* path); bool SortContourList(SkOpContourHead** , bool evenOdd, bool oppEvenOdd); bool HandleCoincidence(SkOpContourHead* , SkOpCoincidence* ); diff --git a/src/pathops/SkPathOpsSimplify.cpp b/src/pathops/SkPathOpsSimplify.cpp index 8cd770dd54..eb71e73f4a 100644 --- a/src/pathops/SkPathOpsSimplify.cpp +++ b/src/pathops/SkPathOpsSimplify.cpp @@ -84,30 +84,25 @@ static bool bridgeWinding(SkOpContourHead* contourList, SkPathWriter* simple) { // returns true if all edges were processed static bool bridgeXor(SkOpContourHead* contourList, SkPathWriter* simple) { - SkOpSegment* current; - SkOpSpanBase* start; - SkOpSpanBase* end; bool unsortable = false; - while ((current = FindUndone(contourList, &start, &end))) { + do { + SkOpSpan* span = FindUndone(contourList); + if (!span) { + break; + } + SkOpSegment* current = span->segment(); + SkOpSpanBase* start = span->next(); + SkOpSpanBase* end = span; do { if (!unsortable && current->done()) { - SkPathOpsDebug::ShowActiveSpans(contourList); + break; } SkASSERT(unsortable || !current->done()); SkOpSpanBase* nextStart = start; SkOpSpanBase* nextEnd = end; - SkOpSegment* next = current->findNextXor(&nextStart, &nextEnd, &unsortable); + SkOpSegment* next = current->findNextXor(&nextStart, &nextEnd, + &unsortable); if (!next) { - if (!unsortable && simple->hasMove() - && current->verb() != SkPath::kLine_Verb - && !simple->isClosed()) { - if (!current->addCurveTo(start, end, simple)) { - return false; - } - if (!simple->isClosed()) { - SkPathOpsDebug::ShowActiveSpans(contourList); - } - } break; } #if DEBUG_FLOW @@ -123,7 +118,6 @@ static bool bridgeXor(SkOpContourHead* contourList, SkPathWriter* simple) { end = nextEnd; } while (!simple->isClosed() && (!unsortable || !start->starter(end)->done())); if (!simple->isClosed()) { - SkASSERT(unsortable); SkOpSpan* spanStart = start->starter(end); if (!spanStart->done()) { if (!current->addCurveTo(start, end, simple)) { @@ -134,7 +128,7 @@ static bool bridgeXor(SkOpContourHead* contourList, SkPathWriter* simple) { } simple->finishContour(); SkPathOpsDebug::ShowActiveSpans(contourList); - } + } while (true); return true; } |