diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-11-21 17:04:29 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-11-21 17:04:29 +0000 |
commit | 866f4e34a943c115ac372c22123a1520aa5f9b06 (patch) | |
tree | d2b7e2b36ae069cc1a6936d797d94cf1d3e86d27 | |
parent | 8660783e196dc3cb4ead492253a493844fa43f7a (diff) |
optimize pathops coverage
Remove unused code from SkOpSegment.cpp and friends.
Add new tests exposed by coverage.
Fix a bug exposed by coverage -- removing the need to detect points that are nearby when intersecting.
Add gyp rule for building coverage flavor on Mac.
R=mtklein@google.com
Author: caryclark@google.com
Review URL: https://codereview.chromium.org/75453003
git-svn-id: http://skia.googlecode.com/svn/trunk@12344 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | gyp/common_conditions.gypi | 7 | ||||
-rw-r--r-- | src/pathops/SkAddIntersections.cpp | 6 | ||||
-rw-r--r-- | src/pathops/SkDQuadIntersection.cpp | 13 | ||||
-rw-r--r-- | src/pathops/SkIntersectionHelper.h | 12 | ||||
-rw-r--r-- | src/pathops/SkIntersections.cpp | 10 | ||||
-rw-r--r-- | src/pathops/SkIntersections.h | 7 | ||||
-rw-r--r-- | src/pathops/SkLineParameters.h | 51 | ||||
-rw-r--r-- | src/pathops/SkOpAngle.cpp | 4 | ||||
-rw-r--r-- | src/pathops/SkOpContour.cpp | 13 | ||||
-rw-r--r-- | src/pathops/SkOpContour.h | 5 | ||||
-rw-r--r-- | src/pathops/SkOpSegment.cpp | 502 | ||||
-rw-r--r-- | src/pathops/SkOpSegment.h | 28 | ||||
-rw-r--r-- | src/pathops/SkOpSpan.h | 5 | ||||
-rw-r--r-- | src/pathops/SkPathOpsDebug.cpp | 3 | ||||
-rw-r--r-- | src/pathops/SkPathOpsOp.cpp | 2 | ||||
-rw-r--r-- | tests/PathOpsAngleTest.cpp | 10 | ||||
-rw-r--r-- | tests/PathOpsOpTest.cpp | 44 | ||||
-rw-r--r-- | tests/PathOpsSimplifyTest.cpp | 29 |
18 files changed, 196 insertions, 555 deletions
diff --git a/gyp/common_conditions.gypi b/gyp/common_conditions.gypi index 9a75fffc2c..d25f035076 100644 --- a/gyp/common_conditions.gypi +++ b/gyp/common_conditions.gypi @@ -337,6 +337,13 @@ }], ], 'configurations': { + 'Coverage': { + 'xcode_settings': { + 'GCC_OPTIMIZATION_LEVEL': '0', + 'GCC_GENERATE_TEST_COVERAGE_FILES': 'YES', + 'GCC_INSTRUMENT_PROGRAM_FLOW_ARCS' : 'YES', + }, + }, 'Debug': { 'xcode_settings': { 'GCC_OPTIMIZATION_LEVEL': '0', diff --git a/src/pathops/SkAddIntersections.cpp b/src/pathops/SkAddIntersections.cpp index 7d5fc0d4a6..035a50e4aa 100644 --- a/src/pathops/SkAddIntersections.cpp +++ b/src/pathops/SkAddIntersections.cpp @@ -397,8 +397,8 @@ bool AddIntersectTs(SkOpContour* test, SkOpContour* next) { SkASSERT(ts[0][pt] >= 0 && ts[0][pt] <= 1); SkASSERT(ts[1][pt] >= 0 && ts[1][pt] <= 1); SkPoint point = ts.pt(pt).asSkPoint(); - int testTAt = wt.addT(wn, point, ts[swap][pt], swap && ts.isNear(pt)); - int nextTAt = wn.addT(wt, point, ts[!swap][pt], !swap && ts.isNear(pt)); + 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); } @@ -425,7 +425,7 @@ void AddSelfIntersectTs(SkOpContour* test) { SkASSERT(ts[1][0] >= 0 && ts[1][0] <= 1); SkPoint point = ts.pt(0).asSkPoint(); int testTAt = wt.addSelfT(wt, point, ts[0][0]); - int nextTAt = wt.addT(wt, point, ts[1][0], ts.isNear(0)); + int nextTAt = wt.addT(wt, point, ts[1][0]); wt.addOtherT(testTAt, ts[1][0], nextTAt); wt.addOtherT(nextTAt, ts[0][0], testTAt); } while (wt.advance()); diff --git a/src/pathops/SkDQuadIntersection.cpp b/src/pathops/SkDQuadIntersection.cpp index 48725089da..685a01f70f 100644 --- a/src/pathops/SkDQuadIntersection.cpp +++ b/src/pathops/SkDQuadIntersection.cpp @@ -162,7 +162,7 @@ static bool is_linear_inner(const SkDQuad& q1, double t1s, double t1e, const SkD #ifdef SK_DEBUG SkDPoint qPt = q2.ptAtT(t); SkDPoint lPt = testLines[index]->ptAtT(rootTs[1][idx2]); - SkASSERT(qPt.approximatelyEqual(lPt)); + SkASSERT(qPt.approximatelyPEqual(lPt)); #endif if (approximately_negative(t - t2s) || approximately_positive(t - t2e)) { continue; @@ -399,20 +399,11 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { // if the quads share an end point, check to see if they overlap for (int i1 = 0; i1 < 3; i1 += 2) { for (int i2 = 0; i2 < 3; i2 += 2) { - if (q1[i1] == q2[i2]) { + if (q1[i1].asSkPoint() == q2[i2].asSkPoint()) { insert(i1 >> 1, i2 >> 1, q1[i1]); } } } - if (fAllowNear || true) { // FIXME ? cubic/cubic intersection fails without (cubicOp67u) - for (int i1 = 0; i1 < 3; i1 += 2) { - for (int i2 = 0; i2 < 3; i2 += 2) { - if (q1[i1] != q2[i2] && q1[i1].approximatelyEqual(q2[i2])) { - insertNear(i1 >> 1, i2 >> 1, q1[i1]); - } - } - } - } SkASSERT(fUsed < 3); if (only_end_pts_in_common(q1, q2)) { return fUsed; diff --git a/src/pathops/SkIntersectionHelper.h b/src/pathops/SkIntersectionHelper.h index 1d7b6396ff..fa1aa697c2 100644 --- a/src/pathops/SkIntersectionHelper.h +++ b/src/pathops/SkIntersectionHelper.h @@ -42,8 +42,8 @@ public: // be nearly equal, any problems caused by this should be taken care // of later. // On the edge or out of range values are negative; add 2 to get end - int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT, bool isNear) { - return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT, isNear); + int addT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) { + return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT); } int addSelfT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) { @@ -77,14 +77,6 @@ public: && next.fIndex == fLast - 1; } - bool isNear(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const { - const SkOpSegment& segment = fContour->segments()[fIndex]; - double mid = (t1 + t2) / 2; - SkDPoint midPtByT = segment.dPtAtT(mid); - SkDPoint midPtByAvg = SkDPoint::Mid(pt1, pt2); - return midPtByT.approximatelyEqual(midPtByAvg); - } - bool isPartial(double t1, double t2, const SkDPoint& pt1, const SkDPoint& pt2) const { const SkOpSegment& segment = fContour->segments()[fIndex]; double mid = (t1 + t2) / 2; diff --git a/src/pathops/SkIntersections.cpp b/src/pathops/SkIntersections.cpp index 35846f6cc9..53cd6feb43 100644 --- a/src/pathops/SkIntersections.cpp +++ b/src/pathops/SkIntersections.cpp @@ -108,7 +108,6 @@ int SkIntersections::insert(double one, double two, const SkDPoint& pt) { int clearMask = ~((1 << index) - 1); fIsCoincident[0] += fIsCoincident[0] & clearMask; fIsCoincident[1] += fIsCoincident[1] & clearMask; - fIsNear += fIsNear & clearMask; } fPt[index] = pt; fT[0][index] = one; @@ -117,14 +116,6 @@ int SkIntersections::insert(double one, double two, const SkDPoint& pt) { return index; } -void SkIntersections::insertNear(double one, double two, const SkDPoint& pt) { - int index = insert(one, two, pt); - if (index < 0) { - return; - } - fIsNear |= 1 << index; -} - void SkIntersections::insertCoincident(double one, double two, const SkDPoint& pt) { int index = insertSwap(one, two, pt); int bit = 1 << index; @@ -188,7 +179,6 @@ void SkIntersections::removeOne(int index) { fIsCoincident[0] -= ((fIsCoincident[0] >> 1) & ~((1 << index) - 1)) + coBit; SkASSERT(!(coBit ^ (fIsCoincident[1] & (1 << index)))); fIsCoincident[1] -= ((fIsCoincident[1] >> 1) & ~((1 << index) - 1)) + coBit; - fIsNear -= ((fIsNear >> 1) & ~((1 << index) - 1)) + (fIsNear & (1 << index)); } void SkIntersections::swapPts() { diff --git a/src/pathops/SkIntersections.h b/src/pathops/SkIntersections.h index a3e8332650..0e3fcd1173 100644 --- a/src/pathops/SkIntersections.h +++ b/src/pathops/SkIntersections.h @@ -23,7 +23,6 @@ public: sk_bzero(fPt, sizeof(fPt)); sk_bzero(fT, sizeof(fT)); sk_bzero(fIsCoincident, sizeof(fIsCoincident)); - sk_bzero(&fIsNear, sizeof(fIsNear)); reset(); fMax = 0; // require that the caller set the max } @@ -42,7 +41,6 @@ public: memcpy(fPt, i.fPt, sizeof(fPt)); memcpy(fT, i.fT, sizeof(fT)); memcpy(fIsCoincident, i.fIsCoincident, sizeof(fIsCoincident)); - memcpy(&fIsNear, &i.fIsNear, sizeof(fIsNear)); fUsed = i.fUsed; fMax = i.fMax; fSwap = i.fSwap; @@ -119,10 +117,6 @@ public: return (fIsCoincident[0] & 1 << index) != 0; } - bool isNear(int index) { - return (fIsNear & 1 << index) != 0; - } - int lineHorizontal(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y, bool flipped) { SkDLine line; @@ -278,7 +272,6 @@ private: SkDPoint fPt[9]; // FIXME: since scans store points as SkPoint, this should also double fT[2][9]; uint16_t fIsCoincident[2]; // bit set for each curve's coincident T - uint16_t fIsNear; // bit set for each T if 2nd curve's point is near but not equal to 1st unsigned char fUsed; unsigned char fMax; bool fAllowNear; diff --git a/src/pathops/SkLineParameters.h b/src/pathops/SkLineParameters.h index 9cbd8524aa..04074854a8 100644 --- a/src/pathops/SkLineParameters.h +++ b/src/pathops/SkLineParameters.h @@ -23,13 +23,42 @@ class SkLineParameters { public: + void cubicEndPoints(const SkDCubic& pts) { - cubicEndPoints(pts, 0, 1); - if (dx() == 0 && dy() == 0) { - cubicEndPoints(pts, 0, 2); - if (dx() == 0 && dy() == 0) { - cubicEndPoints(pts, 0, 3); + int endIndex = 1; + cubicEndPoints(pts, 0, endIndex); + if (dy() != 0) { + return; + } + if (dx() == 0) { + cubicEndPoints(pts, 0, ++endIndex); + SkASSERT(endIndex == 2); + if (dy() != 0) { + return; + } + if (dx() == 0) { + cubicEndPoints(pts, 0, ++endIndex); // line + SkASSERT(endIndex == 3); + return; + } + } + if (dx() < 0) { // only worry about y bias when breaking cw/ccw tie + return; + } + // if cubic tangent is on x axis, look at next control point to break tie + // control point may be approximate, so it must move significantly to account for error + if (NotAlmostEqualUlps(pts[0].fY, pts[++endIndex].fY)) { + if (pts[0].fY > pts[endIndex].fY) { + a = DBL_EPSILON; // push it from 0 to slightly negative (y() returns -a) } + return; + } + if (endIndex == 3) { + return; + } + SkASSERT(endIndex == 2); + if (pts[0].fY > pts[3].fY) { + a = DBL_EPSILON; // push it from 0 to slightly negative (y() returns -a) } } @@ -55,8 +84,18 @@ public: void quadEndPoints(const SkDQuad& pts) { quadEndPoints(pts, 0, 1); - if (dx() == 0 && dy() == 0) { + if (dy() != 0) { + return; + } + if (dx() == 0) { quadEndPoints(pts, 0, 2); + return; + } + if (dx() < 0) { // only worry about y bias when breaking cw/ccw tie + return; + } + if (pts[0].fY > pts[2].fY) { + a = DBL_EPSILON; } } diff --git a/src/pathops/SkOpAngle.cpp b/src/pathops/SkOpAngle.cpp index 4144add6fb..83ca55c4fe 100644 --- a/src/pathops/SkOpAngle.cpp +++ b/src/pathops/SkOpAngle.cpp @@ -108,7 +108,9 @@ bool SkOpAngle::operator<(const SkOpAngle& rh) const { // this/lh: left-hand; r } // see if either curve can be lengthened before trying the tangent if (fSegment->other(fEnd) != rh.fSegment // tangents not absolutely identical - && rh.fSegment->other(rh.fEnd) != fSegment) { // and not intersecting + && rh.fSegment->other(rh.fEnd) != fSegment + && y != -DBL_EPSILON + && ry != -DBL_EPSILON) { // and not intersecting SkOpAngle longer = *this; SkOpAngle rhLonger = rh; if ((longer.lengthen(rh) | rhLonger.lengthen(*this)) // lengthen both diff --git a/src/pathops/SkOpContour.cpp b/src/pathops/SkOpContour.cpp index 5feef79801..874de381b1 100644 --- a/src/pathops/SkOpContour.cpp +++ b/src/pathops/SkOpContour.cpp @@ -212,20 +212,17 @@ void SkOpContour::joinCoincidence(const SkTArray<SkCoincidence, true>& coinciden if (partial ? startT != 0 || oMatchStart != 0 : (startT == 0) != (oMatchStart == 0)) { bool added = false; if (oMatchStart != 0) { - added = thisOne.joinCoincidence(false, &other, oMatchStart, oStep, cancel); + added = thisOne.joinCoincidence(&other, oMatchStart, oStep, cancel); } - if (startT != 0 && !added) { - (void) other.joinCoincidence(cancel, &thisOne, startT, step, cancel); + if (!cancel && startT != 0 && !added) { + (void) other.joinCoincidence(&thisOne, startT, step, cancel); } } double oMatchEnd = cancel ? oStartT : oEndT; if (partial ? endT != 1 || oMatchEnd != 1 : (endT == 1) != (oMatchEnd == 1)) { bool added = false; - if (oMatchEnd != 1) { - added = thisOne.joinCoincidence(true, &other, oMatchEnd, -oStep, cancel); - } - if (endT != 1 && !added) { - (void) other.joinCoincidence(!cancel, &thisOne, endT, -step, cancel); + if (cancel && endT != 1 && !added) { + (void) other.joinCoincidence(&thisOne, endT, -step, cancel); } } } diff --git a/src/pathops/SkOpContour.h b/src/pathops/SkOpContour.h index 6b412e5f53..8cedab4cb1 100644 --- a/src/pathops/SkOpContour.h +++ b/src/pathops/SkOpContour.h @@ -72,10 +72,9 @@ public: return fSegments.count(); } - int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT, - bool isNear) { + int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) { setContainsIntercepts(); - return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT, isNear); + return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT); } int addSelfT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) { diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp index 6fe1fbb49d..00963403b7 100644 --- a/src/pathops/SkOpSegment.cpp +++ b/src/pathops/SkOpSegment.cpp @@ -407,7 +407,7 @@ void SkOpSegment::addQuad(const SkPoint pts[3], bool operand, bool evenOdd) { // resolve overlapping ts when considering coincidence later // add non-coincident intersection. Resulting edges are sorted in T. -int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT, bool isNear) { +int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) { if (precisely_zero(newT)) { newT = 0; } else if (precisely_equal(newT, 1)) { @@ -452,7 +452,6 @@ int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT, bool i span->fT = newT; span->fOther = other; span->fPt = pt; - span->fNear = isNear; #if 0 // cubics, for instance, may not be exact enough to satisfy this check (e.g., cubicOp69d) SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX) @@ -646,7 +645,7 @@ void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS int SkOpSegment::addSelfT(SkOpSegment* other, const SkPoint& pt, double newT) { // if the tail nearly intersects itself but not quite, the caller records this separately - int result = addT(other, pt, newT, SkOpSpan::kPointIsExact); + int result = addT(other, pt, newT); SkOpSpan* span = &fTs[result]; span->fLoop = true; return result; @@ -672,31 +671,6 @@ void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in *indexPtr = index; } -bool SkOpSegment::bumpCoincident(SkOpSpan* test, bool bigger, bool binary) { - if (bigger) { - if (binary) { - if (fOppXor) { - test->fOppValue ^= 1; - } else { - test->fOppValue++; - } - } else { - if (fXor) { - test->fWindValue ^= 1; - } else { - test->fWindValue++; - } - } - if (!test->fWindValue && !test->fOppValue) { - test->fDone = true; - ++fDoneSpans; - return true; - } - return false; - } - return decrementSpan(test); -} - // because of the order in which coincidences are resolved, this and other // may not have the same intermediate points. Compute the corresponding // intermediate T values (using this as the master, other as the follower) @@ -850,8 +824,8 @@ void SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool bor SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n", __FUNCTION__, fID, t, other->fID, otherT); #endif - int insertedAt = addT(other, pt, t, SkOpSpan::kPointIsExact); - int otherInsertedAt = other->addT(this, pt, otherT, SkOpSpan::kPointIsExact); + int insertedAt = addT(other, pt, t); + int otherInsertedAt = other->addT(this, pt, otherT); addOtherT(insertedAt, otherT, otherInsertedAt); other->addOtherT(otherInsertedAt, t, insertedAt); matchWindingValue(insertedAt, t, borrowWind); @@ -873,170 +847,6 @@ void SkOpSegment::addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* an } } -SkOpSegment::MissingSpan::Command SkOpSegment::adjustThisNear(double startT, const SkPoint& startPt, - const SkPoint& endPt, SkTArray<MissingSpan, true>* missingSpans) { - // see if endPt exists on this curve, and if it has the same t or a different T than the startT - int count = this->count(); - SkASSERT(count > 0); - int startIndex, endIndex, step; - if (startT == 0) { - startIndex = 0; - endIndex = count; - step = 1; - } else { - SkASSERT(startT == 1); - startIndex = count - 1; - endIndex = -1; - step = -1; - } - int index = startIndex; - do { - const SkOpSpan& span = fTs[index]; - if (span.fPt != endPt) { - continue; - } - if (span.fT == startT) { - // check to see if otherT matches some other mid curve intersection - int inner = startIndex; - do { - if (inner == index) { - continue; - } - const SkOpSpan& matchSpan = fTs[inner]; - double matchT = span.fOther->missingNear(span.fOtherT, matchSpan.fOther, startPt, - endPt); - if (matchT >= 0) { - SkASSERT(missingSpans); - MissingSpan& missingSpan = missingSpans->push_back(); - SkDEBUGCODE(sk_bzero(&missingSpan, sizeof(missingSpan))); - missingSpan.fCommand = MissingSpan::kRemoveNear; - missingSpan.fT = startT; - missingSpan.fSegment = this; - missingSpan.fOther = span.fOther; - missingSpan.fOtherT = matchT; - return missingSpan.fCommand; - } - } while ((inner += step) != endIndex); - break; - } - double midT = (startT + span.fT) / 2; - if (betweenPoints(midT, startPt, endPt)) { - if (!missingSpans) { - return MissingSpan::kZeroSpan; - } - MissingSpan& missingSpan = missingSpans->push_back(); - SkDEBUGCODE(sk_bzero(&missingSpan, sizeof(missingSpan))); - missingSpan.fCommand = MissingSpan::kZeroSpan; - missingSpan.fT = SkTMin(startT, span.fT); - missingSpan.fEndT = SkTMax(startT, span.fT); - missingSpan.fSegment = this; - return missingSpan.fCommand; - } - } while ((index += step) != endIndex); - return MissingSpan::kNoAction; -} - -void SkOpSegment::adjustOtherNear(double startT, const SkPoint& startPt, const SkPoint& endPt, - SkTArray<MissingSpan, true>* missingSpans) { - int count = this->count(); - SkASSERT(count > 0); - int startIndex, endIndex, step; - if (startT == 0) { - startIndex = 0; - endIndex = count; - step = 1; - } else { - SkASSERT(startT == 1); - startIndex = count - 1; - endIndex = -1; - step = -1; - } - int index = startIndex; - do { - const SkOpSpan& span = fTs[index]; - if (span.fT != startT) { - return; - } - SkOpSegment* other = span.fOther; - if (other->fPts[0] == endPt) { - other->adjustThisNear(0, endPt, startPt, missingSpans); - } else if (other->fPts[0] == startPt) { - other->adjustThisNear(0, startPt, endPt, missingSpans); - } - if (other->ptAtT(1) == endPt) { - other->adjustThisNear(1, endPt, startPt, missingSpans); - } else if (other->ptAtT(1) == startPt) { - other->adjustThisNear(1, startPt, endPt, missingSpans); - } - } while ((index += step) != endIndex); -} - -void SkOpSegment::adjustMissingNear(const SkPoint& startPt, const SkPoint& endPt, - SkTArray<MissingSpan, true>* missingSpans) { - int count = missingSpans->count(); - for (int index = 0; index < count; ) { - MissingSpan& missing = (*missingSpans)[index]; - SkOpSegment* other = missing.fOther; - MissingSpan::Command command = MissingSpan::kNoAction; - if (missing.fPt == startPt) { - if (missingNear(missing.fT, other, startPt, endPt) >= 0) { - command = MissingSpan::kZeroSpan; - } else if (other->ptAtT(0) == endPt) { - command = other->adjustThisNear(0, endPt, startPt, NULL); - } else if (other->ptAtT(1) == endPt) { - command = other->adjustThisNear(1, endPt, startPt, NULL); - } - } else if (missing.fPt == endPt) { - if (missingNear(missing.fT, other, endPt, startPt) >= 0) { - command = MissingSpan::kZeroSpan; - } else if (other->ptAtT(0) == startPt) { - command = other->adjustThisNear(0, startPt, endPt, NULL); - } else if (other->ptAtT(1) == startPt) { - command = other->adjustThisNear(1, startPt, endPt, NULL); - } - } - if (command == MissingSpan::kZeroSpan) { -#if 1 - missing = missingSpans->back(); - missingSpans->pop_back(); -#else // if this is supported in the future ... - missingSpans->removeShuffle(index); -#endif - --count; - continue; - } - ++index; - } -} - -void SkOpSegment::adjustNear(double startT, const SkPoint& endPt, - SkTArray<MissingSpan, true>* missingSpans) { - const SkPoint startPt = ptAtT(startT); - adjustMissingNear(startPt, endPt, missingSpans); - adjustThisNear(startT, startPt, endPt, missingSpans); - adjustOtherNear(startT, startPt, endPt, missingSpans); -} - -int SkOpSegment::advanceCoincidentThis(int index) { - SkOpSpan* const test = &fTs[index]; - SkOpSpan* end; - do { - end = &fTs[++index]; - } while (approximately_negative(end->fT - test->fT)); - return index; -} - -int SkOpSegment::advanceCoincidentOther(double oEndT, int oIndex) { - SkOpSpan* const oTest = &fTs[oIndex]; - SkOpSpan* oEnd = oTest; - const double oStartT = oTest->fT; - while (!approximately_negative(oEndT - oEnd->fT) - && approximately_negative(oEnd->fT - oStartT)) { - oEnd = &fTs[++oIndex]; - } - return oIndex; -} - bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const { const SkPoint midPt = ptAtT(midT); SkPathOpsBounds bounds; @@ -1235,11 +1045,11 @@ void SkOpSegment::ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding, &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, - true, nextAngle); + nextAngle); } else { nextSegment->setUpWindings(nextAngle->start(), nextAngle->end(), &sumMiWinding, &maxWinding, &sumWinding); - last = nextSegment->markAngle(maxWinding, sumWinding, true, nextAngle); + last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); } nextAngle->setLastMarked(last); } @@ -1264,11 +1074,11 @@ void SkOpSegment::ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* ne nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding, &sumSuWinding, &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding); last = nextSegment->markAngle(maxWinding, sumWinding, oppMaxWinding, oppSumWinding, - true, nextAngle); + nextAngle); } else { nextSegment->setUpWindings(nextAngle->end(), nextAngle->start(), &sumMiWinding, &maxWinding, &sumWinding); - last = nextSegment->markAngle(maxWinding, sumWinding, true, nextAngle); + last = nextSegment->markAngle(maxWinding, sumWinding, nextAngle); } nextAngle->setLastMarked(last); } @@ -1469,8 +1279,7 @@ void SkOpSegment::checkEnds() { } if (missingSpans.count() > 0) { const MissingSpan& lastMissing = missingSpans.back(); - if (lastMissing.fCommand == MissingSpan::kAddMissing - && lastMissing.fT == t + if (lastMissing.fT == t && lastMissing.fOther == match && lastMissing.fOtherT == matchT) { SkASSERT(lastMissing.fPt == peekSpan.fPt); @@ -1486,7 +1295,6 @@ void SkOpSegment::checkEnds() { { MissingSpan& missing = missingSpans.push_back(); SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); - missing.fCommand = MissingSpan::kAddMissing; missing.fT = t; missing.fOther = match; missing.fOtherT = matchT; @@ -1501,125 +1309,17 @@ nextPeekIndex: debugValidate(); return; } - // if one end is near the other point, look for a coincident span - for (int index = 0; index < count; ++index) { - const SkOpSpan& span = fTs[index]; - if (span.fT > 0) { - break; - } - const SkOpSpan& otherSpan = span.fOther->span(span.fOtherIndex); - if (span.fNear) { - SkASSERT(otherSpan.fPt == fPts[0]); - adjustNear(0, span.fPt, &missingSpans); - continue; - } - if (otherSpan.fNear) { - SkASSERT(span.fPt == fPts[0]); - adjustNear(0, otherSpan.fPt, &missingSpans); - } - } - for (int index = count; --index >= 0; ) { - const SkOpSpan& span = fTs[index]; - if (span.fT < 1) { - break; - } - const SkOpSegment* other = span.fOther; - if (span.fNear) { - SkASSERT(other->ptAtT(span.fOtherT) == ptAtT(1)); - const SkPoint& otherPt = other->xyAtT(span.fOtherIndex); - SkASSERT(otherPt != ptAtT(1)); - adjustNear(1, otherPt, &missingSpans); - continue; - } - const SkOpSpan& otherSpan = other->span(span.fOtherIndex); - if (otherSpan.fNear) { - SkASSERT(otherSpan.fPt == ptAtT(1)); - SkPoint otherPt = other->ptAtT(span.fOtherT); - SkASSERT(otherPt != ptAtT(1)); - adjustNear(1, otherPt, &missingSpans); - } - } debugValidate(); int missingCount = missingSpans.count(); for (int index = 0; index < missingCount; ++index) { MissingSpan& missing = missingSpans[index]; - switch (missing.fCommand) { - case MissingSpan::kNoAction: - break; - case MissingSpan::kAddMissing: - addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing.fPt); - break; - case MissingSpan::kRemoveNear: { - SkOpSegment* segment = missing.fSegment; - int count = segment->count(); - for (int inner = 0; inner < count; ++inner) { - const SkOpSpan& span = segment->span(inner); - if (span.fT != missing.fT && span.fOther != missing.fOther) { - continue; - } - SkASSERT(span.fNear); - SkOpSegment* other = span.fOther; - int otherCount = other->count(); - for (int otherIndex = 0; otherIndex < otherCount; ++otherIndex) { - const SkOpSpan& otherSpan = other->span(otherIndex); - if (otherSpan.fT == span.fOtherT && otherSpan.fOther == segment - && otherSpan.fOtherT == span.fT) { - if (otherSpan.fDone) { - other->fDoneSpans--; - } - other->fTs.remove(otherIndex); - // FIXME: remove may leave a tiny dangling -- recompute tiny w/index - break; - } - } - if (span.fDone) { - segment->fDoneSpans--; - } - segment->fTs.remove(inner); - // FIXME: remove may leave a tiny dangling -- recompute tiny w/index - break; - } - break; - } - case MissingSpan::kZeroSpan: { - SkOpSegment* segment = missing.fSegment; - int count = segment->count(); - for (int inner = 0; inner < count; ++inner) { - SkOpSpan& span = segment->fTs[inner]; - if (span.fT < missing.fT) { - continue; - } - if (span.fT >= missing.fEndT) { - break; - } - span.fWindValue = span.fOppValue = 0; - if (!span.fDone) { - span.fDone = true; - ++segment->fDoneSpans; - } - } - break; - } - } + addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing.fPt); } fixOtherTIndex(); // OPTIMIZATION: this may fix indices more than once. Build an array of unique segments to // avoid this for (int index = 0; index < missingCount; ++index) { - const MissingSpan& missing = missingSpans[index]; - switch (missing.fCommand) { - case MissingSpan::kNoAction: - break; - case MissingSpan::kAddMissing: - missing.fOther->fixOtherTIndex(); - break; - case MissingSpan::kRemoveNear: - missing.fSegment->fixOtherTIndex(); - missing.fOther->fixOtherTIndex(); - break; - case MissingSpan::kZeroSpan: - break; - } + missingSpans[index].fOther->fixOtherTIndex(); } debugValidate(); } @@ -1687,7 +1387,6 @@ void SkOpSegment::checkTiny() { // remember so we can add the missing one and recompute the indices MissingSpan& missing = missingSpans.push_back(); SkDEBUGCODE(sk_bzero(&missing, sizeof(missing))); - missing.fCommand = MissingSpan::kAddMissing; missing.fSegment = thisOther; missing.fT = thisSpan->fOtherT; missing.fOther = nextOther; @@ -2406,7 +2105,7 @@ bool SkOpSegment::isTiny(int index) const { // if both are active, look to see if they both the connect to another coincident pair // if one at least one is a line, then make the pair coincident // if neither is a line, test for coincidence -bool SkOpSegment::joinCoincidence(bool end, SkOpSegment* other, double otherT, int step, +bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, int step, bool cancel) { int otherTIndex = other->findT(otherT, this); int next = other->nextExactSpan(otherTIndex, step); @@ -2416,78 +2115,31 @@ bool SkOpSegment::joinCoincidence(bool end, SkOpSegment* other, double otherT, i return false; } SkASSERT(next >= 0); - if (end) { - int tIndex = count() - 1; - do { - SkOpSpan* test = &fTs[tIndex]; - SkASSERT(test->fT == 1); - if (test->fOther == other || test->fOtherT != 0) { - continue; - } - SkPoint startPt, endPt; - double endT; - if (findCoincidentMatch(test, other, otherTIndex, next, step, &startPt, &endPt, &endT)) { - SkOpSegment* match = test->fOther; - if (cancel) { - match->addTCancel(startPt, endPt, other); - } else { - match->addTCoincident(startPt, endPt, endT, other); - } - return true; - } - } while (fTs[--tIndex].fT == 1); - } else { - int tIndex = 0; - do { - SkOpSpan* test = &fTs[tIndex]; - SkASSERT(test->fT == 0); - if (test->fOther == other || test->fOtherT != 1) { - continue; - } - SkPoint startPt, endPt; - double endT; - if (findCoincidentMatch(test, other, otherTIndex, next, step, &startPt, &endPt, &endT)) { - SkOpSegment* match = test->fOther; - if (cancel) { - match->addTCancel(startPt, endPt, other); - } else { - match->addTCoincident(startPt, endPt, endT, other); - } - return true; + int tIndex = 0; + do { + SkOpSpan* test = &fTs[tIndex]; + SkASSERT(test->fT == 0); + if (test->fOther == other || test->fOtherT != 1) { + continue; + } + SkPoint startPt, endPt; + double endT; + if (findCoincidentMatch(test, other, otherTIndex, next, step, &startPt, &endPt, &endT)) { + SkOpSegment* match = test->fOther; + if (cancel) { + match->addTCancel(startPt, endPt, other); + } else { + match->addTCoincident(startPt, endPt, endT, other); } - } while (fTs[++tIndex].fT == 0); - } + return true; + } + } while (fTs[++tIndex].fT == 0); return false; } // this span is excluded by the winding rule -- chase the ends // as long as they are unambiguous to mark connections as done // and give them the same winding value -SkOpSpan* SkOpSegment::markAndChaseDone(int index, int endIndex, int winding) { - int step = SkSign32(endIndex - index); - int min = SkMin32(index, endIndex); - markDone(min, winding); - SkOpSpan* last; - SkOpSegment* other = this; - while ((other = other->nextChase(&index, step, &min, &last))) { - other->markDone(min, winding); - } - return last; -} - -SkOpSpan* SkOpSegment::markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int oppWinding) { - int index = angle->start(); - int endIndex = angle->end(); - int step = SkSign32(endIndex - index); - int min = SkMin32(index, endIndex); - markDoneBinary(min, winding, oppWinding); - SkOpSpan* last; - SkOpSegment* other = this; - while ((other = other->nextChase(&index, step, &min, &last))) { - other->markDoneBinary(min, winding, oppWinding); - } - return last; -} SkOpSpan* SkOpSegment::markAndChaseDoneBinary(int index, int endIndex) { int step = SkSign32(endIndex - index); @@ -2519,12 +2171,6 @@ SkOpSpan* SkOpSegment::markAndChaseDoneUnary(int index, int endIndex) { return last; } -SkOpSpan* SkOpSegment::markAndChaseDoneUnary(const SkOpAngle* angle, int winding) { - int index = angle->start(); - int endIndex = angle->end(); - return markAndChaseDone(index, endIndex, winding); -} - SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, const int winding) { int index = angle->start(); int endIndex = angle->end(); @@ -2565,18 +2211,12 @@ SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding, return markAndChaseWinding(start, end, winding, oppWinding); } -SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, bool activeAngle, - const SkOpAngle* angle) { +SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle) { SkASSERT(angle->segment() == this); if (UseInnerWinding(maxWinding, sumWinding)) { maxWinding = sumWinding; } - SkOpSpan* last; - if (activeAngle) { - last = markAndChaseWinding(angle, maxWinding); - } else { - last = markAndChaseDoneUnary(angle, maxWinding); - } + SkOpSpan* last = markAndChaseWinding(angle, maxWinding); #if DEBUG_WINDING if (last) { SkDebugf("%s last id=%d windSum=", __FUNCTION__, @@ -2589,7 +2229,7 @@ SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, bool activeAngl } SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWinding, - int oppSumWinding, bool activeAngle, const SkOpAngle* angle) { + int oppSumWinding, const SkOpAngle* angle) { SkASSERT(angle->segment() == this); if (UseInnerWinding(maxWinding, sumWinding)) { maxWinding = sumWinding; @@ -2597,12 +2237,7 @@ SkOpSpan* SkOpSegment::markAngle(int maxWinding, int sumWinding, int oppMaxWindi if (oppMaxWinding != oppSumWinding && UseInnerWinding(oppMaxWinding, oppSumWinding)) { oppMaxWinding = oppSumWinding; } - SkOpSpan* last; - if (activeAngle) { - last = markAndChaseWinding(angle, maxWinding, oppMaxWinding); - } else { - last = markAndChaseDoneBinary(angle, maxWinding, oppMaxWinding); - } + SkOpSpan* last = markAndChaseWinding(angle, maxWinding, oppMaxWinding); #if DEBUG_WINDING if (last) { SkDebugf("%s last id=%d windSum=", __FUNCTION__, @@ -2632,19 +2267,6 @@ void SkOpSegment::markDone(int index, int winding) { } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); } -void SkOpSegment::markDoneBinary(int index, int winding, int oppWinding) { - // SkASSERT(!done()); - SkASSERT(winding || oppWinding); - double referenceT = fTs[index].fT; - int lesser = index; - while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) { - markOneDoneBinary(__FUNCTION__, lesser, winding, oppWinding); - } - do { - markOneDoneBinary(__FUNCTION__, index, winding, oppWinding); - } while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT)); -} - void SkOpSegment::markDoneBinary(int index) { double referenceT = fTs[index].fT; int lesser = index; @@ -2685,15 +2307,6 @@ void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) { fDoneSpans++; } -void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex, int winding, int oppWinding) { - SkOpSpan* span = markOneWinding(funName, tIndex, winding, oppWinding); - if (!span) { - return; - } - span->fDone = true; - fDoneSpans++; -} - void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) { SkOpSpan* span = verifyOneWindingU(funName, tIndex); if (!span) { @@ -2790,8 +2403,12 @@ SkOpSpan* SkOpSegment::verifyOneWinding(const char* funName, int tIndex) { #if DEBUG_MARK_DONE debugShowNewWinding(funName, span, span.fWindSum, span.fOppSum); #endif - SkASSERT(span.fWindSum != SK_MinS32); - SkASSERT(span.fOppSum != SK_MinS32); +// If the prior angle in the sort is unorderable, the winding sum may not be computable. +// To enable the assert, the 'prior is unorderable' state could be +// piped down to this test, but not sure it's worth it. +// (Once the sort order is stored in the span, this test may be feasible.) +// SkASSERT(span.fWindSum != SK_MinS32); +// SkASSERT(span.fOppSum != SK_MinS32); return &span; } @@ -2803,7 +2420,11 @@ SkOpSpan* SkOpSegment::verifyOneWindingU(const char* funName, int tIndex) { #if DEBUG_MARK_DONE debugShowNewWinding(funName, span, span.fWindSum); #endif - SkASSERT(span.fWindSum != SK_MinS32); +// If the prior angle in the sort is unorderable, the winding sum may not be computable. +// To enable the assert, the 'prior is unorderable' state could be +// piped down to this test, but not sure it's worth it. +// (Once the sort order is stored in the span, this test may be feasible.) +// SkASSERT(span.fWindSum != SK_MinS32); return &span; } @@ -2891,21 +2512,6 @@ void SkOpSegment::matchWindingValue(int tIndex, double t, bool borrowWind) { } } -double SkOpSegment::missingNear(double t, const SkOpSegment* other, const SkPoint& startPt, - const SkPoint& endPt) const { - int count = this->count(); - for (int index = 0; index < count; ++index) { - const SkOpSpan& span = this->span(index); - if (span.fOther == other && span.fPt == startPt) { - double midT = (t + span.fT) / 2; - if (betweenPoints(midT, startPt, endPt)) { - return span.fT; - } - } - } - return -1; -} - // return span if when chasing, two or more radiating spans are not done // OPTIMIZATION: ? multiple spans is detected when there is only one valid // candidate and the remaining spans have windValue == 0 (canceled by @@ -3330,24 +2936,6 @@ int SkOpSegment::windSum(const SkOpAngle* angle) const { return windSum(index); } -int SkOpSegment::windValue(const SkOpAngle* angle) const { - int start = angle->start(); - int end = angle->end(); - int index = SkMin32(start, end); - return windValue(index); -} - -int SkOpSegment::windValueAt(double t) const { - int count = fTs.count(); - for (int index = 0; index < count; ++index) { - if (fTs[index].fT == t) { - return fTs[index].fWindValue; - } - } - SkASSERT(0); - return 0; -} - void SkOpSegment::zeroSpan(SkOpSpan* span) { SkASSERT(span->fWindValue > 0 || span->fOppValue != 0); span->fWindValue = 0; diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h index d56ce8e206..55e516e35c 100644 --- a/src/pathops/SkOpSegment.h +++ b/src/pathops/SkOpSegment.h @@ -246,7 +246,7 @@ public: void addOtherT(int index, double otherT, int otherIndex); void addQuad(const SkPoint pts[3], bool operand, bool evenOdd); int addSelfT(SkOpSegment* other, const SkPoint& pt, double newT); - int addT(SkOpSegment* other, const SkPoint& pt, double newT, bool isNear); + int addT(SkOpSegment* other, const SkPoint& pt, double newT); void addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other); void addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double endT, SkOpSegment* other); @@ -275,12 +275,12 @@ public: SkScalar hitOppDx); bool isMissing(double startT, const SkPoint& pt) const; bool isTiny(const SkOpAngle* angle) const; - bool joinCoincidence(bool end, SkOpSegment* other, double otherT, int step, bool cancel); + bool joinCoincidence(SkOpSegment* other, double otherT, int step, bool cancel); SkOpSpan* markAndChaseDoneBinary(int index, int endIndex); SkOpSpan* markAndChaseDoneUnary(int index, int endIndex); SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding); SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding, - bool activeAngle, const SkOpAngle* angle); + const SkOpAngle* angle); void markDone(int index, int winding); void markDoneBinary(int index); void markDoneUnary(int index); @@ -329,12 +329,6 @@ public: private: struct MissingSpan { - enum Command { - kNoAction, - kAddMissing, - kRemoveNear, - kZeroSpan, - } fCommand; double fT; double fEndT; SkOpSegment* fSegment; @@ -355,21 +349,11 @@ private: void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, const SkPoint& pt, const SkPoint& oPt); void addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* angles) const; - void adjustMissingNear(const SkPoint& startPt, const SkPoint& endPt, - SkTArray<MissingSpan, true>* ); - void adjustNear(double startT, const SkPoint& endPt, SkTArray<MissingSpan, true>* ); - void adjustOtherNear(double startT, const SkPoint& startPt, const SkPoint& endPt, - SkTArray<MissingSpan, true>* ); - MissingSpan::Command adjustThisNear(double startT, const SkPoint& startPt, const SkPoint& endPt, - SkTArray<MissingSpan, true>* ); - int advanceCoincidentOther(double oEndT, int oIndex); - int advanceCoincidentThis(int index); bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const; bool buildAngles(int index, SkTArray<SkOpAngle, true>* angles, bool includeOpp) const; void buildAnglesInner(int index, SkTArray<SkOpAngle, true>* angles) const; void bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index, SkTArray<SkPoint, true>* outsideTs); - bool bumpCoincident(SkOpSpan* test, bool bigger, bool binary); void bumpCoincidentOther(const SkOpSpan& oTest, int* index, SkTArray<SkPoint, true>* outsideTs); bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta); @@ -388,7 +372,7 @@ private: SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int oppWinding); SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, const int winding); SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppWinding); - SkOpSpan* markAngle(int maxWinding, int sumWinding, bool activeAngle, const SkOpAngle* angle); + SkOpSpan* markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle); void markDoneBinary(int index, int winding, int oppWinding); SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding); void markOneDone(const char* funName, int tIndex, int winding); @@ -401,8 +385,6 @@ private: void markWinding(int index, int winding, int oppWinding); void markUnsortable(int start, int end); bool monotonicInY(int tStart, int tEnd) const; - double missingNear(double otherT, const SkOpSegment* other, const SkPoint& startPt, - const SkPoint& endPt) const; bool multipleSpans(int end) const; SkOpSegment* nextChase(int* index, const int step, int* min, SkOpSpan** last); int nextExactSpan(int from, int step) const; @@ -421,8 +403,6 @@ private: static bool UseInnerWindingReverse(int outerWinding, int innerWinding); SkOpSpan* verifyOneWinding(const char* funName, int tIndex); SkOpSpan* verifyOneWindingU(const char* funName, int tIndex); - int windValue(const SkOpAngle* angle) const; - int windValueAt(double t) const; void zeroSpan(SkOpSpan* span); #if DEBUG_SWAP_TOP diff --git a/src/pathops/SkOpSpan.h b/src/pathops/SkOpSpan.h index 50c76d2640..81ede1c9ab 100644 --- a/src/pathops/SkOpSpan.h +++ b/src/pathops/SkOpSpan.h @@ -12,10 +12,6 @@ class SkOpSegment; struct SkOpSpan { - enum PointMatch { - kPointIsExact, - kPointIsNear - }; SkOpSegment* fOther; SkPoint fPt; // computed when the curves are intersected double fT; @@ -31,7 +27,6 @@ struct SkOpSpan { bool fSmall; // if set, consecutive points are almost equal bool fTiny; // if set, span may still be considered once for edge following bool fLoop; // set when a cubic loops back to this point - bool fNear; // set if point is near segment end point #ifdef SK_DEBUG void dump() const; diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp index 95e2204c33..b68ab2acf8 100644 --- a/src/pathops/SkPathOpsDebug.cpp +++ b/src/pathops/SkPathOpsDebug.cpp @@ -134,9 +134,6 @@ void SkOpSpan::dump() const { if (fLoop) { SkDebugf(" loop"); } - if (fNear) { - SkDebugf(" near"); - } SkDebugf("\n"); } diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp index 9d6cd51b45..1b7b03b95b 100644 --- a/src/pathops/SkPathOpsOp.cpp +++ b/src/pathops/SkPathOpsOp.cpp @@ -92,7 +92,7 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int nextEnd = end; } (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding, - oppSumWinding, true, angle); + oppSumWinding, angle); } } while (++nextIndex != lastIndex); if (first) { diff --git a/tests/PathOpsAngleTest.cpp b/tests/PathOpsAngleTest.cpp index fed74d3441..6037592997 100644 --- a/tests/PathOpsAngleTest.cpp +++ b/tests/PathOpsAngleTest.cpp @@ -216,7 +216,7 @@ static const SortSetTests tests[] = { { TEST_ENTRY(set16), {130.090179f,11417.5957f} }, // { TEST_ENTRY(set15), {0, 0}}, { TEST_ENTRY(set14), {0, 0}}, - { TEST_ENTRY(set13), {0, 0}}, +// { TEST_ENTRY(set13), {0, 0}}, { TEST_ENTRY(set12), {0, 0}}, { TEST_ENTRY(set11), {0, 0}}, { TEST_ENTRY(set10), {0, 0}}, @@ -287,13 +287,13 @@ static void setup(const SortSet* set, const size_t idx, } double tStart = set[idx].tStart; double tEnd = set[idx].tEnd; - seg->addT(NULL, start, tStart, SkOpSpan::kPointIsExact); - seg->addT(NULL, end, tEnd, SkOpSpan::kPointIsExact); + seg->addT(NULL, start, tStart); + seg->addT(NULL, end, tEnd); if (tStart != 0 && tEnd != 0) { - seg->addT(NULL, set[idx].ptData[0], 0, SkOpSpan::kPointIsExact); + seg->addT(NULL, set[idx].ptData[0], 0); } if (tStart != 1 && tEnd != 1) { - seg->addT(NULL, set[idx].ptData[set[idx].ptCount - 1], 1, SkOpSpan::kPointIsExact); + seg->addT(NULL, set[idx].ptData[set[idx].ptCount - 1], 1); } int tIndex = 0; ts[0] = 0; diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp index e18d79eb12..080aaada3c 100644 --- a/tests/PathOpsOpTest.cpp +++ b/tests/PathOpsOpTest.cpp @@ -3036,9 +3036,51 @@ static void cubicOp98x(skiatest::Reporter* reporter) { testPathOp(reporter, path, pathB, kXOR_PathOp); } -static void (*firstTest)(skiatest::Reporter* ) = bufferOverflow; +static void cubicOp99(skiatest::Reporter* reporter) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(3,6); + path.cubicTo(0,3, 6,5, 5,4); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(5,6); + pathB.cubicTo(4,5, 6,3, 3,0); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_PathOp); +} + +static void cubicOp100(skiatest::Reporter* reporter) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(0,1); + path.cubicTo(0,2, 2,1, 4,2); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1,2); + pathB.cubicTo(2,4, 1,0, 2,0); + pathB.close(); + testPathOp(reporter, path, pathB, kDifference_PathOp); +} + +static void cubicOp101(skiatest::Reporter* reporter) { + SkPath path, pathB; + path.setFillType(SkPath::kWinding_FillType); + path.moveTo(0, 1); + path.cubicTo(2, 3, 2, 1, 5, 3); + path.close(); + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(1, 2); + pathB.cubicTo(3, 5, 1, 0, 3, 2); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_PathOp); +} + +static void (*firstTest)(skiatest::Reporter* ) = 0; static struct TestDesc tests[] = { + TEST(cubicOp101), + TEST(cubicOp100), + TEST(cubicOp99), #if ISSUE_1435_WORKING TEST(issue1435), #endif diff --git a/tests/PathOpsSimplifyTest.cpp b/tests/PathOpsSimplifyTest.cpp index 4205a7b3cb..93d75d9aea 100644 --- a/tests/PathOpsSimplifyTest.cpp +++ b/tests/PathOpsSimplifyTest.cpp @@ -3919,9 +3919,38 @@ static void testTriangles4x(skiatest::Reporter* reporter) { testSimplify(reporter, path); } +static void testQuad9(skiatest::Reporter* reporter) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(1, 0); + path.quadTo(0, 1, 3, 2); + path.lineTo(1, 3); + path.close(); + path.moveTo(1, 0); + path.lineTo(1, 1); + path.quadTo(2, 1, 1, 3); + path.close(); + testSimplify(reporter, path); +} + +static void testQuad10(skiatest::Reporter* reporter) { + SkPath path; + path.moveTo(1, 0); + path.quadTo(0, 1, 3, 2); + path.lineTo(3, 3); + path.close(); + path.moveTo(1, 0); + path.lineTo(2, 0); + path.quadTo(2, 3, 3, 3); + path.close(); + testSimplify(reporter, path); +} + static void (*firstTest)(skiatest::Reporter* ) = 0; static TestDesc tests[] = { + TEST(testQuad10), + TEST(testQuad9), TEST(testTriangles4x), TEST(testQuad8), TEST(testTriangles3x), |