Index: src/pathops/SkPathOpsOp.cpp |
diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp |
index 1b7b03b95ba6e2b28f78675dbb967055cfa1c1fe..130d4983f9cc2d728ebe80ade042a0b0ccee1dbf 100644 |
--- a/src/pathops/SkPathOpsOp.cpp |
+++ b/src/pathops/SkPathOpsOp.cpp |
@@ -9,23 +9,20 @@ |
#include "SkPathOpsCommon.h" |
#include "SkPathWriter.h" |
-// FIXME: this and find chase should be merge together, along with |
-// other code that walks winding in angles |
-// OPTIMIZATION: Probably, the walked winding should be rolled into the angle structure |
-// so it isn't duplicated by walkers like this one |
-static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int& nextEnd) { |
+static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int* tIndex, int* endIndex) { |
while (chase.count()) { |
SkOpSpan* span; |
chase.pop(&span); |
const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex); |
SkOpSegment* segment = backPtr.fOther; |
- nextStart = backPtr.fOtherIndex; |
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles; |
- int done = 0; |
- if (segment->activeAngle(nextStart, &done, &angles)) { |
- SkOpAngle* last = angles.end() - 1; |
- nextStart = last->start(); |
- nextEnd = last->end(); |
+ *tIndex = backPtr.fOtherIndex; |
+ bool sortable = true; |
+ bool done = true; |
+ *endIndex = -1; |
+ if (const SkOpAngle* last = segment->activeAngle(*tIndex, tIndex, endIndex, &done, |
+ &sortable)) { |
+ *tIndex = last->start(); |
+ *endIndex = last->end(); |
#if TRY_ROTATE |
*chase.insert(0) = span; |
#else |
@@ -33,52 +30,31 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int |
#endif |
return last->segment(); |
} |
- if (done == angles.count()) { |
+ if (done) { |
continue; |
} |
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted; |
- bool sortable = SkOpSegment::SortAngles(angles, &sorted, |
- SkOpSegment::kMayBeUnordered_SortAngleKind); |
- int angleCount = sorted.count(); |
-#if DEBUG_SORT |
- sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, sortable); |
-#endif |
if (!sortable) { |
continue; |
} |
// find first angle, initialize winding to computed fWindSum |
- int firstIndex = -1; |
- const SkOpAngle* angle; |
- bool foundAngle = true; |
+ const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex); |
+ const SkOpAngle* firstAngle = angle; |
+ SkDEBUGCODE(bool loop = false); |
+ int winding; |
do { |
- ++firstIndex; |
- if (firstIndex >= angleCount) { |
- foundAngle = false; |
- break; |
- } |
- angle = sorted[firstIndex]; |
+ angle = angle->next(); |
+ SkASSERT(angle != firstAngle || !loop); |
+ SkDEBUGCODE(loop |= angle == firstAngle); |
segment = angle->segment(); |
- } while (segment->windSum(angle) == SK_MinS32); |
- if (!foundAngle) { |
- continue; |
- } |
- #if DEBUG_SORT |
- segment->debugShowSort(__FUNCTION__, sorted, firstIndex, sortable); |
- #endif |
+ winding = segment->windSum(angle); |
+ } while (winding == SK_MinS32); |
int sumMiWinding = segment->updateWindingReverse(angle); |
int sumSuWinding = segment->updateOppWindingReverse(angle); |
if (segment->operand()) { |
SkTSwap<int>(sumMiWinding, sumSuWinding); |
} |
- int nextIndex = firstIndex + 1; |
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount; |
SkOpSegment* first = NULL; |
- do { |
- SkASSERT(nextIndex != firstIndex); |
- if (nextIndex == angleCount) { |
- nextIndex = 0; |
- } |
- angle = sorted[nextIndex]; |
+ while ((angle = angle->next()) != firstAngle) { |
segment = angle->segment(); |
int start = angle->start(); |
int end = angle->end(); |
@@ -88,13 +64,13 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int |
if (!segment->done(angle)) { |
if (!first) { |
first = segment; |
- nextStart = start; |
- nextEnd = end; |
+ *tIndex = start; |
+ *endIndex = end; |
} |
(void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding, |
oppSumWinding, angle); |
} |
- } while (++nextIndex != lastIndex); |
+ } |
if (first) { |
#if TRY_ROTATE |
*chase.insert(0) = span; |
@@ -160,9 +136,6 @@ static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp o |
if (current->activeOp(index, endIndex, xorMask, xorOpMask, op)) { |
do { |
if (!unsortable && current->done()) { |
- #if DEBUG_ACTIVE_SPANS |
- DebugShowActiveSpans(contourList); |
- #endif |
if (simple->isEmpty()) { |
simple->init(); |
} |
@@ -199,7 +172,6 @@ static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp o |
if (!unsortable && !simple->isEmpty()) { |
unsortable = current->checkSmall(min); |
} |
- SkASSERT(unsortable || simple->isEmpty()); |
if (!current->done(min)) { |
current->addCurveTo(index, endIndex, simple, true); |
current->markDoneBinary(min); |
@@ -208,11 +180,13 @@ static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp o |
simple->close(); |
} else { |
SkOpSpan* last = current->markAndChaseDoneBinary(index, endIndex); |
- if (last && !last->fLoop) { |
+ if (last && !last->fChased && !last->fLoop) { |
+ last->fChased = true; |
+ SkASSERT(!SkPathOpsDebug::ChaseContains(chaseArray, last)); |
*chaseArray.append() = last; |
} |
} |
- current = findChaseOp(chaseArray, index, endIndex); |
+ current = findChaseOp(chaseArray, &index, &endIndex); |
#if DEBUG_ACTIVE_SPANS |
DebugShowActiveSpans(contourList); |
#endif |
@@ -304,7 +278,9 @@ bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { |
for (index = 0; index < contourList.count(); ++index) { |
total += contourList[index]->segments().count(); |
} |
- HandleCoincidence(&contourList, total); |
+ if (!HandleCoincidence(&contourList, total)) { |
+ return false; |
+ } |
// construct closed contours |
SkPathWriter wrapper(*result); |
bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper); |