Fix color stop positions when computing degenerate gradient color
For non-degenerate gradients, the positions are pinned to [0, 1] and
forced to be monotonically increasing in the constructor of
SkGradientShaderBase. This isn't ever called for degenerate gradients,
so the average_gradient_color helper function needs to make the same
fixes or it may calculate an invalid color (e.g. negative alpha because
the original positions are not sorted).
Bug: chromium:1149216
Change-Id: I95c6e66ebb57722370ef2f5dbba3d8d66727e48b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/336437
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/tests/GradientTest.cpp b/tests/GradientTest.cpp
index bf70a9c..9595ffa 100644
--- a/tests/GradientTest.cpp
+++ b/tests/GradientTest.cpp
@@ -11,6 +11,7 @@
#include "include/core/SkSurface.h"
#include "include/effects/SkGradientShader.h"
#include "include/private/SkTemplates.h"
+#include "src/core/SkMatrixProvider.h"
#include "src/core/SkTLazy.h"
#include "src/shaders/SkColorShader.h"
#include "tests/Test.h"
@@ -368,6 +369,36 @@
// Passes if we don't trigger asserts.
}
+// http://crbug.com/1149216
+static void test_unsorted_degenerate(skiatest::Reporter* r) {
+ // Passes if a valid solid color is computed for the degenerate gradient
+ // (unsorted positions are fixed during regular gradient construction, so this ensures the
+ // same fixing happens for degenerate gradients as well). If they aren't fixed, this test
+ // case produces a negative alpha, which asserts during SkPMColor4f::isOpaque().
+ const SkColor4f colors[] = { {0.f, 0.f, 0.f, 0.f},
+ {0.00784314f, 0.f, 0.f, 0.0627451f},
+ {0.f, 0.00392157f, 0.f, 0.f} };
+ const SkScalar positions[] = {0.00753367f, 8.54792e-44f, 1.46955e-39f};
+
+ const SkPoint points[] { { 0.f, 0.f }, { 1e-20f, -1e-8f }}; // must be degenerate
+ // Use kMirror to go through average color stop calculation, vs. kClamp which would pick a color
+ sk_sp<SkShader> gradient = SkGradientShader::MakeLinear(points, colors, nullptr, positions, 3,
+ SkTileMode::kMirror);
+
+ // The degenerate gradient shouldn't be null
+ REPORTER_ASSERT(r, SkToBool(gradient));
+ // And it shouldn't crash when creating a fragment processor
+
+ SkSimpleMatrixProvider provider(SkMatrix::I());
+ GrColorInfo dstColorInfo(GrColorType::kRGBA_8888, kPremul_SkAlphaType,
+ SkColorSpace::MakeSRGB());
+ GrMockOptions options;
+ auto context = GrDirectContext::MakeMock(&options);
+
+ GrFPArgs args(context.get(), provider, kNone_SkFilterQuality, &dstColorInfo);
+ as_SB(gradient)->asFragmentProcessor(args);
+}
+
// "Interesting" fuzzer values.
static void test_linear_fuzzer(skiatest::Reporter*) {
static const SkColor gColors0[] = { 0x30303030, 0x30303030 };
@@ -550,4 +581,5 @@
test_degenerate_linear(reporter);
test_linear_fuzzer(reporter);
test_sweep_fuzzer(reporter);
+ test_unsorted_degenerate(reporter);
}