remove duplicate linked list adjustment
authorcaryclark <caryclark@google.com>
Mon, 31 Aug 2015 16:46:20 +0000 (09:46 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 31 Aug 2015 16:46:20 +0000 (09:46 -0700)
The list of intersection points on a curve segment may have
entries that can be safely removed when nearby points have
nearly the same t value and point value. When a path includes
very large curves as well as small ones, as is the case with
this fuzzer, additional points may lie between the similar
points that do not meet the nearby criteria.

After merging the nearby point with its doppelganger,
SkOpSegment::moveNearby() unnecessarily set the doppelganger's
next pointer to the one following the nearby point. While
this usually has no effect, since the merge already updated
the linked list, the explicit call removes the additional
outlier points from the segment.

TBR=reed@google.com
BUG=526025

Review URL: https://codereview.chromium.org/1323813003

src/pathops/SkOpSegment.cpp
tests/PathOpsBuilderTest.cpp
tests/PathOpsOpTest.cpp

index 99af13a..e332954 100644 (file)
@@ -1437,7 +1437,6 @@ void SkOpSegment::moveNearby() {
                             return;
                         }
                         spanS->merge(test->upCast());
-                        spanS->upCast()->setNext(next);
                         goto checkNextSpan;
                     }
                 } while ((testBase = testBase->next()) != test->ptT());
index 88684fe..88bfe1e 100644 (file)
@@ -271,3 +271,26 @@ DEF_TEST(Fuzz846, reporter) {
     builder.resolve(&result);
 }
 
+#include "SkParsePath.h"
+
+DEF_TEST(fuzzTNG, reporter) {
+    const char* pathStrs[] = {
+"M360,-2147483648.000000000000000000000000000000000000000000000000000001 A3240,3240 0.0 0 11 256,256 L100000000,4140 Z",
+"M360,4140 A11,-1 0.0 0 0 6840,4140 L100,512 L32,16 L360,1024 Z",
+"M360,4140 A3240,1000000001 32768 1024 128 100000000.000000000000000000000000000000000000000000000000000001,512 Z",
+"M127,321 L6840,270 L-21474836481,100000000 L2551,64 Z",
+"M-128,4140 Z",
+    };
+    SkPath clip[SK_ARRAY_COUNT(pathStrs)];
+    SkOpBuilder builder;
+    for (size_t i = 0; i < SK_ARRAY_COUNT(pathStrs); ++i) {
+        SkParsePath::FromSVGString(pathStrs[i], &clip[i]);
+        builder.add(clip[i], kUnion_SkPathOp);
+    }
+    SkPath result;
+    builder.resolve(&result);
+    SkPath path;
+    SkParsePath::FromSVGString("M-315,7425 L4096,7425 L-1000000001,-315 L-315,7425 Z", &path);
+    builder.add(path, kDifference_SkPathOp);
+    testPathOp(reporter, result, path, kDifference_SkPathOp, __FUNCTION__);
+}
index 98189ef..8a64fb9 100644 (file)
@@ -5164,6 +5164,34 @@ static void fuzz38(skiatest::Reporter* reporter, const char* filename) {
     testPathOpCheck(reporter, path, pathB, kUnion_SkPathOp, filename, FLAGS_runFail);
 }
 
+static void fuzz763_3(skiatest::Reporter* reporter, const char* filename) {
+    SkPath path;
+    path.setFillType((SkPath::FillType) 1);
+path.moveTo(SkBits2Float(0x43b40000), SkBits2Float(0xcf000000));  // 360, -2.14748e+09f
+path.cubicTo(SkBits2Float(0x4e0d628f), SkBits2Float(0xceffffff), SkBits2Float(0x4e800003), SkBits2Float(0xcec6b143), SkBits2Float(0x4e800002), SkBits2Float(0xce7ffffc));  // 5.93012e+08f, -2.14748e+09f, 1.07374e+09f, -1.66675e+09f, 1.07374e+09f, -1.07374e+09f
+path.cubicTo(SkBits2Float(0x4e800002), SkBits2Float(0xcde53aee), SkBits2Float(0x4e0d6292), SkBits2Float(0xc307820e), SkBits2Float(0x44627d00), SkBits2Float(0x437ffff2));  // 1.07374e+09f, -4.80731e+08f, 5.93012e+08f, -135.508f, 905.953f, 256
+path.lineTo(SkBits2Float(0x444bf3bc), SkBits2Float(0x4460537e));  // 815.808f, 897.305f
+path.lineTo(SkBits2Float(0x43553abd), SkBits2Float(0x440f3cbd));  // 213.229f, 572.949f
+path.lineTo(SkBits2Float(0x42000000), SkBits2Float(0x41800000));  // 32, 16
+path.lineTo(SkBits2Float(0x42c80000), SkBits2Float(0x44000000));  // 100, 512
+path.lineTo(SkBits2Float(0x43553abd), SkBits2Float(0x440f3cbd));  // 213.229f, 572.949f
+path.lineTo(SkBits2Float(0x43b40000), SkBits2Float(0x44800000));  // 360, 1024
+path.lineTo(SkBits2Float(0x43b40000), SkBits2Float(0x45816000));  // 360, 4140
+
+    SkPath path1(path);
+    path.reset();
+    path.setFillType((SkPath::FillType) 0);
+path.moveTo(SkBits2Float(0x42fe0000), SkBits2Float(0x43a08000));  // 127, 321
+path.lineTo(SkBits2Float(0x45d5c000), SkBits2Float(0x43870000));  // 6840, 270
+path.lineTo(SkBits2Float(0xd0a00000), SkBits2Float(0x4cbebc20));  // -2.14748e+10f, 1e+08
+path.lineTo(SkBits2Float(0x451f7000), SkBits2Float(0x42800000));  // 2551, 64
+path.lineTo(SkBits2Float(0x42fe0000), SkBits2Float(0x43a08000));  // 127, 321
+path.close();
+
+    SkPath path2(path);
+    testPathOp(reporter, path1, path2, (SkPathOp) 2, 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;
@@ -5171,6 +5199,7 @@ static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
 #define TEST(name) { name, #name }
 
 static struct TestDesc tests[] = {
+    TEST(fuzz763_3),
     TEST(fuzz38),
     TEST(cubics44d),
     TEST(cubics45u),