remove filterSpan from SkColorFilter
Bug: skia: Change-Id: Ie8a31ea8131c08d251a825622484342e3e174474 Reviewed-on: https://skia-review.googlesource.com/21207 Commit-Queue: Mike Reed <reed@google.com> Commit-Queue: Mike Klein <mtklein@chromium.org> Reviewed-by: Mike Klein <mtklein@chromium.org> Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
185a3798db
commit
9c1d780228
@ -63,15 +63,6 @@ public:
|
||||
*/
|
||||
virtual bool asComponentTable(SkBitmap* table) const;
|
||||
|
||||
/** Called with a scanline of colors, as if there was a shader installed.
|
||||
The implementation writes out its filtered version into result[].
|
||||
Note: shader and result may be the same buffer.
|
||||
@param src array of colors, possibly generated by a shader
|
||||
@param count the number of entries in the src[] and result[] arrays
|
||||
@param result written by the filter
|
||||
*/
|
||||
virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) const = 0;
|
||||
|
||||
void appendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, bool shaderIsOpaque) const;
|
||||
|
||||
enum Flags {
|
||||
@ -93,17 +84,7 @@ public:
|
||||
*/
|
||||
virtual sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter>) const { return nullptr; }
|
||||
|
||||
/**
|
||||
* Apply this colorfilter to the specified SkColor. This routine handles
|
||||
* converting to SkPMColor, calling the filter, and then converting back
|
||||
* to SkColor. This method is not virtual, but will call filterSpan()
|
||||
* which is virtual.
|
||||
*/
|
||||
SkColor filterColor(SkColor) const;
|
||||
|
||||
/**
|
||||
* Filters a single color.
|
||||
*/
|
||||
SkColor4f filterColor4f(const SkColor4f&) const;
|
||||
|
||||
/** Create a colorfilter that uses the specified color and mode.
|
||||
|
@ -28,8 +28,6 @@ class SK_API SkLumaColorFilter : public SkColorFilter {
|
||||
public:
|
||||
static sk_sp<SkColorFilter> Make();
|
||||
|
||||
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
|
||||
#endif
|
||||
|
@ -49,9 +49,17 @@ void SkColorFilter::appendStages(SkRasterPipeline* p,
|
||||
}
|
||||
|
||||
SkColor SkColorFilter::filterColor(SkColor c) const {
|
||||
SkPMColor dst, src = SkPreMultiplyColor(c);
|
||||
this->filterSpan(&src, 1, &dst);
|
||||
return SkUnPreMultiply::PMColorToColor(dst);
|
||||
const float inv255 = 1.0f / 255;
|
||||
SkColor4f c4 = this->filterColor4f({
|
||||
SkColorGetR(c) * inv255,
|
||||
SkColorGetG(c) * inv255,
|
||||
SkColorGetB(c) * inv255,
|
||||
SkColorGetA(c) * inv255,
|
||||
});
|
||||
return SkColorSetARGB(sk_float_round2int(c4.fA*255),
|
||||
sk_float_round2int(c4.fR*255),
|
||||
sk_float_round2int(c4.fG*255),
|
||||
sk_float_round2int(c4.fB*255));
|
||||
}
|
||||
|
||||
#include "SkRasterPipeline.h"
|
||||
@ -89,11 +97,6 @@ public:
|
||||
return fOuter->getFlags() & fInner->getFlags();
|
||||
}
|
||||
|
||||
void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
|
||||
fInner->filterSpan(shader, count, result);
|
||||
fOuter->filterSpan(result, count, result);
|
||||
}
|
||||
|
||||
#ifndef SK_IGNORE_TO_STRING
|
||||
void toString(SkString* str) const override {
|
||||
SkString outerS, innerS;
|
||||
|
@ -62,81 +62,6 @@ uint32_t SkColorMatrixFilterRowMajor255::getFlags() const {
|
||||
return this->INHERITED::getFlags() | fFlags;
|
||||
}
|
||||
|
||||
static Sk4f scale_rgb(float scale) {
|
||||
static_assert(SkPM4f::A == 3, "Alpha is lane 3");
|
||||
return Sk4f(scale, scale, scale, 1);
|
||||
}
|
||||
|
||||
static Sk4f premul(const Sk4f& x) {
|
||||
return x * scale_rgb(x[SkPM4f::A]);
|
||||
}
|
||||
|
||||
static Sk4f unpremul(const Sk4f& x) {
|
||||
return x * scale_rgb(1 / x[SkPM4f::A]); // TODO: fast/approx invert?
|
||||
}
|
||||
|
||||
static Sk4f clamp_0_1(const Sk4f& x) {
|
||||
return Sk4f::Max(Sk4f::Min(x, Sk4f(1)), Sk4f(0));
|
||||
}
|
||||
|
||||
static SkPMColor round(const Sk4f& x) {
|
||||
SkPMColor c;
|
||||
SkNx_cast<uint8_t>(x * Sk4f(255) + Sk4f(0.5f)).store(&c);
|
||||
return c;
|
||||
}
|
||||
|
||||
template <typename Adaptor, typename T>
|
||||
void filter_span(const float array[], const T src[], int count, T dst[]) {
|
||||
const Sk4f c0 = Sk4f::Load(array + 0);
|
||||
const Sk4f c1 = Sk4f::Load(array + 4);
|
||||
const Sk4f c2 = Sk4f::Load(array + 8);
|
||||
const Sk4f c3 = Sk4f::Load(array + 12);
|
||||
const Sk4f c4 = Sk4f::Load(array + 16);
|
||||
|
||||
// todo: we could cache this in the constructor...
|
||||
T matrix_translate_pmcolor = Adaptor::From4f(premul(clamp_0_1(c4)));
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
Sk4f srcf = Adaptor::To4f(src[i]);
|
||||
float srcA = srcf[SkPM4f::A];
|
||||
|
||||
if (0 == srcA) {
|
||||
dst[i] = matrix_translate_pmcolor;
|
||||
continue;
|
||||
}
|
||||
if (1 != srcA) {
|
||||
srcf = unpremul(srcf);
|
||||
}
|
||||
|
||||
Sk4f r4 = srcf[Adaptor::R];
|
||||
Sk4f g4 = srcf[Adaptor::G];
|
||||
Sk4f b4 = srcf[Adaptor::B];
|
||||
Sk4f a4 = srcf[Adaptor::A];
|
||||
// apply matrix
|
||||
Sk4f dst4 = c0 * r4 + c1 * g4 + c2 * b4 + c3 * a4 + c4;
|
||||
|
||||
dst[i] = Adaptor::From4f(premul(clamp_0_1(dst4)));
|
||||
}
|
||||
}
|
||||
|
||||
struct SkPMColorAdaptor {
|
||||
enum {
|
||||
R = SK_R_INDEX,
|
||||
G = SK_G_INDEX,
|
||||
B = SK_B_INDEX,
|
||||
A = SK_A_INDEX,
|
||||
};
|
||||
static SkPMColor From4f(const Sk4f& c4) {
|
||||
return round(swizzle_rb_if_bgra(c4));
|
||||
}
|
||||
static Sk4f To4f(SkPMColor c) {
|
||||
return Sk4f_fromL32(c);
|
||||
}
|
||||
};
|
||||
void SkColorMatrixFilterRowMajor255::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
|
||||
filter_span<SkPMColorAdaptor>(fTranspose, src, count, dst);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkColorMatrixFilterRowMajor255::flatten(SkWriteBuffer& buffer) const {
|
||||
|
@ -18,7 +18,6 @@ public:
|
||||
/** Creates a color matrix filter that returns the same value in all four channels. */
|
||||
static sk_sp<SkColorFilter> MakeSingleChannelOutput(const SkScalar row[5]);
|
||||
|
||||
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
|
||||
uint32_t getFlags() const override;
|
||||
bool asColorMatrix(SkScalar matrix[20]) const override;
|
||||
sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter>) const override;
|
||||
|
@ -62,47 +62,6 @@ uint32_t SkModeColorFilter::getFlags() const {
|
||||
return flags;
|
||||
}
|
||||
|
||||
void SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const {
|
||||
SkPMColor color = fPMColor;
|
||||
|
||||
switch (fMode) {
|
||||
case SkBlendMode::kSrc:
|
||||
sk_memset32(result, color, count);
|
||||
break;
|
||||
case SkBlendMode::kSrcIn:
|
||||
for (int i = 0; i < count; ++i) {
|
||||
result[i] = SkAlphaMulQ(color, SkAlpha255To256(SkGetPackedA32(shader[i])));
|
||||
}
|
||||
break;
|
||||
case SkBlendMode::kModulate:
|
||||
for (int i = 0; i < count; ++i) {
|
||||
int a = SkMulDiv255Round(SkGetPackedA32(color), SkGetPackedA32(shader[i]));
|
||||
int r = SkMulDiv255Round(SkGetPackedR32(color), SkGetPackedR32(shader[i]));
|
||||
int g = SkMulDiv255Round(SkGetPackedG32(color), SkGetPackedG32(shader[i]));
|
||||
int b = SkMulDiv255Round(SkGetPackedB32(color), SkGetPackedB32(shader[i]));
|
||||
result[i] = SkPackARGB32(a, r, g, b);
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
SkSTArenaAlloc<256> alloc;
|
||||
SkRasterPipeline p(&alloc);
|
||||
|
||||
if (kN32_SkColorType == kBGRA_8888_SkColorType) {
|
||||
p.append(SkRasterPipeline::load_bgra, &shader);
|
||||
} else {
|
||||
p.append(SkRasterPipeline::load_8888, &shader);
|
||||
}
|
||||
this->appendStages(&p, nullptr, &alloc, false);
|
||||
if (kN32_SkColorType == kBGRA_8888_SkColorType) {
|
||||
p.append(SkRasterPipeline::store_bgra, &result);
|
||||
} else {
|
||||
p.append(SkRasterPipeline::store_8888, &result);
|
||||
}
|
||||
p.run(0, 0, count);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
|
||||
buffer.writeColor(fColor);
|
||||
buffer.writeUInt((int)fMode);
|
||||
|
@ -21,7 +21,6 @@ public:
|
||||
|
||||
bool asColorMode(SkColor*, SkBlendMode*) const override;
|
||||
uint32_t getFlags() const override;
|
||||
void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override;
|
||||
|
||||
#ifndef SK_IGNORE_TO_STRING
|
||||
void toString(SkString* str) const override;
|
||||
|
@ -44,9 +44,7 @@ public:
|
||||
}
|
||||
|
||||
// Let fMatrixFilter handle all the other calls directly.
|
||||
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override {
|
||||
fMatrixFilter->filterSpan(src, count, dst);
|
||||
}
|
||||
|
||||
uint32_t getFlags() const override {
|
||||
return fMatrixFilter->getFlags();
|
||||
}
|
||||
|
@ -22,111 +22,6 @@
|
||||
|
||||
using InvertStyle = SkHighContrastConfig::InvertStyle;
|
||||
|
||||
namespace {
|
||||
|
||||
SkScalar Hue2RGB(SkScalar p, SkScalar q, SkScalar t) {
|
||||
if (t < 0) {
|
||||
t += 1;
|
||||
} else if (t > 1) {
|
||||
t -= 1;
|
||||
}
|
||||
|
||||
if (t < 1/6.f) {
|
||||
return p + (q - p) * 6 * t;
|
||||
}
|
||||
|
||||
if (t < 1/2.f) {
|
||||
return q;
|
||||
}
|
||||
|
||||
if (t < 2/3.f) {
|
||||
return p + (q - p) * (2/3.f - t) * 6;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
SkScalar IncreaseContrast(SkScalar f, SkScalar contrast) {
|
||||
SkScalar m = (1 + contrast) / (1 - contrast);
|
||||
SkScalar b = (-0.5f * m + 0.5f);
|
||||
return m * f + b;
|
||||
}
|
||||
|
||||
SkColor4f ApplyHighContrastFilter(const SkHighContrastConfig& config, const SkColor4f& src) {
|
||||
// Apply a gamma of 2.0 so that the rest of the calculations
|
||||
// happen roughly in linear space.
|
||||
float rf = src.fR * src.fR;
|
||||
float gf = src.fG * src.fG;
|
||||
float bf = src.fB * src.fB;
|
||||
|
||||
// Convert to grayscale using luminance coefficients.
|
||||
if (config.fGrayscale) {
|
||||
SkScalar lum =
|
||||
rf * SK_LUM_COEFF_R + gf * SK_LUM_COEFF_G + bf * SK_LUM_COEFF_B;
|
||||
rf = lum;
|
||||
gf = lum;
|
||||
bf = lum;
|
||||
}
|
||||
|
||||
// Now invert.
|
||||
if (config.fInvertStyle == InvertStyle::kInvertBrightness) {
|
||||
rf = 1 - rf;
|
||||
gf = 1 - gf;
|
||||
bf = 1 - bf;
|
||||
} else if (config.fInvertStyle == InvertStyle::kInvertLightness) {
|
||||
// Convert to HSL
|
||||
SkScalar max = SkTMax(SkTMax(rf, gf), bf);
|
||||
SkScalar min = SkTMin(SkTMin(rf, gf), bf);
|
||||
SkScalar l = (max + min) / 2;
|
||||
SkScalar h, s;
|
||||
|
||||
if (max == min) {
|
||||
h = 0;
|
||||
s = 0;
|
||||
} else {
|
||||
SkScalar d = max - min;
|
||||
s = l > 0.5f ? d / (2 - max - min) : d / (max + min);
|
||||
if (max == rf) {
|
||||
h = (gf - bf) / d + (gf < bf ? 6 : 0);
|
||||
} else if (max == gf) {
|
||||
h = (bf - rf) / d + 2;
|
||||
} else {
|
||||
h = (rf - gf) / d + 4;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
// Invert lightness.
|
||||
l = 1 - l;
|
||||
|
||||
// Now convert back to RGB.
|
||||
if (s == 0) {
|
||||
// Grayscale
|
||||
rf = l;
|
||||
gf = l;
|
||||
bf = l;
|
||||
} else {
|
||||
SkScalar q = l < 0.5f ? l * (1 + s) : l + s - l * s;
|
||||
SkScalar p = 2 * l - q;
|
||||
rf = Hue2RGB(p, q, h + 1/3.f);
|
||||
gf = Hue2RGB(p, q, h);
|
||||
bf = Hue2RGB(p, q, h - 1/3.f);
|
||||
}
|
||||
}
|
||||
|
||||
// Increase contrast.
|
||||
if (config.fContrast != 0.0f) {
|
||||
rf = IncreaseContrast(rf, config.fContrast);
|
||||
gf = IncreaseContrast(gf, config.fContrast);
|
||||
bf = IncreaseContrast(bf, config.fContrast);
|
||||
}
|
||||
|
||||
// Convert back from linear to a color space with a gamma of ~2.0.
|
||||
return SkColor4f::Pin(SkScalarSqrt(rf), SkScalarSqrt(gf), SkScalarSqrt(bf), src.fA);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class SkHighContrast_Filter : public SkColorFilter {
|
||||
public:
|
||||
SkHighContrast_Filter(const SkHighContrastConfig& config) {
|
||||
@ -143,7 +38,6 @@ public:
|
||||
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
|
||||
#endif
|
||||
|
||||
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
|
||||
void onAppendStages(SkRasterPipeline* p,
|
||||
SkColorSpace* dst,
|
||||
SkArenaAlloc* scratch,
|
||||
@ -164,20 +58,6 @@ private:
|
||||
typedef SkColorFilter INHERITED;
|
||||
};
|
||||
|
||||
void SkHighContrast_Filter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
|
||||
const float oneOver255 = 1.0f / 255;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
SkColor color = SkUnPreMultiply::PMColorToColor(src[i]);
|
||||
// be sure to NOT treat color as sRGB, as we are in legacy mode here
|
||||
SkColor4f s4 {
|
||||
SkColorGetR(color) * oneOver255, SkColorGetG(color) * oneOver255,
|
||||
SkColorGetB(color) * oneOver255, SkColorGetA(color) * oneOver255,
|
||||
};
|
||||
SkColor4f d4 = ApplyHighContrastFilter(fConfig, s4);
|
||||
dst[i] = d4.premul().toPMColor();
|
||||
}
|
||||
}
|
||||
|
||||
void SkHighContrast_Filter::onAppendStages(SkRasterPipeline* p,
|
||||
SkColorSpace* dstCS,
|
||||
SkArenaAlloc* alloc,
|
||||
|
@ -17,25 +17,6 @@
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#endif
|
||||
|
||||
void SkLumaColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
SkPMColor c = src[i];
|
||||
|
||||
/*
|
||||
* While LuminanceToAlpha is defined to operate on un-premultiplied
|
||||
* inputs, due to the final alpha scaling it can be computed based on
|
||||
* premultipled components:
|
||||
*
|
||||
* LumA = (k1 * r / a + k2 * g / a + k3 * b / a) * a
|
||||
* LumA = (k1 * r + k2 * g + k3 * b)
|
||||
*/
|
||||
unsigned luma = SkComputeLuminance(SkGetPackedR32(c),
|
||||
SkGetPackedG32(c),
|
||||
SkGetPackedB32(c));
|
||||
dst[i] = SkPackARGB32(luma, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SkLumaColorFilter::onAppendStages(SkRasterPipeline* p,
|
||||
SkColorSpace* dst,
|
||||
SkArenaAlloc* scratch,
|
||||
|
@ -12,17 +12,6 @@
|
||||
#include "SkReadBuffer.h"
|
||||
#include "../jumper/SkJumper.h"
|
||||
|
||||
void SkOverdrawColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
|
||||
for (int x = 0; x < count; x++) {
|
||||
uint8_t alpha = SkGetPackedA32(src[x]);
|
||||
if (alpha >= kNumColors) {
|
||||
alpha = kNumColors - 1;
|
||||
}
|
||||
|
||||
dst[x] = fColors[alpha];
|
||||
}
|
||||
}
|
||||
|
||||
void SkOverdrawColorFilter::onAppendStages(SkRasterPipeline* p,
|
||||
SkColorSpace* dstCS,
|
||||
SkArenaAlloc* alloc,
|
||||
|
@ -31,7 +31,6 @@ public:
|
||||
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
|
||||
#endif
|
||||
|
||||
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
|
||||
void toString(SkString* str) const override;
|
||||
|
||||
static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer);
|
||||
|
@ -89,8 +89,6 @@ public:
|
||||
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
|
||||
#endif
|
||||
|
||||
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
|
||||
|
||||
SK_TO_STRING_OVERRIDE()
|
||||
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTable_ColorFilter)
|
||||
@ -141,49 +139,6 @@ private:
|
||||
typedef SkColorFilter INHERITED;
|
||||
};
|
||||
|
||||
void SkTable_ColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
|
||||
const uint8_t* table = fStorage;
|
||||
const uint8_t* tableA = gIdentityTable;
|
||||
const uint8_t* tableR = gIdentityTable;
|
||||
const uint8_t* tableG = gIdentityTable;
|
||||
const uint8_t* tableB = gIdentityTable;
|
||||
if (fFlags & kA_Flag) {
|
||||
tableA = table; table += 256;
|
||||
}
|
||||
if (fFlags & kR_Flag) {
|
||||
tableR = table; table += 256;
|
||||
}
|
||||
if (fFlags & kG_Flag) {
|
||||
tableG = table; table += 256;
|
||||
}
|
||||
if (fFlags & kB_Flag) {
|
||||
tableB = table;
|
||||
}
|
||||
|
||||
const SkUnPreMultiply::Scale* scaleTable = SkUnPreMultiply::GetScaleTable();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
SkPMColor c = src[i];
|
||||
unsigned a, r, g, b;
|
||||
if (0 == c) {
|
||||
a = r = g = b = 0;
|
||||
} else {
|
||||
a = SkGetPackedA32(c);
|
||||
r = SkGetPackedR32(c);
|
||||
g = SkGetPackedG32(c);
|
||||
b = SkGetPackedB32(c);
|
||||
|
||||
if (a < 255) {
|
||||
SkUnPreMultiply::Scale scale = scaleTable[a];
|
||||
r = SkUnPreMultiply::ApplyScale(scale, r);
|
||||
g = SkUnPreMultiply::ApplyScale(scale, g);
|
||||
b = SkUnPreMultiply::ApplyScale(scale, b);
|
||||
}
|
||||
}
|
||||
dst[i] = SkPremultiplyARGBInline(tableA[a], tableR[r],
|
||||
tableG[g], tableB[b]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SK_IGNORE_TO_STRING
|
||||
void SkTable_ColorFilter::toString(SkString* str) const {
|
||||
const uint8_t* table = fStorage;
|
||||
|
@ -39,21 +39,6 @@ void SkColorFilterShader::flatten(SkWriteBuffer& buffer) const {
|
||||
buffer.writeFlattenable(fFilter.get());
|
||||
}
|
||||
|
||||
uint32_t SkColorFilterShader::FilterShaderContext::getFlags() const {
|
||||
const SkColorFilterShader& filterShader = static_cast<const SkColorFilterShader&>(fShader);
|
||||
|
||||
uint32_t shaderF = fShaderContext->getFlags();
|
||||
uint32_t filterF = filterShader.fFilter->getFlags();
|
||||
|
||||
// If the filter does not support a given feature, but sure to clear the corresponding flag
|
||||
// in the shader flags.
|
||||
//
|
||||
if (!(filterF & SkColorFilter::kAlphaUnchanged_Flag)) {
|
||||
shaderF &= ~kOpaqueAlpha_Flag;
|
||||
}
|
||||
return shaderF;
|
||||
}
|
||||
|
||||
bool SkColorFilterShader::onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS,
|
||||
SkArenaAlloc* alloc, const SkMatrix& ctm,
|
||||
const SkPaint& paint, const SkMatrix* localM) const {
|
||||
@ -64,55 +49,10 @@ bool SkColorFilterShader::onAppendStages(SkRasterPipeline* pipeline, SkColorSpac
|
||||
return true;
|
||||
}
|
||||
|
||||
SkShaderBase::Context* SkColorFilterShader::onMakeContext(const ContextRec& rec,
|
||||
SkArenaAlloc* alloc) const {
|
||||
auto* shaderContext = as_SB(fShader)->makeContext(rec, alloc);
|
||||
if (nullptr == shaderContext) {
|
||||
return nullptr;
|
||||
}
|
||||
return alloc->make<FilterShaderContext>(*this, shaderContext, rec);
|
||||
}
|
||||
|
||||
sk_sp<SkShader> SkColorFilterShader::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
|
||||
return xformer->apply(fShader.get())->makeWithColorFilter(xformer->apply(fFilter.get()));
|
||||
}
|
||||
|
||||
SkColorFilterShader::FilterShaderContext::FilterShaderContext(
|
||||
const SkColorFilterShader& filterShader,
|
||||
SkShaderBase::Context* shaderContext,
|
||||
const ContextRec& rec)
|
||||
: INHERITED(filterShader, rec)
|
||||
, fShaderContext(shaderContext)
|
||||
{}
|
||||
|
||||
void SkColorFilterShader::FilterShaderContext::shadeSpan(int x, int y, SkPMColor result[],
|
||||
int count) {
|
||||
const SkColorFilterShader& filterShader = static_cast<const SkColorFilterShader&>(fShader);
|
||||
|
||||
fShaderContext->shadeSpan(x, y, result, count);
|
||||
filterShader.fFilter->filterSpan(result, count, result);
|
||||
}
|
||||
|
||||
#include "SkRasterPipeline.h"
|
||||
void SkColorFilterShader::FilterShaderContext::shadeSpan4f(int x, int y, SkPM4f result[],
|
||||
int count) {
|
||||
const SkColorFilterShader& filterShader = static_cast<const SkColorFilterShader&>(fShader);
|
||||
|
||||
fShaderContext->shadeSpan4f(x, y, result, count);
|
||||
|
||||
// now apply the filter
|
||||
|
||||
SkSTArenaAlloc<128> alloc;
|
||||
SkRasterPipeline pipeline(&alloc);
|
||||
|
||||
const SkPM4f* src = result;
|
||||
pipeline.append(SkRasterPipeline::load_f32, &src);
|
||||
filterShader.fFilter->appendStages(&pipeline, nullptr, &alloc, filterShader.isOpaque());
|
||||
SkPM4f* dst = result;
|
||||
pipeline.append(SkRasterPipeline::store_f32, &dst);
|
||||
pipeline.run(0,y, count);
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -21,33 +21,11 @@ public:
|
||||
sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override;
|
||||
#endif
|
||||
|
||||
class FilterShaderContext : public Context {
|
||||
public:
|
||||
// Takes ownership of shaderContext and calls its destructor.
|
||||
FilterShaderContext(const SkColorFilterShader&, SkShaderBase::Context*, const ContextRec&);
|
||||
|
||||
uint32_t getFlags() const override;
|
||||
|
||||
void shadeSpan(int x, int y, SkPMColor[], int count) override;
|
||||
void shadeSpan4f(int x, int y, SkPM4f[], int count) override;
|
||||
|
||||
void set3DMask(const SkMask* mask) override {
|
||||
// forward to our proxy
|
||||
fShaderContext->set3DMask(mask);
|
||||
}
|
||||
|
||||
private:
|
||||
SkShaderBase::Context* fShaderContext;
|
||||
|
||||
typedef Context INHERITED;
|
||||
};
|
||||
|
||||
SK_TO_STRING_OVERRIDE()
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorFilterShader)
|
||||
|
||||
protected:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
Context* onMakeContext(const ContextRec&, SkArenaAlloc* alloc) const override;
|
||||
sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
|
||||
bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
|
||||
const SkMatrix&, const SkPaint&, const SkMatrix* localM) const override;
|
||||
|
@ -37,8 +37,6 @@ public:
|
||||
return sk_sp<SkColorFilter>(new SkGaussianColorFilter);
|
||||
}
|
||||
|
||||
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
|
||||
#endif
|
||||
@ -58,75 +56,6 @@ private:
|
||||
typedef SkColorFilter INHERITED;
|
||||
};
|
||||
|
||||
static inline float eval_gaussian(float x) {
|
||||
// x = 1 - x;
|
||||
// return sk_float_exp(-x * x * 4) - 0.018f;
|
||||
|
||||
return 0.00030726194381713867f +
|
||||
x*(0.15489584207534790039f +
|
||||
x*(0.21345567703247070312f +
|
||||
(2.89795351028442382812f - 2.26661229133605957031f*x)*x));
|
||||
}
|
||||
|
||||
static void build_table() {
|
||||
SkDebugf("const uint8_t gByteExpU8Table[256] = {");
|
||||
for (int i = 0; i <= 255; ++i) {
|
||||
if (!(i % 8)) {
|
||||
SkDebugf("\n");
|
||||
}
|
||||
int v = (int)(eval_gaussian(i / 255.f) * 256);
|
||||
SkDebugf(" 0x%02X,", v);
|
||||
}
|
||||
SkDebugf("\n};\n");
|
||||
}
|
||||
|
||||
const uint8_t gByteExpU8Table[256] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04,
|
||||
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07,
|
||||
0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09,
|
||||
0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0D,
|
||||
0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10, 0x10, 0x11,
|
||||
0x11, 0x12, 0x12, 0x13, 0x14, 0x14, 0x15, 0x15,
|
||||
0x16, 0x17, 0x17, 0x18, 0x19, 0x19, 0x1A, 0x1B,
|
||||
0x1C, 0x1C, 0x1D, 0x1E, 0x1F, 0x1F, 0x20, 0x21,
|
||||
0x22, 0x23, 0x24, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
|
||||
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39,
|
||||
0x3A, 0x3B, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x42,
|
||||
0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, 0x4C, 0x4D,
|
||||
0x4E, 0x50, 0x51, 0x53, 0x54, 0x55, 0x57, 0x58,
|
||||
0x5A, 0x5B, 0x5D, 0x5E, 0x60, 0x61, 0x63, 0x64,
|
||||
0x66, 0x68, 0x69, 0x6B, 0x6C, 0x6E, 0x70, 0x71,
|
||||
0x73, 0x75, 0x76, 0x78, 0x79, 0x7B, 0x7D, 0x7F,
|
||||
0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8A, 0x8C,
|
||||
0x8E, 0x90, 0x91, 0x93, 0x95, 0x96, 0x98, 0x9A,
|
||||
0x9C, 0x9D, 0x9F, 0xA1, 0xA2, 0xA4, 0xA6, 0xA8,
|
||||
0xA9, 0xAB, 0xAD, 0xAE, 0xB0, 0xB2, 0xB3, 0xB5,
|
||||
0xB7, 0xB8, 0xBA, 0xBC, 0xBD, 0xBF, 0xC0, 0xC2,
|
||||
0xC3, 0xC5, 0xC7, 0xC8, 0xCA, 0xCB, 0xCD, 0xCE,
|
||||
0xCF, 0xD1, 0xD2, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9,
|
||||
0xDA, 0xDC, 0xDD, 0xDE, 0xDF, 0xE1, 0xE2, 0xE3,
|
||||
0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB,
|
||||
0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF0, 0xF1, 0xF2,
|
||||
0xF3, 0xF3, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7,
|
||||
0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xF9, 0xFA, 0xFA,
|
||||
0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
|
||||
};
|
||||
|
||||
void SkGaussianColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
|
||||
// to re-build the table, call build_table() which will dump it out using SkDebugf.
|
||||
if (false) {
|
||||
build_table();
|
||||
}
|
||||
for (int i = 0; i < count; ++i) {
|
||||
SkPMColor c = src[i];
|
||||
uint8_t a = gByteExpU8Table[SkGetPackedA32(c)];
|
||||
dst[i] = SkPackARGB32(a, a, a, a);
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<SkFlattenable> SkGaussianColorFilter::CreateProc(SkReadBuffer&) {
|
||||
return Make();
|
||||
}
|
||||
|
@ -110,124 +110,3 @@ DEF_TEST(ColorFilter, reporter) {
|
||||
|
||||
test_composecolorfilter_limit(reporter);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DEF_TEST(LumaColorFilter, reporter) {
|
||||
SkPMColor in, out;
|
||||
auto lf(SkLumaColorFilter::Make());
|
||||
|
||||
// Applying luma to white produces black with the same transparency.
|
||||
for (unsigned i = 0; i < 256; ++i) {
|
||||
in = SkPackARGB32(i, i, i, i);
|
||||
lf->filterSpan(&in, 1, &out);
|
||||
REPORTER_ASSERT(reporter, SkGetPackedA32(out) == i);
|
||||
REPORTER_ASSERT(reporter, SkGetPackedR32(out) == 0);
|
||||
REPORTER_ASSERT(reporter, SkGetPackedG32(out) == 0);
|
||||
REPORTER_ASSERT(reporter, SkGetPackedB32(out) == 0);
|
||||
}
|
||||
|
||||
// Applying luma to black yields transparent black (luminance(black) == 0)
|
||||
for (unsigned i = 0; i < 256; ++i) {
|
||||
in = SkPackARGB32(i, 0, 0, 0);
|
||||
lf->filterSpan(&in, 1, &out);
|
||||
REPORTER_ASSERT(reporter, out == SK_ColorTRANSPARENT);
|
||||
}
|
||||
|
||||
// For general colors, a luma filter generates black with an attenuated alpha channel.
|
||||
for (unsigned i = 1; i < 256; ++i) {
|
||||
in = SkPackARGB32(i, i, i / 2, i / 3);
|
||||
lf->filterSpan(&in, 1, &out);
|
||||
REPORTER_ASSERT(reporter, out != in);
|
||||
REPORTER_ASSERT(reporter, SkGetPackedA32(out) <= i);
|
||||
REPORTER_ASSERT(reporter, SkGetPackedR32(out) == 0);
|
||||
REPORTER_ASSERT(reporter, SkGetPackedG32(out) == 0);
|
||||
REPORTER_ASSERT(reporter, SkGetPackedB32(out) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SkColorMatrixFilter.h"
|
||||
|
||||
static void get_brightness_matrix(float amount, float matrix[20]) {
|
||||
// Spec implementation
|
||||
// (http://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#brightnessEquivalent)
|
||||
// <feFunc[R|G|B] type="linear" slope="[amount]">
|
||||
memset(matrix, 0, 20 * sizeof(SkScalar));
|
||||
matrix[0] = matrix[6] = matrix[12] = amount;
|
||||
matrix[18] = 1.f;
|
||||
}
|
||||
|
||||
static void get_grayscale_matrix(float amount, float matrix[20]) {
|
||||
// Note, these values are computed to ensure MatrixNeedsClamping is false
|
||||
// for amount in [0..1]
|
||||
matrix[0] = 0.2126f + 0.7874f * amount;
|
||||
matrix[1] = 0.7152f - 0.7152f * amount;
|
||||
matrix[2] = 1.f - (matrix[0] + matrix[1]);
|
||||
matrix[3] = matrix[4] = 0.f;
|
||||
|
||||
matrix[5] = 0.2126f - 0.2126f * amount;
|
||||
matrix[6] = 0.7152f + 0.2848f * amount;
|
||||
matrix[7] = 1.f - (matrix[5] + matrix[6]);
|
||||
matrix[8] = matrix[9] = 0.f;
|
||||
|
||||
matrix[10] = 0.2126f - 0.2126f * amount;
|
||||
matrix[11] = 0.7152f - 0.7152f * amount;
|
||||
matrix[12] = 1.f - (matrix[10] + matrix[11]);
|
||||
matrix[13] = matrix[14] = 0.f;
|
||||
|
||||
matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
|
||||
matrix[18] = 1.f;
|
||||
}
|
||||
|
||||
static sk_sp<SkColorFilter> make_cf0() {
|
||||
SkScalar matrix[20];
|
||||
get_brightness_matrix(0.5f, matrix);
|
||||
return SkColorFilter::MakeMatrixFilterRowMajor255(matrix);
|
||||
}
|
||||
static sk_sp<SkColorFilter> make_cf1() {
|
||||
SkScalar matrix[20];
|
||||
get_grayscale_matrix(1, matrix);
|
||||
return SkColorFilter::MakeMatrixFilterRowMajor255(matrix);
|
||||
}
|
||||
static sk_sp<SkColorFilter> make_cf2() {
|
||||
SkColorMatrix m0, m1;
|
||||
get_brightness_matrix(0.5f, m0.fMat);
|
||||
get_grayscale_matrix(1, m1.fMat);
|
||||
m0.preConcat(m1);
|
||||
return SkColorFilter::MakeMatrixFilterRowMajor255(m0.fMat);
|
||||
}
|
||||
static sk_sp<SkColorFilter> make_cf3() {
|
||||
SkColorMatrix m0, m1;
|
||||
get_brightness_matrix(0.5f, m0.fMat);
|
||||
get_grayscale_matrix(1, m1.fMat);
|
||||
m0.postConcat(m1);
|
||||
return SkColorFilter::MakeMatrixFilterRowMajor255(m0.fMat);
|
||||
}
|
||||
typedef sk_sp<SkColorFilter> (*CFProc)();
|
||||
|
||||
// Test that a colormatrix that "should" preserve opaquness actually does.
|
||||
DEF_TEST(ColorMatrixFilter, reporter) {
|
||||
const CFProc procs[] = {
|
||||
make_cf0, make_cf1, make_cf2, make_cf3,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
|
||||
auto cf(procs[i]());
|
||||
|
||||
// generate all possible r,g,b triples
|
||||
for (int r = 0; r < 256; ++r) {
|
||||
for (int g = 0; g < 256; ++g) {
|
||||
SkPMColor storage[256];
|
||||
for (int b = 0; b < 256; ++b) {
|
||||
storage[b] = SkPackARGB32(0xFF, r, g, b);
|
||||
}
|
||||
cf->filterSpan(storage, 256, storage);
|
||||
for (int b = 0; b < 256; ++b) {
|
||||
REPORTER_ASSERT(reporter, 0xFF == SkGetPackedA32(storage[b]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,9 +37,6 @@ public:
|
||||
return GrSRGBEffect::Make(fMode);
|
||||
}
|
||||
|
||||
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override {
|
||||
SK_ABORT("SkSRGBColorFilter is only implemented for GPU");
|
||||
}
|
||||
void onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, bool) const override {
|
||||
SK_ABORT("SkSRGBColorFilter is only implemented for GPU");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user