[4fGradient] Relax interval checks

We're currently considering intervals open at one extremity, in order to
ensure that a given value is always contained in a single interval.

This creates problems with synthetic clamp intervals [1, +inf), for
t == +inf (no interval can contain it).

Treat intervals as closed at both extremities instead.  This introduces
some ambiguitiy for overlapping values (contained in both adjacent
intervals), but solves the more serious problem above.

BUG=skia:6213

Change-Id: I33064f762fa9c2b914615e27977115d6654b12f4
Reviewed-on: https://skia-review.googlesource.com/8270
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/tests/GradientTest.cpp b/tests/GradientTest.cpp
index 50643f1..dc8a2bd 100644
--- a/tests/GradientTest.cpp
+++ b/tests/GradientTest.cpp
@@ -9,9 +9,11 @@
 #include "SkColorPriv.h"
 #include "SkColorShader.h"
 #include "SkGradientShader.h"
+#include "SkLinearGradient.h"
 #include "SkShader.h"
 #include "SkSurface.h"
 #include "SkTemplates.h"
+#include "SkTLazy.h"
 #include "Test.h"
 
 // https://code.google.com/p/chromium/issues/detail?id=448299
@@ -350,7 +352,7 @@
 }
 
 // http://crbug.com/636194
-static void text_degenerate_linear(skiatest::Reporter*) {
+static void test_degenerate_linear(skiatest::Reporter*) {
     SkPaint p;
     const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN };
     const SkPoint pts[] = {
@@ -365,6 +367,62 @@
     // Passes if we don't trigger asserts.
 }
 
+// "Interesting" fuzzer values.
+static void test_linear_fuzzer(skiatest::Reporter*) {
+    static const SkColor gColors0[] = { 0x30303030, 0x30303030 };
+    static const SkScalar gMatrix0[9] =
+        { 6.40969056e-10f, 0, 6.40969056e-10f, 0, 4.42539023e-39f, 6.40969056e-10f, 0, 0, 1 };
+
+    static const struct {
+        SkPoint            fPts[2];
+        const SkColor*     fColors;
+        const SkScalar*    fPos;
+        int                fCount;
+        SkShader::TileMode fTileMode;
+        uint32_t           fFlags;
+        const SkScalar*    fLocalMatrix;
+        const SkScalar*    fGlobalMatrix;
+    } gConfigs[] = {
+        {
+          {{0, -2.752941f}, {0, 0}},
+          gColors0,
+          nullptr,
+          SK_ARRAY_COUNT(gColors0),
+          SkShader::kClamp_TileMode,
+          0,
+          gMatrix0,
+          nullptr
+        },
+    };
+
+    static const uint32_t gForceFlags[] = { 0, SkLinearGradient::kForce4fContext_PrivateFlag };
+
+    sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(100, 100);
+    SkCanvas* canvas = surface->getCanvas();
+    SkPaint paint;
+
+    for (auto forceFlags : gForceFlags) {
+        for (const auto& config : gConfigs) {
+            SkAutoCanvasRestore acr(canvas, false);
+            SkTLazy<SkMatrix> localMatrix;
+            if (config.fLocalMatrix) {
+                localMatrix.init();
+                localMatrix.get()->set9(config.fLocalMatrix);
+            }
+
+            paint.setShader(SkGradientShader::MakeLinear(config.fPts,
+                                                         config.fColors,
+                                                         config.fPos,
+                                                         config.fCount,
+                                                         config.fTileMode,
+                                                         config.fFlags | forceFlags,
+                                                         localMatrix.getMaybeNull()));
+            canvas->drawPaint(paint);
+        }
+    }
+}
+
+
 DEF_TEST(Gradient, reporter) {
     TestGradientShaders(reporter);
     TestGradientOptimization(reporter);
@@ -375,5 +433,6 @@
     test_linear_fuzz(reporter);
     test_two_point_conical_zero_radius(reporter);
     test_clamping_overflow(reporter);
-    text_degenerate_linear(reporter);
+    test_degenerate_linear(reporter);
+    test_linear_fuzzer(reporter);
 }