diff options
author | reed <reed@chromium.org> | 2015-03-01 18:00:47 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-01 18:00:47 -0800 |
commit | b675a73c1f3f4a433c4893199a0bd11126dfe130 (patch) | |
tree | cb375f619ce5b041693feb3525e01d7b47c7ee36 | |
parent | 73165bd417d6cd4b4513df54b58e23e33f151a3f (diff) |
add compose-colorfilter
BUG=skia:
Review URL: https://codereview.chromium.org/969673002
-rw-r--r-- | gm/tablecolorfilter.cpp | 103 | ||||
-rw-r--r-- | include/core/SkColorFilter.h | 6 | ||||
-rw-r--r-- | src/core/SkColorFilter.cpp | 78 |
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)); +} + + |