Index: src/pathops/SkPathOpsQuad.cpp |
diff --git a/src/pathops/SkPathOpsQuad.cpp b/src/pathops/SkPathOpsQuad.cpp |
index dafa3f5b7588cbebbcb64465fb527526d1efba5b..ab1ba05c5691646c010a2677c2a0b79c50da6174 100644 |
--- a/src/pathops/SkPathOpsQuad.cpp |
+++ b/src/pathops/SkPathOpsQuad.cpp |
@@ -10,6 +10,28 @@ |
#include "SkPathOpsCurve.h" |
#include "SkPathOpsQuad.h" |
+// from blackpawn.com/texts/pointinpoly |
+static bool pointInTriangle(const SkDPoint fPts[3], const SkDPoint& test) { |
+ SkDVector v0 = fPts[2] - fPts[0]; |
+ SkDVector v1 = fPts[1] - fPts[0]; |
+ SkDVector v2 = test - fPts[0]; |
+ double dot00 = v0.dot(v0); |
+ double dot01 = v0.dot(v1); |
+ double dot02 = v0.dot(v2); |
+ double dot11 = v1.dot(v1); |
+ double dot12 = v1.dot(v2); |
+ // Compute barycentric coordinates |
+ double invDenom = 1 / (dot00 * dot11 - dot01 * dot01); |
+ double u = (dot11 * dot02 - dot01 * dot12) * invDenom; |
+ double v = (dot00 * dot12 - dot01 * dot02) * invDenom; |
+ // Check if point is in triangle |
+ return u >= 0 && v >= 0 && u + v < 1; |
+} |
+ |
+static bool matchesEnd(const SkDPoint fPts[3], const SkDPoint& test) { |
+ return fPts[0] == test || fPts[2] == test; |
+} |
+ |
/* started with at_most_end_pts_in_common from SkDQuadIntersection.cpp */ |
// Do a quick reject by rotating all points relative to a line formed by |
// a pair of one quad's points. If the 2nd quad's points |
@@ -44,6 +66,14 @@ bool SkDQuad::hullIntersects(const SkDQuad& q2, bool* isLinear) const { |
return false; |
} |
} |
+ if (linear && !matchesEnd(fPts, q2.fPts[0]) && !matchesEnd(fPts, q2.fPts[2])) { |
+ // if the end point of the opposite quad is inside the hull that is nearly a line, |
+ // then representing the quad as a line may cause the intersection to be missed. |
+ // Check to see if the endpoint is in the triangle. |
+ if (pointInTriangle(fPts, q2.fPts[0]) || pointInTriangle(fPts, q2.fPts[2])) { |
+ linear = false; |
+ } |
+ } |
*isLinear = linear; |
return true; |
} |