From 5f9102f2912ef702e013c48466b5461f2a0b9eb9 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Wed, 10 Jan 2018 13:36:22 -0500 Subject: [skotty,sksg] Initial matte layer support TBR= Change-Id: I5b689f5d7b0d147fa200cf5bffe476077085cb19 Reviewed-on: https://skia-review.googlesource.com/93300 Reviewed-by: Florin Malita Commit-Queue: Florin Malita --- experimental/skotty/Skotty.cpp | 13 +++++++ experimental/sksg/SkSGNode.h | 1 + experimental/sksg/effects/SkSGMaskEffect.cpp | 51 ++++++++++++++++++++++++++++ experimental/sksg/effects/SkSGMaskEffect.h | 44 ++++++++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 experimental/sksg/effects/SkSGMaskEffect.cpp create mode 100644 experimental/sksg/effects/SkSGMaskEffect.h (limited to 'experimental') diff --git a/experimental/skotty/Skotty.cpp b/experimental/skotty/Skotty.cpp index df5e6e289d..284b37704a 100644 --- a/experimental/skotty/Skotty.cpp +++ b/experimental/skotty/Skotty.cpp @@ -24,6 +24,7 @@ #include "SkSGGroup.h" #include "SkSGImage.h" #include "SkSGInvalidationController.h" +#include "SkSGMaskEffect.h" #include "SkSGMerge.h" #include "SkSGOpacityEffect.h" #include "SkSGPath.h" @@ -689,6 +690,7 @@ struct AttachLayerContext { AttachContext* fCtx; std::unordered_map> fLayerMatrixCache; std::unordered_map fLayerIndexCache; + sk_sp fCurrentMatte; const Json::Value* findLayer(int index) { SkASSERT(fLayerList.isArray()); @@ -795,6 +797,17 @@ sk_sp AttachLayer(const Json::Value& jlayer, layerCtx->fCtx->fAnimators.push_back(skstd::make_unique(layerControl, in, out)); + if (ParseBool(jlayer["td"], false)) { + // This layer is a matte. We apply it as a mask to the next layer. + layerCtx->fCurrentMatte = std::move(layerControl); + return nullptr; + } + + if (layerCtx->fCurrentMatte) { + // There is a pending matte. Apply and reset. + return sksg::MaskEffect::Make(std::move(layerControl), std::move(layerCtx->fCurrentMatte)); + } + return layerControl; } diff --git a/experimental/sksg/SkSGNode.h b/experimental/sksg/SkSGNode.h index 1ed2a782d2..37139339f2 100644 --- a/experimental/sksg/SkSGNode.h +++ b/experimental/sksg/SkSGNode.h @@ -71,6 +71,7 @@ private: friend class Draw; friend class EffectNode; friend class Group; + friend class MaskEffect; friend class Matrix; friend class Merge; friend class Stroke; diff --git a/experimental/sksg/effects/SkSGMaskEffect.cpp b/experimental/sksg/effects/SkSGMaskEffect.cpp new file mode 100644 index 0000000000..d4ce6df4db --- /dev/null +++ b/experimental/sksg/effects/SkSGMaskEffect.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSGMaskEffect.h" + +#include "SkCanvas.h" + +namespace sksg { + +MaskEffect::MaskEffect(sk_sp child, sk_sp mask) + : INHERITED(std::move(child)) + , fMaskNode(std::move(mask)) { + fMaskNode->addInvalReceiver(this); +} + +MaskEffect::~MaskEffect() { + fMaskNode->removeInvalReceiver(this); +} + +void MaskEffect::onRender(SkCanvas* canvas) const { + if (this->bounds().isEmpty()) + return; + + SkAutoCanvasRestore acr(canvas, false); + + canvas->saveLayer(this->bounds(), nullptr); + fMaskNode->render(canvas); + + + SkPaint p; + p.setBlendMode(SkBlendMode::kSrcIn); + canvas->saveLayer(this->bounds(), &p); + + this->INHERITED::onRender(canvas); +} + + +SkRect MaskEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { + SkASSERT(this->hasInval()); + + const auto maskBounds = fMaskNode->revalidate(ic, ctm); + auto childBounds = this->INHERITED::onRevalidate(ic, ctm); + + return childBounds.intersect(maskBounds) ? childBounds : SkRect::MakeEmpty(); +} + +} // namespace sksg diff --git a/experimental/sksg/effects/SkSGMaskEffect.h b/experimental/sksg/effects/SkSGMaskEffect.h new file mode 100644 index 0000000000..aef82b4ef6 --- /dev/null +++ b/experimental/sksg/effects/SkSGMaskEffect.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkSGMaskEffect_DEFINED +#define SkSGMaskEffect_DEFINED + +#include "SkSGEffectNode.h" + +namespace sksg { + +/** + * Concrete Effect node, applying a mask to its descendants. + * + */ +class MaskEffect final : public EffectNode { +public: + static sk_sp Make(sk_sp child, sk_sp mask) { + return (child && mask) + ? sk_sp(new MaskEffect(std::move(child), std::move(mask))) + : nullptr; + } + + ~MaskEffect() override; + +protected: + MaskEffect(sk_sp, sk_sp mask); + + void onRender(SkCanvas*) const override; + + SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + +private: + sk_sp fMaskNode; + + typedef EffectNode INHERITED; +}; + +} // namespace sksg + +#endif // SkSGMaskEffect_DEFINED -- cgit v1.2.3