cherry-pick https://codereview.chromium.org/2159223005
authorreed <reed@google.com>
Mon, 25 Jul 2016 15:46:18 +0000 (08:46 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 25 Jul 2016 15:46:18 +0000 (08:46 -0700)
BUG=629455
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2174383002
NOTREECHECKS=true
NOTRY=true
NOPRESUBMIT=true

Review-Url: https://codereview.chromium.org/2174383002

src/core/SkEdgeClipper.cpp
tests/PathTest.cpp

index 85c519d3644a4e7a1f921bcd5f67ec9e712c62f4..b5ac27ae590886d8bbb50368e7489b42645bfe16 100644 (file)
@@ -263,9 +263,25 @@ static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) {
     if (pts[0].fY < clip.fTop) {
         SkPoint tmp[7];
         chop_mono_cubic_at_y(pts, clip.fTop, tmp);
+
+        /*
+         *  For a large range in the points, we can do a poor job of chopping, such that the t
+         *  we computed resulted in the lower cubic still being partly above the clip.
+         *
+         *  If just the first or first 2 Y values are above the fTop, we can just smash them
+         *  down. If the first 3 Ys are above fTop, we can't smash all 3, as that can really
+         *  distort the cubic. In this case, we take the first output (tmp[3..6] and treat it as
+         *  a guess, and re-chop against fTop. Then we fall through to checking if we need to
+         *  smash the first 1 or 2 Y values.
+         */
+        if (tmp[3].fY < clip.fTop && tmp[4].fY < clip.fTop && tmp[5].fY < clip.fTop) {
+            SkPoint tmp2[4];
+            memcpy(tmp2, &tmp[3].fX, 4 * sizeof(SkPoint));
+            chop_mono_cubic_at_y(tmp2, clip.fTop, tmp);
+        }
+
         // tmp[3, 4].fY should all be to the below clip.fTop.
-        // Since we can't trust the numerics of
-        // the chopper, we force those conditions now
+        // Since we can't trust the numerics of the chopper, we force those conditions now
         tmp[3].fY = clip.fTop;
         clamp_ge(tmp[4].fY, clip.fTop);
 
index 5bc3d95b6f4b33b5529c76a759a11420935179ac..03e3459966100cccc0b433039685e10d2bad15a9 100644 (file)
@@ -4116,6 +4116,21 @@ public:
     }
 };
 
+static void test_crbug_629455(skiatest::Reporter* reporter) {
+    SkPath path;
+    path.moveTo(0, 0);
+    path.cubicTo(SkBits2Float(0xcdcdcd00), SkBits2Float(0xcdcdcdcd),
+                 SkBits2Float(0xcdcdcdcd), SkBits2Float(0xcdcdcdcd),
+                 SkBits2Float(0x423fcdcd), SkBits2Float(0x40ed9341));
+//  AKA: cubicTo(-4.31596e+08f, -4.31602e+08f, -4.31602e+08f, -4.31602e+08f, 47.951f, 7.42423f);
+    path.lineTo(0, 0);
+
+    auto surface = SkSurface::MakeRasterN32Premul(100, 100);
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    surface->getCanvas()->drawPath(path, paint);
+}
+
 static void test_interp(skiatest::Reporter* reporter) {
     SkPath p1, p2, out;
     REPORTER_ASSERT(reporter, p1.isInterpolatable(p2));
@@ -4164,6 +4179,7 @@ DEF_TEST(PathContains, reporter) {
 }
 
 DEF_TEST(Paths, reporter) {
+    test_crbug_629455(reporter);
     test_path_crbug364224();
 
     SkTSize<SkScalar>::Make(3,4);