return SkColorMatrixFilter::Create(cm);
}
+static SkColorFilter* make_cf1() {
+ SkColorMatrix cm;
+ cm.setSaturation(0.75f);
+ SkAutoTUnref<SkColorFilter> a(SkColorMatrixFilter::Create(cm));
+ // CreateComposedFilter will try to concat these two matrices, resulting in a single
+ // filter (which is good for speed). For this test, we want to force a real compose of
+ // these two, so our inner filter has a scale-up, which disables the optimization of
+ // combining the two matrices.
+ cm.setScale(1.1f, 0.9f, 1);
+ SkAutoTUnref<SkColorFilter> b(SkColorMatrixFilter::Create(cm));
+ return SkColorFilter::CreateComposeFilter(a, b);
+}
+
static void draw_into_canvas(SkCanvas* canvas) {
const SkRect r = SkRect::MakeWH(100, 100);
SkShader* (*shaders[])() { make_opaque_color, make_alpha_color };
- SkColorFilter* (*filters[])() { make_cf_null, make_cf0 };
+ SkColorFilter* (*filters[])() { make_cf_null, make_cf0, make_cf1 };
SkPaint paint;
for (auto shProc : shaders) {
}
}
-DEF_SIMPLE_GM(color4f, canvas, 510, 250) {
+DEF_SIMPLE_GM(color4f, canvas, 620, 260) {
canvas->translate(20, 20);
SkPaint bg;
SkColorProfileType const profiles[] { kLinear_SkColorProfileType, kSRGB_SkColorProfileType };
for (auto profile : profiles) {
- const SkImageInfo info = SkImageInfo::Make(500, 100, kN32_SkColorType, kPremul_SkAlphaType,
+ const SkImageInfo info = SkImageInfo::Make(600, 100, kN32_SkColorType, kPremul_SkAlphaType,
profile);
SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
surface->getCanvas()->drawPaint(bg);
///////////////////////////////////////////////////////////////////////////////////////////////////
+struct SkColor4f;
+
/*
* The float values are 0...1 premultiplied
*/
float a() const { return fVec[A]; }
+ SkColor4f unpremul() const;
+
static SkPM4f FromPMColor(SkPMColor);
#ifdef SK_DEBUG
*/
SkColor filterColor(SkColor) const;
+ /**
+ * Filters a single color.
+ */
+ SkColor4f filterColor4f(const SkColor4f&) const;
+
/** Create a colorfilter that uses the specified color and mode.
If the Mode is DST, this function will return NULL (since that
mode will have no effect on the result).
return c4;
}
+SkColor4f SkPM4f::unpremul() const {
+ float alpha = fVec[A];
+ if (0 == alpha) {
+ return { 0, 0, 0, 0 };
+ } else {
+ float invAlpha = 1 / alpha;
+ return { alpha, fVec[R] * invAlpha, fVec[G] * invAlpha, fVec[B] * invAlpha };
+ }
+}
+
SkColor4f SkColor4f::FromColor(SkColor c) {
Sk4f value = SkNx_shuffle<3,2,1,0>(SkNx_cast<float>(Sk4b::Load(&c)));
SkColor4f c4;
return false;
}
+void SkColorFilter::filterSpan4f(const SkPM4f[], int count, SkPM4f[]) const {
+ if (this->supports4f()) {
+ SkASSERT(false && "colorfilter supports4f but didn't override");
+ } else {
+ SkASSERT(false && "filterSpan4f called but not supported");
+ }
+}
+
SkColor SkColorFilter::filterColor(SkColor c) const {
SkPMColor dst, src = SkPreMultiplyColor(c);
this->filterSpan(&src, 1, &dst);
return SkUnPreMultiply::PMColorToColor(dst);
}
-void SkColorFilter::filterSpan4f(const SkPM4f[], int count, SkPM4f[]) const {
- SkASSERT(false && "filterSpan4f called but not implemented");
+SkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const {
+ SkPM4f dst, src = c.premul();
+ this->filterSpan4f(&src, 1, &dst);
+ return dst.unpremul();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class SkComposeColorFilter : public SkColorFilter {
public:
uint32_t getFlags() const override {
- // Can only claim alphaunchanged and 16bit support if both our proxys do.
+ // Can only claim alphaunchanged and SkPM4f support if both our proxys do.
return fOuter->getFlags() & fInner->getFlags();
}
fOuter->filterSpan(result, count, result);
}
+ void filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const override {
+ SkASSERT(fInner->supports4f());
+ SkASSERT(fOuter->supports4f());
+ fInner->filterSpan4f(shader, count, result);
+ fOuter->filterSpan4f(result, count, result);
+ }
+
#ifndef SK_IGNORE_TO_STRING
void toString(SkString* str) const override {
SkString outerS, innerS;