Index: src/pathops/SkDCubicIntersection.cpp |
diff --git a/src/pathops/SkDCubicIntersection.cpp b/src/pathops/SkDCubicIntersection.cpp |
index ce2344841b30c5db598811775fcdc783c2831767..27b16341a80af775e27f154d0374bbb816bc980d 100644 |
--- a/src/pathops/SkDCubicIntersection.cpp |
+++ b/src/pathops/SkDCubicIntersection.cpp |
@@ -292,6 +292,7 @@ bool SkIntersections::cubicExactEnd(const SkDCubic& cubic1, bool start, const Sk |
tmpLine[1].fX += cubic2[2 - start].fY - cubic2[t1Index].fY; |
tmpLine[1].fY -= cubic2[2 - start].fX - cubic2[t1Index].fX; |
SkIntersections impTs; |
+ impTs.allowNear(false); |
impTs.intersectRay(cubic1, tmpLine); |
for (int index = 0; index < impTs.used(); ++index) { |
SkDPoint realPt = impTs.pt(index); |
@@ -446,6 +447,7 @@ int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) { |
return fUsed; |
} |
} else { |
+ // OPTIMIZATION: set exact end bits here to avoid cubic exact end later |
for (int i1 = 0; i1 < 4; i1 += 3) { |
for (int i2 = 0; i2 < 4; i2 += 3) { |
if (c1[i1].approximatelyEqual(c2[i2])) { |
@@ -483,21 +485,22 @@ int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) { |
return fUsed; |
} |
// FIXME: pass in cached bounds from caller |
- SkDRect c1Bounds, c2Bounds; |
- c1Bounds.setBounds(c1); // OPTIMIZE use setRawBounds ? |
+ SkDRect c2Bounds; |
c2Bounds.setBounds(c2); |
- if (!(exactEndBits & 1)) { |
+ if (!(exactEndBits & 4)) { |
cubicNearEnd(c1, false, c2, c2Bounds); |
} |
- if (!(exactEndBits & 2)) { |
+ if (!(exactEndBits & 8)) { |
cubicNearEnd(c1, true, c2, c2Bounds); |
} |
if (!selfIntersect) { |
+ SkDRect c1Bounds; |
+ c1Bounds.setBounds(c1); // OPTIMIZE use setRawBounds ? |
swap(); |
- if (!(exactEndBits & 4)) { |
+ if (!(exactEndBits & 1)) { |
cubicNearEnd(c2, false, c1, c1Bounds); |
} |
- if (!(exactEndBits & 8)) { |
+ if (!(exactEndBits & 2)) { |
cubicNearEnd(c2, true, c1, c1Bounds); |
} |
swap(); |
@@ -506,7 +509,61 @@ int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) { |
SkASSERT(!selfIntersect); |
return fUsed; |
} |
- ::intersect(c1, 0, 1, c2, 0, 1, 1, *this); |
+ SkIntersections i; |
+ i.fAllowNear = false; |
+ i.fMax = 9; |
+ ::intersect(c1, 0, 1, c2, 0, 1, 1, i); |
+ int compCount = i.used(); |
+ if (compCount) { |
+ int exactCount = used(); |
+ if (exactCount == 0) { |
+ set(i); |
+ } else { |
+ // at least one is exact or near, and at least one was computed. Eliminate duplicates |
+ for (int exIdx = 0; exIdx < exactCount; ++exIdx) { |
+ for (int cpIdx = 0; cpIdx < compCount; ) { |
+ if (fT[0][0] == i[0][0] && fT[1][0] == i[1][0]) { |
+ i.removeOne(cpIdx); |
+ --compCount; |
+ continue; |
+ } |
+ double tAvg = (fT[0][exIdx] + i[0][cpIdx]) / 2; |
+ SkDPoint pt = c1.ptAtT(tAvg); |
+ if (!pt.approximatelyEqual(fPt[exIdx])) { |
+ ++cpIdx; |
+ continue; |
+ } |
+ tAvg = (fT[1][exIdx] + i[1][cpIdx]) / 2; |
+ pt = c2.ptAtT(tAvg); |
+ if (!pt.approximatelyEqual(fPt[exIdx])) { |
+ ++cpIdx; |
+ continue; |
+ } |
+ i.removeOne(cpIdx); |
+ --compCount; |
+ } |
+ } |
+ // if mid t evaluates to nearly the same point, skip the t |
+ for (int cpIdx = 0; cpIdx < compCount - 1; ) { |
+ double tAvg = (fT[0][cpIdx] + i[0][cpIdx + 1]) / 2; |
+ SkDPoint pt = c1.ptAtT(tAvg); |
+ if (!pt.approximatelyEqual(fPt[cpIdx])) { |
+ ++cpIdx; |
+ continue; |
+ } |
+ tAvg = (fT[1][cpIdx] + i[1][cpIdx + 1]) / 2; |
+ pt = c2.ptAtT(tAvg); |
+ if (!pt.approximatelyEqual(fPt[cpIdx])) { |
+ ++cpIdx; |
+ continue; |
+ } |
+ i.removeOne(cpIdx); |
+ --compCount; |
+ } |
+ // in addition to adding below missing function, think about how to say |
+ append(i); |
+ } |
+ } |
// If an end point and a second point very close to the end is returned, the second |
// point may have been detected because the approximate quads |
// intersected at the end and close to it. Verify that the second point is valid. |