diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp index 5b0e836997..ad513fdc75 100644 --- a/experimental/skottie/Skottie.cpp +++ b/experimental/skottie/Skottie.cpp @@ -1095,8 +1095,18 @@ sk_sp AttachLayer(const Json::Value& jlayer, if (layerCtx->fCurrentMatte) { // There is a pending matte. Apply and reset. - return sksg::MaskEffect::Make(std::move(controller_node), - std::move(layerCtx->fCurrentMatte)); + static constexpr sksg::MaskEffect::Mode gMaskModes[] = { + sksg::MaskEffect::Mode::kNormal, // tt: 1 + sksg::MaskEffect::Mode::kInvert, // tt: 2 + }; + const auto matteType = ParseDefault(jlayer["tt"], 1) - 1; + + if (matteType >= 0 && matteType < SkTo(SK_ARRAY_COUNT(gMaskModes))) { + return sksg::MaskEffect::Make(std::move(controller_node), + std::move(layerCtx->fCurrentMatte), + gMaskModes[matteType]); + } + layerCtx->fCurrentMatte.reset(); } return controller_node; diff --git a/experimental/sksg/effects/SkSGMaskEffect.cpp b/experimental/sksg/effects/SkSGMaskEffect.cpp index 17b4da7037..16e4c0dd8d 100644 --- a/experimental/sksg/effects/SkSGMaskEffect.cpp +++ b/experimental/sksg/effects/SkSGMaskEffect.cpp @@ -11,9 +11,10 @@ namespace sksg { -MaskEffect::MaskEffect(sk_sp child, sk_sp mask) +MaskEffect::MaskEffect(sk_sp child, sk_sp mask, Mode mode) : INHERITED(std::move(child)) - , fMaskNode(std::move(mask)) { + , fMaskNode(std::move(mask)) + , fMaskMode(mode) { this->observeInval(fMaskNode); } @@ -32,7 +33,7 @@ void MaskEffect::onRender(SkCanvas* canvas) const { SkPaint p; - p.setBlendMode(SkBlendMode::kSrcIn); + p.setBlendMode(fMaskMode == Mode::kNormal ? SkBlendMode::kSrcIn : SkBlendMode::kSrcOut); canvas->saveLayer(this->bounds(), &p); this->INHERITED::onRender(canvas); @@ -45,7 +46,9 @@ SkRect MaskEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) const auto maskBounds = fMaskNode->revalidate(ic, ctm); auto childBounds = this->INHERITED::onRevalidate(ic, ctm); - return childBounds.intersect(maskBounds) ? childBounds : SkRect::MakeEmpty(); + return (fMaskMode == Mode::kInvert || childBounds.intersect(maskBounds)) + ? childBounds + : SkRect::MakeEmpty(); } } // namespace sksg diff --git a/experimental/sksg/effects/SkSGMaskEffect.h b/experimental/sksg/effects/SkSGMaskEffect.h index aef82b4ef6..c4fd0120e5 100644 --- a/experimental/sksg/effects/SkSGMaskEffect.h +++ b/experimental/sksg/effects/SkSGMaskEffect.h @@ -18,23 +18,30 @@ namespace sksg { */ class MaskEffect final : public EffectNode { public: - static sk_sp Make(sk_sp child, sk_sp mask) { + enum class Mode { + kNormal, + kInvert + }; + + static sk_sp Make(sk_sp child, sk_sp mask, + Mode mode = Mode::kNormal) { return (child && mask) - ? sk_sp(new MaskEffect(std::move(child), std::move(mask))) + ? sk_sp(new MaskEffect(std::move(child), std::move(mask), mode)) : nullptr; } ~MaskEffect() override; protected: - MaskEffect(sk_sp, sk_sp mask); + MaskEffect(sk_sp, sk_sp mask, Mode); void onRender(SkCanvas*) const override; SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; private: - sk_sp fMaskNode; + const sk_sp fMaskNode; + const Mode fMaskMode; typedef EffectNode INHERITED; };