From 8f457591e6a21c240fd2fca56a97281b556ce796 Mon Sep 17 00:00:00 2001 From: fmalita Date: Fri, 21 Oct 2016 06:02:22 -0700 Subject: [PATCH] [Sk4fGradient] Use infinity floats for clamp-mode extreme positions In clamp mode, we use a couple of synthetic edges that are supposed to extend to +/- infinity (-inf .. P0 and Pn .. inf). Currently we use SK_ScalarMin/Max, but these can be overrun with large/malicious inputs. Use SK_ScalarInfinity/SK_ScalarNegativeInfinity instead, and tweak compute_interval_props() to handle inf values gracefully. BUG=skia:5835 R=reed@google.com GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2441733002 Review-Url: https://chromiumcodereview.appspot.com/2441733002 --- src/effects/gradients/Sk4fGradientBase.cpp | 13 ++++++++++--- src/effects/gradients/Sk4fLinearGradient.cpp | 13 +++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/effects/gradients/Sk4fGradientBase.cpp b/src/effects/gradients/Sk4fGradientBase.cpp index 4cd213fe14..5cabab967a 100644 --- a/src/effects/gradients/Sk4fGradientBase.cpp +++ b/src/effects/gradients/Sk4fGradientBase.cpp @@ -127,7 +127,14 @@ Interval::Interval(const Sk4f& c0, SkScalar p0, , fZeroRamp((c0 == c1).allTrue()) { SkASSERT(p0 != p1); - const Sk4f dc = (c1 - c0) / (p1 - p0); + // Either p0 or p1 can be (-)inf for synthetic clamp edge intervals. + SkASSERT(SkScalarIsFinite(p0) || SkScalarIsFinite(p1)); + + const auto dp = p1 - p0; + + // Clamp edge intervals are always zero-ramp. + SkASSERT(SkScalarIsFinite(dp) || fZeroRamp); + const Sk4f dc = SkScalarIsFinite(dp) ? (c1 - c0) / dp : 0; c0.store(&fC0.fVec); dc.store(&fDc.fVec); @@ -223,7 +230,7 @@ GradientShaderBase4fContext::buildIntervals(const SkGradientShaderBase& shader, // synthetic edge interval: -/+inf .. P0 const Sk4f clamp_color = pack_color(shader.fOrigColors[first_index], fColorsArePremul, componentScale); - const SkScalar clamp_pos = reverse ? SK_ScalarMax : SK_ScalarMin; + const SkScalar clamp_pos = reverse ? SK_ScalarInfinity : SK_ScalarNegativeInfinity; fIntervals.emplace_back(clamp_color, clamp_pos, clamp_color, first_pos); } else if (shader.fTileMode == SkShader::kMirror_TileMode && reverse) { @@ -248,7 +255,7 @@ GradientShaderBase4fContext::buildIntervals(const SkGradientShaderBase& shader, // synthetic edge interval: Pn .. +/-inf const Sk4f clamp_color = pack_color(shader.fOrigColors[last_index], fColorsArePremul, componentScale); - const SkScalar clamp_pos = reverse ? SK_ScalarMin : SK_ScalarMax; + const SkScalar clamp_pos = reverse ? SK_ScalarNegativeInfinity : SK_ScalarInfinity; fIntervals.emplace_back(clamp_color, last_pos, clamp_color, clamp_pos); } else if (shader.fTileMode == SkShader::kMirror_TileMode && !reverse) { diff --git a/src/effects/gradients/Sk4fLinearGradient.cpp b/src/effects/gradients/Sk4fLinearGradient.cpp index 6d5e5dde96..ebfd13812e 100644 --- a/src/effects/gradients/Sk4fLinearGradient.cpp +++ b/src/effects/gradients/Sk4fLinearGradient.cpp @@ -322,11 +322,16 @@ public: private: void compute_interval_props(SkScalar t) { - const Sk4f dC = DstTraits::load(fInterval->fDc); - fCc = DstTraits::load(fInterval->fC0); - fCc = fCc + dC * Sk4f(t); - fDcDx = dC * fDx; fZeroRamp = fIsVertical || fInterval->isZeroRamp(); + fCc = DstTraits::load(fInterval->fC0); + + if (fInterval->isZeroRamp()) { + fDcDx = 0; + } else { + const Sk4f dC = DstTraits::load(fInterval->fDc); + fCc = fCc + dC * Sk4f(t); + fDcDx = dC * fDx; + } } const Interval* next_interval(const Interval* i) const {