From f7cdb06d62bd732599c7ee407dfd76d32d671755 Mon Sep 17 00:00:00 2001 From: reed Date: Thu, 4 Feb 2016 11:35:27 -0800 Subject: [PATCH] extend compose-colorfilter to 4f BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1664663003 Review URL: https://codereview.chromium.org/1664663003 --- gm/color4f.cpp | 19 ++++++++++++++++--- include/core/SkColor.h | 4 ++++ include/core/SkColorFilter.h | 5 +++++ src/core/SkColor.cpp | 10 ++++++++++ src/core/SkColorFilter.cpp | 23 ++++++++++++++++++++--- 5 files changed, 55 insertions(+), 6 deletions(-) diff --git a/gm/color4f.cpp b/gm/color4f.cpp index 98ce082..e912654 100644 --- a/gm/color4f.cpp +++ b/gm/color4f.cpp @@ -32,10 +32,23 @@ static SkColorFilter* make_cf0() { return SkColorMatrixFilter::Create(cm); } +static SkColorFilter* make_cf1() { + SkColorMatrix cm; + cm.setSaturation(0.75f); + SkAutoTUnref 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 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) { @@ -48,7 +61,7 @@ static void draw_into_canvas(SkCanvas* canvas) { } } -DEF_SIMPLE_GM(color4f, canvas, 510, 250) { +DEF_SIMPLE_GM(color4f, canvas, 620, 260) { canvas->translate(20, 20); SkPaint bg; @@ -58,7 +71,7 @@ DEF_SIMPLE_GM(color4f, canvas, 510, 250) { 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 surface(SkSurface::NewRaster(info)); surface->getCanvas()->drawPaint(bg); diff --git a/include/core/SkColor.h b/include/core/SkColor.h index 461a538..90453f5 100644 --- a/include/core/SkColor.h +++ b/include/core/SkColor.h @@ -160,6 +160,8 @@ typedef SkPMColor (*SkXfermodeProc)(SkPMColor src, SkPMColor dst); /////////////////////////////////////////////////////////////////////////////////////////////////// +struct SkColor4f; + /* * The float values are 0...1 premultiplied */ @@ -174,6 +176,8 @@ struct SkPM4f { float a() const { return fVec[A]; } + SkColor4f unpremul() const; + static SkPM4f FromPMColor(SkPMColor); #ifdef SK_DEBUG diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h index 14192c5..ad97a73 100644 --- a/include/core/SkColorFilter.h +++ b/include/core/SkColorFilter.h @@ -102,6 +102,11 @@ public: */ 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). diff --git a/src/core/SkColor.cpp b/src/core/SkColor.cpp index 865fe0d..87e3a9d 100644 --- a/src/core/SkColor.cpp +++ b/src/core/SkColor.cpp @@ -111,6 +111,16 @@ SkPM4f SkPM4f::FromPMColor(SkPMColor c) { 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(Sk4b::Load(&c))); SkColor4f c4; diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp index 4bfacfe..72f5470 100644 --- a/src/core/SkColorFilter.cpp +++ b/src/core/SkColorFilter.cpp @@ -29,14 +29,24 @@ bool SkColorFilter::asComponentTable(SkBitmap*) const { 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(); } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -54,7 +64,7 @@ void SkColorFilter::filterSpan4f(const SkPM4f[], int count, SkPM4f[]) const { 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(); } @@ -63,6 +73,13 @@ public: 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; -- 2.7.4