diff options
author | Cary Clark <caryclark@skia.org> | 2018-07-10 10:57:54 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-07-10 15:25:35 +0000 |
commit | 1d314433ffd5a5149438dd82d10c04736325004d (patch) | |
tree | 618f7311c51690a0a624be89f8e95bae508691e4 /src/pathops | |
parent | 3be2e10ce534a9bf8eb008d3704be26b2ba04437 (diff) |
fix line intersect divide by zero
Test filinmangust14 exposes two problems:
- finding top of contour can expose divide by zero
- joining partial contour results can add diagonal
The latter makes the test return the wrong result,
and has not been seen in other tests. The fix
is to join disconnected contours by only following
the contours provided as input. Working on that.
The former bug is more straight-forward; just
don't try to compute axis-aligned intersection
if the denominator is zero.
All existing tests prior to the new one work
with this change.
R=caryclark@google.com
Bug: skia:8125
Change-Id: Ic878d090066708d9baca8475f27d4d5aba2294cc
Reviewed-on: https://skia-review.googlesource.com/140121
Reviewed-by: Cary Clark <caryclark@skia.org>
Commit-Queue: Cary Clark <caryclark@skia.org>
Auto-Submit: Cary Clark <caryclark@skia.org>
Diffstat (limited to 'src/pathops')
-rw-r--r-- | src/pathops/SkDLineIntersection.cpp | 4 | ||||
-rw-r--r-- | src/pathops/SkPathOpsCurve.h | 6 | ||||
-rw-r--r-- | src/pathops/SkPathOpsDebug.h | 1 | ||||
-rw-r--r-- | src/pathops/SkPathWriter.cpp | 16 |
4 files changed, 26 insertions, 1 deletions
diff --git a/src/pathops/SkDLineIntersection.cpp b/src/pathops/SkDLineIntersection.cpp index 43c37decb8..5dcc067369 100644 --- a/src/pathops/SkDLineIntersection.cpp +++ b/src/pathops/SkDLineIntersection.cpp @@ -197,7 +197,8 @@ static int horizontal_coincident(const SkDLine& line, double y) { } double SkIntersections::HorizontalIntercept(const SkDLine& line, double y) { - return SkPinT((y - line[0].fY) / (line[1].fY - line[0].fY)); + SkASSERT(line[1].fY != line[0].fY); + return SkPinT((y - line[0].fY) / (line[1].fY - line[0].fY)); } int SkIntersections::horizontal(const SkDLine& line, double left, double right, @@ -274,6 +275,7 @@ static int vertical_coincident(const SkDLine& line, double x) { } double SkIntersections::VerticalIntercept(const SkDLine& line, double x) { + SkASSERT(line[1].fX != line[0].fX); return SkPinT((x - line[0].fX) / (line[1].fX - line[0].fX)); } diff --git a/src/pathops/SkPathOpsCurve.h b/src/pathops/SkPathOpsCurve.h index 2b50864e5b..7823146d78 100644 --- a/src/pathops/SkPathOpsCurve.h +++ b/src/pathops/SkPathOpsCurve.h @@ -358,12 +358,18 @@ static void (* const CurveDIntersectRay[])(const SkDCurve& , const SkDLine& , Sk }; static int line_intercept_h(const SkPoint a[2], SkScalar , SkScalar y, double* roots) { + if (a[0].fY == a[1].fY) { + return false; + } SkDLine line; roots[0] = SkIntersections::HorizontalIntercept(line.set(a), y); return between(0, roots[0], 1); } static int line_intercept_v(const SkPoint a[2], SkScalar , SkScalar x, double* roots) { + if (a[0].fX == a[1].fX) { + return false; + } SkDLine line; roots[0] = SkIntersections::VerticalIntercept(line.set(a), x); return between(0, roots[0], 1); diff --git a/src/pathops/SkPathOpsDebug.h b/src/pathops/SkPathOpsDebug.h index 9aec715de1..724713a74a 100644 --- a/src/pathops/SkPathOpsDebug.h +++ b/src/pathops/SkPathOpsDebug.h @@ -8,6 +8,7 @@ #define SkPathOpsDebug_DEFINED #include "SkPathOps.h" +#include "SkString.h" #include "SkTypes.h" #include <stdlib.h> diff --git a/src/pathops/SkPathWriter.cpp b/src/pathops/SkPathWriter.cpp index 7291002593..950f8fbce5 100644 --- a/src/pathops/SkPathWriter.cpp +++ b/src/pathops/SkPathWriter.cpp @@ -301,6 +301,22 @@ void SkPathWriter::assemble() { #endif do { const SkPath& contour = fPartials[rIndex]; + if (!first) { + SkPoint prior, next; + SkAssertResult(fPathPtr->getLastPt(&prior)); + if (forward) { + next = contour.getPoint(0); + } else { + SkAssertResult(contour.getLastPt(&next)); + } + if (prior != next) { + /* TODO: if there is a gap between open path written so far and path to come, + connect by following segments from one to the other, rather than introducing + a diagonal to connect the two. + */ + SkDebugf(""); + } + } if (forward) { fPathPtr->addPath(contour, first ? SkPath::kAppend_AddPathMode : SkPath::kExtend_AddPathMode); |