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);
+ iter.iterate([&] (SkColor c0, SkColor c1, SkScalar t0, SkScalar t1) {
+ SkASSERT(buffer->empty() || buffer->back().fT1 == 2 - t0);
- const auto mirror_p0 = 2 - p0;
- const auto mirror_p1 = 2 - p1;
+ const auto mirror_t0 = 2 - t0;
+ const auto mirror_t1 = 2 - t1;
// 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);
+ if (mirror_t0 != mirror_t1) {
+ buffer->emplace_back(pack_color(c0, premulColors, componentScale), mirror_t0,
+ pack_color(c1, premulColors, componentScale), mirror_t1);
}
});
}
} // anonymous namespace
-Sk4fGradientInterval::Sk4fGradientInterval(const Sk4f& c0, SkScalar p0,
- const Sk4f& c1, SkScalar p1)
- : fP0(p0)
- , fP1(p1)
+Sk4fGradientInterval::Sk4fGradientInterval(const Sk4f& c0, SkScalar t0,
+ const Sk4f& c1, SkScalar t1)
+ : fT0(t0)
+ , fT1(t1)
, fZeroRamp((c0 == c1).allTrue()) {
- SkASSERT(p0 != p1);
+ SkASSERT(t0 != t1);
// Either p0 or p1 can be (-)inf for synthetic clamp edge intervals.
- SkASSERT(SkScalarIsFinite(p0) || SkScalarIsFinite(p1));
+ SkASSERT(SkScalarIsFinite(t0) || SkScalarIsFinite(t1));
- const auto dp = p1 - p0;
+ const auto dt = t1 - t0;
// Clamp edge intervals are always zero-ramp.
- SkASSERT(SkScalarIsFinite(dp) || fZeroRamp);
- const Sk4f dc = SkScalarIsFinite(dp) ? (c1 - c0) / dp : 0;
+ SkASSERT(SkScalarIsFinite(dt) || fZeroRamp);
+ SkASSERT(SkScalarIsFinite(t0) || fZeroRamp);
+ const Sk4f dc = SkScalarIsFinite(dt) ? (c1 - c0) / dt : 0;
+ const Sk4f bias = c0 - (SkScalarIsFinite(t0) ? t0 * dc : 0);
- c0.store(&fC0.fVec);
- dc.store(&fDc.fVec);
+ bias.store(&fCb.fVec);
+ dc.store(&fCg.fVec);
}
void Sk4fGradientIntervalBuffer::init(const SkColor colors[], const SkScalar pos[], int count,
}
const IntervalIterator iter(colors, pos, count, reverse);
- iter.iterate([&] (SkColor c0, SkColor c1, SkScalar p0, SkScalar p1) {
- SkASSERT(fIntervals.empty() || fIntervals.back().fP1 == p0);
+ iter.iterate([&] (SkColor c0, SkColor c1, SkScalar t0, SkScalar t1) {
+ SkASSERT(fIntervals.empty() || fIntervals.back().fT1 == t0);
- fIntervals.emplace_back(pack_color(c0, premulColors, componentScale), p0,
- pack_color(c1, premulColors, componentScale), p1);
+ fIntervals.emplace_back(pack_color(c0, premulColors, componentScale), t0,
+ pack_color(c1, premulColors, componentScale), t1);
});
if (tileMode == SkShader::kClamp_TileMode) {
while (i0 != i1) {
SkASSERT(i0 < i1);
- SkASSERT(t >= i0->fP0 && t <= i1->fP1);
+ SkASSERT(t >= i0->fT0 && t <= i1->fT1);
const auto* i = i0 + ((i1 - i0) >> 1);
- if (t > i->fP1) {
+ if (t > i->fT1) {
i0 = i + 1;
} else {
i1 = i;
SkASSERT(!prev->contains(t));
SkASSERT(prev >= fIntervals.begin() && prev < fIntervals.end());
- SkASSERT(t >= fIntervals.front().fP0 && t <= fIntervals.back().fP1);
+ SkASSERT(t >= fIntervals.front().fT0 && t <= fIntervals.back().fT1);
const auto* i = prev;
Sk4f lerp(SkScalar t) {
SkASSERT(fInterval->contains(t));
- return fCc + fDc * (t - fInterval->fP0);
+ return fCb + fCg * t;
}
void loadIntervalData(const Sk4fGradientInterval* i) {
- fCc = DstTraits<dstType, premul>::load(i->fC0);
- fDc = DstTraits<dstType, premul>::load(i->fDc);
+ fCb = DstTraits<dstType, premul>::load(i->fCb);
+ fCg = DstTraits<dstType, premul>::load(i->fCg);
}
const GradientShaderBase4fContext& fCtx;
const Sk4fGradientInterval* fInterval;
SkScalar fPrevT;
SkScalar fLargestIntervalValue;
- Sk4f fCc;
- Sk4f fDc;
+ Sk4f fCb;
+ Sk4f fCg;
};
#include "SkTArray.h"
struct Sk4fGradientInterval {
- Sk4fGradientInterval(const Sk4f& c0, SkScalar p0,
- const Sk4f& c1, SkScalar p1);
+ Sk4fGradientInterval(const Sk4f& c0, SkScalar t0,
+ const Sk4f& c1, SkScalar t1);
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;
+ SkASSERT(fT0 < fT1);
+ return t >= fT0 && t <= fT1;
}
- SkPM4f fC0, fDc;
- SkScalar fP0, fP1;
+ // Color bias and color gradient, such that for a t in this interval
+ //
+ // C = fCb + t * fCg;
+ SkPM4f fCb, fCg;
+ SkScalar fT0, fT1;
bool fZeroRamp;
};
const Sk4fGradientInterval*
SkLinearGradient::LinearGradient4fContext::findInterval(SkScalar fx) const {
- SkASSERT(in_range(fx, fIntervals->front().fP0, fIntervals->back().fP1));
+ SkASSERT(in_range(fx, fIntervals->front().fT0, fIntervals->back().fT1));
if (1) {
// Linear search, using the last scanline interval as a starting point.
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)) {
+ while (!in_range(fx, fCachedInterval->fT0, fCachedInterval->fT1)) {
fCachedInterval += search_dir;
if (fCachedInterval >= fIntervals->end()) {
fCachedInterval = fIntervals->begin();
while (i0 != i1) {
SkASSERT(i0 < i1);
- SkASSERT(in_range(fx, i0->fP0, i1->fP1));
+ SkASSERT(in_range(fx, i0->fT0, i1->fT1));
const auto* i = i0 + ((i1 - i0) >> 1);
- if (in_range(fx, i0->fP0, i->fP1)) {
+ if (in_range(fx, i0->fT0, i->fT1)) {
i1 = i;
} else {
- SkASSERT(in_range(fx, i->fP1, i1->fP1));
+ SkASSERT(in_range(fx, i->fT1, i1->fT1));
i0 = i + 1;
}
}
- SkASSERT(in_range(fx, i0->fP0, i0->fP1));
+ SkASSERT(in_range(fx, i0->fT0, i0->fT1));
return i0;
}
}
SkScalar fx,
SkScalar dx,
bool is_vertical)
- : fAdvX(is_vertical ? SK_ScalarInfinity : (i->fP1 - fx) / dx)
+ : fAdvX(is_vertical ? SK_ScalarInfinity : (i->fT1 - fx) / dx)
, fFirstInterval(firstInterval)
, fLastInterval(lastInterval)
, fInterval(i)
{
SkASSERT(fAdvX >= 0);
SkASSERT(firstInterval <= lastInterval);
- SkASSERT(in_range(fx, i->fP0, i->fP1));
if (tileMode != kClamp_TileMode && !is_vertical) {
- const auto spanX = (lastInterval->fP1 - firstInterval->fP0) / dx;
+ const auto spanX = (lastInterval->fT1 - firstInterval->fT0) / dx;
SkASSERT(spanX >= 0);
// If we're in a repeating tile mode and the whole gradient is compressed into a
}
}
- this->compute_interval_props(fx - i->fP0);
+ this->compute_interval_props(fx);
}
SkScalar currentAdvance() const {
SkASSERT(fAdvX >= 0);
- SkASSERT(fAdvX <= (fInterval->fP1 - fInterval->fP0) / fDx || !std::isfinite(fAdvX));
+ SkASSERT(fAdvX <= (fInterval->fT1 - fInterval->fT0) / fDx || !std::isfinite(fAdvX));
return fAdvX;
}
private:
void compute_interval_props(SkScalar t) {
+ SkASSERT(in_range(t, fInterval->fT0, fInterval->fT1));
+
fZeroRamp = fIsVertical || fInterval->fZeroRamp;
- fCc = DstTraits<dstType, premul>::load(fInterval->fC0);
+ fCc = DstTraits<dstType, premul>::load(fInterval->fCb);
if (fInterval->fZeroRamp) {
fDcDx = 0;
} else {
- const Sk4f dC = DstTraits<dstType, premul>::load(fInterval->fDc);
+ const Sk4f dC = DstTraits<dstType, premul>::load(fInterval->fCg);
fCc = fCc + dC * Sk4f(t);
fDcDx = dC * fDx;
}
for (const auto* i = fFirstInterval; i <= fLastInterval; ++i) {
// Each interval contributes its average color to the total/weighted average:
//
- // C = (c0 + c1) / 2 = (c0 + c0 + dc * (p1 - p0)) / 2
+ // C = (c0 + c1) / 2 = (Cb + Cg * t0 + Cb + Cg * t1) / 2 = Cb + Cg *(t0 + t1) / 2
//
- // Avg += C * (p1 - p0)
+ // Avg += C * (t1 - t0)
//
- const auto dp = i->fP1 - i->fP0;
- auto c = DstTraits<dstType, premul>::load(i->fC0);
+ auto c = DstTraits<dstType, premul>::load(i->fCb);
if (!i->fZeroRamp) {
- c = c + DstTraits<dstType, premul>::load(i->fDc) * dp * 0.5f;
+ c = c + DstTraits<dstType, premul>::load(i->fCg) * (i->fT0 + i->fT1) * 0.5f;
}
- fCc = fCc + c * dp;
+ fCc = fCc + c * (i->fT1 - i->fT0);
}
}
do {
advX -= fAdvX;
fInterval = this->next_interval(fInterval);
- fAdvX = (fInterval->fP1 - fInterval->fP0) / fDx;
+ fAdvX = (fInterval->fT1 - fInterval->fT0) / fDx;
SkASSERT(fAdvX > 0);
} while (advX >= fAdvX);
- compute_interval_props(0);
+ compute_interval_props(fInterval->fT0);
SkASSERT(advX >= 0);
return advX;