diff options
author | Florin Malita <fmalita@chromium.org> | 2018-01-23 13:37:59 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-01-23 18:59:20 +0000 |
commit | 25366fad43043f1bfe02135f9c18515639a3c9b0 (patch) | |
tree | 0bf3b68c9fca7172d1f1fe9d88d0c781fae01700 /experimental/skottie | |
parent | 74d6e113a54da48be669645deacaa48235f77e53 (diff) |
[skottie] Initial mask support
TBR=
Change-Id: Ibf4baeb17f98e1ed359f04deefe2f1c09414540d
Reviewed-on: https://skia-review.googlesource.com/98840
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'experimental/skottie')
-rw-r--r-- | experimental/skottie/Skottie.cpp | 77 |
1 files changed, 68 insertions, 9 deletions
diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp index 73818d0035..2199f51f2a 100644 --- a/experimental/skottie/Skottie.cpp +++ b/experimental/skottie/Skottie.cpp @@ -173,17 +173,18 @@ sk_sp<sksg::RenderNode> AttachOpacity(const Json::Value& jtransform, AttachConte sk_sp<sksg::RenderNode> AttachComposition(const Json::Value&, AttachContext* ctx); -sk_sp<sksg::GeometryNode> AttachPathGeometry(const Json::Value& jpath, AttachContext* ctx) { - SkASSERT(jpath.isObject()); - +sk_sp<sksg::Path> AttachPath(const Json::Value& jpath, AttachContext* ctx) { auto path_node = sksg::Path::Make(); - auto path_attached = BindProperty<ShapeValue>(jpath["ks"], ctx, path_node, - [](sksg::Path* node, const ShapeValue& p) { node->setPath(p); }); + return BindProperty<ShapeValue>(jpath, ctx, path_node, + [](sksg::Path* node, const ShapeValue& p) { node->setPath(p); }) + ? path_node + : nullptr; +} - if (path_attached) - LOG("** Attached path geometry - verbs: %d\n", path_node->getPath().countVerbs()); +sk_sp<sksg::GeometryNode> AttachPathGeometry(const Json::Value& jpath, AttachContext* ctx) { + SkASSERT(jpath.isObject()); - return path_attached ? path_node : nullptr; + return AttachPath(jpath["ks"], ctx); } sk_sp<sksg::GeometryNode> AttachRRectGeometry(const Json::Value& jrect, AttachContext* ctx) { @@ -881,6 +882,62 @@ struct AttachLayerContext { } }; +SkBlendMode MaskBlendMode(char mode) { + switch (mode) { + case 'a': return SkBlendMode::kSrcOver; // Additive + case 's': return SkBlendMode::kExclusion; // Subtract + case 'i': return SkBlendMode::kDstIn; // Intersect + case 'l': return SkBlendMode::kLighten; // Lighten + case 'd': return SkBlendMode::kDarken; // Darken + case 'f': return SkBlendMode::kDifference; // Difference + default: break; + } + + return SkBlendMode::kSrcOver; +} + +sk_sp<sksg::RenderNode> AttachMask(const Json::Value& jmask, + AttachContext* ctx, + sk_sp<sksg::RenderNode> childNode) { + if (!jmask.isArray()) + return childNode; + + auto mask_group = sksg::Group::Make(); + + for (const auto& m : jmask) { + if (!m.isObject()) + continue; + + const auto inverted = ParseBool(m["inv"], false); + // TODO + if (inverted) { + LogFail(m, "Unsupported inverse mask"); + continue; + } + + auto mask_path = AttachPath(m["pt"], ctx); + if (!mask_path) { + LogFail(m, "Could not parse mask path"); + continue; + } + + auto mode = ParseString(m["mode"], ""); + if (mode.size() != 1 || !strcmp(mode.c_str(), "n")) // "None" masks have no effect. + continue; + + auto mask_paint = sksg::Color::Make(SK_ColorBLACK); + mask_paint->setBlendMode(MaskBlendMode(mode.c_str()[0])); + BindProperty<ScalarValue>(m["o"], ctx, mask_paint, + [](sksg::Color* node, const ScalarValue& o) { node->setOpacity(o * 0.01f); }); + + mask_group->addChild(sksg::Draw::Make(std::move(mask_path), std::move(mask_paint))); + } + + return mask_group->empty() + ? childNode + : sksg::MaskEffect::Make(std::move(childNode), std::move(mask_group)); +} + sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer, AttachLayerContext* layerCtx) { if (!jlayer.isObject()) @@ -903,8 +960,10 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer, // Layer content. auto layer = gLayerAttachers[type](jlayer, layerCtx->fCtx); + // Optional layer mask. + layer = AttachMask(jlayer["masksProperties"], layerCtx->fCtx, std::move(layer)); + // Optional layer transform. if (auto layerMatrix = layerCtx->AttachLayerMatrix(jlayer)) { - // Optional layer transform. layer = sksg::Transform::Make(std::move(layer), std::move(layerMatrix)); } // Optional layer opacity. |