diff --git a/modules/skottie/skottie.gni b/modules/skottie/skottie.gni index f0585b0247..ee6d320392 100644 --- a/modules/skottie/skottie.gni +++ b/modules/skottie/skottie.gni @@ -45,6 +45,7 @@ skia_skottie_sources = [ "$_src/effects/Effects.h", "$_src/effects/FillEffect.cpp", "$_src/effects/GaussianBlurEffect.cpp", + "$_src/effects/GlowStyles.cpp", "$_src/effects/GradientEffect.cpp", "$_src/effects/HueSaturationEffect.cpp", "$_src/effects/InvertEffect.cpp", diff --git a/modules/skottie/src/effects/Effects.cpp b/modules/skottie/src/effects/Effects.cpp index cbbf4eb73a..e34a955d4d 100644 --- a/modules/skottie/src/effects/Effects.cpp +++ b/modules/skottie/src/effects/Effects.cpp @@ -130,6 +130,8 @@ sk_sp EffectBuilder::attachStyles(const skjson::ArrayValue& js nullptr, // 'ty': 0 -> stroke &EffectBuilder::attachDropShadowStyle, // 'ty': 1 -> drop shadow &EffectBuilder::attachInnerShadowStyle, // 'ty': 2 -> inner shadow + &EffectBuilder::attachOuterGlowStyle, // 'ty': 3 -> outer glow + &EffectBuilder::attachInnerGlowStyle, // 'ty': 4 -> inner glow }; for (const skjson::ObjectValue* jstyle : jstyles) { diff --git a/modules/skottie/src/effects/Effects.h b/modules/skottie/src/effects/Effects.h index 7a48982ea4..86ce8134d8 100644 --- a/modules/skottie/src/effects/Effects.h +++ b/modules/skottie/src/effects/Effects.h @@ -75,6 +75,10 @@ private: sk_sp) const; sk_sp attachInnerShadowStyle(const skjson::ObjectValue&, sk_sp) const; + sk_sp attachInnerGlowStyle(const skjson::ObjectValue&, + sk_sp) const; + sk_sp attachOuterGlowStyle(const skjson::ObjectValue&, + sk_sp) const; EffectBuilderT findBuilder(const skjson::ObjectValue&) const; diff --git a/modules/skottie/src/effects/GlowStyles.cpp b/modules/skottie/src/effects/GlowStyles.cpp new file mode 100644 index 0000000000..f87a3743db --- /dev/null +++ b/modules/skottie/src/effects/GlowStyles.cpp @@ -0,0 +1,111 @@ +/* + * Copyright 2020 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "modules/skottie/src/effects/Effects.h" + +#include "include/core/SkColorFilter.h" +#include "include/effects/SkColorMatrix.h" +#include "include/effects/SkImageFilters.h" +#include "modules/skottie/src/Adapter.h" +#include "modules/skottie/src/SkottieJson.h" +#include "modules/skottie/src/SkottieValue.h" +#include "modules/sksg/include/SkSGRenderEffect.h" + +namespace skottie::internal { + +namespace { + +class GlowAdapter final : public DiscardableAdapterBase { +public: + enum Type { + kOuterGlow, + kInnerGlow, + }; + + GlowAdapter(const skjson::ObjectValue& jstyle, const AnimationBuilder& abuilder, Type type) + : fType(type) { + this->bind(abuilder, jstyle["c" ], fColor); + this->bind(abuilder, jstyle["o" ], fOpacity); + this->bind(abuilder, jstyle["s" ], fSize); + this->bind(abuilder, jstyle["sr"], fInnerSource); + } + +private: + void onSync() override { + const auto sigma = fSize * kBlurSizeToSigma, + opacity = SkTPin(fOpacity / 100, 0.0f, 1.0f); + const auto color = static_cast(fColor); + + // Select and colorize the source alpha channel. + SkColorMatrix cm{0, 0, 0, 0, color.fR, + 0, 0, 0, 0, color.fG, + 0, 0, 0, 0, color.fB, + 0, 0, 0, opacity * color.fA, 0}; + + // Inner glows with an edge source use the alpha inverse. + if (fType == Type::kInnerGlow && SkScalarRoundToInt(fInnerSource) == kEdge) { + cm.preConcat({1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0,-1, 1}); + } + auto f = SkImageFilters::ColorFilter(SkColorFilters::Matrix(cm), nullptr); + + if (sigma > 0) { + f = SkImageFilters::Blur(sigma, sigma, std::move(f)); + } + + sk_sp source; + + if (fType == Type::kInnerGlow) { + // Inner glows draw on top of, and are masked with, the source. + f = SkImageFilters::Xfermode(SkBlendMode::kDstIn, std::move(f)); + + std::swap(source, f); + } + + this->node()->setImageFilter(SkImageFilters::Merge(std::move(f), + std::move(source))); + } + + enum InnerSource { + kEdge = 1, + kCenter = 2, + }; + + const Type fType; + + VectorValue fColor; + ScalarValue fOpacity = 100, // percentage + fSize = 0, + fInnerSource = kEdge; + + using INHERITED = DiscardableAdapterBase; +}; + +static sk_sp make_glow_effect(const skjson::ObjectValue& jstyle, + const AnimationBuilder& abuilder, + sk_sp layer, + GlowAdapter::Type type) { + auto filter_node = abuilder.attachDiscardableAdapter(jstyle, abuilder, type); + + return sksg::ImageFilterEffect::Make(std::move(layer), std::move(filter_node)); +} + +} // namespace + +sk_sp EffectBuilder::attachOuterGlowStyle(const skjson::ObjectValue& jstyle, + sk_sp layer) const { + return make_glow_effect(jstyle, *fBuilder, std::move(layer), GlowAdapter::Type::kOuterGlow); +} + +sk_sp EffectBuilder::attachInnerGlowStyle(const skjson::ObjectValue& jstyle, + sk_sp layer) const { + return make_glow_effect(jstyle, *fBuilder, std::move(layer), GlowAdapter::Type::kInnerGlow); +} + +} // namespace skottie::internal diff --git a/resources/skottie/skottie-innerglow-style.json b/resources/skottie/skottie-innerglow-style.json new file mode 100644 index 0000000000..34ac12ab29 --- /dev/null +++ b/resources/skottie/skottie-innerglow-style.json @@ -0,0 +1 @@ +{"v":"5.6.8","fr":60,"ip":0,"op":600,"w":500,"h":500,"nm":"inner glow","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sr","sy":1,"d":1,"pt":{"a":0,"k":5,"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":600,"s":[720]}],"ix":5},"ir":{"a":0,"k":35,"ix":6},"is":{"a":0,"k":0,"ix":8},"or":{"a":0,"k":100,"ix":7},"os":{"a":0,"k":0,"ix":9},"ix":1,"nm":"Polystar Path 1","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"fl","c":{"a":0,"k":[0.186933204532,0.489476114511,1,1],"ix":4},"o":{"a":0,"k":75,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[150,150],"ix":2},"p":{"a":0,"k":[80,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.230637252331,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":21,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.799341320992,0.889966309071,0.211565569043,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":600,"s":[-360]}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":601,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"precomp","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":599,"s":[-360]}],"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":150,"s":[150,150,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":300,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":450,"s":[75,75,100]},{"t":599,"s":[100,100,100]}],"ix":6}},"ao":0,"sy":[{"c":{"a":0,"k":[1,0,0,1],"ix":5},"o":{"a":0,"k":100,"ix":2},"s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":150,"s":[200]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":300,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":301,"s":[300]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":450,"s":[0]},{"t":599,"s":[300]}],"ix":11},"r":{"a":0,"k":100,"ix":12},"sr":{"a":1,"k":[{"t":0,"s":[1],"h":1},{"t":301,"s":[2],"h":1}],"ix":9},"ch":{"a":0,"k":0,"ix":10},"bm":{"a":0,"k":1,"ix":1},"no":{"a":0,"k":0,"ix":3},"j":{"a":0,"k":0,"ix":13},"ty":4,"nm":"Inner Glow"}],"w":500,"h":500,"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":1,"nm":"bg","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"sw":500,"sh":500,"sc":"#ffffff","ip":0,"op":600,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/resources/skottie/skottie-outerglow-style.json b/resources/skottie/skottie-outerglow-style.json new file mode 100644 index 0000000000..2b1ac87c7a --- /dev/null +++ b/resources/skottie/skottie-outerglow-style.json @@ -0,0 +1 @@ +{"v":"5.6.8","fr":60,"ip":0,"op":600,"w":500,"h":500,"nm":"outer glow","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sr","sy":1,"d":1,"pt":{"a":0,"k":5,"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":600,"s":[720]}],"ix":5},"ir":{"a":0,"k":35,"ix":6},"is":{"a":0,"k":0,"ix":8},"or":{"a":0,"k":100,"ix":7},"os":{"a":0,"k":0,"ix":9},"ix":1,"nm":"Polystar Path 1","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"fl","c":{"a":0,"k":[0.186933204532,0.489476114511,1,1],"ix":4},"o":{"a":0,"k":75,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[150,150],"ix":2},"p":{"a":0,"k":[80,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.230637252331,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":21,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.799341320992,0.889966309071,0.211565569043,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":600,"s":[-360]}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":601,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"precomp","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":599,"s":[-360]}],"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":150,"s":[150,150,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":300,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":450,"s":[75,75,100]},{"t":599,"s":[100,100,100]}],"ix":6}},"ao":0,"sy":[{"c":{"a":0,"k":[1,0,0,1],"ix":5},"o":{"a":0,"k":85,"ix":2},"s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":300,"s":[100]},{"t":599,"s":[0]}],"ix":10},"r":{"a":0,"k":100,"ix":11},"ch":{"a":0,"k":0,"ix":9},"bm":{"a":0,"k":1,"ix":1},"no":{"a":0,"k":0,"ix":3},"j":{"a":0,"k":100,"ix":12},"ty":3,"nm":"Outer Glow"}],"w":500,"h":500,"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":1,"nm":"bg","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"sw":500,"sh":500,"sc":"#ffffff","ip":0,"op":600,"st":0,"bm":0}],"markers":[]} \ No newline at end of file