aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkGeometry.cpp
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2016-09-22 10:24:59 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-09-22 10:24:59 -0700
commitbac104605ef3d9a8ed0022694990f00518b809e9 (patch)
treeef64ee5043762606de08fde3da60b39777c3bc22 /src/core/SkGeometry.cpp
parent08b345588414b861af8a55950e7dc21a1bd85a28 (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.cpp32
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);