Extract 4f gradient interval functionality
authorFlorin Malita <fmalita@chromium.org>
Thu, 23 Mar 2017 21:04:54 +0000 (17:04 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Thu, 23 Mar 2017 23:06:07 +0000 (23:06 +0000)
... into structures usable outside Sk4fGradient classes.

Change-Id: Ifffdbe8bafa4f027f2016ce71eefede6034dd3ae
Reviewed-on: https://skia-review.googlesource.com/10060
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>

src/effects/gradients/Sk4fGradientBase.cpp
src/effects/gradients/Sk4fGradientBase.h
src/effects/gradients/Sk4fLinearGradient.cpp
src/effects/gradients/Sk4fLinearGradient.h

index e234e9b..b385d8c 100644 (file)
@@ -95,11 +95,30 @@ private:
     const int       fAdvance;
 };
 
+void addMirrorIntervals(const SkColor colors[],
+                        const SkScalar pos[], int count,
+                        const Sk4f& componentScale,
+                        bool premulColors, bool reverse,
+                        Sk4fGradientIntervalBuffer::BufferType* buffer) {
+    const IntervalIterator iter(colors, pos, count, reverse);
+    iter.iterate([&] (SkColor c0, SkColor c1, SkScalar p0, SkScalar p1) {
+        SkASSERT(buffer->empty() || buffer->back().fP1 == 2 - p0);
+
+        const auto mirror_p0 = 2 - p0;
+        const auto mirror_p1 = 2 - p1;
+        // mirror_p1 & mirror_p1 may collapse for very small values - recheck to avoid
+        // triggering Interval asserts.
+        if (mirror_p0 != mirror_p1) {
+            buffer->emplace_back(pack_color(c0, premulColors, componentScale), mirror_p0,
+                                 pack_color(c1, premulColors, componentScale), mirror_p1);
+        }
+    });
+}
+
 } // anonymous namespace
 
-SkGradientShaderBase::GradientShaderBase4fContext::
-Interval::Interval(const Sk4f& c0, SkScalar p0,
-                   const Sk4f& c1, SkScalar p1)
+Sk4fGradientInterval::Sk4fGradientInterval(const Sk4f& c0, SkScalar p0,
+                                           const Sk4f& c1, SkScalar p1)
     : fP0(p0)
     , fP1(p1)
     , fZeroRamp((c0 == c1).allTrue()) {
@@ -117,39 +136,9 @@ Interval::Interval(const Sk4f& c0, SkScalar p0,
     dc.store(&fDc.fVec);
 }
 
-SkGradientShaderBase::
-GradientShaderBase4fContext::GradientShaderBase4fContext(const SkGradientShaderBase& shader,
-                                                         const ContextRec& rec)
-    : INHERITED(shader, rec)
-    , fFlags(this->INHERITED::getFlags())
-#ifdef SK_SUPPORT_LEGACY_GRADIENT_DITHERING
-    , fDither(true)
-#else
-    , fDither(rec.fPaint->isDither())
-#endif
-{
-    const SkMatrix& inverse = this->getTotalInverse();
-    fDstToPos.setConcat(shader.fPtsToUnit, inverse);
-    fDstToPosProc = fDstToPos.getMapXYProc();
-    fDstToPosClass = static_cast<uint8_t>(INHERITED::ComputeMatrixClass(fDstToPos));
-
-    if (shader.fColorsAreOpaque && this->getPaintAlpha() == SK_AlphaOPAQUE) {
-        fFlags |= kOpaqueAlpha_Flag;
-    }
-
-    fColorsArePremul =
-        (shader.fGradFlags & SkGradientShader::kInterpolateColorsInPremul_Flag)
-        || shader.fColorsAreOpaque;
-}
-
-bool SkGradientShaderBase::
-GradientShaderBase4fContext::isValid() const {
-    return fDstToPos.isFinite();
-}
-
-void SkGradientShaderBase::
-GradientShaderBase4fContext::buildIntervals(const SkGradientShaderBase& shader,
-                                            const ContextRec& rec, bool reverse) {
+void Sk4fGradientIntervalBuffer::init(const SkColor colors[], const SkScalar pos[], int count,
+                                      SkShader::TileMode tileMode, bool premulColors,
+                                      SkScalar alpha, bool reverse) {
     // The main job here is to build a specialized interval list: a different
     // representation of the color stops data, optimized for efficient scan line
     // access during shading.
@@ -191,77 +180,131 @@ GradientShaderBase4fContext::buildIntervals(const SkGradientShaderBase& shader,
     //
     // TODO: investigate collapsing intervals << 1px.
 
-    SkASSERT(shader.fColorCount > 0);
-    SkASSERT(shader.fOrigColors);
+    SkASSERT(count > 0);
+    SkASSERT(colors);
 
-    const float paintAlpha = rec.fPaint->getAlpha() * (1.0f / 255);
-    const Sk4f componentScale = fColorsArePremul
-        ? Sk4f(paintAlpha)
-        : Sk4f(1.0f, 1.0f, 1.0f, paintAlpha);
-    const int first_index = reverse ? shader.fColorCount - 1 : 0;
-    const int last_index = shader.fColorCount - 1 - first_index;
+    fIntervals.reset();
+
+    const Sk4f componentScale = premulColors
+        ? Sk4f(alpha)
+        : Sk4f(1.0f, 1.0f, 1.0f, alpha);
+    const int first_index = reverse ? count - 1 : 0;
+    const int last_index = count - 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) {
+    if (tileMode == SkShader::kClamp_TileMode) {
         // synthetic edge interval: -/+inf .. P0
-        const Sk4f clamp_color = pack_color(shader.fOrigColors[first_index],
-                                            fColorsArePremul, componentScale);
+        const Sk4f clamp_color = pack_color(colors[first_index],
+                                            premulColors, componentScale);
         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) {
+    } else if (tileMode == SkShader::kMirror_TileMode && reverse) {
         // synthetic mirror intervals injected before main intervals: (2 .. 1]
-        addMirrorIntervals(shader, componentScale, false);
+        addMirrorIntervals(colors, pos, count, componentScale, premulColors, false, &fIntervals);
     }
 
-    const IntervalIterator iter(shader.fOrigColors,
-                                shader.fOrigPos,
-                                shader.fColorCount,
-                                reverse);
-    iter.iterate([this, &componentScale] (SkColor c0, SkColor c1, SkScalar p0, SkScalar p1) {
+    const IntervalIterator iter(colors, pos, count, reverse);
+    iter.iterate([&] (SkColor c0, SkColor c1, SkScalar p0, SkScalar p1) {
         SkASSERT(fIntervals.empty() || fIntervals.back().fP1 == p0);
 
-        fIntervals.emplace_back(pack_color(c0, fColorsArePremul, componentScale),
-                                p0,
-                                pack_color(c1, fColorsArePremul, componentScale),
-                                p1);
+        fIntervals.emplace_back(pack_color(c0, premulColors, componentScale), p0,
+                                pack_color(c1, premulColors, componentScale), p1);
     });
 
-    if (shader.fTileMode == SkShader::kClamp_TileMode) {
+    if (tileMode == SkShader::kClamp_TileMode) {
         // synthetic edge interval: Pn .. +/-inf
-        const Sk4f clamp_color = pack_color(shader.fOrigColors[last_index],
-                                            fColorsArePremul, componentScale);
+        const Sk4f clamp_color = pack_color(colors[last_index], premulColors, componentScale);
         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) {
+    } else if (tileMode == SkShader::kMirror_TileMode && !reverse) {
         // synthetic mirror intervals injected after main intervals: [1 .. 2)
-        addMirrorIntervals(shader, componentScale, true);
+        addMirrorIntervals(colors, pos, count, componentScale, premulColors, true, &fIntervals);
     }
 }
 
-void SkGradientShaderBase::
-GradientShaderBase4fContext::addMirrorIntervals(const SkGradientShaderBase& shader,
-                                            const Sk4f& componentScale, bool reverse) {
-    const IntervalIterator iter(shader.fOrigColors,
-                                shader.fOrigPos,
-                                shader.fColorCount,
-                                reverse);
-    iter.iterate([this, &componentScale] (SkColor c0, SkColor c1, SkScalar p0, SkScalar p1) {
-        SkASSERT(fIntervals.empty() || fIntervals.back().fP1 == 2 - p0);
+const Sk4fGradientInterval* Sk4fGradientIntervalBuffer::find(SkScalar t) const {
+    // Binary search.
+    const auto* i0 = fIntervals.begin();
+    const auto* i1 = fIntervals.end() - 1;
 
-        const auto mirror_p0 = 2 - p0;
-        const auto mirror_p1 = 2 - p1;
-        // mirror_p1 & mirror_p1 may collapse for very small values - recheck to avoid
-        // triggering Interval asserts.
-        if (mirror_p0 != mirror_p1) {
-            fIntervals.emplace_back(pack_color(c0, fColorsArePremul, componentScale),
-                                    mirror_p0,
-                                    pack_color(c1, fColorsArePremul, componentScale),
-                                    mirror_p1);
+    while (i0 != i1) {
+        SkASSERT(i0 < i1);
+        SkASSERT(t >= i0->fP0 && t <= i1->fP1);
+
+        const auto* i = i0 + ((i1 - i0) >> 1);
+
+        if (t > i->fP1) {
+            i0 = i + 1;
+        } else {
+            i1 = i;
         }
-    });
+    }
+
+    SkASSERT(i0->contains(t));
+    return i0;
+}
+
+const Sk4fGradientInterval* Sk4fGradientIntervalBuffer::findNext(
+    SkScalar t, const Sk4fGradientInterval* prev, bool increasing) const {
+
+    SkASSERT(!prev->contains(t));
+    SkASSERT(prev >= fIntervals.begin() && prev < fIntervals.end());
+    SkASSERT(t >= fIntervals.front().fP0 && t <= fIntervals.back().fP1);
+
+    const auto* i = prev;
+
+    // Use the |increasing| signal to figure which direction we should search for
+    // the next interval, then perform a linear search.
+    if (increasing) {
+        do {
+            i += 1;
+            if (i >= fIntervals.end()) {
+                i = fIntervals.begin();
+            }
+        } while (!i->contains(t));
+    } else {
+        do {
+            i -= 1;
+            if (i < fIntervals.begin()) {
+                i = fIntervals.end() - 1;
+            }
+        } while (!i->contains(t));
+    }
+
+    return i;
+}
+
+SkGradientShaderBase::
+GradientShaderBase4fContext::GradientShaderBase4fContext(const SkGradientShaderBase& shader,
+                                                         const ContextRec& rec)
+    : INHERITED(shader, rec)
+    , fFlags(this->INHERITED::getFlags())
+#ifdef SK_SUPPORT_LEGACY_GRADIENT_DITHERING
+    , fDither(true)
+#else
+    , fDither(rec.fPaint->isDither())
+#endif
+{
+    const SkMatrix& inverse = this->getTotalInverse();
+    fDstToPos.setConcat(shader.fPtsToUnit, inverse);
+    fDstToPosProc = fDstToPos.getMapXYProc();
+    fDstToPosClass = static_cast<uint8_t>(INHERITED::ComputeMatrixClass(fDstToPos));
+
+    if (shader.fColorsAreOpaque && this->getPaintAlpha() == SK_AlphaOPAQUE) {
+        fFlags |= kOpaqueAlpha_Flag;
+    }
+
+    fColorsArePremul =
+        (shader.fGradFlags & SkGradientShader::kInterpolateColorsInPremul_Flag)
+        || shader.fColorsAreOpaque;
+}
+
+bool SkGradientShaderBase::
+GradientShaderBase4fContext::isValid() const {
+    return fDstToPos.isFinite();
 }
 
 void SkGradientShaderBase::
@@ -335,10 +378,8 @@ template<DstType dstType, ApplyPremul premul, SkShader::TileMode tileMode>
 class SkGradientShaderBase::GradientShaderBase4fContext::TSampler {
 public:
     TSampler(const GradientShaderBase4fContext& ctx)
-        : fFirstInterval(ctx.fIntervals.begin())
-        , fLastInterval(ctx.fIntervals.end() - 1)
+        : fCtx(ctx)
         , fInterval(nullptr) {
-        SkASSERT(fLastInterval >= fFirstInterval);
         switch (tileMode) {
         case kClamp_TileMode:
             fLargestIntervalValue = SK_ScalarInfinity;
@@ -358,10 +399,10 @@ public:
         if (!fInterval) {
             // Very first sample => locate the initial interval.
             // TODO: maybe do this in ctor to remove a branch?
-            fInterval = this->findFirstInterval(tiled_t);
+            fInterval = fCtx.fIntervals.find(tiled_t);
             this->loadIntervalData(fInterval);
         } else if (!fInterval->contains(tiled_t)) {
-            fInterval = this->findNextInterval(t, tiled_t);
+            fInterval = fCtx.fIntervals.findNext(tiled_t, fInterval, t >= fPrevT);
             this->loadIntervalData(fInterval);
         }
 
@@ -395,65 +436,15 @@ private:
         return fCc + fDc * (t - fInterval->fP0);
     }
 
-    const Interval* findFirstInterval(SkScalar t) const {
-        // Binary search.
-        const Interval* i0 = fFirstInterval;
-        const Interval* i1 = fLastInterval;
-
-        while (i0 != i1) {
-            SkASSERT(i0 < i1);
-            SkASSERT(t >= i0->fP0 && t <= i1->fP1);
-
-            const Interval* i = i0 + ((i1 - i0) >> 1);
-
-            if (t > i->fP1) {
-                i0 = i + 1;
-            } else {
-                i1 = i;
-            }
-        }
-
-        SkASSERT(i0->contains(t));
-        return i0;
-    }
-
-    const Interval* findNextInterval(SkScalar t, SkScalar tiled_t) const {
-        SkASSERT(!fInterval->contains(tiled_t));
-        SkASSERT(tiled_t >= fFirstInterval->fP0 && tiled_t <= fLastInterval->fP1);
-
-        const Interval* i = fInterval;
-
-        // Use the t vs. prev_t signal to figure which direction we should search for
-        // the next interval, then perform a linear search.
-        if (t >= fPrevT) {
-            do {
-                i += 1;
-                if (i > fLastInterval) {
-                    i = fFirstInterval;
-                }
-            } while (!i->contains(tiled_t));
-        } else {
-            do {
-                i -= 1;
-                if (i < fFirstInterval) {
-                    i = fLastInterval;
-                }
-            } while (!i->contains(tiled_t));
-        }
-
-        return i;
-    }
-
-    void loadIntervalData(const Interval* i) {
+    void loadIntervalData(const Sk4fGradientInterval* i) {
         fCc = DstTraits<dstType, premul>::load(i->fC0);
         fDc = DstTraits<dstType, premul>::load(i->fDc);
     }
 
-    const Interval* fFirstInterval;
-    const Interval* fLastInterval;
-    const Interval* fInterval;
-    SkScalar        fPrevT;
-    SkScalar        fLargestIntervalValue;
-    Sk4f            fCc;
-    Sk4f            fDc;
+    const GradientShaderBase4fContext& fCtx;
+    const Sk4fGradientInterval*        fInterval;
+    SkScalar                           fPrevT;
+    SkScalar                           fLargestIntervalValue;
+    Sk4f                               fCc;
+    Sk4f                               fDc;
 };
index 6d0c3b9..2826f9e 100644 (file)
 #include "SkShader.h"
 #include "SkTArray.h"
 
+struct Sk4fGradientInterval {
+    Sk4fGradientInterval(const Sk4f& c0, SkScalar p0,
+                         const Sk4f& c1, SkScalar p1);
+
+    bool contains(SkScalar t) const {
+        // True if t is in [p0,p1].  Note: this helper assumes a
+        // natural/increasing interval - so it's not usable in Sk4fLinearGradient.
+        SkASSERT(fP0 < fP1);
+        return t >= fP0 && t <= fP1;
+    }
+
+    SkPM4f   fC0, fDc;
+    SkScalar fP0, fP1;
+    bool     fZeroRamp;
+};
+
+class Sk4fGradientIntervalBuffer {
+public:
+    void init(const SkColor colors[], const SkScalar pos[], int count,
+              SkShader::TileMode tileMode, bool premulColors, SkScalar alpha, bool reverse);
+
+    const Sk4fGradientInterval* find(SkScalar t) const;
+    const Sk4fGradientInterval* findNext(SkScalar t, const Sk4fGradientInterval* prev,
+                                         bool increasing) const;
+
+    using BufferType = SkSTArray<8, Sk4fGradientInterval, true>;
+
+    const BufferType* operator->() const { return &fIntervals; }
+
+private:
+    BufferType fIntervals;
+};
+
 class SkGradientShaderBase::
 GradientShaderBase4fContext : public SkShader::Context {
 public:
@@ -31,35 +64,15 @@ public:
     bool isValid() const;
 
 protected:
-    struct Interval {
-        Interval(const Sk4f& c0, SkScalar p0,
-                 const Sk4f& c1, SkScalar p1);
-
-        bool isZeroRamp() const { return fZeroRamp; }
-
-        bool contains(SkScalar p) const {
-            // True if p is in [p0,p1].  Note: this helper assumes a
-            // natural/increasing interval - so it's not usable in Sk4fLinearGradient.
-            SkASSERT(fP0 < fP1);
-            return p >= fP0 && p <= fP1;
-        }
-
-        SkPM4f   fC0, fDc;
-        SkScalar fP0, fP1;
-        bool     fZeroRamp;
-    };
-
     virtual void mapTs(int x, int y, SkScalar ts[], int count) const = 0;
 
-    void buildIntervals(const SkGradientShaderBase&, const ContextRec&, bool reverse);
-
-    SkSTArray<8, Interval, true> fIntervals;
-    SkMatrix                     fDstToPos;
-    SkMatrix::MapXYProc          fDstToPosProc;
-    uint8_t                      fDstToPosClass;
-    uint8_t                      fFlags;
-    bool                         fDither;
-    bool                         fColorsArePremul;
+    Sk4fGradientIntervalBuffer fIntervals;
+    SkMatrix                   fDstToPos;
+    SkMatrix::MapXYProc        fDstToPosProc;
+    uint8_t                    fDstToPosClass;
+    uint8_t                    fFlags;
+    bool                       fDither;
+    bool                       fColorsArePremul;
 
 private:
     using INHERITED = SkShader::Context;
index 354c941..1256b8f 100644 (file)
@@ -129,40 +129,41 @@ LinearGradient4fContext::LinearGradient4fContext(const SkLinearGradient& shader,
 
     // Our fast path expects interval points to be monotonically increasing in x.
     const bool reverseIntervals = this->isFast() && std::signbit(fDstToPos.getScaleX());
-    this->buildIntervals(shader, rec, reverseIntervals);
+    fIntervals.init(shader.fOrigColors, shader.fOrigPos, shader.fColorCount, shader.fTileMode,
+                    fColorsArePremul, rec.fPaint->getAlpha() * (1.0f / 255), reverseIntervals);
 
-    SkASSERT(fIntervals.count() > 0);
-    fCachedInterval = fIntervals.begin();
+    SkASSERT(fIntervals->count() > 0);
+    fCachedInterval = fIntervals->begin();
 }
 
-const SkGradientShaderBase::GradientShaderBase4fContext::Interval*
+const Sk4fGradientInterval*
 SkLinearGradient::LinearGradient4fContext::findInterval(SkScalar fx) const {
-    SkASSERT(in_range(fx, fIntervals.front().fP0, fIntervals.back().fP1));
+    SkASSERT(in_range(fx, fIntervals->front().fP0, fIntervals->back().fP1));
 
     if (1) {
         // Linear search, using the last scanline interval as a starting point.
-        SkASSERT(fCachedInterval >= fIntervals.begin());
-        SkASSERT(fCachedInterval < fIntervals.end());
+        SkASSERT(fCachedInterval >= fIntervals->begin());
+        SkASSERT(fCachedInterval < fIntervals->end());
         const int search_dir = fDstToPos.getScaleX() >= 0 ? 1 : -1;
         while (!in_range(fx, fCachedInterval->fP0, fCachedInterval->fP1)) {
             fCachedInterval += search_dir;
-            if (fCachedInterval >= fIntervals.end()) {
-                fCachedInterval = fIntervals.begin();
-            } else if (fCachedInterval < fIntervals.begin()) {
-                fCachedInterval = fIntervals.end() - 1;
+            if (fCachedInterval >= fIntervals->end()) {
+                fCachedInterval = fIntervals->begin();
+            } else if (fCachedInterval < fIntervals->begin()) {
+                fCachedInterval = fIntervals->end() - 1;
             }
         }
         return fCachedInterval;
     } else {
         // Binary search.  Seems less effective than linear + caching.
-        const Interval* i0 = fIntervals.begin();
-        const Interval* i1 = fIntervals.end() - 1;
+        const auto* i0 = fIntervals->begin();
+        const auto* i1 = fIntervals->end() - 1;
 
         while (i0 != i1) {
             SkASSERT(i0 < i1);
             SkASSERT(in_range(fx, i0->fP0, i1->fP1));
 
-            const Interval* i = i0 + ((i1 - i0) >> 1);
+            const auto* i = i0 + ((i1 - i0) >> 1);
 
             if (in_range(fx, i0->fP0, i->fP1)) {
                 i1 = i;
@@ -251,8 +252,8 @@ LinearGradient4fContext::shadeSpanInternal(int x, int y,
                   &pt);
     const SkScalar fx = pinFx<tileMode>(pt.x());
     const SkScalar dx = fDstToPos.getScaleX();
-    LinearIntervalProcessor<dstType, premul, tileMode> proc(fIntervals.begin(),
-                                                            fIntervals.end() - 1,
+    LinearIntervalProcessor<dstType, premul, tileMode> proc(fIntervals->begin(),
+                                                            fIntervals->end() - 1,
                                                             this->findInterval(fx),
                                                             fx,
                                                             dx,
@@ -289,9 +290,9 @@ template<DstType dstType, ApplyPremul premul, SkShader::TileMode tileMode>
 class SkLinearGradient::
 LinearGradient4fContext::LinearIntervalProcessor {
 public:
-    LinearIntervalProcessor(const Interval* firstInterval,
-                            const Interval* lastInterval,
-                            const Interval* i,
+    LinearIntervalProcessor(const Sk4fGradientInterval* firstInterval,
+                            const Sk4fGradientInterval* lastInterval,
+                            const Sk4fGradientInterval* i,
                             SkScalar fx,
                             SkScalar dx,
                             bool is_vertical)
@@ -349,10 +350,10 @@ public:
 
 private:
     void compute_interval_props(SkScalar t) {
-        fZeroRamp     = fIsVertical || fInterval->isZeroRamp();
+        fZeroRamp     = fIsVertical || fInterval->fZeroRamp;
         fCc           = DstTraits<dstType, premul>::load(fInterval->fC0);
 
-        if (fInterval->isZeroRamp()) {
+        if (fInterval->fZeroRamp) {
             fDcDx = 0;
         } else {
             const Sk4f dC = DstTraits<dstType, premul>::load(fInterval->fDc);
@@ -384,7 +385,7 @@ private:
         }
     }
 
-    const Interval* next_interval(const Interval* i) const {
+    const Sk4fGradientInterval* next_interval(const Sk4fGradientInterval* i) const {
         SkASSERT(i >= fFirstInterval);
         SkASSERT(i <= fLastInterval);
         i++;
@@ -419,11 +420,11 @@ private:
     SkScalar        fAdvX;      // remaining interval advance in dst
     bool            fZeroRamp;  // current interval color grad is 0
 
-    const Interval* fFirstInterval;
-    const Interval* fLastInterval;
-    const Interval* fInterval;  // current interval
-    const SkScalar  fDx;        // 'dx' for consistency with other impls; actually dt/dx
-    const bool      fIsVertical;
+    const Sk4fGradientInterval* fFirstInterval;
+    const Sk4fGradientInterval* fLastInterval;
+    const Sk4fGradientInterval* fInterval;  // current interval
+    const SkScalar              fDx;        // 'dx' for consistency with other impls; actually dt/dx
+    const bool                  fIsVertical;
 };
 
 void SkLinearGradient::
index 762b644..eebd30f 100644 (file)
@@ -38,14 +38,14 @@ private:
     void shadeSpanInternal(int x, int y, typename DstTraits<dstType, premul>::Type[],
                            int count) const;
 
-    const Interval* findInterval(SkScalar fx) const;
+    const Sk4fGradientInterval* findInterval(SkScalar fx) const;
 
     bool isFast() const { return fDstToPosClass == kLinear_MatrixClass; }
 
     static void D32_BlitBW(BlitState*, int x, int y, const SkPixmap& dst, int count);
     static void D64_BlitBW(BlitState*, int x, int y, const SkPixmap& dst, int count);
 
-    mutable const Interval*      fCachedInterval;
+    mutable const Sk4fGradientInterval* fCachedInterval;
 };
 
 #endif // Sk4fLinearGradient_DEFINED