[skotty,sksg] Initial matte layer support

TBR=
Change-Id: I5b689f5d7b0d147fa200cf5bffe476077085cb19
Reviewed-on: https://skia-review.googlesource.com/93300
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/experimental/skotty/Skotty.cpp b/experimental/skotty/Skotty.cpp
index df5e6e2..284b377 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 @@
     AttachContext*                                              fCtx;
     std::unordered_map<const Json::Value*, sk_sp<sksg::Matrix>> fLayerMatrixCache;
     std::unordered_map<int, const Json::Value*>                 fLayerIndexCache;
+    sk_sp<sksg::RenderNode>                                     fCurrentMatte;
 
     const Json::Value* findLayer(int index) {
         SkASSERT(fLayerList.isArray());
@@ -795,6 +797,17 @@
 
     layerCtx->fCtx->fAnimators.push_back(skstd::make_unique<Activator>(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;
 }