| Index: src/pathops/SkAddIntersections.cpp
|
| diff --git a/src/pathops/SkAddIntersections.cpp b/src/pathops/SkAddIntersections.cpp
|
| index c27434f9f778cb1a4df19570b6ecfdbeb8d90e38..b507eb7560989665109fd358e7b5fc9b359c4f21 100644
|
| --- a/src/pathops/SkAddIntersections.cpp
|
| +++ b/src/pathops/SkAddIntersections.cpp
|
| @@ -5,6 +5,7 @@
|
| * found in the LICENSE file.
|
| */
|
| #include "SkAddIntersections.h"
|
| +#include "SkOpCoincidence.h"
|
| #include "SkPathOpsBounds.h"
|
|
|
| #if DEBUG_ADD_INTERSECTING_TS
|
| @@ -130,20 +131,6 @@ static void debugShowCubicIntersection(int pts, const SkIntersectionHelper& wt,
|
| SkDebugf("\n");
|
| }
|
|
|
| -static void debugShowCubicIntersection(int pts, const SkIntersectionHelper& wt,
|
| - const SkIntersections& i) {
|
| - SkASSERT(i.used() == pts);
|
| - if (!pts) {
|
| - SkDebugf("%s no self intersect " CUBIC_DEBUG_STR "\n", __FUNCTION__,
|
| - CUBIC_DEBUG_DATA(wt.pts()));
|
| - return;
|
| - }
|
| - SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
|
| - i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
|
| - SkDebugf(" " T_DEBUG_STR(wtTs, 1), i[1][0]);
|
| - SkDebugf("\n");
|
| -}
|
| -
|
| #else
|
| static void debugShowLineIntersection(int , const SkIntersectionHelper& ,
|
| const SkIntersectionHelper& , const SkIntersections& ) {
|
| @@ -168,13 +155,10 @@ static void debugShowCubicQuadIntersection(int , const SkIntersectionHelper& ,
|
| static void debugShowCubicIntersection(int , const SkIntersectionHelper& ,
|
| const SkIntersectionHelper& , const SkIntersections& ) {
|
| }
|
| -
|
| -static void debugShowCubicIntersection(int , const SkIntersectionHelper& ,
|
| - const SkIntersections& ) {
|
| -}
|
| #endif
|
|
|
| -bool AddIntersectTs(SkOpContour* test, SkOpContour* next) {
|
| +bool AddIntersectTs(SkOpContour* test, SkOpContour* next, SkOpCoincidence* coincidence,
|
| + SkChunkAlloc* allocator) {
|
| if (test != next) {
|
| if (AlmostLessUlps(test->bounds().fBottom, next->bounds().fTop)) {
|
| return false;
|
| @@ -186,10 +170,11 @@ bool AddIntersectTs(SkOpContour* test, SkOpContour* next) {
|
| }
|
| SkIntersectionHelper wt;
|
| wt.init(test);
|
| - bool foundCommonContour = test == next;
|
| do {
|
| SkIntersectionHelper wn;
|
| wn.init(next);
|
| + test->debugValidate();
|
| + next->debugValidate();
|
| if (test == next && !wn.startAfter(wt)) {
|
| continue;
|
| }
|
| @@ -306,14 +291,22 @@ bool AddIntersectTs(SkOpContour* test, SkOpContour* next) {
|
| break;
|
| }
|
| case SkIntersectionHelper::kQuad_Segment: {
|
| - pts = ts.quadQuad(wt.pts(), wn.pts());
|
| - ts.alignQuadPts(wt.pts(), wn.pts());
|
| + SkDQuad quad1;
|
| + quad1.set(wt.pts());
|
| + SkDQuad quad2;
|
| + quad2.set(wn.pts());
|
| + pts = ts.intersect(quad1, quad2);
|
| debugShowQuadIntersection(pts, wt, wn, ts);
|
| break;
|
| }
|
| case SkIntersectionHelper::kCubic_Segment: {
|
| swap = true;
|
| - pts = ts.cubicQuad(wn.pts(), wt.pts());
|
| + SkDQuad quad1;
|
| + quad1.set(wt.pts());
|
| + SkDCubic cubic1 = quad1.toCubic();
|
| + SkDCubic cubic2;
|
| + cubic2.set(wn.pts());
|
| + pts = ts.intersect(cubic2, cubic1);
|
| debugShowCubicQuadIntersection(pts, wn, wt, ts);
|
| break;
|
| }
|
| @@ -339,12 +332,21 @@ bool AddIntersectTs(SkOpContour* test, SkOpContour* next) {
|
| break;
|
| }
|
| case SkIntersectionHelper::kQuad_Segment: {
|
| - pts = ts.cubicQuad(wt.pts(), wn.pts());
|
| + SkDCubic cubic1;
|
| + cubic1.set(wt.pts());
|
| + SkDQuad quad2;
|
| + quad2.set(wn.pts());
|
| + SkDCubic cubic2 = quad2.toCubic();
|
| + pts = ts.intersect(cubic1, cubic2);
|
| debugShowCubicQuadIntersection(pts, wt, wn, ts);
|
| break;
|
| }
|
| case SkIntersectionHelper::kCubic_Segment: {
|
| - pts = ts.cubicCubic(wt.pts(), wn.pts());
|
| + SkDCubic cubic1;
|
| + cubic1.set(wt.pts());
|
| + SkDCubic cubic2;
|
| + cubic2.set(wn.pts());
|
| + pts = ts.intersect(cubic1, cubic2);
|
| debugShowCubicIntersection(pts, wt, wn, ts);
|
| break;
|
| }
|
| @@ -355,102 +357,53 @@ bool AddIntersectTs(SkOpContour* test, SkOpContour* next) {
|
| default:
|
| SkASSERT(0);
|
| }
|
| - if (!foundCommonContour && pts > 0) {
|
| - test->addCross(next);
|
| - next->addCross(test);
|
| - foundCommonContour = true;
|
| - }
|
| - // in addition to recording T values, record matching segment
|
| - if (pts == 2) {
|
| - if (wn.segmentType() <= SkIntersectionHelper::kLine_Segment
|
| - && wt.segmentType() <= SkIntersectionHelper::kLine_Segment) {
|
| - if (wt.addCoincident(wn, ts, swap)) {
|
| - continue;
|
| - }
|
| - pts = ts.cleanUpCoincidence(); // prefer (t == 0 or t == 1)
|
| - } else if (wn.segmentType() >= SkIntersectionHelper::kQuad_Segment
|
| - && wt.segmentType() >= SkIntersectionHelper::kQuad_Segment
|
| - && ts.isCoincident(0)) {
|
| - SkASSERT(ts.coincidentUsed() == 2);
|
| - if (wt.addCoincident(wn, ts, swap)) {
|
| - continue;
|
| - }
|
| - pts = ts.cleanUpCoincidence(); // prefer (t == 0 or t == 1)
|
| - }
|
| - }
|
| - if (pts >= 2) {
|
| - for (int pt = 0; pt < pts - 1; ++pt) {
|
| - const SkDPoint& point = ts.pt(pt);
|
| - const SkDPoint& next = ts.pt(pt + 1);
|
| - if (wt.isPartial(ts[swap][pt], ts[swap][pt + 1], point, next)
|
| - && wn.isPartial(ts[!swap][pt], ts[!swap][pt + 1], point, next)) {
|
| - if (!wt.addPartialCoincident(wn, ts, pt, swap)) {
|
| - // remove extra point if two map to same float values
|
| - pts = ts.cleanUpCoincidence(); // prefer (t == 0 or t == 1)
|
| - }
|
| - }
|
| - }
|
| - }
|
| + int coinIndex = -1;
|
| + SkOpPtT* coinPtT[2];
|
| for (int pt = 0; pt < pts; ++pt) {
|
| SkASSERT(ts[0][pt] >= 0 && ts[0][pt] <= 1);
|
| SkASSERT(ts[1][pt] >= 0 && ts[1][pt] <= 1);
|
| - SkPoint point = ts.pt(pt).asSkPoint();
|
| - wt.alignTPt(wn, swap, pt, &ts, &point);
|
| - int testTAt = wt.addT(wn, point, ts[swap][pt]);
|
| - int nextTAt = wn.addT(wt, point, ts[!swap][pt]);
|
| - wt.addOtherT(testTAt, ts[!swap][pt], nextTAt);
|
| - wn.addOtherT(nextTAt, ts[swap][pt], testTAt);
|
| + wt.segment()->debugValidate();
|
| + SkOpPtT* testTAt = wt.segment()->addT(ts[swap][pt], SkOpSegment::kAllowAlias,
|
| + allocator);
|
| + wn.segment()->debugValidate();
|
| + SkOpPtT* nextTAt = wn.segment()->addT(ts[!swap][pt], SkOpSegment::kAllowAlias,
|
| + allocator);
|
| + testTAt->addOpp(nextTAt);
|
| + if (testTAt->fPt != nextTAt->fPt) {
|
| + testTAt->span()->unaligned();
|
| + nextTAt->span()->unaligned();
|
| + }
|
| + wt.segment()->debugValidate();
|
| + wn.segment()->debugValidate();
|
| + if (!ts.isCoincident(pt)) {
|
| + continue;
|
| + }
|
| + if (coinIndex < 0) {
|
| + coinPtT[0] = testTAt;
|
| + coinPtT[1] = nextTAt;
|
| + coinIndex = pt;
|
| + continue;
|
| + }
|
| + if (coinPtT[0]->span() == testTAt->span()) {
|
| + coinIndex = -1;
|
| + continue;
|
| + }
|
| + if (coinPtT[1]->span() == nextTAt->span()) {
|
| + coinIndex = -1; // coincidence span collapsed
|
| + continue;
|
| + }
|
| + if (swap) {
|
| + SkTSwap(coinPtT[0], coinPtT[1]);
|
| + SkTSwap(testTAt, nextTAt);
|
| + }
|
| + SkASSERT(coinPtT[0]->span()->t() < testTAt->span()->t());
|
| + coincidence->add(coinPtT[0], testTAt, coinPtT[1], nextTAt, allocator);
|
| + wt.segment()->debugValidate();
|
| + wn.segment()->debugValidate();
|
| + coinIndex = -1;
|
| }
|
| + SkASSERT(coinIndex < 0); // expect coincidence to be paired
|
| } while (wn.advance());
|
| } while (wt.advance());
|
| return true;
|
| }
|
| -
|
| -void AddSelfIntersectTs(SkOpContour* test) {
|
| - SkIntersectionHelper wt;
|
| - wt.init(test);
|
| - do {
|
| - if (wt.segmentType() != SkIntersectionHelper::kCubic_Segment) {
|
| - continue;
|
| - }
|
| - SkIntersections ts;
|
| - int pts = ts.cubic(wt.pts());
|
| - debugShowCubicIntersection(pts, wt, ts);
|
| - if (!pts) {
|
| - continue;
|
| - }
|
| - SkASSERT(pts == 1);
|
| - SkASSERT(ts[0][0] >= 0 && ts[0][0] <= 1);
|
| - SkASSERT(ts[1][0] >= 0 && ts[1][0] <= 1);
|
| - SkPoint point = ts.pt(0).asSkPoint();
|
| - int testTAt = wt.addSelfT(point, ts[0][0]);
|
| - int nextTAt = wt.addSelfT(point, ts[1][0]);
|
| - wt.addOtherT(testTAt, ts[1][0], nextTAt);
|
| - wt.addOtherT(nextTAt, ts[0][0], testTAt);
|
| - } while (wt.advance());
|
| -}
|
| -
|
| -// resolve any coincident pairs found while intersecting, and
|
| -// see if coincidence is formed by clipping non-concident segments
|
| -bool CoincidenceCheck(SkTArray<SkOpContour*, true>* contourList, int total) {
|
| - int contourCount = (*contourList).count();
|
| - for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
|
| - SkOpContour* contour = (*contourList)[cIndex];
|
| - contour->resolveNearCoincidence();
|
| - }
|
| - for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
|
| - SkOpContour* contour = (*contourList)[cIndex];
|
| - contour->addCoincidentPoints();
|
| - }
|
| - for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
|
| - SkOpContour* contour = (*contourList)[cIndex];
|
| - if (!contour->calcCoincidentWinding()) {
|
| - return false;
|
| - }
|
| - }
|
| - for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
|
| - SkOpContour* contour = (*contourList)[cIndex];
|
| - contour->calcPartialCoincidentWinding();
|
| - }
|
| - return true;
|
| -}
|
|
|