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