diff options
author | reed <reed@google.com> | 2016-01-05 10:01:38 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-05 10:01:38 -0800 |
commit | aeab8ea4d7492dc996fa72de7298de81f8deed93 (patch) | |
tree | 6199717e6ea013b7e8e535a2e5f5268b5db9042d | |
parent | 05dd251e5e135626d170b9e77eb64729bd482169 (diff) |
fix linear gradient assert, by explicitly clamping
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1556993003
Review URL: https://codereview.chromium.org/1556993003
-rw-r--r-- | src/effects/gradients/SkLinearGradient.cpp | 11 | ||||
-rw-r--r-- | tests/GradientTest.cpp | 22 |
2 files changed, 29 insertions, 4 deletions
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp index 298466c8a6..4f90c27c8c 100644 --- a/src/effects/gradients/SkLinearGradient.cpp +++ b/src/effects/gradients/SkLinearGradient.cpp @@ -668,12 +668,12 @@ void SkLinearGradient::LinearGradientContext::shade4_dx_clamp(SkPMColor dstC[], } fx += n * dx; - count -= n; - SkASSERT(count >= 0); + // fx should now outside of the p0..p1 interval. However, due to float precision loss, + // its possible that fx is slightly too small/large, so we clamp it. if (dx_is_pos) { - SkASSERT(0 == count || fx >= p1); + fx = SkTMax(fx, p1); } else { - SkASSERT(0 == count || fx <= p0); + fx = SkTMin(fx, p0); } ramp<apply_alpha>(dstC, n, c, dc, dither0, dither1); @@ -683,6 +683,9 @@ void SkLinearGradient::LinearGradientContext::shade4_dx_clamp(SkPMColor dstC[], if (n & 1) { SkTSwap(dither0, dither1); } + + count -= n; + SkASSERT(count >= 0); } } diff --git a/tests/GradientTest.cpp b/tests/GradientTest.cpp index 8d73569f64..6a277d520e 100644 --- a/tests/GradientTest.cpp +++ b/tests/GradientTest.cpp @@ -212,9 +212,31 @@ static void test_nearly_vertical(skiatest::Reporter* reporter) { surface->getCanvas()->drawPaint(paint); } +// A linear gradient interval can, due to numerical imprecision (likely in the divide) +// finish an interval with the final fx not landing outside of [p0...p1]. +// The old code had an assert which this test triggered. +// We now explicitly clamp the resulting fx value. +static void test_linear_fuzz(skiatest::Reporter* reporter) { + SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(1300, 630)); + + const SkPoint pts[] = {{ 179.5f, -179.5f }, { 1074.5f, 715.5f }}; + const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE }; + const SkScalar pos[] = {0, 0.200000003f, 0.800000012f, 1 }; + + + SkAutoTUnref<SkShader> gradient( + SkGradientShader::CreateLinear(pts, colors, pos, 4, SkShader::kClamp_TileMode)); + + SkPaint paint; + paint.setShader(gradient); + SkRect r = {0, 83, 1254, 620}; + surface->getCanvas()->drawRect(r, paint); +} + DEF_TEST(Gradient, reporter) { TestGradientShaders(reporter); TestConstantGradient(reporter); test_big_grad(reporter); test_nearly_vertical(reporter); + test_linear_fuzz(reporter); } |