| Index: src/pathops/SkPathOpsCommon.cpp
|
| diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp
|
| index c48a7eef68926a50721c3f2a3f4974f98753f277..f34148390cb8c6cbdb21d4d0c129a746216dcd87 100644
|
| --- a/src/pathops/SkPathOpsCommon.cpp
|
| +++ b/src/pathops/SkPathOpsCommon.cpp
|
| @@ -111,75 +111,62 @@ SkOpSegment* FindUndone(SkTArray<SkOpContour*, true>& contourList, int* start, i
|
| return NULL;
|
| }
|
|
|
| -SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex) {
|
| - while (chase.count()) {
|
| +SkOpSegment* FindChase(SkTDArray<SkOpSpan*>* chase, int* tIndex, int* endIndex) {
|
| + while (chase->count()) {
|
| SkOpSpan* span;
|
| - chase.pop(&span);
|
| + chase->pop(&span);
|
| const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex);
|
| SkOpSegment* segment = backPtr.fOther;
|
| - tIndex = backPtr.fOtherIndex;
|
| - SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
|
| - int done = 0;
|
| - if (segment->activeAngle(tIndex, &done, &angles)) {
|
| - SkOpAngle* last = angles.end() - 1;
|
| - tIndex = last->start();
|
| - endIndex = last->end();
|
| - #if TRY_ROTATE
|
| - *chase.insert(0) = span;
|
| - #else
|
| - *chase.append() = span;
|
| - #endif
|
| + *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
|
| + *chase->append() = span;
|
| + #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, 0, 0, sortable);
|
| -#endif
|
| if (!sortable) {
|
| continue;
|
| }
|
| // find first angle, initialize winding to computed fWindSum
|
| - int firstIndex = -1;
|
| - const SkOpAngle* angle;
|
| + const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex);
|
| + const SkOpAngle* firstAngle;
|
| + SkDEBUGCODE(firstAngle = angle);
|
| + SkDEBUGCODE(bool loop = false);
|
| int winding;
|
| do {
|
| - angle = sorted[++firstIndex];
|
| + angle = angle->next();
|
| + SkASSERT(angle != firstAngle || !loop);
|
| + SkDEBUGCODE(loop |= angle == firstAngle);
|
| segment = angle->segment();
|
| winding = segment->windSum(angle);
|
| } while (winding == SK_MinS32);
|
| int spanWinding = segment->spanSign(angle->start(), angle->end());
|
| #if DEBUG_WINDING
|
| - SkDebugf("%s winding=%d spanWinding=%d\n",
|
| - __FUNCTION__, winding, spanWinding);
|
| + SkDebugf("%s winding=%d spanWinding=%d\n", __FUNCTION__, winding, spanWinding);
|
| #endif
|
| // turn span winding into contour winding
|
| if (spanWinding * winding < 0) {
|
| winding += spanWinding;
|
| }
|
| - #if DEBUG_SORT
|
| - segment->debugShowSort(__FUNCTION__, sorted, firstIndex, winding, 0, sortable);
|
| - #endif
|
| // we care about first sign and whether wind sum indicates this
|
| // edge is inside or outside. Maybe need to pass span winding
|
| // or first winding or something into this function?
|
| // advance to first undone angle, then return it and winding
|
| // (to set whether edges are active or not)
|
| - int nextIndex = firstIndex + 1;
|
| - int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
|
| - angle = sorted[firstIndex];
|
| - winding -= angle->segment()->spanSign(angle);
|
| - do {
|
| - SkASSERT(nextIndex != firstIndex);
|
| - if (nextIndex == angleCount) {
|
| - nextIndex = 0;
|
| - }
|
| - angle = sorted[nextIndex];
|
| + firstAngle = angle;
|
| + winding -= firstAngle->segment()->spanSign(firstAngle);
|
| + while ((angle = angle->next()) != firstAngle) {
|
| segment = angle->segment();
|
| int maxWinding = winding;
|
| winding -= segment->spanSign(angle);
|
| @@ -187,9 +174,9 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex)
|
| SkDebugf("%s id=%d maxWinding=%d winding=%d sign=%d\n", __FUNCTION__,
|
| segment->debugID(), maxWinding, winding, angle->sign());
|
| #endif
|
| - tIndex = angle->start();
|
| - endIndex = angle->end();
|
| - int lesser = SkMin32(tIndex, endIndex);
|
| + *tIndex = angle->start();
|
| + *endIndex = angle->end();
|
| + int lesser = SkMin32(*tIndex, *endIndex);
|
| const SkOpSpan& nextSpan = segment->span(lesser);
|
| if (!nextSpan.fDone) {
|
| // FIXME: this be wrong? assign startWinding if edge is in
|
| @@ -201,8 +188,8 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex)
|
| segment->markAndChaseWinding(angle, maxWinding, 0);
|
| break;
|
| }
|
| - } while (++nextIndex != lastIndex);
|
| - *chase.insert(0) = span;
|
| + }
|
| + *chase->insert(0) = span;
|
| return segment;
|
| }
|
| return NULL;
|
| @@ -221,6 +208,8 @@ static SkOpSegment* findSortableTop(const SkTArray<SkOpContour*, true>& contourL
|
| int* index, int* endIndex, SkPoint* topLeft, bool* unsortable,
|
| bool* done, bool onlySortable) {
|
| SkOpSegment* result;
|
| + const SkOpSegment* lastTopStart = NULL;
|
| + int lastIndex = -1, lastEndIndex = -1;
|
| do {
|
| SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax};
|
| int contourCount = contourList.count();
|
| @@ -249,7 +238,16 @@ static SkOpSegment* findSortableTop(const SkTArray<SkOpContour*, true>& contourL
|
| return NULL;
|
| }
|
| *topLeft = bestXY;
|
| - result = topStart->findTop(index, endIndex, unsortable, onlySortable);
|
| + result = topStart->findTop(index, endIndex, unsortable);
|
| + if (!result) {
|
| + if (lastTopStart == topStart && lastIndex == *index && lastEndIndex == *endIndex) {
|
| + *done = true;
|
| + return NULL;
|
| + }
|
| + lastTopStart = topStart;
|
| + lastIndex = *index;
|
| + lastEndIndex = *endIndex;
|
| + }
|
| } while (!result);
|
| if (result) {
|
| *unsortable = false;
|
| @@ -303,7 +301,7 @@ SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList,
|
| const int index = *indexPtr;
|
| const int endIndex = *endIndexPtr;
|
| if (*firstContour) {
|
| - current->initWinding(index, endIndex);
|
| + current->initWinding(index, endIndex, angleIncludeType);
|
| *firstContour = false;
|
| return current;
|
| }
|
| @@ -313,9 +311,11 @@ SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList,
|
| return current;
|
| }
|
| SkASSERT(current->windSum(SkMin32(index, endIndex)) == SK_MinS32);
|
| - SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
|
| - SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
|
| - sumWinding = current->computeSum(index, endIndex, angleIncludeType, &angles, &sorted);
|
| + const SkOpSpan& span = current->span(endIndex);
|
| + if ((index < endIndex ? span.fFromAngleIndex : span.fToAngleIndex) < 0) {
|
| + current->addSimpleAngle(endIndex);
|
| + }
|
| + sumWinding = current->computeSum(index, endIndex, angleIncludeType);
|
| if (sumWinding != SK_MinS32 && sumWinding != SK_NaN32) {
|
| return current;
|
| }
|
| @@ -351,6 +351,25 @@ SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList,
|
| return current;
|
| }
|
|
|
| +static bool calcAngles(SkTArray<SkOpContour*, true>* contourList) {
|
| + int contourCount = (*contourList).count();
|
| + for (int cTest = 0; cTest < contourCount; ++cTest) {
|
| + SkOpContour* contour = (*contourList)[cTest];
|
| + if (!contour->calcAngles()) {
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +static void checkDuplicates(SkTArray<SkOpContour*, true>* contourList) {
|
| + int contourCount = (*contourList).count();
|
| + for (int cTest = 0; cTest < contourCount; ++cTest) {
|
| + SkOpContour* contour = (*contourList)[cTest];
|
| + contour->checkDuplicates();
|
| + }
|
| +}
|
| +
|
| static void checkEnds(SkTArray<SkOpContour*, true>* contourList) {
|
| // it's hard to determine if the end of a cubic or conic nearly intersects another curve.
|
| // instead, look to see if the connecting curve intersected at that same end.
|
| @@ -361,6 +380,25 @@ static void checkEnds(SkTArray<SkOpContour*, true>* contourList) {
|
| }
|
| }
|
|
|
| +static void checkMultiples(SkTArray<SkOpContour*, true>* contourList) {
|
| + // it's hard to determine if the end of a cubic or conic nearly intersects another curve.
|
| + // instead, look to see if the connecting curve intersected at that same end.
|
| + int contourCount = (*contourList).count();
|
| + for (int cTest = 0; cTest < contourCount; ++cTest) {
|
| + SkOpContour* contour = (*contourList)[cTest];
|
| + contour->checkMultiples();
|
| + }
|
| +}
|
| +
|
| +// A small interval of a pair of curves may collapse to lines for each, triggering coincidence
|
| +static void checkSmall(SkTArray<SkOpContour*, true>* contourList) {
|
| + int contourCount = (*contourList).count();
|
| + for (int cTest = 0; cTest < contourCount; ++cTest) {
|
| + SkOpContour* contour = (*contourList)[cTest];
|
| + contour->checkSmall();
|
| + }
|
| +}
|
| +
|
| // A tiny interval may indicate an undiscovered coincidence. Find and fix.
|
| static void checkTiny(SkTArray<SkOpContour*, true>* contourList) {
|
| int contourCount = (*contourList).count();
|
| @@ -386,6 +424,14 @@ static void joinCoincidence(SkTArray<SkOpContour*, true>* contourList) {
|
| }
|
| }
|
|
|
| +static void sortAngles(SkTArray<SkOpContour*, true>* contourList) {
|
| + int contourCount = (*contourList).count();
|
| + for (int cTest = 0; cTest < contourCount; ++cTest) {
|
| + SkOpContour* contour = (*contourList)[cTest];
|
| + contour->sortAngles();
|
| + }
|
| +}
|
| +
|
| static void sortSegments(SkTArray<SkOpContour*, true>* contourList) {
|
| int contourCount = (*contourList).count();
|
| for (int cTest = 0; cTest < contourCount; ++cTest) {
|
| @@ -613,7 +659,7 @@ void Assemble(const SkPathWriter& path, SkPathWriter* simple) {
|
| #endif
|
| }
|
|
|
| -void HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) {
|
| +bool HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) {
|
| #if DEBUG_SHOW_WINDING
|
| SkOpContour::debugShowWindingValues(contourList);
|
| #endif
|
| @@ -623,10 +669,18 @@ void HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) {
|
| #endif
|
| fixOtherTIndex(contourList);
|
| checkEnds(contourList);
|
| + checkMultiples(contourList);
|
| + checkDuplicates(contourList);
|
| checkTiny(contourList);
|
| + checkSmall(contourList);
|
| joinCoincidence(contourList);
|
| sortSegments(contourList);
|
| + if (!calcAngles(contourList)) {
|
| + return false;
|
| + }
|
| + sortAngles(contourList);
|
| #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
|
| DebugShowActiveSpans(*contourList);
|
| #endif
|
| + return true;
|
| }
|
|
|