diff options
-rw-r--r-- | gm/tablecolorfilter.cpp | 103 | ||||
-rw-r--r-- | include/core/SkColorFilter.h | 6 | ||||
-rw-r--r-- | include/effects/SkModeColorFilter.h | 63 | ||||
-rw-r--r-- | src/core/SkColorFilter.cpp | 83 | ||||
-rw-r--r-- | src/effects/SkColorFilters.cpp | 118 | ||||
-rw-r--r-- | src/ports/SkGlobalInitialization_chromium.cpp | 2 | ||||
-rw-r--r-- | src/ports/SkGlobalInitialization_default.cpp | 2 |
7 files changed, 272 insertions, 105 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/include/effects/SkModeColorFilter.h b/include/effects/SkModeColorFilter.h new file mode 100644 index 0000000000..16c6e13359 --- /dev/null +++ b/include/effects/SkModeColorFilter.h @@ -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 diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp index aadb29cb2d..d49fc52fa1 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,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 + diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp index 95041b5b57..10e6958570 100644 --- a/src/effects/SkColorFilters.cpp +++ b/src/effects/SkColorFilters.cpp @@ -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" @@ -15,93 +16,49 @@ #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 diff --git a/src/ports/SkGlobalInitialization_chromium.cpp b/src/ports/SkGlobalInitialization_chromium.cpp index f3e16db12c..0f7d71b207 100644 --- a/src/ports/SkGlobalInitialization_chromium.cpp +++ b/src/ports/SkGlobalInitialization_chromium.cpp @@ -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) diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp index f3e16db12c..0f7d71b207 100644 --- a/src/ports/SkGlobalInitialization_default.cpp +++ b/src/ports/SkGlobalInitialization_default.cpp @@ -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) |