extend compose-colorfilter to 4f
authorreed <reed@google.com>
Thu, 4 Feb 2016 19:35:27 +0000 (11:35 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 4 Feb 2016 19:35:27 +0000 (11:35 -0800)
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
include/core/SkColor.h
include/core/SkColorFilter.h
src/core/SkColor.cpp
src/core/SkColorFilter.cpp

index 98ce082..e912654 100644 (file)
@@ -32,10 +32,23 @@ static SkColorFilter* make_cf0() {
     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) {
@@ -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<SkSurface> surface(SkSurface::NewRaster(info));
         surface->getCanvas()->drawPaint(bg);
index 461a538..90453f5 100644 (file)
@@ -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
index 14192c5..ad97a73 100644 (file)
@@ -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).
index 865fe0d..87e3a9d 100644 (file)
@@ -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<float>(Sk4b::Load(&c)));
     SkColor4f c4;
index 4bfacfe..72f5470 100644 (file)
@@ -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;