aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-11-21 17:04:29 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-11-21 17:04:29 +0000
commit866f4e34a943c115ac372c22123a1520aa5f9b06 (patch)
treed2b7e2b36ae069cc1a6936d797d94cf1d3e86d27
parent8660783e196dc3cb4ead492253a493844fa43f7a (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.gypi7
-rw-r--r--src/pathops/SkAddIntersections.cpp6
-rw-r--r--src/pathops/SkDQuadIntersection.cpp13
-rw-r--r--src/pathops/SkIntersectionHelper.h12
-rw-r--r--src/pathops/SkIntersections.cpp10
-rw-r--r--src/pathops/SkIntersections.h7
-rw-r--r--src/pathops/SkLineParameters.h51
-rw-r--r--src/pathops/SkOpAngle.cpp4
-rw-r--r--src/pathops/SkOpContour.cpp13
-rw-r--r--src/pathops/SkOpContour.h5
-rw-r--r--src/pathops/SkOpSegment.cpp502
-rw-r--r--src/pathops/SkOpSegment.h28
-rw-r--r--src/pathops/SkOpSpan.h5
-rw-r--r--src/pathops/SkPathOpsDebug.cpp3
-rw-r--r--src/pathops/SkPathOpsOp.cpp2
-rw-r--r--tests/PathOpsAngleTest.cpp10
-rw-r--r--tests/PathOpsOpTest.cpp44
-rw-r--r--tests/PathOpsSimplifyTest.cpp29
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),