Index: src/pathops/SkDCubicIntersection.cpp |
=================================================================== |
--- src/pathops/SkDCubicIntersection.cpp (revision 9040) |
+++ src/pathops/SkDCubicIntersection.cpp (working copy) |
@@ -138,7 +138,6 @@ |
} |
} else { |
double offset = precisionScale / 16; // FIME: const is arbitrary: test, refine |
-#if 1 |
double c1Bottom = tIdx == 0 ? 0 : |
(t1Start + (t1 - t1Start) * locals[0][tIdx - 1] + to1) / 2; |
double c1Min = SkTMax(c1Bottom, to1 - offset); |
@@ -240,46 +239,6 @@ |
i.used(), i.used() > 0 ? i[0][i.used() - 1] : -1); |
#endif |
} |
-#else |
- double c1Bottom = tIdx == 0 ? 0 : |
- (t1Start + (t1 - t1Start) * locals.fT[0][tIdx - 1] + to1) / 2; |
- double c1Min = SkTMax(c1Bottom, to1 - offset); |
- double c1Top = tIdx == tCount - 1 ? 1 : |
- (t1Start + (t1 - t1Start) * locals.fT[0][tIdx + 1] + to1) / 2; |
- double c1Max = SkTMin(c1Top, to1 + offset); |
- double c2Bottom = tIdx == 0 ? to2 : |
- (t2Start + (t2 - t2Start) * locals.fT[1][tIdx - 1] + to2) / 2; |
- double c2Top = tIdx == tCount - 1 ? to2 : |
- (t2Start + (t2 - t2Start) * locals.fT[1][tIdx + 1] + to2) / 2; |
- if (c2Bottom > c2Top) { |
- SkTSwap(c2Bottom, c2Top); |
- } |
- if (c2Bottom == to2) { |
- c2Bottom = 0; |
- } |
- if (c2Top == to2) { |
- c2Top = 1; |
- } |
- double c2Min = SkTMax(c2Bottom, to2 - offset); |
- double c2Max = SkTMin(c2Top, to2 + offset); |
- #if ONE_OFF_DEBUG |
- SkDebugf("%s contains1=%d/%d contains2=%d/%d\n", __FUNCTION__, |
- c1Min <= 0.210357794 && 0.210357794 <= c1Max |
- && c2Min <= 0.223476406 && 0.223476406 <= c2Max, |
- to1 - offset <= 0.210357794 && 0.210357794 <= to1 + offset |
- && to2 - offset <= 0.223476406 && 0.223476406 <= to2 + offset, |
- c1Min <= 0.211324707 && 0.211324707 <= c1Max |
- && c2Min <= 0.211327209 && 0.211327209 <= c2Max, |
- to1 - offset <= 0.211324707 && 0.211324707 <= to1 + offset |
- && to2 - offset <= 0.211327209 && 0.211327209 <= to2 + offset); |
- SkDebugf("%s c1Bottom=%1.9g c1Top=%1.9g c2Bottom=%1.9g c2Top=%1.9g" |
- " 1-o=%1.9g 1+o=%1.9g 2-o=%1.9g 2+o=%1.9g offset=%1.9g\n", |
- __FUNCTION__, c1Bottom, c1Top, c2Bottom, c2Top, |
- to1 - offset, to1 + offset, to2 - offset, to2 + offset, offset); |
- SkDebugf("%s to1=%1.9g to2=%1.9g c1Min=%1.9g c1Max=%1.9g c2Min=%1.9g" |
- " c2Max=%1.9g\n", __FUNCTION__, to1, to2, c1Min, c1Max, c2Min, c2Max); |
- #endif |
-#endif |
intersect(cubic1, c1Min, c1Max, cubic2, c2Min, c2Max, offset, i); |
// FIXME: if no intersection is found, either quadratics intersected where |
// cubics did not, or the intersection was missed. In the former case, expect |
@@ -303,9 +262,11 @@ |
const SkDRect& bounds2, SkIntersections& i) { |
SkDLine line; |
int t1Index = start ? 0 : 3; |
- line[0] = cubic1[t1Index]; |
// don't bother if the two cubics are connnected |
+#if 1 |
SkTDArray<double> tVals; // OPTIMIZE: replace with hard-sized array |
+ line[0] = cubic1[t1Index]; |
+ // this variant looks for intersections with the end point and lines parallel to other points |
for (int index = 0; index < 4; ++index) { |
if (index == t1Index) { |
continue; |
@@ -335,7 +296,7 @@ |
i.insert(start ? 0 : 1, foundT, line[0]); |
} |
} else { |
- *tVals.append() = local[0][idx2]; |
+ *tVals.append() = foundT; |
} |
} |
} |
@@ -362,6 +323,57 @@ |
} |
tIdx = tLast + 1; |
} while (tIdx < tVals.count()); |
+#else |
+ const SkDPoint& endPt = cubic1[t1Index]; |
+ if (!bounds2.contains(endPt)) { |
+ return; |
+ } |
+ // this variant looks for intersections within an 'x' of the endpoint |
+ double delta = SkTMax(bounds2.width(), bounds2.height()); |
+ for (int index = 0; index < 2; ++index) { |
+ if (index == 0) { |
+ line[0].fY = line[1].fY = endPt.fY; |
+ line[0].fX = endPt.fX - delta; |
+ line[1].fX = endPt.fX + delta; |
+ } else { |
+ line[0].fX = line[1].fX = cubic1[t1Index].fX; |
+ line[0].fY = endPt.fY - delta; |
+ line[1].fY = endPt.fY + delta; |
+ } |
+ SkIntersections local; |
+ local.intersectRay(cubic2, line); // OPTIMIZE: special for horizontal/vertical lines |
+ int used = local.used(); |
+ for (int index = 0; index < used; ++index) { |
+ double foundT = local[0][index]; |
+ if (approximately_less_than_zero(foundT) || approximately_greater_than_one(foundT)) { |
+ continue; |
+ } |
+ if (!local.pt(index).approximatelyEqual(endPt)) { |
+ continue; |
+ } |
+ if (i.swapped()) { // FIXME: insert should respect swap |
+ i.insert(foundT, start ? 0 : 1, endPt); |
+ } else { |
+ i.insert(start ? 0 : 1, foundT, endPt); |
+ } |
+ return; |
+ } |
+ } |
+// the above doesn't catch when the end of the cubic missed the other cubic because the quad |
+// approximation moved too far away, so something like the below is still needed. The enabled |
+// code above tries to avoid this heavy lifting unless the convex hull intersected the cubic. |
+ double tMin1 = start ? 0 : 1 - LINE_FRACTION; |
+ double tMax1 = start ? LINE_FRACTION : 1; |
+ double tMin2 = SkTMax(foundT - LINE_FRACTION, 0.0); |
+ double tMax2 = SkTMin(foundT + LINE_FRACTION, 1.0); |
+ int lastUsed = i.used(); |
+ intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i); |
+ if (lastUsed == i.used()) { |
+ tMin2 = SkTMax(foundT - (1.0 / SkDCubic::gPrecisionUnit), 0.0); |
+ tMax2 = SkTMin(foundT + (1.0 / SkDCubic::gPrecisionUnit), 1.0); |
+ intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i); |
+ } |
+#endif |
return; |
} |