diff --git a/bench/XfermodeBench.cpp b/bench/XfermodeBench.cpp index 0d85fefe1..71cf0e69b 100644 --- a/bench/XfermodeBench.cpp +++ b/bench/XfermodeBench.cpp @@ -12,6 +12,7 @@ #include "SkRandom.h" #include "SkString.h" #include "SkXfermode.h" +#include "SkLumaXfermode.h" // Benchmark that draws non-AA rects with an SkXfermode::Mode class XfermodeBench : public SkBenchmark { @@ -22,6 +23,13 @@ public: fName.printf("Xfermode_%s", SkXfermode::ModeName(mode)); } + XfermodeBench(void* param, SkXfermode* xferMode, const char* name) + : SkBenchmark(param) { + SkASSERT(NULL != xferMode); + fXfermode.reset(xferMode); + fName.printf("Xfermode_%s", name); + } + protected: virtual const char* onGetName() SK_OVERRIDE { return fName.c_str(); } @@ -58,62 +66,44 @@ private: ////////////////////////////////////////////////////////////////////////////// -static SkBenchmark* Fact00(void* p) { return new XfermodeBench(p, SkXfermode::kClear_Mode); } -static SkBenchmark* Fact01(void* p) { return new XfermodeBench(p, SkXfermode::kSrc_Mode); } -static SkBenchmark* Fact02(void* p) { return new XfermodeBench(p, SkXfermode::kDst_Mode); } -static SkBenchmark* Fact03(void* p) { return new XfermodeBench(p, SkXfermode::kSrcOver_Mode); } -static SkBenchmark* Fact04(void* p) { return new XfermodeBench(p, SkXfermode::kDstOver_Mode); } -static SkBenchmark* Fact05(void* p) { return new XfermodeBench(p, SkXfermode::kSrcIn_Mode); } -static SkBenchmark* Fact06(void* p) { return new XfermodeBench(p, SkXfermode::kDstIn_Mode); } -static SkBenchmark* Fact07(void* p) { return new XfermodeBench(p, SkXfermode::kSrcOut_Mode); } -static SkBenchmark* Fact08(void* p) { return new XfermodeBench(p, SkXfermode::kDstOut_Mode); } -static SkBenchmark* Fact09(void* p) { return new XfermodeBench(p, SkXfermode::kSrcATop_Mode); } -static SkBenchmark* Fact10(void* p) { return new XfermodeBench(p, SkXfermode::kDstATop_Mode); } -static SkBenchmark* Fact11(void* p) { return new XfermodeBench(p, SkXfermode::kXor_Mode); } -static SkBenchmark* Fact12(void* p) { return new XfermodeBench(p, SkXfermode::kPlus_Mode); } -static SkBenchmark* Fact13(void* p) { return new XfermodeBench(p, SkXfermode::kModulate_Mode); } -static SkBenchmark* Fact14(void* p) { return new XfermodeBench(p, SkXfermode::kScreen_Mode); } -static SkBenchmark* Fact15(void* p) { return new XfermodeBench(p, SkXfermode::kOverlay_Mode); } -static SkBenchmark* Fact16(void* p) { return new XfermodeBench(p, SkXfermode::kDarken_Mode); } -static SkBenchmark* Fact17(void* p) { return new XfermodeBench(p, SkXfermode::kLighten_Mode); } -static SkBenchmark* Fact18(void* p) { return new XfermodeBench(p, SkXfermode::kColorDodge_Mode); } -static SkBenchmark* Fact19(void* p) { return new XfermodeBench(p, SkXfermode::kColorBurn_Mode); } -static SkBenchmark* Fact20(void* p) { return new XfermodeBench(p, SkXfermode::kHardLight_Mode); } -static SkBenchmark* Fact21(void* p) { return new XfermodeBench(p, SkXfermode::kSoftLight_Mode); } -static SkBenchmark* Fact22(void* p) { return new XfermodeBench(p, SkXfermode::kDifference_Mode); } -static SkBenchmark* Fact23(void* p) { return new XfermodeBench(p, SkXfermode::kExclusion_Mode); } -static SkBenchmark* Fact24(void* p) { return new XfermodeBench(p, SkXfermode::kMultiply_Mode); } -static SkBenchmark* Fact25(void* p) { return new XfermodeBench(p, SkXfermode::kHue_Mode); } -static SkBenchmark* Fact26(void* p) { return new XfermodeBench(p, SkXfermode::kSaturation_Mode); } -static SkBenchmark* Fact27(void* p) { return new XfermodeBench(p, SkXfermode::kColor_Mode); } -static SkBenchmark* Fact28(void* p) { return new XfermodeBench(p, SkXfermode::kLuminosity_Mode); } +#define CONCAT_I(x, y) x ## y +#define CONCAT(x, y) CONCAT_I(x, y) // allow for macro expansion +#define BENCH(...) \ + static SkBenchmark* CONCAT(Fact, __LINE__)(void *p) { return new XfermodeBench(p, __VA_ARGS__); };\ + static BenchRegistry CONCAT(gReg, __LINE__)(CONCAT(Fact, __LINE__)); -static BenchRegistry gReg00(Fact00); -static BenchRegistry gReg01(Fact01); -static BenchRegistry gReg02(Fact02); -static BenchRegistry gReg03(Fact03); -static BenchRegistry gReg04(Fact04); -static BenchRegistry gReg05(Fact05); -static BenchRegistry gReg06(Fact06); -static BenchRegistry gReg07(Fact07); -static BenchRegistry gReg08(Fact08); -static BenchRegistry gReg09(Fact09); -static BenchRegistry gReg10(Fact10); -static BenchRegistry gReg11(Fact11); -static BenchRegistry gReg12(Fact12); -static BenchRegistry gReg13(Fact13); -static BenchRegistry gReg14(Fact14); -static BenchRegistry gReg15(Fact15); -static BenchRegistry gReg16(Fact16); -static BenchRegistry gReg17(Fact17); -static BenchRegistry gReg18(Fact18); -static BenchRegistry gReg19(Fact19); -static BenchRegistry gReg20(Fact20); -static BenchRegistry gReg21(Fact21); -static BenchRegistry gReg22(Fact22); -static BenchRegistry gReg23(Fact23); -static BenchRegistry gReg24(Fact24); -static BenchRegistry gReg25(Fact25); -static BenchRegistry gReg26(Fact26); -static BenchRegistry gReg27(Fact27); -static BenchRegistry gReg28(Fact28); +BENCH(SkXfermode::kClear_Mode) +BENCH(SkXfermode::kSrc_Mode) +BENCH(SkXfermode::kDst_Mode) +BENCH(SkXfermode::kSrcOver_Mode) +BENCH(SkXfermode::kDstOver_Mode) +BENCH(SkXfermode::kSrcIn_Mode) +BENCH(SkXfermode::kDstIn_Mode) +BENCH(SkXfermode::kSrcOut_Mode) +BENCH(SkXfermode::kDstOut_Mode) +BENCH(SkXfermode::kSrcATop_Mode) +BENCH(SkXfermode::kDstATop_Mode) +BENCH(SkXfermode::kXor_Mode) + +BENCH(SkXfermode::kPlus_Mode) +BENCH(SkXfermode::kModulate_Mode) +BENCH(SkXfermode::kScreen_Mode) + +BENCH(SkXfermode::kOverlay_Mode) +BENCH(SkXfermode::kDarken_Mode) +BENCH(SkXfermode::kLighten_Mode) +BENCH(SkXfermode::kColorDodge_Mode) +BENCH(SkXfermode::kColorBurn_Mode) +BENCH(SkXfermode::kHardLight_Mode) +BENCH(SkXfermode::kSoftLight_Mode) +BENCH(SkXfermode::kDifference_Mode) +BENCH(SkXfermode::kExclusion_Mode) +BENCH(SkXfermode::kMultiply_Mode) + +BENCH(SkXfermode::kHue_Mode) +BENCH(SkXfermode::kSaturation_Mode) +BENCH(SkXfermode::kColor_Mode) +BENCH(SkXfermode::kLuminosity_Mode) + +BENCH(SkLumaMaskXfermode::Create(SkXfermode::kSrcIn_Mode), "SrcInLuma") +BENCH(SkLumaMaskXfermode::Create(SkXfermode::kDstIn_Mode), "DstInLuma") diff --git a/gm/lumamode.cpp b/gm/lumamode.cpp new file mode 100644 index 000000000..ddafc7c35 --- /dev/null +++ b/gm/lumamode.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gm.h" +#include "SkCanvas.h" +#include "SkLumaXfermode.h" + +static void show_scene(SkCanvas* canvas, SkXfermode* mode, const char* label) { + SkPaint paint; + paint.setAntiAlias(true); + SkRect r, c, bounds = { 10, 10, 110, 110 }; + + c = bounds; + c.fRight = bounds.centerX(); + r = bounds; + r.fBottom = bounds.centerY(); + canvas->drawRect(r, paint); + + SkScalar tw = paint.measureText(label, strlen(label)); + canvas->drawText(label, strlen(label), bounds.centerX() - tw / 2, + bounds.bottom() + 15, paint); + + canvas->saveLayer(&bounds, NULL); + + r = bounds; + r.inset(20, 0); + paint.setColor(0x80FFFF00); + canvas->drawOval(r, paint); + canvas->save(); + canvas->clipRect(c); + paint.setColor(0xFFFFFF00); + canvas->drawOval(r, paint); + canvas->restore(); + + SkPaint xferPaint; + xferPaint.setXfermode(mode); + canvas->saveLayer(&bounds, &xferPaint); + + r = bounds; + r.inset(0, 20); + paint.setColor(0x8080FF00); + canvas->drawOval(r, paint); + canvas->save(); + canvas->clipRect(c); + paint.setColor(0xFF80FF00); + canvas->drawOval(r, paint); + canvas->restore(); + + canvas->restore(); + canvas->restore(); +} + +class LumaXfermodeGM : public skiagm::GM { +public: + LumaXfermodeGM() {} + +protected: + virtual SkString onShortName() SK_OVERRIDE { + return SkString("lumamode"); + } + + virtual SkISize onISize() SK_OVERRIDE { + return SkISize::Make(450, 140); + } + + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { + show_scene(canvas, NULL, "SrcOver"); + canvas->translate(150, 0); + SkAutoTUnref src_in(SkLumaMaskXfermode::Create(SkXfermode::kSrcIn_Mode)); + show_scene(canvas, src_in.get(), "SrcInLuma"); + canvas->translate(150, 0); + SkAutoTUnref dst_in(SkLumaMaskXfermode::Create(SkXfermode::kDstIn_Mode)); + show_scene(canvas, dst_in.get(), "DstInLuma"); + } + +private: + typedef skiagm::GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +DEF_GM( return SkNEW(LumaXfermodeGM); ) diff --git a/gyp/effects.gypi b/gyp/effects.gypi index 84d38acf2..56ba59f09 100644 --- a/gyp/effects.gypi +++ b/gyp/effects.gypi @@ -39,6 +39,7 @@ '<(skia_src_path)/effects/SkLayerRasterizer.cpp', '<(skia_src_path)/effects/SkLerpXfermode.cpp', '<(skia_src_path)/effects/SkLightingImageFilter.cpp', + '<(skia_src_path)/effects/SkLumaXfermode.cpp', '<(skia_src_path)/effects/SkMagnifierImageFilter.cpp', '<(skia_src_path)/effects/SkMatrixConvolutionImageFilter.cpp', '<(skia_src_path)/effects/SkMergeImageFilter.cpp', @@ -99,6 +100,7 @@ '<(skia_include_path)/effects/SkLayerRasterizer.h', '<(skia_include_path)/effects/SkLerpXfermode.h', '<(skia_include_path)/effects/SkLightingImageFilter.h', + '<(skia_include_path)/effects/SkLumaXfermode.h', '<(skia_include_path)/effects/SkOffsetImageFilter.h', '<(skia_include_path)/effects/SkMorphologyImageFilter.h', '<(skia_include_path)/effects/SkPaintFlagsDrawFilter.h', diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index 76b6739d9..b2afc5ef1 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -68,6 +68,7 @@ '../gm/inversepaths.cpp', '../gm/lerpmode.cpp', '../gm/lighting.cpp', + '../gm/lumamode.cpp', '../gm/image.cpp', '../gm/imagefiltersbase.cpp', '../gm/imagefilterscropped.cpp', diff --git a/gyp/public_headers.gypi b/gyp/public_headers.gypi index 10f30e530..472fe2914 100644 --- a/gyp/public_headers.gypi +++ b/gyp/public_headers.gypi @@ -78,6 +78,7 @@ 'effects/SkMergeImageFilter.h', 'effects/SkPerlinNoiseShader.h', 'effects/SkLerpXfermode.h', + 'effects/SkLumaXfermode.h', 'effects/SkRectShaderImageFilter.h', 'effects/SkMagnifierImageFilter.h', 'effects/SkBicubicImageFilter.h', diff --git a/include/effects/SkLumaXfermode.h b/include/effects/SkLumaXfermode.h new file mode 100644 index 000000000..5bcd10eff --- /dev/null +++ b/include/effects/SkLumaXfermode.h @@ -0,0 +1,58 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkLumaXfermode_DEFINED +#define SkLumaXfermode_DEFINED + +#include "SkXfermode.h" + +/** + * Luminance mask transfer, as defined in + * http://www.w3.org/TR/SVG/masking.html#Masking + * http://www.w3.org/TR/css-masking/#MaskValues + * + * The luminance-to-alpha function is applied before performing a standard + * SrcIn/DstIn xfer: + * + * luma(C) = (0.2125 * C.r + 0.7154 * C.g + 0.0721 * C.b) * C.a + * + * (where C is un-premultiplied) + */ +class SK_API SkLumaMaskXfermode : public SkXfermode { +public: + /** Return an SkLumaMaskXfermode object for the specified submode. + * + * Only kSrcIn_Mode and kDstIn_Mode are supported - for everything else, + * the factory returns NULL. + */ + static SkXfermode* Create(SkXfermode::Mode); + + virtual SkPMColor xferColor(SkPMColor, SkPMColor) const SK_OVERRIDE; + virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const SK_OVERRIDE; + + SK_DEVELOPER_TO_STRING() + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLumaMaskXfermode) + +#if SK_SUPPORT_GPU + virtual bool asNewEffectOrCoeff(GrContext*, GrEffectRef**, Coeff*, Coeff*, + GrTexture*) const SK_OVERRIDE; +#endif + +protected: + SkLumaMaskXfermode(SkFlattenableReadBuffer&); + virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + +private: + SkLumaMaskXfermode(SkXfermode::Mode); + + const SkXfermode::Mode fMode; + + typedef SkXfermode INHERITED; +}; + +#endif diff --git a/src/effects/SkLumaXfermode.cpp b/src/effects/SkLumaXfermode.cpp new file mode 100644 index 000000000..df0a663c3 --- /dev/null +++ b/src/effects/SkLumaXfermode.cpp @@ -0,0 +1,221 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkLumaXfermode.h" +#include "SkColorPriv.h" +#include "SkFlattenableBuffers.h" +#include "SkString.h" + +#if SK_SUPPORT_GPU +#include "gl/GrGLEffect.h" +#include "gl/GrGLEffectMatrix.h" +#include "GrContext.h" +#include "GrTBackendEffectFactory.h" +#endif + +static inline SkPMColor luma_proc(const SkPMColor a, const SkPMColor b) { + unsigned luma = SkComputeLuminance(SkGetPackedR32(b), + SkGetPackedG32(b), + SkGetPackedB32(b)); + return SkAlphaMulQ(a, SkAlpha255To256(luma)); +} + +template +static inline const T* lumaOpA(SkXfermode::Mode mode, + const T* src, const T* dst) { + return SkXfermode::kSrcIn_Mode == mode ? src : dst; +} + +template +static inline const T* lumaOpB(SkXfermode::Mode mode, + const T* src, const T* dst) { + return SkXfermode::kSrcIn_Mode == mode ? dst : src; +} + +SkXfermode* SkLumaMaskXfermode::Create(SkXfermode::Mode mode) { + if (kSrcIn_Mode == mode || kDstIn_Mode == mode) { + return SkNEW_ARGS(SkLumaMaskXfermode, (mode)); + } + return NULL; +} + +SkLumaMaskXfermode::SkLumaMaskXfermode(SkXfermode::Mode mode) + : fMode(mode) { + SkASSERT(kSrcIn_Mode == mode || kDstIn_Mode == mode); +} + +SkLumaMaskXfermode::SkLumaMaskXfermode(SkFlattenableReadBuffer& buffer) + : INHERITED(buffer) + , fMode((SkXfermode::Mode)buffer.readUInt()) { + SkASSERT(kSrcIn_Mode == fMode || kDstIn_Mode == fMode); +} + +void SkLumaMaskXfermode::flatten(SkFlattenableWriteBuffer& buffer) const { + INHERITED::flatten(buffer); + buffer.writeUInt(fMode); +} + +SkPMColor SkLumaMaskXfermode::xferColor(SkPMColor src, SkPMColor dst) const { + const SkPMColor* a = lumaOpA(fMode, &src, &dst); + const SkPMColor* b = lumaOpB(fMode, &src, &dst); + return luma_proc(*a, *b); +} + +void SkLumaMaskXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], + int count, const SkAlpha aa[]) const { + const SkPMColor* a = lumaOpA(fMode, src, dst); + const SkPMColor* b = lumaOpB(fMode, src, dst); + + if (aa) { + for (int i = 0; i < count; ++i) { + unsigned cov = aa[i]; + if (cov) { + unsigned resC = luma_proc(a[i], b[i]); + if (cov < 255) { + resC = SkAlphaMulQ(resC, SkAlpha255To256(cov)); + } + dst[i] = resC; + } + } + } else { + for (int i = 0; i < count; ++i) { + dst[i] = luma_proc(a[i], b[i]); + } + } +} + +#ifdef SK_DEVELOPER +void SkLumaMaskXfermode::toString(SkString* str) const { + str->printf("SkLumaMaskXfermode: mode: %s", + fMode == kSrcIn_Mode ? "SRC_IN" : "DST_IN"); +} +#endif + +#if SK_SUPPORT_GPU +////////////////////////////////////////////////////////////////////////////// + +class GrGLLumaMaskEffect : public GrGLEffect { +public: + GrGLLumaMaskEffect(const GrBackendEffectFactory&, const GrDrawEffect&); + virtual ~GrGLLumaMaskEffect(); + + virtual void emitCode(GrGLShaderBuilder*, + const GrDrawEffect&, + EffectKey, + const char* outputColor, + const char* inputColor, + const TextureSamplerArray&) SK_OVERRIDE; + + static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); + +private: + typedef GrGLEffect INHERITED; +}; + +class GrLumaMaskEffect : public GrEffect { +public: + static GrEffectRef* Create(SkXfermode::Mode mode) { + AutoEffectUnref effect(SkNEW_ARGS(GrLumaMaskEffect, (mode))); + return CreateEffectRef(effect); + } + + virtual ~GrLumaMaskEffect(); + + typedef GrGLLumaMaskEffect GLEffect; + static const char* Name() { return "LumaMask"; } + + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; + virtual void getConstantColorComponents(GrColor*, uint32_t*) const SK_OVERRIDE; + + SkXfermode::Mode getMode() const { return fMode; } + +private: + GrLumaMaskEffect(SkXfermode::Mode); + + virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; + + const SkXfermode::Mode fMode; +}; + +////////////////////////////////////////////////////////////////////////////// + +GrGLLumaMaskEffect::GrGLLumaMaskEffect(const GrBackendEffectFactory& factory, + const GrDrawEffect&) + : INHERITED(factory) { +} + +GrGLLumaMaskEffect::~GrGLLumaMaskEffect() { +} + +void GrGLLumaMaskEffect::emitCode(GrGLShaderBuilder* builder, + const GrDrawEffect& effect, + EffectKey key, + const char* outputColor, + const char* inputColor, + const TextureSamplerArray& samplers) { + + const GrLumaMaskEffect& lumaEffect = effect.castEffect(); + const char* dstColor = builder->dstColor(); + SkASSERT(NULL != dstColor); + if (NULL == inputColor) { + inputColor = GrGLSLOnesVecf(4); + } + + const char *opA = lumaOpA(lumaEffect.getMode(), inputColor, dstColor); + const char *opB = lumaOpB(lumaEffect.getMode(), inputColor, dstColor); + + builder->fsCodeAppendf("\t\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb); \n", + SK_ITU_BT709_LUM_COEFF_R, + SK_ITU_BT709_LUM_COEFF_G, + SK_ITU_BT709_LUM_COEFF_B, + opB); + builder->fsCodeAppendf("\t\t%s = %s * luma;\n", outputColor, opA); +} + +GrGLEffect::EffectKey GrGLLumaMaskEffect::GenKey(const GrDrawEffect& drawEffect, + const GrGLCaps&) { + const GrLumaMaskEffect& effect = drawEffect.castEffect(); + return (EffectKey)effect.getMode(); +} + +////////////////////////////////////////////////////////////////////////////// + +GrLumaMaskEffect::GrLumaMaskEffect(SkXfermode::Mode mode) + : fMode(mode) { + this->setWillReadDstColor(); +} + +GrLumaMaskEffect::~GrLumaMaskEffect() { +} + +const GrBackendEffectFactory& GrLumaMaskEffect::getFactory() const { + return GrTBackendEffectFactory::getInstance(); +} + +void GrLumaMaskEffect::getConstantColorComponents(GrColor*, uint32_t *validFlags) const { + *validFlags = 0; +} + +bool GrLumaMaskEffect::onIsEqual(const GrEffect& sBase) const { + return fMode == CastEffect(sBase).fMode; +} + +////////////////////////////////////////////////////////////////////////////// + +bool SkLumaMaskXfermode::asNewEffectOrCoeff(GrContext*, GrEffectRef** effect, + Coeff*, Coeff*, + GrTexture* background) const { + // No background texture support. + if (effect && !background) { + *effect = GrLumaMaskEffect::Create(fMode); + return true; + } + + return false; +} + +#endif // SK_SUPPORT_GPU diff --git a/src/ports/SkGlobalInitialization_chromium.cpp b/src/ports/SkGlobalInitialization_chromium.cpp index d05af7099..ebdbffb7c 100644 --- a/src/ports/SkGlobalInitialization_chromium.cpp +++ b/src/ports/SkGlobalInitialization_chromium.cpp @@ -15,6 +15,7 @@ #include "SkLayerDrawLooper.h" #include "SkMallocPixelRef.h" #include "SkXfermode.h" +#include "SkLumaXfermode.h" #include "SkMagnifierImageFilter.h" void SkFlattenable::InitializeFlattenables() { @@ -24,6 +25,7 @@ void SkFlattenable::InitializeFlattenables() { SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkCornerPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDashPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerDrawLooper) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaMaskXfermode) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMallocPixelRef) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMagnifierImageFilter) diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp index 24edd31e6..05c3c4e14 100644 --- a/src/ports/SkGlobalInitialization_default.cpp +++ b/src/ports/SkGlobalInitialization_default.cpp @@ -46,6 +46,7 @@ #include "SkLayerRasterizer.h" #include "SkLerpXfermode.h" #include "SkLightingImageFilter.h" +#include "SkLumaXfermode.h" #include "SkMagnifierImageFilter.h" #include "SkMatrixConvolutionImageFilter.h" #include "SkMergeImageFilter.h" @@ -86,6 +87,7 @@ void SkFlattenable::InitializeFlattenables() { SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerDrawLooper) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerRasterizer) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLerpXfermode) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaMaskXfermode) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Sk2DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect)