1 /*
2  * Copyright 2019 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkCanvas.h"
9 #include "SkMakeUnique.h"
10 #include "SkTypes.h"
11 #include "Skottie.h"
12 
13 #include <string>
14 
15 #include <emscripten.h>
16 #include <emscripten/bind.h>
17 #include "WasmAliases.h"
18 
19 #if SK_INCLUDE_MANAGED_SKOTTIE
20 #include "SkottieProperty.h"
21 #include "SkottieUtils.h"
22 #endif // SK_INCLUDE_MANAGED_SKOTTIE
23 
24 using namespace emscripten;
25 
26 #if SK_INCLUDE_MANAGED_SKOTTIE
27 namespace {
28 
29 class ManagedAnimation final : public SkRefCnt {
30 public:
Make(const std::string & json)31     static sk_sp<ManagedAnimation> Make(const std::string& json) {
32         auto mgr = skstd::make_unique<skottie_utils::CustomPropertyManager>();
33         auto animation = skottie::Animation::Builder()
34                             .setMarkerObserver(mgr->getMarkerObserver())
35                             .setPropertyObserver(mgr->getPropertyObserver())
36                             .make(json.c_str(), json.size());
37 
38         return animation
39             ? sk_sp<ManagedAnimation>(new ManagedAnimation(std::move(animation), std::move(mgr)))
40             : nullptr;
41     }
42 
43     // skottie::Animation API
render(SkCanvas * canvas) const44     void render(SkCanvas* canvas) const { fAnimation->render(canvas, nullptr); }
render(SkCanvas * canvas,const SkRect & dst) const45     void render(SkCanvas* canvas, const SkRect& dst) const { fAnimation->render(canvas, &dst); }
seek(SkScalar t)46     void seek(SkScalar t) { fAnimation->seek(t); }
duration() const47     SkScalar duration() const { return fAnimation->duration(); }
size() const48     const SkSize&      size() const { return fAnimation->size(); }
version() const49     std::string version() const { return std::string(fAnimation->version().c_str()); }
50 
51     // CustomPropertyManager API
getColorProps() const52     JSArray getColorProps() const {
53         JSArray props = emscripten::val::array();
54 
55         for (const auto& cp : fPropMgr->getColorProps()) {
56             JSObject prop = emscripten::val::object();
57             prop.set("key", cp);
58             prop.set("value", fPropMgr->getColor(cp));
59             props.call<void>("push", prop);
60         }
61 
62         return props;
63     }
64 
getOpacityProps() const65     JSArray getOpacityProps() const {
66         JSArray props = emscripten::val::array();
67 
68         for (const auto& op : fPropMgr->getOpacityProps()) {
69             JSObject prop = emscripten::val::object();
70             prop.set("key", op);
71             prop.set("value", fPropMgr->getOpacity(op));
72             props.call<void>("push", prop);
73         }
74 
75         return props;
76     }
77 
setColor(const std::string & key,JSColor c)78     bool setColor(const std::string& key, JSColor c) {
79         return fPropMgr->setColor(key, static_cast<SkColor>(c));
80     }
81 
setOpacity(const std::string & key,float o)82     bool setOpacity(const std::string& key, float o) {
83         return fPropMgr->setOpacity(key, o);
84     }
85 
getMarkers() const86     JSArray getMarkers() const {
87         JSArray markers = emscripten::val::array();
88         for (const auto& m : fPropMgr->markers()) {
89             JSObject marker = emscripten::val::object();
90             marker.set("name", m.name);
91             marker.set("t0"  , m.t0);
92             marker.set("t1"  , m.t1);
93             markers.call<void>("push", marker);
94         }
95         return markers;
96     }
97 
98 private:
ManagedAnimation(sk_sp<skottie::Animation> animation,std::unique_ptr<skottie_utils::CustomPropertyManager> propMgr)99     ManagedAnimation(sk_sp<skottie::Animation> animation,
100                      std::unique_ptr<skottie_utils::CustomPropertyManager> propMgr)
101         : fAnimation(std::move(animation))
102         , fPropMgr(std::move(propMgr)) {}
103 
104     sk_sp<skottie::Animation>                             fAnimation;
105     std::unique_ptr<skottie_utils::CustomPropertyManager> fPropMgr;
106 };
107 
108 } // anonymous ns
109 #endif // SK_INCLUDE_MANAGED_SKOTTIE
110 
EMSCRIPTEN_BINDINGS(Skottie)111 EMSCRIPTEN_BINDINGS(Skottie) {
112     // Animation things (may eventually go in own library)
113     class_<skottie::Animation>("Animation")
114         .smart_ptr<sk_sp<skottie::Animation>>("sk_sp<Animation>")
115         .function("version", optional_override([](skottie::Animation& self)->std::string {
116             return std::string(self.version().c_str());
117         }))
118         .function("size", &skottie::Animation::size)
119         .function("duration", &skottie::Animation::duration)
120         .function("seek", &skottie::Animation::seek)
121         .function("render", optional_override([](skottie::Animation& self, SkCanvas* canvas)->void {
122             self.render(canvas, nullptr);
123         }), allow_raw_pointers())
124         .function("render", optional_override([](skottie::Animation& self, SkCanvas* canvas,
125                                                  const SkRect r)->void {
126             self.render(canvas, &r);
127         }), allow_raw_pointers());
128 
129     function("MakeAnimation", optional_override([](std::string json)->sk_sp<skottie::Animation> {
130         return skottie::Animation::Make(json.c_str(), json.length());
131     }));
132     constant("skottie", true);
133 
134 #if SK_INCLUDE_MANAGED_SKOTTIE
135     class_<ManagedAnimation>("ManagedAnimation")
136         .smart_ptr<sk_sp<ManagedAnimation>>("sk_sp<ManagedAnimation>")
137         .function("version"   , &ManagedAnimation::version)
138         .function("size"      , &ManagedAnimation::size)
139         .function("duration"  , &ManagedAnimation::duration)
140         .function("seek"      , &ManagedAnimation::seek)
141         .function("render"    , select_overload<void(SkCanvas*) const>(&ManagedAnimation::render), allow_raw_pointers())
142         .function("render"    , select_overload<void(SkCanvas*, const SkRect&) const>
143                                     (&ManagedAnimation::render), allow_raw_pointers())
144         .function("setColor"  , &ManagedAnimation::setColor)
145         .function("setOpacity", &ManagedAnimation::setOpacity)
146         .function("getMarkers", &ManagedAnimation::getMarkers)
147         .function("getColorProps"  , &ManagedAnimation::getColorProps)
148         .function("getOpacityProps", &ManagedAnimation::getOpacityProps);
149 
150     function("MakeManagedAnimation", &ManagedAnimation::Make);
151     constant("managed_skottie", true);
152 #endif // SK_INCLUDE_MANAGED_SKOTTIE
153 }
154