aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pathops/SkPathOpsOp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pathops/SkPathOpsOp.cpp')
-rw-r--r--src/pathops/SkPathOpsOp.cpp84
1 files changed, 30 insertions, 54 deletions
diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp
index 1b7b03b95b..130d4983f9 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);