Index: src/pathops/SkDCubicIntersection.cpp |
diff --git a/src/pathops/SkDCubicIntersection.cpp b/src/pathops/SkDCubicIntersection.cpp |
index dd51195d77ac746c1078da27b59f482d0a139d9f..1c237d9cf12fbebdb072be8a2feb3e46a1b06abc 100644 |
--- a/src/pathops/SkDCubicIntersection.cpp |
+++ b/src/pathops/SkDCubicIntersection.cpp |
@@ -303,15 +303,39 @@ bool SkIntersections::cubicExactEnd(const SkDCubic& cubic1, bool start, const Sk |
continue; |
} |
if (swap) { |
- insert(testT, impTs[0][index], tmpLine[0]); |
+ cubicInsert(testT, impTs[0][index], tmpLine[0], cubic2, cubic1); |
} else { |
- insert(impTs[0][index], testT, tmpLine[0]); |
+ cubicInsert(impTs[0][index], testT, tmpLine[0], cubic1, cubic2); |
} |
return true; |
} |
return false; |
} |
+ |
+void SkIntersections::cubicInsert(double one, double two, const SkDPoint& pt, |
+ const SkDCubic& cubic1, const SkDCubic& cubic2) { |
+ for (int index = 0; index < fUsed; ++index) { |
+ if (fT[0][index] == one) { |
+ double oldTwo = fT[1][index]; |
+ if (oldTwo == two) { |
+ return; |
+ } |
+ SkDPoint mid = cubic2.ptAtT((oldTwo + two) / 2); |
+ if (mid.approximatelyEqual(fPt[index])) { |
+ return; |
+ } |
+ } |
+ if (fT[1][index] == two) { |
+ SkDPoint mid = cubic1.ptAtT((fT[0][index] + two) / 2); |
+ if (mid.approximatelyEqual(fPt[index])) { |
+ return; |
+ } |
+ } |
+ } |
+ insert(one, two, pt); |
+} |
+ |
void SkIntersections::cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2, |
const SkDRect& bounds2) { |
SkDLine line; |
@@ -371,11 +395,15 @@ void SkIntersections::cubicNearEnd(const SkDCubic& cubic1, bool start, const SkD |
double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0); |
double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0); |
int lastUsed = used(); |
- ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this); |
+ if (start ? tMax1 < tMin2 : tMax2 < tMin1) { |
+ ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this); |
+ } |
if (lastUsed == used()) { |
tMin2 = SkTMax(tVals[tIdx] - (1.0 / SkDCubic::gPrecisionUnit), 0.0); |
tMax2 = SkTMin(tVals[tLast] + (1.0 / SkDCubic::gPrecisionUnit), 1.0); |
- ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this); |
+ if (start ? tMax1 < tMin2 : tMax2 < tMin1) { |
+ ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this); |
+ } |
} |
tIdx = tLast + 1; |
} while (tIdx < tVals.count()); |
@@ -421,6 +449,9 @@ static bool only_end_pts_in_common(const SkDCubic& c1, const SkDCubic& c2) { |
} |
double adj = endPt[oppTest]->fX - origX; |
double opp = endPt[oppTest]->fY - origY; |
+ if (adj == 0 && opp == 0) { // if the other point equals the test point, ignore it |
+ continue; |
+ } |
double sign = (c1[oddMan].fY - origY) * adj - (c1[oddMan].fX - origX) * opp; |
if (approximately_zero(sign)) { |
goto tryNextHalfPlane; |
@@ -531,7 +562,7 @@ int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) { |
if (compCount) { |
int exactCount = used(); |
if (exactCount == 0) { |
- set(i); |
+ *this = i; |
} else { |
// at least one is exact or near, and at least one was computed. Eliminate duplicates |
for (int exIdx = 0; exIdx < exactCount; ++exIdx) { |