| Index: src/pathops/SkPathOpsCommon.cpp
|
| diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp
|
| index 98cce15fb29554df3bc5622ac84d53bea331f2e3..4ead297f7dcfd958ed004de6cf95c965bfa98651 100644
|
| --- a/src/pathops/SkPathOpsCommon.cpp
|
| +++ b/src/pathops/SkPathOpsCommon.cpp
|
| @@ -394,6 +394,13 @@ static void align(SkOpContourHead* contourList) {
|
| } while ((contour = contour->next()));
|
| }
|
|
|
| +static void addAlignIntersections(SkOpContourHead* contourList, SkChunkAlloc* allocator) {
|
| + SkOpContour* contour = contourList;
|
| + do {
|
| + contour->addAlignIntersections(contourList, allocator);
|
| + } while ((contour = contour->next()));
|
| +}
|
| +
|
| static void calcAngles(SkOpContourHead* contourList, SkChunkAlloc* allocator) {
|
| SkOpContour* contour = contourList;
|
| do {
|
| @@ -401,12 +408,14 @@ static void calcAngles(SkOpContourHead* contourList, SkChunkAlloc* allocator) {
|
| } while ((contour = contour->next()));
|
| }
|
|
|
| -static void missingCoincidence(SkOpContourHead* contourList,
|
| +static bool missingCoincidence(SkOpContourHead* contourList,
|
| SkOpCoincidence* coincidence, SkChunkAlloc* allocator) {
|
| SkOpContour* contour = contourList;
|
| + bool result = false;
|
| do {
|
| - contour->missingCoincidence(coincidence, allocator);
|
| + result |= contour->missingCoincidence(coincidence, allocator);
|
| } while ((contour = contour->next()));
|
| + return result;
|
| }
|
|
|
| static void moveMultiples(SkOpContourHead* contourList) {
|
| @@ -438,23 +447,42 @@ bool HandleCoincidence(SkOpContourHead* contourList, SkOpCoincidence* coincidenc
|
| // move t values and points together to eliminate small/tiny gaps
|
| moveNearby(contourList);
|
| align(contourList); // give all span members common values
|
| + coincidence->fixAligned(); // aligning may have marked a coincidence pt-t deleted
|
| #if DEBUG_VALIDATE
|
| globalState->setPhase(SkOpGlobalState::kIntersecting);
|
| #endif
|
| + // look for intersections on line segments formed by moving end points
|
| + addAlignIntersections(contourList, allocator);
|
| coincidence->addMissing(allocator);
|
| #if DEBUG_VALIDATE
|
| globalState->setPhase(SkOpGlobalState::kWalking);
|
| #endif
|
| - coincidence->expand(); // check to see if, loosely, coincident ranges may be expanded
|
| + // check to see if, loosely, coincident ranges may be expanded
|
| + if (coincidence->expand()) {
|
| + coincidence->addExpanded(allocator PATH_OPS_DEBUG_VALIDATE_PARAMS(globalState));
|
| + }
|
| + // the expanded ranges may not align -- add the missing spans
|
| coincidence->mark(); // mark spans of coincident segments as coincident
|
| - missingCoincidence(contourList, coincidence, allocator); // look for coincidence missed earlier
|
| - if (!coincidence->apply()) { // adjust the winding value to account for coincident edges
|
| - return false;
|
| + // look for coincidence missed earlier
|
| + if (missingCoincidence(contourList, coincidence, allocator)) {
|
| + (void) coincidence->expand();
|
| + coincidence->addExpanded(allocator PATH_OPS_DEBUG_VALIDATE_PARAMS(globalState));
|
| + coincidence->mark();
|
| }
|
| + SkOpCoincidence overlaps;
|
| + do {
|
| + SkOpCoincidence* pairs = overlaps.isEmpty() ? coincidence : &overlaps;
|
| + if (!pairs->apply()) { // adjust the winding value to account for coincident edges
|
| + return false;
|
| + }
|
| + // For each coincident pair that overlaps another, when the receivers (the 1st of the pair)
|
| + // are different, construct a new pair to resolve their mutual span
|
| + pairs->findOverlaps(&overlaps, allocator);
|
| + } while (!overlaps.isEmpty());
|
| calcAngles(contourList, allocator);
|
| sortAngles(contourList);
|
| if (globalState->angleCoincidence()) {
|
| - missingCoincidence(contourList, coincidence, allocator);
|
| + (void) missingCoincidence(contourList, coincidence, allocator);
|
| if (!coincidence->apply()) {
|
| return false;
|
| }
|
|
|