aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@skia.org>2018-02-02 15:09:49 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-02 20:39:09 +0000
commit4efcb7d100e824926e03f598d616f6bda5682e14 (patch)
tree83f8fb9ec7d81801d08e64eecb1867b4159b7a05
parent27738e043a8eeeb8045397b7e1140a0b1bcb04a3 (diff)
handle degenerate cubic loops
fuzzer generated a cubic with a very tiny loop at one end. Breaking the cubic in two generated a piece so small it was discarded, passing the original along. Instead, use the loop detection as a hint that passing the original may fail further along. Keep the big piece, which is more linear than the original; and change its end to match the original input if the small piece isn't worth keeping. R=kjlubick Bug: skia:7480 Change-Id: If4c5cd46dbf7e16526269f2854e4f2278f427461 Reviewed-on: https://skia-review.googlesource.com/103100 Reviewed-by: Kevin Lubick <kjlubick@google.com> Commit-Queue: Cary Clark <caryclark@skia.org>
-rw-r--r--src/pathops/SkOpEdgeBuilder.cpp11
-rw-r--r--tests/PathOpsCubicIntersectionTest.cpp1
-rw-r--r--tests/PathOpsSimplifyTest.cpp15
-rw-r--r--tools/pathops_sorter.htm16
4 files changed, 23 insertions, 20 deletions
diff --git a/src/pathops/SkOpEdgeBuilder.cpp b/src/pathops/SkOpEdgeBuilder.cpp
index 572942dab4..cda6850701 100644
--- a/src/pathops/SkOpEdgeBuilder.cpp
+++ b/src/pathops/SkOpEdgeBuilder.cpp
@@ -307,6 +307,7 @@ bool SkOpEdgeBuilder::walk() {
}
if (prior < index) {
split->fT[0] = splits[prior].fT[0];
+ split->fPts[0] = splits[prior].fPts[0];
}
int next = index;
int breakLimit = SkTMin(breaks, (int) SK_ARRAY_COUNT(splits) - 1);
@@ -315,17 +316,9 @@ bool SkOpEdgeBuilder::walk() {
}
if (next > index) {
split->fT[1] = splits[next].fT[1];
+ split->fPts[3] = splits[next].fPts[3];
}
if (prior < index || next > index) {
- if (0 == split->fT[0] && 1 == split->fT[1]) {
- fContourBuilder.addCubic(pointsPtr);
- break;
- }
- SkDCubic part = SkDCubic::SubDivide(pointsPtr, split->fT[0],
- split->fT[1]);
- if (!part.toFloatPoints(split->fPts)) {
- return false;
- }
split->fVerb = SkReduceOrder::Cubic(split->fPts, split->fReduced);
}
SkPoint* curve = SkPath::kCubic_Verb == split->fVerb
diff --git a/tests/PathOpsCubicIntersectionTest.cpp b/tests/PathOpsCubicIntersectionTest.cpp
index 7871fde931..8a7ec1ac81 100644
--- a/tests/PathOpsCubicIntersectionTest.cpp
+++ b/tests/PathOpsCubicIntersectionTest.cpp
@@ -168,6 +168,7 @@ static const CubicPts testSet[] = {
const int testSetCount = (int) SK_ARRAY_COUNT(testSet);
static const CubicPts newTestSet[] = {
+
{ { { 130.0427549999999997, 11417.41309999999976 },{ 130.2331240000000037, 11418.3192999999992 },{ 131.0370790000000056, 11419 },{ 132, 11419 } } },
{ { { 132, 11419 },{ 130.8954319999999996, 11419 },{ 130, 11418.10449999999946 },{ 130, 11417 } } },
diff --git a/tests/PathOpsSimplifyTest.cpp b/tests/PathOpsSimplifyTest.cpp
index 75c139afe0..5caee93b85 100644
--- a/tests/PathOpsSimplifyTest.cpp
+++ b/tests/PathOpsSimplifyTest.cpp
@@ -7679,11 +7679,26 @@ static void joel_16x(skiatest::Reporter* reporter, const char* filename) {
testSimplify(reporter, path, filename);
}
+static void coincubics(skiatest::Reporter* reporter, const char* filename) {
+ SkPath path;
+ path.moveTo(SkDoubleToScalar(0.00000000000000000), SkDoubleToScalar(0.00000000000000000));
+ path.cubicTo(SkDoubleToScalar(0.00022939755581319332), SkDoubleToScalar(0.00022927834652364254),
+ SkDoubleToScalar(0.00022930106206331402), SkDoubleToScalar(0.00022929999977350235),
+ SkDoubleToScalar(0.00022930069826543331), SkDoubleToScalar(0.00022913678549230099));
+ path.lineTo(SkDoubleToScalar(0.00022930069826543331), SkDoubleToScalar(0.00022930069826543331));
+ path.cubicTo(SkDoubleToScalar(0.00011465034913271666), SkDoubleToScalar(0.00011465034913271666),
+ SkDoubleToScalar(0.00011465061106719077), SkDoubleToScalar(0.00011460937093943357),
+ SkDoubleToScalar(0.00014331332931760699), SkDoubleToScalar(0.00014325146912597120));
+testSimplify(reporter, path, filename);
+}
+
+
static void (*skipTest)(skiatest::Reporter* , const char* filename) = nullptr;
static void (*firstTest)(skiatest::Reporter* , const char* filename) = nullptr;
static void (*stopTest)(skiatest::Reporter* , const char* filename) = nullptr;
static TestDesc tests[] = {
+ TEST(coincubics),
TEST(joel_16x),
TEST(joel_16),
TEST(joel_15x),
diff --git a/tools/pathops_sorter.htm b/tools/pathops_sorter.htm
index 42708c428c..017d9165bf 100644
--- a/tools/pathops_sorter.htm
+++ b/tools/pathops_sorter.htm
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
@@ -6,16 +6,10 @@
<title></title>
<div style="height:0">
-<div id="cubics">
-{{{152, 16}, {152, 16.0685501}, {91.06044, 16.1242027}, {16, 16.1242027}}}, id=0
-{{{16, 16.1242027}, {-59.06044, 16.1242027}, {-120, 16.0685501}, {-120, 16}}}, id=1
-{{{-120, 16}, {-120, 15.9314508}, {-59.06044, 15.8757973}, {16, 15.8757973}}}, id=2
-{{{16, 15.8757973}, {91.06044, 15.8757973}, {152, 15.9314508}, {152, 16}}}, id=3
-{{{16, 16}, {152, 16}}}, id=4
-{{{16, 17}, {152, 17}}}, id=5
-{{{16, 16}, {16, 17}}}, id=6
-{{{152, 16}, {152, 17}}}, id=7
-</div>
+ <div id="cubics">
+ {{{0.00000000000000000, 0.00000000000000000 }, {0.00022939755581319332, 0.00022927834652364254 },{0.00022930106206331402, 0.00022929999977350235 }, {0.00022930069826543331, 0.00022913678549230099}}},
+ {{{0.00022930069826543331, 0.00022930069826543331 }, {0.00011465034913271666, 0.00011465034913271666 },{0.00011465061106719077, 0.00011460937093943357 }, {0.00014331332931760699, 0.00014325146912597120}}},
+ </div>
</div>