aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@chromium.org>2015-03-01 18:00:47 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-03-01 18:00:47 -0800
commitb675a73c1f3f4a433c4893199a0bd11126dfe130 (patch)
treecb375f619ce5b041693feb3525e01d7b47c7ee36
parent73165bd417d6cd4b4513df54b58e23e33f151a3f (diff)
add compose-colorfilter
-rw-r--r--gm/tablecolorfilter.cpp103
-rw-r--r--include/core/SkColorFilter.h6
-rw-r--r--src/core/SkColorFilter.cpp78
3 files changed, 164 insertions, 23 deletions
diff --git a/gm/tablecolorfilter.cpp b/gm/tablecolorfilter.cpp
index a49859bf8f..2acb15c677 100644
--- a/gm/tablecolorfilter.cpp
+++ b/gm/tablecolorfilter.cpp
@@ -11,6 +11,15 @@
#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; )
+
diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h
index 929607a398..bb628053a6 100644
--- a/include/core/SkColorFilter.h
+++ b/include/core/SkColorFilter.h
@@ -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/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index aadb29cb2d..8c760be6cf 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -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,76 @@ 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;
+
+ 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));
+}
+
+