123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /*
- * Copyright 2019 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/core/SkCanvas.h"
- #include "include/core/SkImage.h"
- #include "include/core/SkString.h"
- #include "include/core/SkTypes.h"
- #include "modules/skottie/include/Skottie.h"
- #include "modules/sksg/include/SkSGInvalidationController.h"
- #include "src/core/SkMakeUnique.h"
- #include <string>
- #include <vector>
- #include <emscripten.h>
- #include <emscripten/bind.h>
- #include "modules/canvaskit/WasmAliases.h"
- #if SK_INCLUDE_MANAGED_SKOTTIE
- #include "modules/skottie/include/SkottieProperty.h"
- #include "modules/skottie/utils/SkottieUtils.h"
- #endif // SK_INCLUDE_MANAGED_SKOTTIE
- using namespace emscripten;
- #if SK_INCLUDE_MANAGED_SKOTTIE
- namespace {
- class SkottieAssetProvider : public skottie::ResourceProvider {
- public:
- ~SkottieAssetProvider() override = default;
- // Tried using a map, but that gave strange errors like
- // https://emscripten.org/docs/porting/guidelines/function_pointer_issues.html
- // Not entirely sure why, but perhaps the iterator in the map was
- // confusing enscripten.
- using AssetVec = std::vector<std::pair<SkString, sk_sp<SkData>>>;
- static sk_sp<SkottieAssetProvider> Make(AssetVec assets) {
- if (assets.empty()) {
- return nullptr;
- }
- return sk_sp<SkottieAssetProvider>(new SkottieAssetProvider(std::move(assets)));
- }
- sk_sp<skottie::ImageAsset> loadImageAsset(const char[] /* path */,
- const char name[],
- const char[] /* id */) const override {
- // For CK/Skottie we ignore paths & IDs, and identify images based solely on name.
- if (auto data = this->findAsset(name)) {
- return skottie_utils::MultiFrameImageAsset::Make(std::move(data), true /* predecode */);
- }
- return nullptr;
- }
- sk_sp<SkData> loadFont(const char name[], const char[] /* url */) const override {
- // Same as images paths, we ignore font URLs.
- return this->findAsset(name);
- }
- private:
- explicit SkottieAssetProvider(AssetVec assets) : fAssets(std::move(assets)) {}
- sk_sp<SkData> findAsset(const char name[]) const {
- for (const auto& asset : fAssets) {
- if (asset.first.equals(name)) {
- return asset.second;
- }
- }
- SkDebugf("Could not find %s\n", name);
- return nullptr;
- }
- const AssetVec fAssets;
- };
- class ManagedAnimation final : public SkRefCnt {
- public:
- static sk_sp<ManagedAnimation> Make(const std::string& json, sk_sp<SkottieAssetProvider> ap) {
- auto mgr = skstd::make_unique<skottie_utils::CustomPropertyManager>();
- auto animation = skottie::Animation::Builder()
- .setMarkerObserver(mgr->getMarkerObserver())
- .setPropertyObserver(mgr->getPropertyObserver())
- .setResourceProvider(ap)
- .make(json.c_str(), json.size());
- return animation
- ? sk_sp<ManagedAnimation>(new ManagedAnimation(std::move(animation), std::move(mgr)))
- : nullptr;
- }
- ~ManagedAnimation() override = default;
- // skottie::Animation API
- void render(SkCanvas* canvas) const { fAnimation->render(canvas, nullptr); }
- void render(SkCanvas* canvas, const SkRect& dst) const { fAnimation->render(canvas, &dst); }
- // Returns a damage rect.
- SkRect seek(SkScalar t) {
- sksg::InvalidationController ic;
- fAnimation->seek(t, &ic);
- return ic.bounds();
- }
- SkScalar duration() const { return fAnimation->duration(); }
- const SkSize& size() const { return fAnimation->size(); }
- std::string version() const { return std::string(fAnimation->version().c_str()); }
- // CustomPropertyManager API
- JSArray getColorProps() const {
- JSArray props = emscripten::val::array();
- for (const auto& cp : fPropMgr->getColorProps()) {
- JSObject prop = emscripten::val::object();
- prop.set("key", cp);
- prop.set("value", fPropMgr->getColor(cp));
- props.call<void>("push", prop);
- }
- return props;
- }
- JSArray getOpacityProps() const {
- JSArray props = emscripten::val::array();
- for (const auto& op : fPropMgr->getOpacityProps()) {
- JSObject prop = emscripten::val::object();
- prop.set("key", op);
- prop.set("value", fPropMgr->getOpacity(op));
- props.call<void>("push", prop);
- }
- return props;
- }
- bool setColor(const std::string& key, SkColor c) {
- return fPropMgr->setColor(key, c);
- }
- bool setOpacity(const std::string& key, float o) {
- return fPropMgr->setOpacity(key, o);
- }
- JSArray getMarkers() const {
- JSArray markers = emscripten::val::array();
- for (const auto& m : fPropMgr->markers()) {
- JSObject marker = emscripten::val::object();
- marker.set("name", m.name);
- marker.set("t0" , m.t0);
- marker.set("t1" , m.t1);
- markers.call<void>("push", marker);
- }
- return markers;
- }
- private:
- ManagedAnimation(sk_sp<skottie::Animation> animation,
- std::unique_ptr<skottie_utils::CustomPropertyManager> propMgr)
- : fAnimation(std::move(animation))
- , fPropMgr(std::move(propMgr)) {}
- sk_sp<skottie::Animation> fAnimation;
- std::unique_ptr<skottie_utils::CustomPropertyManager> fPropMgr;
- };
- } // anonymous ns
- #endif // SK_INCLUDE_MANAGED_SKOTTIE
- EMSCRIPTEN_BINDINGS(Skottie) {
- // Animation things (may eventually go in own library)
- class_<skottie::Animation>("Animation")
- .smart_ptr<sk_sp<skottie::Animation>>("sk_sp<Animation>")
- .function("version", optional_override([](skottie::Animation& self)->std::string {
- return std::string(self.version().c_str());
- }))
- .function("size", &skottie::Animation::size)
- .function("duration", &skottie::Animation::duration)
- .function("seek", optional_override([](skottie::Animation& self, SkScalar t)->void {
- self.seek(t);
- }))
- .function("render", optional_override([](skottie::Animation& self, SkCanvas* canvas)->void {
- self.render(canvas, nullptr);
- }), allow_raw_pointers())
- .function("render", optional_override([](skottie::Animation& self, SkCanvas* canvas,
- const SkRect r)->void {
- self.render(canvas, &r);
- }), allow_raw_pointers());
- function("MakeAnimation", optional_override([](std::string json)->sk_sp<skottie::Animation> {
- return skottie::Animation::Make(json.c_str(), json.length());
- }));
- constant("skottie", true);
- #if SK_INCLUDE_MANAGED_SKOTTIE
- class_<ManagedAnimation>("ManagedAnimation")
- .smart_ptr<sk_sp<ManagedAnimation>>("sk_sp<ManagedAnimation>")
- .function("version" , &ManagedAnimation::version)
- .function("size" , &ManagedAnimation::size)
- .function("duration" , &ManagedAnimation::duration)
- .function("seek" , &ManagedAnimation::seek)
- .function("render" , select_overload<void(SkCanvas*) const>(&ManagedAnimation::render), allow_raw_pointers())
- .function("render" , select_overload<void(SkCanvas*, const SkRect&) const>
- (&ManagedAnimation::render), allow_raw_pointers())
- .function("setColor" , &ManagedAnimation::setColor)
- .function("setOpacity", &ManagedAnimation::setOpacity)
- .function("getMarkers", &ManagedAnimation::getMarkers)
- .function("getColorProps" , &ManagedAnimation::getColorProps)
- .function("getOpacityProps", &ManagedAnimation::getOpacityProps);
- function("_MakeManagedAnimation", optional_override([](std::string json,
- size_t assetCount,
- uintptr_t /* char** */ nptr,
- uintptr_t /* uint8_t** */ dptr,
- uintptr_t /* size_t* */ sptr)
- ->sk_sp<ManagedAnimation> {
- const auto assetNames = reinterpret_cast<char** >(nptr);
- const auto assetDatas = reinterpret_cast<uint8_t**>(dptr);
- const auto assetSizes = reinterpret_cast<size_t* >(sptr);
- SkottieAssetProvider::AssetVec assets;
- assets.reserve(assetCount);
- for (size_t i = 0; i < assetCount; i++) {
- auto name = SkString(assetNames[i]);
- auto bytes = SkData::MakeFromMalloc(assetDatas[i], assetSizes[i]);
- assets.push_back(std::make_pair(std::move(name), std::move(bytes)));
- }
- return ManagedAnimation::Make(json, SkottieAssetProvider::Make(std::move(assets)));
- }));
- constant("managed_skottie", true);
- #endif // SK_INCLUDE_MANAGED_SKOTTIE
- }
|