fix pathops bug 8380
Paths to intersect have two nearly coincident cubics. Where they
cross, the intersection error makes the curves start at slightly
different points. To sort the intersection, one curve is translated
to the start of the opposite point, moving it from one side to the
other, introducing a winding error.
The fix looks for that error in a very tiny range (enlarging that
range causes other tests that now pass to fail). This fix is very
fragile and points to the need for a better approach than sorting
angles to find winding values, as documented in the bug.
Also renamed some angle functions to show that they operate only
on lines and not general curves.
All tests pass with this fix:
./out/release/pathops_unittest -V -x
./out/debug/pathops_unittest -V -x
TBR=reed@google.com
Bug: skia:8380
Change-Id: I04e53d4c6a96035f661a4c9f31a17055ce13e3eb
Reviewed-on: https://skia-review.googlesource.com/c/179241
Commit-Queue: Cary Clark <caryclark@skia.org>
Reviewed-by: Cary Clark <caryclark@skia.org>
diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp
index b664fa5..070f802 100644
--- a/tests/PathOpsOpTest.cpp
+++ b/tests/PathOpsOpTest.cpp
@@ -9079,6 +9079,30 @@
testPathOp(reporter, path1, path2, kIntersect_SkPathOp, filename);
}
+static void bug8380(skiatest::Reporter* reporter, const char* filename) {
+SkPath path, path2;
+path.setFillType(SkPath::kEvenOdd_FillType);
+path.moveTo(SkBits2Float(0xa6800000), SkBits2Float(0x43b0f22d)); // -8.88178e-16f, 353.892f
+path.lineTo(SkBits2Float(0x42fc0000), SkBits2Float(0x4116566d)); // 126, 9.3961f
+path.cubicTo(SkBits2Float(0x42fb439d), SkBits2Float(0x4114bbc7), SkBits2Float(0x42fa3ed7), SkBits2Float(0x411565bd), SkBits2Float(0x42f934d2), SkBits2Float(0x4116131e)); // 125.632f, 9.29584f, 125.123f, 9.33734f, 124.603f, 9.37967f
+path.cubicTo(SkBits2Float(0x42f84915), SkBits2Float(0x4116acc3), SkBits2Float(0x42f75939), SkBits2Float(0x41174918), SkBits2Float(0x42f693f8), SkBits2Float(0x4116566d)); // 124.143f, 9.41718f, 123.674f, 9.45535f, 123.289f, 9.3961f
+path.lineTo(SkBits2Float(0x42ec3cee), SkBits2Float(0x410127bb)); // 118.119f, 8.0722f
+path.lineTo(SkBits2Float(0x4102c0ec), SkBits2Float(0x42d06d0e)); // 8.1721f, 104.213f
+path.lineTo(SkBits2Float(0xa6000000), SkBits2Float(0x4381a63d)); // -4.44089e-16f, 259.299f
+path.lineTo(SkBits2Float(0x00000000), SkBits2Float(0x43b0f22d)); // 0, 353.892f
+path.lineTo(SkBits2Float(0xa6800000), SkBits2Float(0x43b0f22d)); // -8.88178e-16f, 353.892f
+path.close();
+path2.setFillType(SkPath::kEvenOdd_FillType);
+path2.moveTo(SkBits2Float(0x4102c0ec), SkBits2Float(0x42d06d0e)); // 8.1721f, 104.213f
+path2.lineTo(SkBits2Float(0xc0ba5a1d), SkBits2Float(0x43b8e831)); // -5.8235f, 369.814f
+path2.lineTo(SkBits2Float(0x42fc0000), SkBits2Float(0x411656d6)); // 126, 9.3962f
+path2.cubicTo(SkBits2Float(0x42fa9cac), SkBits2Float(0x41134fdf), SkBits2Float(0x42f837cf), SkBits2Float(0x41185aee), SkBits2Float(0x42f693f8), SkBits2Float(0x411656d6)); // 125.306f, 9.207f, 124.109f, 9.5222f, 123.289f, 9.3962f
+path2.lineTo(SkBits2Float(0x42ec3cee), SkBits2Float(0x410127bb)); // 118.119f, 8.0722f
+path2.lineTo(SkBits2Float(0x4102c0ec), SkBits2Float(0x42d06d0e)); // 8.1721f, 104.213f
+path2.close();
+ testPathOp(reporter, path, path2, kIntersect_SkPathOp, filename);
+}
+
static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
@@ -9086,6 +9110,7 @@
#define TEST(name) { name, #name }
static struct TestDesc tests[] = {
+ TEST(bug8380),
TEST(crbug_526025),
TEST(bug8228),
TEST(op_4),