Bug 1315848 - Skia clamped gradient fix r=mchang a=ritu
authorLee Salzman <lsalzman@mozilla.com>
Mon, 28 Nov 2016 14:26:59 -0500
changeset 358989 6d73e2b511eecab191cbc4f5f66248beb7706d6d
parent 358988 110c796d437215afb95f6cf3c9dbb45fb4b6f342
child 358990 772bef558e259fe6c01fef4d2fb772a83f5f053b
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmchang, ritu
bugs1315848
milestone51.0
Bug 1315848 - Skia clamped gradient fix r=mchang a=ritu
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,23 @@ Interval::Interval(SkPMColor c0, SkScala
                    const Sk4f& componentScale)
     : fP0(p0)
     , fP1(p1)
     , fZeroRamp(c0 == c1) {
     SkASSERT(p0 != p1);
 
     const Sk4f c4f0 = SkPM4f::FromPMColor(c0).to4f() * componentScale;
     const Sk4f c4f1 = SkPM4f::FromPMColor(c1).to4f() * componentScale;
-    const Sk4f dc4f = (c4f1 - c4f0) / (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 dc4f = SkScalarIsFinite(dp) ? (c4f1 - c4f0) / dp : 0;
 
     c4f0.store(&fC0.fVec);
     dc4f.store(&fDc.fVec);
 }
 
 SkGradientShaderBase::
 GradientShaderBase4fContext::GradientShaderBase4fContext(const SkGradientShaderBase& shader,
                                                          const ContextRec& rec)
@@ -218,17 +224,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 SkPMColor clamp_color = pack_color(shader.fOrigColors[first_index],
                                                  fColorsArePremul);
-        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,
                                 componentScale);
     } else if (shader.fTileMode == SkShader::kMirror_TileMode && reverse) {
         // synthetic mirror intervals injected before main intervals: (2 .. 1]
         addMirrorIntervals(shader, componentScale, false);
     }
 
@@ -245,17 +251,17 @@ GradientShaderBase4fContext::buildInterv
                                 p1,
                                 componentScale);
     });
 
     if (shader.fTileMode == SkShader::kClamp_TileMode) {
         // synthetic edge interval: Pn .. +/-inf
         const SkPMColor clamp_color =
             pack_color(shader.fOrigColors[last_index], fColorsArePremul);
-        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,
                                 componentScale);
     } 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
@@ -313,21 +313,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) {