aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@google.com>2016-12-16 17:17:25 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-12-16 22:47:00 +0000
commitab2d73b06fe6c518be1d399a79c9cc39db21abb6 (patch)
treeb0a7c6a51acbaeb6aaca55361a838daabd506003 /src
parentee1c73fc1b8a616ac79572759b02435698171fbf (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.cpp2
-rw-r--r--src/pathops/SkOpContour.cpp16
-rw-r--r--src/pathops/SkOpContour.h2
-rw-r--r--src/pathops/SkOpSegment.cpp14
-rw-r--r--src/pathops/SkOpSegment.h2
-rw-r--r--src/pathops/SkPathOpsCommon.cpp11
-rw-r--r--src/pathops/SkPathOpsCommon.h3
-rw-r--r--src/pathops/SkPathOpsSimplify.cpp30
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;
}