Index: src/pathops/SkDQuadLineIntersection.cpp |
diff --git a/src/pathops/SkDQuadLineIntersection.cpp b/src/pathops/SkDQuadLineIntersection.cpp |
index afaa1552e478fb2a7952db1e2c8cd166b21021ad..216e31f285bc63ea1553032f1b35c5c0cfaf8f02 100644 |
--- a/src/pathops/SkDQuadLineIntersection.cpp |
+++ b/src/pathops/SkDQuadLineIntersection.cpp |
@@ -200,38 +200,57 @@ protected: |
// add endpoints first to get zero and one t values exactly |
void addEndPoints() { |
for (int qIndex = 0; qIndex < 3; qIndex += 2) { |
+ bool foundEnd = false; |
for (int lIndex = 0; lIndex < 2; lIndex++) { |
if (quad[qIndex] == line[lIndex]) { |
intersections->insert(qIndex >> 1, lIndex, line[lIndex]); |
+ foundEnd = true; |
} |
} |
+ if (foundEnd) { |
+ continue; |
+ } |
+ // See if the quad end touches the line. |
+ double dist = line.isLeft(quad[qIndex]); // this distance isn't cartesian |
+ SkDVector lineLen = line[1] - line[0]; // the x/y magnitudes of the line |
+ // compute the ULPS of the larger of the x/y deltas |
+ double larger = SkTMax(SkTAbs(lineLen.fX), SkTAbs(lineLen.fY)); |
+ if (!RoughlyEqualUlps(larger, larger + dist)) { // is the dist within ULPS tolerance? |
+ continue; |
+ } |
+ double lineT = findLineT(qIndex >> 1); |
+ if (!between(0, lineT, 1)) { |
+ continue; |
+ } |
+ SkDPoint linePt = line.xyAtT(lineT); |
+ if (linePt.approximatelyEqual(quad[qIndex])) { |
+ intersections->insert(qIndex >> 1, lineT, quad[qIndex]); |
+ } |
} |
} |
void addHorizontalEndPoints(double left, double right, double y) { |
for (int qIndex = 0; qIndex < 3; qIndex += 2) { |
- if (quad[qIndex].fY != y) { |
+ if (!AlmostEqualUlps(quad[qIndex].fY, y)) { |
continue; |
} |
- if (quad[qIndex].fX == left) { |
- intersections->insert(qIndex >> 1, 0, quad[qIndex]); |
- } |
- if (quad[qIndex].fX == right) { |
- intersections->insert(qIndex >> 1, 1, quad[qIndex]); |
+ double x = quad[qIndex].fX; |
+ if (between(left, x, right)) { |
+ double t = (x - left) / (right - left); |
+ intersections->insert(qIndex >> 1, t, quad[qIndex]); |
} |
} |
} |
void addVerticalEndPoints(double top, double bottom, double x) { |
for (int qIndex = 0; qIndex < 3; qIndex += 2) { |
- if (quad[qIndex].fX != x) { |
+ if (!AlmostEqualUlps(quad[qIndex].fX, x)) { |
continue; |
} |
- if (quad[qIndex].fY == top) { |
- intersections->insert(qIndex >> 1, 0, quad[qIndex]); |
- } |
- if (quad[qIndex].fY == bottom) { |
- intersections->insert(qIndex >> 1, 1, quad[qIndex]); |
+ double y = quad[qIndex].fY; |
+ if (between(top, y, bottom)) { |
+ double t = (y - top) / (bottom - top); |
+ intersections->insert(qIndex >> 1, t, quad[qIndex]); |
} |
} |
} |
@@ -240,10 +259,22 @@ protected: |
SkDPoint xy = quad.xyAtT(t); |
double dx = line[1].fX - line[0].fX; |
double dy = line[1].fY - line[0].fY; |
+#if 0 |
if (fabs(dx) > fabs(dy)) { |
return (xy.fX - line[0].fX) / dx; |
} |
return (xy.fY - line[0].fY) / dy; |
+#else |
+ double dxT = (xy.fX - line[0].fX) / dx; |
+ double dyT = (xy.fY - line[0].fY) / dy; |
+ if (!between(FLT_EPSILON, dxT, 1 - FLT_EPSILON) && between(0, dyT, 1)) { |
+ return dyT; |
+ } |
+ if (!between(FLT_EPSILON, dyT, 1 - FLT_EPSILON) && between(0, dxT, 1)) { |
+ return dxT; |
+ } |
+ return fabs(dx) > fabs(dy) ? dxT : dyT; |
+#endif |
} |
static bool PinTs(double* quadT, double* lineT) { |