add compose-colorfilter
authorreed <reed@chromium.org>
Mon, 2 Mar 2015 03:53:47 +0000 (19:53 -0800)
committerCommit bot <commit-bot@chromium.org>
Mon, 2 Mar 2015 03:53:47 +0000 (19:53 -0800)
now with serialization registration

This reverts commit 5bd055c0386499f2dc8c66173a7534b75af602bf.

BUG=skia:
TBR=

Review URL: https://codereview.chromium.org/970753002

gm/tablecolorfilter.cpp
include/core/SkColorFilter.h
include/effects/SkModeColorFilter.h [new file with mode: 0644]
src/core/SkColorFilter.cpp
src/effects/SkColorFilters.cpp
src/ports/SkGlobalInitialization_chromium.cpp
src/ports/SkGlobalInitialization_default.cpp

index a49859b..2acb15c 100644 (file)
 #include "SkGradientShader.h"
 #include "SkTableColorFilter.h"
 
+static SkShader* make_shader0(int w, int h) {
+    SkPoint pts[] = { {0, 0}, {SkIntToScalar(w), SkIntToScalar(h)} };
+    SkColor colors[] = {
+        SK_ColorBLACK, SK_ColorGREEN, SK_ColorCYAN,
+        SK_ColorRED, 0, SK_ColorBLUE, SK_ColorWHITE
+    };
+    return SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors),
+                                          SkShader::kClamp_TileMode);
+}
 static void make_bm0(SkBitmap* bm) {
     int W = 120;
     int H = 120;
@@ -19,34 +28,29 @@ static void make_bm0(SkBitmap* bm) {
 
     SkCanvas canvas(*bm);
     SkPaint paint;
-    SkPoint pts[] = { {0, 0}, {SkIntToScalar(W), SkIntToScalar(H)} };
+    paint.setShader(make_shader0(W, H))->unref();
+    canvas.drawPaint(paint);
+}
+static SkShader* make_shader1(int w, int h) {
+    SkScalar cx = SkIntToScalar(w)/2;
+    SkScalar cy = SkIntToScalar(h)/2;
     SkColor colors[] = {
-        SK_ColorBLACK, SK_ColorGREEN, SK_ColorCYAN,
-        SK_ColorRED, 0, SK_ColorBLUE, SK_ColorWHITE
+        SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
     };
-    SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors),
-                                                 SkShader::kClamp_TileMode);
-    paint.setShader(s)->unref();
-    canvas.drawPaint(paint);
+    return SkGradientShader::CreateRadial(SkPoint::Make(cx, cy), cx, colors, NULL,
+                                          SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode);
 }
 static void make_bm1(SkBitmap* bm) {
     int W = 120;
     int H = 120;
+    SkScalar cx = SkIntToScalar(W)/2;
+    SkScalar cy = SkIntToScalar(H)/2;
     bm->allocN32Pixels(W, H);
     bm->eraseColor(SK_ColorTRANSPARENT);
 
     SkCanvas canvas(*bm);
     SkPaint paint;
-    SkScalar cx = SkIntToScalar(W)/2;
-    SkScalar cy = SkIntToScalar(H)/2;
-    SkColor colors[] = {
-        SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
-    };
-    SkShader* s = SkGradientShader::CreateRadial(SkPoint::Make(SkIntToScalar(W)/2,
-                                                               SkIntToScalar(H)/2),
-                                                 SkIntToScalar(W)/2, colors, NULL, SK_ARRAY_COUNT(colors),
-                                                 SkShader::kClamp_TileMode);
-    paint.setShader(s)->unref();
+    paint.setShader(make_shader1(W, H))->unref();
     paint.setAntiAlias(true);
     canvas.drawCircle(cx, cy, cx, paint);
 }
@@ -184,8 +188,69 @@ protected:
 private:
     typedef GM INHERITED;
 };
+DEF_GM( return new TableColorFilterGM; )
 
 //////////////////////////////////////////////////////////////////////////////
 
-static skiagm::GM* MyFactory(void*) { return new TableColorFilterGM; }
-static skiagm::GMRegistry reg(MyFactory);
+class ComposeColorFilterGM : public skiagm::GM {
+public:
+    ComposeColorFilterGM() {}
+    
+protected:
+    virtual SkString onShortName() {
+        return SkString("composecolorfilter");
+    }
+    
+    virtual SkISize onISize() {
+        return SkISize::Make(730, 730);
+    }
+
+    virtual void onDraw(SkCanvas* canvas) {
+        SkBitmap bm;
+        make_bm1(&bm);
+
+        canvas->drawColor(0xFFDDDDDD);
+
+        SkColor colors[] = { SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW };
+        SkXfermode::Mode modes[] = {
+            SkXfermode::kOverlay_Mode,
+            SkXfermode::kDarken_Mode,
+            SkXfermode::kColorBurn_Mode,
+            SkXfermode::kExclusion_Mode,
+        };
+
+        const int MODES = SK_ARRAY_COUNT(modes) * SK_ARRAY_COUNT(colors);
+        SkAutoTUnref<SkColorFilter> filters[MODES];
+        int index = 0;
+        for (size_t i = 0; i < SK_ARRAY_COUNT(modes); ++i) {
+            for (size_t j = 0; j < SK_ARRAY_COUNT(colors); ++j) {
+                filters[index++].reset(SkColorFilter::CreateModeFilter(colors[j], modes[i]));
+            }
+        }
+
+        SkPaint paint;
+        paint.setShader(make_shader1(50, 50))->unref();
+        SkRect r = SkRect::MakeWH(50, 50);
+        const SkScalar spacer = 10;
+
+        canvas->translate(spacer, spacer);
+
+        for (size_t y = 0; y < MODES; ++y) {
+            canvas->save();
+            for (size_t x = 0; x < MODES; ++x) {
+                SkAutoTUnref<SkColorFilter> compose(SkColorFilter::CreateComposeFilter(filters[y],
+                                                                                       filters[x]));
+                paint.setColorFilter(compose);
+                canvas->drawRect(r, paint);
+                canvas->translate(r.width() + spacer, 0);
+            }
+            canvas->restore();
+            canvas->translate(0, r.height() + spacer);
+        }
+    }
+    
+private:
+    typedef GM INHERITED;
+};
+DEF_GM( return new ComposeColorFilterGM; )
+
index 929607a..bb62805 100644 (file)
@@ -123,6 +123,12 @@ public:
     */
     static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add);
 
+    /** Construct a colorfilter whose effect is to first apply the inner filter and then apply
+     *  the outer filter to the result of the inner's.
+     *  The reference counts for outer and inner are incremented.
+     */
+    static SkColorFilter* CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner);
+
     /** A subclass may implement this factory function to work with the GPU backend. If the return
         is non-NULL then the caller owns a ref on the returned object.
      */
diff --git a/include/effects/SkModeColorFilter.h b/include/effects/SkModeColorFilter.h
new file mode 100644 (file)
index 0000000..16c6e13
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkModeColorFilter_DEFINED
+#define SkModeColorFilter_DEFINED
+
+#include "SkColorFilter.h"
+#include "SkColorPriv.h"
+#include "SkString.h"
+#include "SkXfermode.h"
+
+class SkModeColorFilter : public SkColorFilter {
+public:
+    SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
+        fColor = color;
+        fMode = mode;
+        this->updateCache();
+    };
+
+    SkColor getColor() const { return fColor; }
+    SkXfermode::Mode getMode() const { return fMode; }
+    SkPMColor getPMColor() const { return fPMColor; }
+
+    bool asColorMode(SkColor*, SkXfermode::Mode*) const SK_OVERRIDE;
+    uint32_t getFlags() const SK_OVERRIDE;
+    void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const SK_OVERRIDE;
+    void filterSpan16(const uint16_t shader[], int count, uint16_t result[]) const SK_OVERRIDE;
+
+#ifndef SK_IGNORE_TO_STRING
+    void toString(SkString* str) const SK_OVERRIDE {
+        str->append("SkModeColorFilter: color: 0x");
+        str->appendHex(fColor);
+        str->append(" mode: ");
+        str->append(SkXfermode::ModeName(fMode));
+    }
+#endif
+
+#if SK_SUPPORT_GPU
+    GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
+#endif
+    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
+
+protected:
+    void flatten(SkWriteBuffer&) const SK_OVERRIDE;
+
+private:
+    SkColor             fColor;
+    SkXfermode::Mode    fMode;
+    // cache
+    SkPMColor           fPMColor;
+    SkXfermodeProc      fProc;
+    SkXfermodeProc16    fProc16;
+
+    void updateCache();
+
+    typedef SkColorFilter INHERITED;
+};
+
+#endif
index aadb29c..d49fc52 100644 (file)
@@ -6,12 +6,9 @@
  */
 
 #include "SkColorFilter.h"
-
 #include "SkReadBuffer.h"
-#include "SkWriteBuffer.h"
-#include "SkShader.h"
-#include "SkUnPreMultiply.h"
 #include "SkString.h"
+#include "SkWriteBuffer.h"
 
 bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
     return false;
@@ -43,3 +40,81 @@ SkColor SkColorFilter::filterColor(SkColor c) const {
 GrFragmentProcessor* SkColorFilter::asFragmentProcessor(GrContext*) const {
     return NULL;
 }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkComposeColorFilter : public SkColorFilter {
+public:
+    SkComposeColorFilter(SkColorFilter* outer, SkColorFilter* inner)
+        : fOuter(SkRef(outer))
+        , fInner(SkRef(inner))
+    {}
+    
+    uint32_t getFlags() const SK_OVERRIDE {
+        // Can only claim alphaunchanged and 16bit support if both our proxys do.
+        return fOuter->getFlags() & fInner->getFlags();
+    }
+    
+    void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const SK_OVERRIDE {
+        fInner->filterSpan(shader, count, result);
+        fOuter->filterSpan(result, count, result);
+    }
+    
+    void filterSpan16(const uint16_t shader[], int count, uint16_t result[]) const SK_OVERRIDE {
+        SkASSERT(this->getFlags() & kHasFilter16_Flag);
+        fInner->filterSpan16(shader, count, result);
+        fOuter->filterSpan16(result, count, result);
+    }
+    
+#ifndef SK_IGNORE_TO_STRING
+    void toString(SkString* str) const SK_OVERRIDE {
+        SkString outerS, innerS;
+        fOuter->toString(&outerS);
+        fInner->toString(&innerS);
+        str->appendf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(), innerS.c_str());
+    }
+#endif
+
+#if 0   // TODO: should we support composing the fragments?
+#if SK_SUPPORT_GPU
+    GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
+#endif
+#endif
+
+    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)
+    
+protected:
+    void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
+        buffer.writeFlattenable(fOuter);
+        buffer.writeFlattenable(fInner);
+    }
+    
+private:
+    SkAutoTUnref<SkColorFilter> fOuter;
+    SkAutoTUnref<SkColorFilter> fInner;
+
+    friend class SkColorFilter;
+
+    typedef SkColorFilter INHERITED;
+};
+
+SkFlattenable* SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
+    SkAutoTUnref<SkColorFilter> outer(buffer.readColorFilter());
+    SkAutoTUnref<SkColorFilter> inner(buffer.readColorFilter());
+    return CreateComposeFilter(outer, inner);
+}
+
+SkColorFilter* SkColorFilter::CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner) {
+    if (!outer) {
+        return SkSafeRef(inner);
+    }
+    if (!inner) {
+        return SkSafeRef(outer);
+    }
+    return SkNEW_ARGS(SkComposeColorFilter, (outer, inner));
+}
+
+SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
+SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
+SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
+
index 95041b5..10e6958 100644 (file)
@@ -8,6 +8,7 @@
 #include "SkBlitRow.h"
 #include "SkColorFilter.h"
 #include "SkColorPriv.h"
+#include "SkModeColorFilter.h"
 #include "SkReadBuffer.h"
 #include "SkWriteBuffer.h"
 #include "SkUtils.h"
 #include "SkValidationUtils.h"
 #include "SkColorMatrixFilter.h"
 
-// baseclass for filters that store a color and mode
-class SkModeColorFilter : public SkColorFilter {
-public:
-    SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
-        fColor = color;
-        fMode = mode;
-        this->updateCache();
-    };
-
-    SkColor getColor() const { return fColor; }
-    SkXfermode::Mode getMode() const { return fMode; }
-    SkPMColor getPMColor() const { return fPMColor; }
-
-    bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const SK_OVERRIDE {
-        if (color) {
-            *color = fColor;
-        }
-        if (mode) {
-            *mode = fMode;
-        }
-        return true;
-    }
-
-    uint32_t getFlags() const SK_OVERRIDE {
-        return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
-    }
-
-    virtual void filterSpan(const SkPMColor shader[], int count,
-                            SkPMColor result[]) const SK_OVERRIDE {
-        SkPMColor       color = fPMColor;
-        SkXfermodeProc  proc = fProc;
-
-        for (int i = 0; i < count; i++) {
-            result[i] = proc(color, shader[i]);
-        }
-    }
-
-    virtual void filterSpan16(const uint16_t shader[], int count,
-                              uint16_t result[]) const SK_OVERRIDE {
-        SkASSERT(this->getFlags() & kHasFilter16_Flag);
-
-        SkPMColor        color = fPMColor;
-        SkXfermodeProc16 proc16 = fProc16;
-
-        for (int i = 0; i < count; i++) {
-            result[i] = proc16(color, shader[i]);
-        }
+bool SkModeColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
+    if (color) {
+        *color = fColor;
     }
-
-#ifndef SK_IGNORE_TO_STRING
-    void toString(SkString* str) const SK_OVERRIDE {
-        str->append("SkModeColorFilter: color: 0x");
-        str->appendHex(fColor);
-        str->append(" mode: ");
-        str->append(SkXfermode::ModeName(fMode));
+    if (mode) {
+        *mode = fMode;
     }
-#endif
+    return true;
+}
 
-#if SK_SUPPORT_GPU
-    GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
-#endif
-    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
+uint32_t SkModeColorFilter::getFlags() const {
+    return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
+}
 
-protected:
-    void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
-        buffer.writeColor(fColor);
-        buffer.writeUInt(fMode);
+void SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const {
+    SkPMColor       color = fPMColor;
+    SkXfermodeProc  proc = fProc;
+    
+    for (int i = 0; i < count; i++) {
+        result[i] = proc(color, shader[i]);
     }
+}
 
-private:
-    SkColor             fColor;
-    SkXfermode::Mode    fMode;
-    // cache
-    SkPMColor           fPMColor;
-    SkXfermodeProc      fProc;
-    SkXfermodeProc16    fProc16;
-
-    void updateCache() {
-        fPMColor = SkPreMultiplyColor(fColor);
-        fProc = SkXfermode::GetProc(fMode);
-        fProc16 = SkXfermode::GetProc16(fMode, fColor);
+void SkModeColorFilter::filterSpan16(const uint16_t shader[], int count, uint16_t result[]) const {
+    SkASSERT(this->getFlags() & kHasFilter16_Flag);
+    
+    SkPMColor        color = fPMColor;
+    SkXfermodeProc16 proc16 = fProc16;
+    
+    for (int i = 0; i < count; i++) {
+        result[i] = proc16(color, shader[i]);
     }
+}
+void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
+    buffer.writeColor(fColor);
+    buffer.writeUInt(fMode);
+}
 
-    friend class SkColorFilter;
-
-    typedef SkColorFilter INHERITED;
-};
+void SkModeColorFilter::updateCache() {
+    fPMColor = SkPreMultiplyColor(fColor);
+    fProc = SkXfermode::GetProc(fMode);
+    fProc16 = SkXfermode::GetProc16(fMode, fColor);
+}
 
 SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
     SkColor color = buffer.readColor();
@@ -549,6 +506,3 @@ SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
     return SkColorMatrixFilter::Create(matrix);
 }
 
-SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
-    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
-SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
index f3e16db..0f7d71b 100644 (file)
@@ -46,6 +46,7 @@
 #include "SkMagnifierImageFilter.h"
 #include "SkMatrixConvolutionImageFilter.h"
 #include "SkMergeImageFilter.h"
+#include "SkModeColorFilter.h"
 #include "SkMorphologyImageFilter.h"
 #include "SkOffsetImageFilter.h"
 #include "SkOnce.h"
@@ -89,6 +90,7 @@ public:
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaColorFilter)
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect)
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect)
+        SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect)
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader)
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPictureImageFilter)
index f3e16db..0f7d71b 100644 (file)
@@ -46,6 +46,7 @@
 #include "SkMagnifierImageFilter.h"
 #include "SkMatrixConvolutionImageFilter.h"
 #include "SkMergeImageFilter.h"
+#include "SkModeColorFilter.h"
 #include "SkMorphologyImageFilter.h"
 #include "SkOffsetImageFilter.h"
 #include "SkOnce.h"
@@ -89,6 +90,7 @@ public:
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaColorFilter)
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect)
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect)
+        SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect)
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader)
         SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPictureImageFilter)