Index: src/pathops/SkDQuadIntersection.cpp |
diff --git a/src/pathops/SkDQuadIntersection.cpp b/src/pathops/SkDQuadIntersection.cpp |
index 5869d7db19c0ac927b1130e1173626df8589dd01..71ebf9abc056f1f5d054d9c964f4ca0728b510f5 100644 |
--- a/src/pathops/SkDQuadIntersection.cpp |
+++ b/src/pathops/SkDQuadIntersection.cpp |
@@ -139,7 +139,7 @@ static bool add_intercept(const SkDQuad& q1, const SkDQuad& q2, double tMin, dou |
return false; |
} |
SkDPoint pt2 = q1.ptAtT(rootTs[0][0]); |
- if (!pt2.approximatelyEqualHalf(mid)) { |
+ if (!pt2.approximatelyEqual(mid)) { |
return false; |
} |
i->insertSwap(rootTs[0][0], tMid, pt2); |
@@ -249,31 +249,36 @@ static bool is_linear(const SkDQuad& q1, const SkDQuad& q2, SkIntersections* i) |
} |
// FIXME: if flat measure is sufficiently large, then probably the quartic solution failed |
-static void relaxed_is_linear(const SkDQuad& q1, const SkDQuad& q2, SkIntersections* i) { |
- double m1 = flat_measure(q1); |
- double m2 = flat_measure(q2); |
-#if DEBUG_FLAT_QUADS |
- double min = SkTMin(m1, m2); |
- if (min > 5) { |
- SkDebugf("%s maybe not flat enough.. %1.9g\n", __FUNCTION__, min); |
- } |
-#endif |
+// avoid imprecision incurred with chopAt |
+static void relaxed_is_linear(const SkDQuad* q1, double s1, double e1, const SkDQuad* q2, |
+ double s2, double e2, SkIntersections* i) { |
+ double m1 = flat_measure(*q1); |
+ double m2 = flat_measure(*q2); |
i->reset(); |
- const SkDQuad& rounder = m2 < m1 ? q1 : q2; |
- const SkDQuad& flatter = m2 < m1 ? q2 : q1; |
+ const SkDQuad* rounder, *flatter; |
+ double sf, midf, ef, sr, er; |
+ if (m2 < m1) { |
+ rounder = q1; |
+ sr = s1; |
+ er = e1; |
+ flatter = q2; |
+ sf = s2; |
+ midf = (s2 + e2) / 2; |
+ ef = e2; |
+ } else { |
+ rounder = q2; |
+ sr = s2; |
+ er = e2; |
+ flatter = q1; |
+ sf = s1; |
+ midf = (s1 + e1) / 2; |
+ ef = e1; |
+ } |
bool subDivide = false; |
- is_linear_inner(flatter, 0, 1, rounder, 0, 1, i, &subDivide); |
+ is_linear_inner(*flatter, sf, ef, *rounder, sr, er, i, &subDivide); |
if (subDivide) { |
- SkDQuadPair pair = flatter.chopAt(0.5); |
- SkIntersections firstI, secondI; |
- relaxed_is_linear(pair.first(), rounder, &firstI); |
- for (int index = 0; index < firstI.used(); ++index) { |
- i->insert(firstI[0][index] * 0.5, firstI[1][index], firstI.pt(index)); |
- } |
- relaxed_is_linear(pair.second(), rounder, &secondI); |
- for (int index = 0; index < secondI.used(); ++index) { |
- i->insert(0.5 + secondI[0][index] * 0.5, secondI[1][index], secondI.pt(index)); |
- } |
+ relaxed_is_linear(flatter, sf, midf, rounder, sr, er, i); |
+ relaxed_is_linear(flatter, midf, ef, rounder, sr, er, i); |
} |
if (m2 < m1) { |
i->swapPts(); |
@@ -378,7 +383,7 @@ static void lookNearEnd(const SkDQuad& q1, const SkDQuad& q2, int testT, |
impTs.intersectRay(q1, tmpLine); |
for (int index = 0; index < impTs.used(); ++index) { |
SkDPoint realPt = impTs.pt(index); |
- if (!tmpLine[0].approximatelyEqualHalf(realPt)) { |
+ if (!tmpLine[0].approximatelyEqual(realPt)) { |
continue; |
} |
if (swap) { |
@@ -390,6 +395,7 @@ static void lookNearEnd(const SkDQuad& q1, const SkDQuad& q2, int testT, |
} |
int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { |
+ fMax = 4; |
// 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) { |
@@ -401,7 +407,7 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { |
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].approximatelyEqualHalf(q2[i2])) { |
+ if (q1[i1] != q2[i2] && q1[i1].approximatelyEqual(q2[i2])) { |
insertNear(i1 >> 1, i2 >> 1, q1[i1]); |
} |
} |
@@ -420,6 +426,7 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { |
return fUsed; |
} |
SkIntersections swapped; |
+ swapped.setMax(fMax); |
if (is_linear(q2, q1, &swapped)) { |
swapped.swapPts(); |
set(swapped); |
@@ -484,7 +491,7 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { |
} |
if (r1Count == r2Count && r1Count <= 1) { |
if (r1Count == 1) { |
- if (pts1[0].approximatelyEqualHalf(pts2[0])) { |
+ if (pts1[0].approximatelyEqual(pts2[0])) { |
insert(roots1Copy[0], roots2Copy[0], pts1[0]); |
} else if (pts1[0].moreRoughlyEqual(pts2[0])) { |
// experiment: try to find intersection by chasing t |
@@ -506,7 +513,7 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { |
dist[index] = DBL_MAX; |
closest[index] = -1; |
for (int ndex2 = 0; ndex2 < r2Count; ++ndex2) { |
- if (!pts2[ndex2].approximatelyEqualHalf(pts1[index])) { |
+ if (!pts2[ndex2].approximatelyEqual(pts1[index])) { |
continue; |
} |
double dx = pts2[ndex2].fX - pts1[index].fX; |
@@ -532,7 +539,7 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { |
} |
} |
if (r1Count && r2Count && !foundSomething) { |
- relaxed_is_linear(q1, q2, this); |
+ relaxed_is_linear(&q1, 0, 1, &q2, 0, 1, this); |
return fUsed; |
} |
int used = 0; |