diff options
author | caryclark <caryclark@google.com> | 2016-09-22 10:24:59 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-09-22 10:24:59 -0700 |
commit | bac104605ef3d9a8ed0022694990f00518b809e9 (patch) | |
tree | ef64ee5043762606de08fde3da60b39777c3bc22 /src/core/SkGeometry.cpp | |
parent | 08b345588414b861af8a55950e7dc21a1bd85a28 (diff) |
Reland of ix for conic fuzz (patchset #1 id:1 of https://codereview.chromium.org/2361473004/ )
Reason for revert:
Landed suppression in Chrome's LayoutTests/TestExpectations
Original issue's description:
> Revert of fix for conic fuzz (patchset #3 id:40001 of https://codereview.chromium.org/2350263003/ )
>
> Reason for revert:
> See if this fixes the layout tests.
>
> Original issue's description:
> > fix for conic fuzz
> >
> > A fuzzer generates a conic that hangs when drawn.
> > The quads that approximate the conics move up and down
> > in y, confusing the renderer.
> >
> > This fix ensures that the split conic maintains the
> > same y direction as the original conic.
> >
> > R=reed@google.com
> > BUG=647922
> > GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2350263003
> >
> > Committed: https://skia.googlesource.com/skia/+/ac78863acdef4b428aaf66985b80c76d1be0fdea
>
> TBR=reed@google.com
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=647922
>
> Committed: https://skia.googlesource.com/skia/+/08b345588414b861af8a55950e7dc21a1bd85a28
TBR=reed@google.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=647922
Review-Url: https://codereview.chromium.org/2359253002
Diffstat (limited to 'src/core/SkGeometry.cpp')
-rw-r--r-- | src/core/SkGeometry.cpp | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp index a3ebfb38a8..027b65f0f1 100644 --- a/src/core/SkGeometry.cpp +++ b/src/core/SkGeometry.cpp @@ -1153,6 +1153,12 @@ int SkConic::computeQuadPOW2(SkScalar tol) const { return pow2; } +// This was originally developed and tested for pathops: see SkOpTypes.h +// returns true if (a <= b <= c) || (a >= b >= c) +static bool between(SkScalar a, SkScalar b, SkScalar c) { + return (a - b) * (c - b) <= 0; +} + static SkPoint* subdivide(const SkConic& src, SkPoint pts[], int level) { SkASSERT(level >= 0); @@ -1162,6 +1168,32 @@ static SkPoint* subdivide(const SkConic& src, SkPoint pts[], int level) { } else { SkConic dst[2]; src.chop(dst); + const SkScalar startY = src.fPts[0].fY; + const SkScalar endY = src.fPts[2].fY; + if (between(startY, src.fPts[1].fY, endY)) { + // If the input is monotonic and the output is not, the scan converter hangs. + // Ensure that the chopped conics maintain their y-order. + SkScalar midY = dst[0].fPts[2].fY; + if (!between(startY, midY, endY)) { + // If the computed midpoint is outside the ends, move it to the closer one. + SkScalar closerY = SkTAbs(midY - startY) < SkTAbs(midY - endY) ? startY : endY; + dst[0].fPts[2].fY = dst[1].fPts[0].fY = closerY; + } + if (!between(startY, dst[0].fPts[1].fY, dst[0].fPts[2].fY)) { + // If the 1st control is not between the start and end, put it at the start. + // This also reduces the quad to a line. + dst[0].fPts[1].fY = startY; + } + if (!between(dst[1].fPts[0].fY, dst[1].fPts[1].fY, endY)) { + // If the 2nd control is not between the start and end, put it at the end. + // This also reduces the quad to a line. + dst[1].fPts[1].fY = endY; + } + // Verify that all five points are in order. + SkASSERT(between(startY, dst[0].fPts[1].fY, dst[0].fPts[2].fY)); + SkASSERT(between(dst[0].fPts[1].fY, dst[0].fPts[2].fY, dst[1].fPts[1].fY)); + SkASSERT(between(dst[0].fPts[2].fY, dst[1].fPts[1].fY, endY)); + } --level; pts = subdivide(dst[0], pts, level); return subdivide(dst[1], pts, level); |