Remove SkPM4f

Bug: skia:
Change-Id: If5ed79680f215ac5087469b4c04942885bdb5fd0
Reviewed-on: https://skia-review.googlesource.com/c/159322
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2018-10-03 15:42:47 -04:00 committed by Skia Commit-Bot
parent 712476ecdb
commit 781e35071d
16 changed files with 101 additions and 145 deletions

View File

@ -228,8 +228,6 @@ SK_API SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
*/ */
SK_API SkPMColor SkPreMultiplyColor(SkColor c); SK_API SkPMColor SkPreMultiplyColor(SkColor c);
struct SkPM4f;
template <SkAlphaType kAT> template <SkAlphaType kAT>
struct SkRGBA4f { struct SkRGBA4f {
float fR; float fR;
@ -271,6 +269,8 @@ struct SkRGBA4f {
static SkRGBA4f FromColor(SkColor); // impl. depends on kAT static SkRGBA4f FromColor(SkColor); // impl. depends on kAT
SkColor toSkColor() const; // impl. depends on kAT SkColor toSkColor() const; // impl. depends on kAT
static SkRGBA4f FromPMColor(SkPMColor); // impl. depends on kAT
SkRGBA4f<kPremul_SkAlphaType> premul() const { SkRGBA4f<kPremul_SkAlphaType> premul() const {
static_assert(kAT == kUnpremul_SkAlphaType, ""); static_assert(kAT == kUnpremul_SkAlphaType, "");
return { fR * fA, fG * fA, fB * fA, fA }; return { fR * fA, fG * fA, fB * fA, fA };
@ -286,9 +286,6 @@ struct SkRGBA4f {
return { fR * invAlpha, fG * invAlpha, fB * invAlpha, fA }; return { fR * invAlpha, fG * invAlpha, fB * invAlpha, fA };
} }
} }
// TODO: remove?
SkPM4f toPM4f() const; // impl. depends on kAT
}; };
using SkColor4f = SkRGBA4f<kUnpremul_SkAlphaType>; using SkColor4f = SkRGBA4f<kUnpremul_SkAlphaType>;

View File

@ -105,25 +105,8 @@ SkColor SkHSVToColor(U8CPU a, const SkScalar hsv[3]) {
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
#include "SkHalf.h"
#include "SkPM4f.h" #include "SkPM4f.h"
SkPM4f SkPM4f::FromPMColor(SkPMColor c) {
return From4f(swizzle_rb_if_bgra(Sk4f_fromL32(c)));
}
SkColor4f SkPM4f::unpremul() const {
float alpha = fVec[A];
if (0 == alpha) {
return { 0, 0, 0, 0 };
} else {
float invAlpha = 1 / alpha;
return { fVec[R] * invAlpha, fVec[G] * invAlpha, fVec[B] * invAlpha, alpha };
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
template <> template <>
SkColor4f SkColor4f::FromColor(SkColor bgra) { SkColor4f SkColor4f::FromColor(SkColor bgra) {
SkColor4f rgba; SkColor4f rgba;
@ -136,15 +119,16 @@ SkColor SkColor4f::toSkColor() const {
return Sk4f_toL32(swizzle_rb(Sk4f::Load(this->vec()))); return Sk4f_toL32(swizzle_rb(Sk4f::Load(this->vec())));
} }
template <>
SkPMColor4f SkPMColor4f::FromPMColor(SkPMColor c) {
SkPMColor4f color;
swizzle_rb_if_bgra(Sk4f_fromL32(c)).store(&color);
return color;
}
template <> template <>
SkColor4f SkColor4f::Pin(float r, float g, float b, float a) { SkColor4f SkColor4f::Pin(float r, float g, float b, float a) {
SkColor4f c4; SkColor4f c4;
Sk4f::Min(Sk4f::Max(Sk4f(r, g, b, a), Sk4f(0)), Sk4f(1)).store(c4.vec()); Sk4f::Min(Sk4f::Max(Sk4f(r, g, b, a), Sk4f(0)), Sk4f(1)).store(c4.vec());
return c4; return c4;
} }
template <>
SkPM4f SkColor4f::toPM4f() const {
auto rgba = Sk4f::Load(this->vec());
return SkPM4f::From4f(rgba * Sk4f(rgba[3], rgba[3], rgba[3], 1));
}

View File

@ -94,7 +94,7 @@ SkColor4f SkColorFilter::filterColor4f(const SkColor4f& c, SkColorSpace* colorSp
class SkComposeColorFilter : public SkColorFilter { class SkComposeColorFilter : public SkColorFilter {
public: public:
uint32_t getFlags() const override { uint32_t getFlags() const override {
// Can only claim alphaunchanged and SkPM4f support if both our proxys do. // Can only claim alphaunchanged support if both our proxys do.
return fOuter->getFlags() & fInner->getFlags(); return fOuter->getFlags() & fInner->getFlags();
} }

View File

@ -44,33 +44,6 @@ static inline uint32_t Sk4f_toL32(const Sk4f& px) {
return l32; return l32;
} }
/*
* The float values are 0...1 premultiplied in RGBA order (regardless of SkPMColor order)
*/
struct SK_API SkPM4f {
enum {
R, G, B, A,
};
float fVec[4];
float r() const { return fVec[R]; }
float g() const { return fVec[G]; }
float b() const { return fVec[B]; }
float a() const { return fVec[A]; }
static SkPM4f From4f(const Sk4f& x) {
SkPM4f pm;
x.store(pm.fVec);
return pm;
}
static SkPM4f FromPMColor(SkPMColor);
Sk4f to4f() const { return Sk4f::Load(fVec); }
Sk4f to4f_pmorder() const { return swizzle_rb_if_bgra(this->to4f()); }
SkColor4f unpremul() const;
};
using SkPMColor4f = SkRGBA4f<kPremul_SkAlphaType>; using SkPMColor4f = SkRGBA4f<kPremul_SkAlphaType>;
#endif #endif

View File

@ -81,7 +81,7 @@ private:
float fCurrentCoverage = 0.0f; float fCurrentCoverage = 0.0f;
float fDitherRate = 0.0f; float fDitherRate = 0.0f;
std::vector<SkPM4f> fShaderBuffer; std::vector<SkPMColor4f> fShaderBuffer;
typedef SkBlitter INHERITED; typedef SkBlitter INHERITED;
}; };

View File

@ -54,13 +54,13 @@ void SkOverdrawColorFilter::onAppendStages(SkRasterPipeline* p,
ctx->colors = fColors; ctx->colors = fColors;
ctx->fn = [](SkJumper_CallbackCtx* arg, int active_pixels) { ctx->fn = [](SkJumper_CallbackCtx* arg, int active_pixels) {
auto ctx = (Ctx*)arg; auto ctx = (Ctx*)arg;
auto pixels = (SkPM4f*)ctx->rgba; auto pixels = (SkPMColor4f*)ctx->rgba;
for (int i = 0; i < active_pixels; i++) { for (int i = 0; i < active_pixels; i++) {
uint8_t alpha = (int)(pixels[i].a() * 255); uint8_t alpha = (int)(pixels[i].fA * 255);
if (alpha >= kNumColors) { if (alpha >= kNumColors) {
alpha = kNumColors - 1; alpha = kNumColors - 1;
} }
pixels[i] = SkPM4f::FromPMColor(ctx->colors[alpha]); pixels[i] = SkPMColor4f::FromPMColor(ctx->colors[alpha]);
} }
}; };
p->append(SkRasterPipeline::callback, ctx); p->append(SkRasterPipeline::callback, ctx);

View File

@ -56,7 +56,7 @@ SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shade
SkColor4f c4 = SkColor4f::FromColor(shader.fColor); SkColor4f c4 = SkColor4f::FromColor(shader.fColor);
c4.fA *= rec.fPaint->getAlpha() / 255.0f; c4.fA *= rec.fPaint->getAlpha() / 255.0f;
fPM4f = c4.toPM4f(); fPMColor4f = c4.premul();
fFlags = kConstInY32_Flag; fFlags = kConstInY32_Flag;
if (255 == a) { if (255 == a) {
@ -68,9 +68,9 @@ void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[]
sk_memset32(span, fPMColor, count); sk_memset32(span, fPMColor, count);
} }
void SkColorShader::ColorShaderContext::shadeSpan4f(int x, int y, SkPM4f span[], int count) { void SkColorShader::ColorShaderContext::shadeSpan4f(int x, int y, SkPMColor4f span[], int count) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
span[i] = fPM4f; span[i] = fPMColor4f;
} }
} }
@ -171,7 +171,7 @@ SkColor4Shader::Color4Context::Color4Context(const SkColor4Shader& shader,
SkColor4f c4 = shader.fColor4; SkColor4f c4 = shader.fColor4;
c4.fA *= rec.fPaint->getAlpha() * (1 / 255.0f); c4.fA *= rec.fPaint->getAlpha() * (1 / 255.0f);
fPM4f = c4.toPM4f(); fPMColor4f = c4.premul();
fFlags = kConstInY32_Flag; fFlags = kConstInY32_Flag;
if (255 == a) { if (255 == a) {
@ -183,9 +183,9 @@ void SkColor4Shader::Color4Context::shadeSpan(int x, int y, SkPMColor span[], in
sk_memset32(span, fPMColor, count); sk_memset32(span, fPMColor, count);
} }
void SkColor4Shader::Color4Context::shadeSpan4f(int x, int y, SkPM4f span[], int count) { void SkColor4Shader::Color4Context::shadeSpan4f(int x, int y, SkPMColor4f span[], int count) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
span[i] = fPM4f; span[i] = fPMColor4f;
} }
} }

View File

@ -34,10 +34,10 @@ public:
uint32_t getFlags() const override; uint32_t getFlags() const override;
void shadeSpan(int x, int y, SkPMColor span[], int count) override; void shadeSpan(int x, int y, SkPMColor span[], int count) override;
void shadeSpan4f(int x, int y, SkPM4f[], int count) override; void shadeSpan4f(int x, int y, SkPMColor4f[], int count) override;
private: private:
SkPM4f fPM4f; SkPMColor4f fPMColor4f;
SkPMColor fPMColor; SkPMColor fPMColor;
uint32_t fFlags; uint32_t fFlags;
@ -89,10 +89,10 @@ public:
uint32_t getFlags() const override; uint32_t getFlags() const override;
void shadeSpan(int x, int y, SkPMColor span[], int count) override; void shadeSpan(int x, int y, SkPMColor span[], int count) override;
void shadeSpan4f(int x, int y, SkPM4f[], int count) override; void shadeSpan4f(int x, int y, SkPMColor4f[], int count) override;
private: private:
SkPM4f fPM4f; SkPMColor4f fPMColor4f;
SkPMColor fPMColor; SkPMColor fPMColor;
uint32_t fFlags; uint32_t fFlags;

View File

@ -142,14 +142,14 @@ SkShaderBase::Context::Context(const SkShaderBase& shader, const ContextRec& rec
SkShaderBase::Context::~Context() {} SkShaderBase::Context::~Context() {}
void SkShaderBase::Context::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { void SkShaderBase::Context::shadeSpan4f(int x, int y, SkPMColor4f dst[], int count) {
const int N = 128; const int N = 128;
SkPMColor tmp[N]; SkPMColor tmp[N];
while (count > 0) { while (count > 0) {
int n = SkTMin(count, N); int n = SkTMin(count, N);
this->shadeSpan(x, y, tmp, n); this->shadeSpan(x, y, tmp, n);
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
dst[i] = SkPM4f::FromPMColor(tmp[i]); dst[i] = SkPMColor4f::FromPMColor(tmp[i]);
} }
dst += n; dst += n;
x += n; x += n;
@ -232,7 +232,7 @@ bool SkShaderBase::onAppendStages(const StageRec& rec) const {
auto c = (CallbackCtx*)self; auto c = (CallbackCtx*)self;
int x = (int)c->rgba[0], int x = (int)c->rgba[0],
y = (int)c->rgba[1]; y = (int)c->rgba[1];
c->ctx->shadeSpan4f(x,y, (SkPM4f*)c->rgba, active_pixels); c->ctx->shadeSpan4f(x,y, (SkPMColor4f*)c->rgba, active_pixels);
}; };
if (cb->ctx) { if (cb->ctx) {

View File

@ -13,6 +13,7 @@
#include "SkMask.h" #include "SkMask.h"
#include "SkMatrix.h" #include "SkMatrix.h"
#include "SkNoncopyable.h" #include "SkNoncopyable.h"
#include "SkPM4f.h"
#include "SkShader.h" #include "SkShader.h"
#include "SkTLazy.h" #include "SkTLazy.h"
@ -98,7 +99,7 @@ public:
*/ */
virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0; virtual void shadeSpan(int x, int y, SkPMColor[], int count) = 0;
virtual void shadeSpan4f(int x, int y, SkPM4f[], int count); virtual void shadeSpan4f(int x, int y, SkPMColor4f[], int count);
// Notification from blitter::blitMask in case we need to see the non-alpha channels // Notification from blitter::blitMask in case we need to see the non-alpha channels
virtual void set3DMask(const SkMask*) {} virtual void set3DMask(const SkMask*) {}

View File

@ -13,8 +13,8 @@ namespace {
Sk4f pack_color(const SkColor4f& c4f, bool premul, const Sk4f& component_scale) { Sk4f pack_color(const SkColor4f& c4f, bool premul, const Sk4f& component_scale) {
Sk4f pm4f = premul Sk4f pm4f = premul
? c4f.toPM4f().to4f() ? Sk4f::Load(c4f.premul().vec())
: Sk4f{c4f.fR, c4f.fG, c4f.fB, c4f.fA}; : Sk4f::Load(c4f.vec());
if (premul) { if (premul) {
// If the stops are premul, we clamp them to gamut now. // If the stops are premul, we clamp them to gamut now.
@ -133,8 +133,8 @@ Sk4fGradientInterval::Sk4fGradientInterval(const Sk4f& c0, SkScalar t0,
const Sk4f dc = SkScalarIsFinite(dt) ? (c1 - c0) / dt : 0; const Sk4f dc = SkScalarIsFinite(dt) ? (c1 - c0) / dt : 0;
const Sk4f bias = c0 - (SkScalarIsFinite(t0) ? t0 * dc : 0); const Sk4f bias = c0 - (SkScalarIsFinite(t0) ? t0 * dc : 0);
bias.store(&fCb.fVec); bias.store(fCb.vec());
dc.store(&fCg.fVec); dc.store(fCg.vec());
} }
void Sk4fGradientIntervalBuffer::init(const SkGradientShaderBase& shader, SkColorSpace* dstCS, void Sk4fGradientIntervalBuffer::init(const SkGradientShaderBase& shader, SkColorSpace* dstCS,
@ -156,7 +156,7 @@ void Sk4fGradientIntervalBuffer::init(const SkGradientShaderBase& shader, SkColo
// this stage: // this stage:
// //
// 1) scale the color components depending on paint alpha and the requested // 1) scale the color components depending on paint alpha and the requested
// interpolation space (note: the interval color storage is SkPM4f, but // interpolation space (note: the interval color storage is SkPMColor4f, but
// that doesn't necessarily mean the colors are premultiplied; that // that doesn't necessarily mean the colors are premultiplied; that
// property is tracked in fColorsArePremul) // property is tracked in fColorsArePremul)
// //

View File

@ -31,8 +31,8 @@ struct Sk4fGradientInterval {
// Color bias and color gradient, such that for a t in this interval // Color bias and color gradient, such that for a t in this interval
// //
// C = fCb + t * fCg; // C = fCb + t * fCg;
SkPM4f fCb, fCg; SkPMColor4f fCb, fCg;
SkScalar fT0, fT1; SkScalar fT0, fT1;
}; };
class Sk4fGradientIntervalBuffer { class Sk4fGradientIntervalBuffer {

View File

@ -32,7 +32,7 @@ struct PremulTraits<ApplyPremul::False> {
template <> template <>
struct PremulTraits<ApplyPremul::True> { struct PremulTraits<ApplyPremul::True> {
static Sk4f apply(const Sk4f& c) { static Sk4f apply(const Sk4f& c) {
const float alpha = c[SkPM4f::A]; const float alpha = c[3];
// FIXME: portable swizzle? // FIXME: portable swizzle?
return c * Sk4f(alpha, alpha, alpha, 1); return c * Sk4f(alpha, alpha, alpha, 1);
} }
@ -40,7 +40,7 @@ struct PremulTraits<ApplyPremul::True> {
// Struct encapsulating various dest-dependent ops: // Struct encapsulating various dest-dependent ops:
// //
// - load() Load a SkPM4f value into Sk4f. Normally called once per interval // - load() Load a SkPMColor4f value into Sk4f. Normally called once per interval
// advance. Also applies a scale and swizzle suitable for DstType. // advance. Also applies a scale and swizzle suitable for DstType.
// //
// - store() Store one Sk4f to dest. Optionally handles premul, color space // - store() Store one Sk4f to dest. Optionally handles premul, color space
@ -58,10 +58,11 @@ struct DstTraits<SkPMColor, premul> {
using PM = PremulTraits<premul>; using PM = PremulTraits<premul>;
// For L32, prescaling by 255 saves a per-pixel multiplication when premul is not needed. // For L32, prescaling by 255 saves a per-pixel multiplication when premul is not needed.
static Sk4f load(const SkPM4f& c) { static Sk4f load(const SkPMColor4f& c) {
Sk4f c4f = swizzle_rb_if_bgra(Sk4f::Load(c.vec()));
return premul == ApplyPremul::False return premul == ApplyPremul::False
? c.to4f_pmorder() * Sk4f(255) ? c4f * Sk4f(255)
: c.to4f_pmorder(); : c4f;
} }
static void store(const Sk4f& c, SkPMColor* dst, const Sk4f& bias) { static void store(const Sk4f& c, SkPMColor* dst, const Sk4f& bias) {
@ -102,27 +103,27 @@ struct DstTraits<SkPMColor, premul> {
}; };
template <ApplyPremul premul> template <ApplyPremul premul>
struct DstTraits<SkPM4f, premul> { struct DstTraits<SkPMColor4f, premul> {
using PM = PremulTraits<premul>; using PM = PremulTraits<premul>;
static Sk4f load(const SkPM4f& c) { static Sk4f load(const SkPMColor4f& c) {
return c.to4f(); return Sk4f::Load(c.vec());
} }
static void store(const Sk4f& c, SkPM4f* dst, const Sk4f& /*bias*/) { static void store(const Sk4f& c, SkPMColor4f* dst, const Sk4f& /*bias*/) {
PM::apply(c).store(dst->fVec); PM::apply(c).store(dst->vec());
} }
static void store(const Sk4f& c, SkPM4f* dst, int n) { static void store(const Sk4f& c, SkPMColor4f* dst, int n) {
const Sk4f pmc = PM::apply(c); const Sk4f pmc = PM::apply(c);
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
pmc.store(dst[i].fVec); pmc.store(dst[i].vec());
} }
} }
static void store4x(const Sk4f& c0, const Sk4f& c1, static void store4x(const Sk4f& c0, const Sk4f& c1,
const Sk4f& c2, const Sk4f& c3, const Sk4f& c2, const Sk4f& c3,
SkPM4f* dst, SkPMColor4f* dst,
const Sk4f& bias0, const Sk4f& bias1) { const Sk4f& bias0, const Sk4f& bias1) {
store(c0, dst + 0, bias0); store(c0, dst + 0, bias0);
store(c1, dst + 1, bias1); store(c1, dst + 1, bias1);

View File

@ -185,16 +185,16 @@ LinearGradient4fContext::shadeSpan(int x, int y, SkPMColor dst[], int count) {
} }
void SkLinearGradient:: void SkLinearGradient::
LinearGradient4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { LinearGradient4fContext::shadeSpan4f(int x, int y, SkPMColor4f dst[], int count) {
SkASSERT(count > 0); SkASSERT(count > 0);
// 4f dests are dithered at a later stage, if needed. // 4f dests are dithered at a later stage, if needed.
static constexpr float bias0 = 0, static constexpr float bias0 = 0,
bias1 = 0; bias1 = 0;
if (fColorsArePremul) { if (fColorsArePremul) {
this->shadePremulSpan<SkPM4f, ApplyPremul::False>(x, y, dst, count, bias0, bias1); this->shadePremulSpan<SkPMColor4f, ApplyPremul::False>(x, y, dst, count, bias0, bias1);
} else { } else {
this->shadePremulSpan<SkPM4f, ApplyPremul::True >(x, y, dst, count, bias0, bias1); this->shadePremulSpan<SkPMColor4f, ApplyPremul::True >(x, y, dst, count, bias0, bias1);
} }
} }

View File

@ -17,7 +17,7 @@ public:
LinearGradient4fContext(const SkLinearGradient&, const ContextRec&); LinearGradient4fContext(const SkLinearGradient&, const ContextRec&);
void shadeSpan(int x, int y, SkPMColor dst[], int count) override; void shadeSpan(int x, int y, SkPMColor dst[], int count) override;
void shadeSpan4f(int x, int y, SkPM4f dst[], int count) override; void shadeSpan4f(int x, int y, SkPMColor4f dst[], int count) override;
private: private:
using INHERITED = GradientShaderBase4fContext; using INHERITED = GradientShaderBase4fContext;

View File

@ -217,58 +217,58 @@ void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
desc.flatten(buffer); desc.flatten(buffer);
} }
static void add_stop_color(SkJumper_GradientCtx* ctx, size_t stop, SkPM4f Fs, SkPM4f Bs) { static void add_stop_color(SkJumper_GradientCtx* ctx, size_t stop, SkPMColor4f Fs, SkPMColor4f Bs) {
(ctx->fs[0])[stop] = Fs.r(); (ctx->fs[0])[stop] = Fs.fR;
(ctx->fs[1])[stop] = Fs.g(); (ctx->fs[1])[stop] = Fs.fG;
(ctx->fs[2])[stop] = Fs.b(); (ctx->fs[2])[stop] = Fs.fB;
(ctx->fs[3])[stop] = Fs.a(); (ctx->fs[3])[stop] = Fs.fA;
(ctx->bs[0])[stop] = Bs.r(); (ctx->bs[0])[stop] = Bs.fR;
(ctx->bs[1])[stop] = Bs.g(); (ctx->bs[1])[stop] = Bs.fG;
(ctx->bs[2])[stop] = Bs.b(); (ctx->bs[2])[stop] = Bs.fB;
(ctx->bs[3])[stop] = Bs.a(); (ctx->bs[3])[stop] = Bs.fA;
} }
static void add_const_color(SkJumper_GradientCtx* ctx, size_t stop, SkPM4f color) { static void add_const_color(SkJumper_GradientCtx* ctx, size_t stop, SkPMColor4f color) {
add_stop_color(ctx, stop, {{ 0, 0, 0, 0 }}, color); add_stop_color(ctx, stop, { 0, 0, 0, 0 }, color);
} }
// Calculate a factor F and a bias B so that color = F*t + B when t is in range of // Calculate a factor F and a bias B so that color = F*t + B when t is in range of
// the stop. Assume that the distance between stops is 1/gapCount. // the stop. Assume that the distance between stops is 1/gapCount.
static void init_stop_evenly( static void init_stop_evenly(
SkJumper_GradientCtx* ctx, float gapCount, size_t stop, SkPM4f c_l, SkPM4f c_r) { SkJumper_GradientCtx* ctx, float gapCount, size_t stop, SkPMColor4f c_l, SkPMColor4f c_r) {
// Clankium's GCC 4.9 targeting ARMv7 is barfing when we use Sk4f math here, so go scalar... // Clankium's GCC 4.9 targeting ARMv7 is barfing when we use Sk4f math here, so go scalar...
SkPM4f Fs = {{ SkPMColor4f Fs = {
(c_r.r() - c_l.r()) * gapCount, (c_r.fR - c_l.fR) * gapCount,
(c_r.g() - c_l.g()) * gapCount, (c_r.fG - c_l.fG) * gapCount,
(c_r.b() - c_l.b()) * gapCount, (c_r.fB - c_l.fB) * gapCount,
(c_r.a() - c_l.a()) * gapCount, (c_r.fA - c_l.fA) * gapCount,
}}; };
SkPM4f Bs = {{ SkPMColor4f Bs = {
c_l.r() - Fs.r()*(stop/gapCount), c_l.fR - Fs.fR*(stop/gapCount),
c_l.g() - Fs.g()*(stop/gapCount), c_l.fG - Fs.fG*(stop/gapCount),
c_l.b() - Fs.b()*(stop/gapCount), c_l.fB - Fs.fB*(stop/gapCount),
c_l.a() - Fs.a()*(stop/gapCount), c_l.fA - Fs.fA*(stop/gapCount),
}}; };
add_stop_color(ctx, stop, Fs, Bs); add_stop_color(ctx, stop, Fs, Bs);
} }
// For each stop we calculate a bias B and a scale factor F, such that // For each stop we calculate a bias B and a scale factor F, such that
// for any t between stops n and n+1, the color we want is B[n] + F[n]*t. // for any t between stops n and n+1, the color we want is B[n] + F[n]*t.
static void init_stop_pos( static void init_stop_pos(
SkJumper_GradientCtx* ctx, size_t stop, float t_l, float t_r, SkPM4f c_l, SkPM4f c_r) { SkJumper_GradientCtx* ctx, size_t stop, float t_l, float t_r, SkPMColor4f c_l, SkPMColor4f c_r) {
// See note about Clankium's old compiler in init_stop_evenly(). // See note about Clankium's old compiler in init_stop_evenly().
SkPM4f Fs = {{ SkPMColor4f Fs = {
(c_r.r() - c_l.r()) / (t_r - t_l), (c_r.fR - c_l.fR) / (t_r - t_l),
(c_r.g() - c_l.g()) / (t_r - t_l), (c_r.fG - c_l.fG) / (t_r - t_l),
(c_r.b() - c_l.b()) / (t_r - t_l), (c_r.fB - c_l.fB) / (t_r - t_l),
(c_r.a() - c_l.a()) / (t_r - t_l), (c_r.fA - c_l.fA) / (t_r - t_l),
}}; };
SkPM4f Bs = {{ SkPMColor4f Bs = {
c_l.r() - Fs.r()*t_l, c_l.fR - Fs.fR*t_l,
c_l.g() - Fs.g()*t_l, c_l.fG - Fs.fG*t_l,
c_l.b() - Fs.b()*t_l, c_l.fB - Fs.fB*t_l,
c_l.a() - Fs.a()*t_l, c_l.fA - Fs.fA*t_l,
}}; };
ctx->ts[stop] = t_l; ctx->ts[stop] = t_l;
add_stop_color(ctx, stop, Fs, Bs); add_stop_color(ctx, stop, Fs, Bs);
} }
@ -317,19 +317,19 @@ bool SkGradientShaderBase::onAppendStages(const StageRec& rec) const {
auto prepareColor = [premulGrad, &xformedColors](int i) { auto prepareColor = [premulGrad, &xformedColors](int i) {
SkColor4f c = xformedColors.fColors[i]; SkColor4f c = xformedColors.fColors[i];
return premulGrad ? c.toPM4f() return premulGrad ? c.premul()
: SkPM4f::From4f(Sk4f::Load(&c)); : SkPMColor4f{ c.fR, c.fG, c.fB, c.fA };
}; };
// The two-stop case with stops at 0 and 1. // The two-stop case with stops at 0 and 1.
if (fColorCount == 2 && fOrigPos == nullptr) { if (fColorCount == 2 && fOrigPos == nullptr) {
const SkPM4f c_l = prepareColor(0), const SkPMColor4f c_l = prepareColor(0),
c_r = prepareColor(1); c_r = prepareColor(1);
// See F and B below. // See F and B below.
auto ctx = alloc->make<SkJumper_EvenlySpaced2StopGradientCtx>(); auto ctx = alloc->make<SkJumper_EvenlySpaced2StopGradientCtx>();
(c_r.to4f() - c_l.to4f()).store(ctx->f); (Sk4f::Load(c_r.vec()) - Sk4f::Load(c_l.vec())).store(ctx->f);
( c_l.to4f()).store(ctx->b); ( Sk4f::Load(c_l.vec())).store(ctx->b);
ctx->interpolatedInPremul = premulGrad; ctx->interpolatedInPremul = premulGrad;
p->append(SkRasterPipeline::evenly_spaced_2_stop_gradient, ctx); p->append(SkRasterPipeline::evenly_spaced_2_stop_gradient, ctx);
@ -351,9 +351,9 @@ bool SkGradientShaderBase::onAppendStages(const StageRec& rec) const {
size_t stopCount = fColorCount; size_t stopCount = fColorCount;
float gapCount = stopCount - 1; float gapCount = stopCount - 1;
SkPM4f c_l = prepareColor(0); SkPMColor4f c_l = prepareColor(0);
for (size_t i = 0; i < stopCount - 1; i++) { for (size_t i = 0; i < stopCount - 1; i++) {
SkPM4f c_r = prepareColor(i + 1); SkPMColor4f c_r = prepareColor(i + 1);
init_stop_evenly(ctx, gapCount, i, c_l, c_r); init_stop_evenly(ctx, gapCount, i, c_l, c_r);
c_l = c_r; c_l = c_r;
} }
@ -381,12 +381,12 @@ bool SkGradientShaderBase::onAppendStages(const StageRec& rec) const {
size_t stopCount = 0; size_t stopCount = 0;
float t_l = fOrigPos[firstStop]; float t_l = fOrigPos[firstStop];
SkPM4f c_l = prepareColor(firstStop); SkPMColor4f c_l = prepareColor(firstStop);
add_const_color(ctx, stopCount++, c_l); add_const_color(ctx, stopCount++, c_l);
// N.B. lastStop is the index of the last stop, not one after. // N.B. lastStop is the index of the last stop, not one after.
for (int i = firstStop; i < lastStop; i++) { for (int i = firstStop; i < lastStop; i++) {
float t_r = fOrigPos[i + 1]; float t_r = fOrigPos[i + 1];
SkPM4f c_r = prepareColor(i + 1); SkPMColor4f c_r = prepareColor(i + 1);
SkASSERT(t_l <= t_r); SkASSERT(t_l <= t_r);
if (t_l < t_r) { if (t_l < t_r) {
init_stop_pos(ctx, stopCount, t_l, t_r, c_l, c_r); init_stop_pos(ctx, stopCount, t_l, t_r, c_l, c_r);