Bug 1315848 - Skia clamped gradient fix r=mchang
authorLee Salzman <lsalzman@mozilla.com>
Mon, 21 Nov 2016 14:10:05 -0500
changeset 324734 cdff330f17a4922320f37bffb50109cbc9c0fc81
parent 324733 f0d6ed7b1ebe5564332df5d0dcec9c3438f7a4f8
child 324735 f6961e572571fa8b018fc972c34de3b0671b91f4
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersmchang
bugs1315848
milestone53.0a1
Bug 1315848 - Skia clamped gradient fix r=mchang MozReview-Commit-ID: GUHZC7VRrlC
gfx/skia/skia/src/effects/gradients/Sk4fGradientBase.cpp
gfx/skia/skia/src/effects/gradients/Sk4fLinearGradient.cpp
--- a/gfx/skia/skia/src/effects/gradients/Sk4fGradientBase.cpp
+++ b/gfx/skia/skia/src/effects/gradients/Sk4fGradientBase.cpp
@@ -122,17 +122,24 @@ private:
 SkGradientShaderBase::GradientShaderBase4fContext::
 Interval::Interval(const Sk4f& c0, SkScalar p0,
                    const Sk4f& c1, SkScalar p1)
     : fP0(p0)
     , fP1(p1)
     , 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);
 }
 
 SkGradientShaderBase::
 GradientShaderBase4fContext::GradientShaderBase4fContext(const SkGradientShaderBase& shader,
                                                          const ContextRec& rec)
@@ -218,17 +225,17 @@ GradientShaderBase4fContext::buildInterv
     const int last_index = shader.fColorCount - 1 - first_index;
     const SkScalar first_pos = reverse ? SK_Scalar1 : 0;
     const SkScalar last_pos = SK_Scalar1 - first_pos;
 
     if (shader.fTileMode == SkShader::kClamp_TileMode) {
         // 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) {
         // synthetic mirror intervals injected before main intervals: (2 .. 1]
         addMirrorIntervals(shader, componentScale, false);
     }
 
     const IntervalIterator iter(shader.fOrigColors,
@@ -243,17 +250,17 @@ GradientShaderBase4fContext::buildInterv
                                 pack_color(c1, fColorsArePremul, componentScale),
                                 p1);
     });
 
     if (shader.fTileMode == SkShader::kClamp_TileMode) {
         // 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) {
         // synthetic mirror intervals injected after main intervals: [1 .. 2)
         addMirrorIntervals(shader, componentScale, true);
     }
 }
 
--- a/gfx/skia/skia/src/effects/gradients/Sk4fLinearGradient.cpp
+++ b/gfx/skia/skia/src/effects/gradients/Sk4fLinearGradient.cpp
@@ -317,21 +317,26 @@ public:
         SkASSERT(advX < fAdvX);
 
         fCc = fCc + fDcDx * Sk4f(advX);
         fAdvX -= advX;
     }
 
 private:
     void compute_interval_props(SkScalar t) {
-        const Sk4f dC = DstTraits<dstType>::load(fInterval->fDc);
+        fZeroRamp     = fIsVertical || fInterval->isZeroRamp();
         fCc           = DstTraits<dstType>::load(fInterval->fC0);
-        fCc           = fCc + dC * Sk4f(t);
-        fDcDx         = dC * fDx;
-        fZeroRamp     = fIsVertical || fInterval->isZeroRamp();
+
+        if (fInterval->isZeroRamp()) {
+            fDcDx = 0;
+        } else {
+            const Sk4f dC = DstTraits<dstType>::load(fInterval->fDc);
+            fCc           = fCc + dC * Sk4f(t);
+            fDcDx         = dC * fDx;
+        }
     }
 
     const Interval* next_interval(const Interval* i) const {
         SkASSERT(i >= fFirstInterval);
         SkASSERT(i <= fLastInterval);
         i++;
 
         if (tileMode == kClamp_TileMode) {