1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "modules/skottie/utils/SkottieUtils.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_cinamespace skottie_utils { 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ciclass CustomPropertyManager::PropertyInterceptor final : public skottie::PropertyObserver { 13cb93a386Sopenharmony_cipublic: 14cb93a386Sopenharmony_ci explicit PropertyInterceptor(CustomPropertyManager* mgr) : fMgr(mgr) {} 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci void onColorProperty(const char node_name[], 17cb93a386Sopenharmony_ci const LazyHandle<skottie::ColorPropertyHandle>& c) override { 18cb93a386Sopenharmony_ci const auto key = fMgr->acceptKey(node_name, ".Color"); 19cb93a386Sopenharmony_ci if (!key.empty()) { 20cb93a386Sopenharmony_ci fMgr->fColorMap[key].push_back(c()); 21cb93a386Sopenharmony_ci } 22cb93a386Sopenharmony_ci } 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ci void onOpacityProperty(const char node_name[], 25cb93a386Sopenharmony_ci const LazyHandle<skottie::OpacityPropertyHandle>& o) override { 26cb93a386Sopenharmony_ci const auto key = fMgr->acceptKey(node_name, ".Opacity"); 27cb93a386Sopenharmony_ci if (!key.empty()) { 28cb93a386Sopenharmony_ci fMgr->fOpacityMap[key].push_back(o()); 29cb93a386Sopenharmony_ci } 30cb93a386Sopenharmony_ci } 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci void onTransformProperty(const char node_name[], 33cb93a386Sopenharmony_ci const LazyHandle<skottie::TransformPropertyHandle>& t) override { 34cb93a386Sopenharmony_ci const auto key = fMgr->acceptKey(node_name, ".Transform"); 35cb93a386Sopenharmony_ci if (!key.empty()) { 36cb93a386Sopenharmony_ci fMgr->fTransformMap[key].push_back(t()); 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci } 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci void onTextProperty(const char node_name[], 41cb93a386Sopenharmony_ci const LazyHandle<skottie::TextPropertyHandle>& t) override { 42cb93a386Sopenharmony_ci const auto key = fMgr->acceptKey(node_name, ".Text"); 43cb93a386Sopenharmony_ci if (!key.empty()) { 44cb93a386Sopenharmony_ci fMgr->fTextMap[key].push_back(t()); 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci } 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci void onEnterNode(const char node_name[], PropertyObserver::NodeType node_type) override { 49cb93a386Sopenharmony_ci if (node_name == nullptr) { 50cb93a386Sopenharmony_ci return; 51cb93a386Sopenharmony_ci } 52cb93a386Sopenharmony_ci fMgr->fCurrentNode = 53cb93a386Sopenharmony_ci fMgr->fCurrentNode.empty() ? node_name : fMgr->fCurrentNode + "." + node_name; 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci void onLeavingNode(const char node_name[], PropertyObserver::NodeType node_type) override { 57cb93a386Sopenharmony_ci if (node_name == nullptr) { 58cb93a386Sopenharmony_ci return; 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci auto length = strlen(node_name); 61cb93a386Sopenharmony_ci fMgr->fCurrentNode = 62cb93a386Sopenharmony_ci fMgr->fCurrentNode.length() > length 63cb93a386Sopenharmony_ci ? fMgr->fCurrentNode.substr( 64cb93a386Sopenharmony_ci 0, fMgr->fCurrentNode.length() - strlen(node_name) - 1) 65cb93a386Sopenharmony_ci : ""; 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ciprivate: 69cb93a386Sopenharmony_ci CustomPropertyManager* fMgr; 70cb93a386Sopenharmony_ci}; 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ciclass CustomPropertyManager::MarkerInterceptor final : public skottie::MarkerObserver { 73cb93a386Sopenharmony_cipublic: 74cb93a386Sopenharmony_ci explicit MarkerInterceptor(CustomPropertyManager* mgr) : fMgr(mgr) {} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci void onMarker(const char name[], float t0, float t1) override { 77cb93a386Sopenharmony_ci // collect all markers 78cb93a386Sopenharmony_ci fMgr->fMarkers.push_back({ std::string(name), t0, t1 }); 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ciprivate: 82cb93a386Sopenharmony_ci CustomPropertyManager* fMgr; 83cb93a386Sopenharmony_ci}; 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ciCustomPropertyManager::CustomPropertyManager(Mode mode, const char* prefix) 86cb93a386Sopenharmony_ci : fMode(mode) 87cb93a386Sopenharmony_ci , fPrefix(prefix ? prefix : "$") 88cb93a386Sopenharmony_ci , fPropertyInterceptor(sk_make_sp<PropertyInterceptor>(this)) 89cb93a386Sopenharmony_ci , fMarkerInterceptor(sk_make_sp<MarkerInterceptor>(this)) {} 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ciCustomPropertyManager::~CustomPropertyManager() = default; 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_cistd::string CustomPropertyManager::acceptKey(const char* name, const char* suffix) const { 94cb93a386Sopenharmony_ci if (!SkStrStartsWith(name, fPrefix.c_str())) { 95cb93a386Sopenharmony_ci return std::string(); 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci return fMode == Mode::kCollapseProperties 99cb93a386Sopenharmony_ci ? std::string(name) 100cb93a386Sopenharmony_ci : fCurrentNode + suffix; 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_cisk_sp<skottie::PropertyObserver> CustomPropertyManager::getPropertyObserver() const { 104cb93a386Sopenharmony_ci return fPropertyInterceptor; 105cb93a386Sopenharmony_ci} 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_cisk_sp<skottie::MarkerObserver> CustomPropertyManager::getMarkerObserver() const { 108cb93a386Sopenharmony_ci return fMarkerInterceptor; 109cb93a386Sopenharmony_ci} 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_citemplate <typename T> 112cb93a386Sopenharmony_cistd::vector<CustomPropertyManager::PropKey> 113cb93a386Sopenharmony_ciCustomPropertyManager::getProps(const PropMap<T>& container) const { 114cb93a386Sopenharmony_ci std::vector<PropKey> props; 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci for (const auto& prop_list : container) { 117cb93a386Sopenharmony_ci SkASSERT(!prop_list.second.empty()); 118cb93a386Sopenharmony_ci props.push_back(prop_list.first); 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci return props; 122cb93a386Sopenharmony_ci} 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_citemplate <typename V, typename T> 125cb93a386Sopenharmony_ciV CustomPropertyManager::get(const PropKey& key, const PropMap<T>& container) const { 126cb93a386Sopenharmony_ci auto prop_group = container.find(key); 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ci return prop_group == container.end() 129cb93a386Sopenharmony_ci ? V() 130cb93a386Sopenharmony_ci : prop_group->second.front()->get(); 131cb93a386Sopenharmony_ci} 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_citemplate <typename V, typename T> 134cb93a386Sopenharmony_cibool CustomPropertyManager::set(const PropKey& key, const V& val, const PropMap<T>& container) { 135cb93a386Sopenharmony_ci auto prop_group = container.find(key); 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_ci if (prop_group == container.end()) { 138cb93a386Sopenharmony_ci return false; 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci for (auto& handle : prop_group->second) { 142cb93a386Sopenharmony_ci handle->set(val); 143cb93a386Sopenharmony_ci } 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_ci return true; 146cb93a386Sopenharmony_ci} 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_cistd::vector<CustomPropertyManager::PropKey> 149cb93a386Sopenharmony_ciCustomPropertyManager::getColorProps() const { 150cb93a386Sopenharmony_ci return this->getProps(fColorMap); 151cb93a386Sopenharmony_ci} 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ciskottie::ColorPropertyValue CustomPropertyManager::getColor(const PropKey& key) const { 154cb93a386Sopenharmony_ci return this->get<skottie::ColorPropertyValue>(key, fColorMap); 155cb93a386Sopenharmony_ci} 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_cibool CustomPropertyManager::setColor(const PropKey& key, const skottie::ColorPropertyValue& c) { 158cb93a386Sopenharmony_ci return this->set(key, c, fColorMap); 159cb93a386Sopenharmony_ci} 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_cistd::vector<CustomPropertyManager::PropKey> 162cb93a386Sopenharmony_ciCustomPropertyManager::getOpacityProps() const { 163cb93a386Sopenharmony_ci return this->getProps(fOpacityMap); 164cb93a386Sopenharmony_ci} 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ciskottie::OpacityPropertyValue CustomPropertyManager::getOpacity(const PropKey& key) const { 167cb93a386Sopenharmony_ci return this->get<skottie::OpacityPropertyValue>(key, fOpacityMap); 168cb93a386Sopenharmony_ci} 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_cibool CustomPropertyManager::setOpacity(const PropKey& key, const skottie::OpacityPropertyValue& o) { 171cb93a386Sopenharmony_ci return this->set(key, o, fOpacityMap); 172cb93a386Sopenharmony_ci} 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_cistd::vector<CustomPropertyManager::PropKey> 175cb93a386Sopenharmony_ciCustomPropertyManager::getTransformProps() const { 176cb93a386Sopenharmony_ci return this->getProps(fTransformMap); 177cb93a386Sopenharmony_ci} 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ciskottie::TransformPropertyValue CustomPropertyManager::getTransform(const PropKey& key) const { 180cb93a386Sopenharmony_ci return this->get<skottie::TransformPropertyValue>(key, fTransformMap); 181cb93a386Sopenharmony_ci} 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_cibool CustomPropertyManager::setTransform(const PropKey& key, 184cb93a386Sopenharmony_ci const skottie::TransformPropertyValue& t) { 185cb93a386Sopenharmony_ci return this->set(key, t, fTransformMap); 186cb93a386Sopenharmony_ci} 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_cistd::vector<CustomPropertyManager::PropKey> 189cb93a386Sopenharmony_ciCustomPropertyManager::getTextProps() const { 190cb93a386Sopenharmony_ci return this->getProps(fTextMap); 191cb93a386Sopenharmony_ci} 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ciskottie::TextPropertyValue CustomPropertyManager::getText(const PropKey& key) const { 194cb93a386Sopenharmony_ci return this->get<skottie::TextPropertyValue>(key, fTextMap); 195cb93a386Sopenharmony_ci} 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_cibool CustomPropertyManager::setText(const PropKey& key, const skottie::TextPropertyValue& o) { 198cb93a386Sopenharmony_ci return this->set(key, o, fTextMap); 199cb93a386Sopenharmony_ci} 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_cinamespace { 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_ciclass ExternalAnimationLayer final : public skottie::ExternalLayer { 204cb93a386Sopenharmony_cipublic: 205cb93a386Sopenharmony_ci ExternalAnimationLayer(sk_sp<skottie::Animation> anim, const SkSize& size) 206cb93a386Sopenharmony_ci : fAnimation(std::move(anim)) 207cb93a386Sopenharmony_ci , fSize(size) {} 208cb93a386Sopenharmony_ci 209cb93a386Sopenharmony_ciprivate: 210cb93a386Sopenharmony_ci void render(SkCanvas* canvas, double t) override { 211cb93a386Sopenharmony_ci fAnimation->seekFrameTime(t); 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_ci const auto dst_rect = SkRect::MakeSize(fSize); 214cb93a386Sopenharmony_ci fAnimation->render(canvas, &dst_rect); 215cb93a386Sopenharmony_ci } 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_ci const sk_sp<skottie::Animation> fAnimation; 218cb93a386Sopenharmony_ci const SkSize fSize; 219cb93a386Sopenharmony_ci}; 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_ci} // namespace 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_ciExternalAnimationPrecompInterceptor::ExternalAnimationPrecompInterceptor( 224cb93a386Sopenharmony_ci sk_sp<skresources::ResourceProvider> rprovider, 225cb93a386Sopenharmony_ci const char prefixp[]) 226cb93a386Sopenharmony_ci : fResourceProvider(std::move(rprovider)) 227cb93a386Sopenharmony_ci , fPrefix(prefixp) {} 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_ciExternalAnimationPrecompInterceptor::~ExternalAnimationPrecompInterceptor() = default; 230cb93a386Sopenharmony_ci 231cb93a386Sopenharmony_cisk_sp<skottie::ExternalLayer> ExternalAnimationPrecompInterceptor::onLoadPrecomp( 232cb93a386Sopenharmony_ci const char[], const char name[], const SkSize& size) { 233cb93a386Sopenharmony_ci if (0 != strncmp(name, fPrefix.c_str(), fPrefix.size())) { 234cb93a386Sopenharmony_ci return nullptr; 235cb93a386Sopenharmony_ci } 236cb93a386Sopenharmony_ci 237cb93a386Sopenharmony_ci auto data = fResourceProvider->load("", name + fPrefix.size()); 238cb93a386Sopenharmony_ci if (!data) { 239cb93a386Sopenharmony_ci return nullptr; 240cb93a386Sopenharmony_ci } 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_ci auto anim = skottie::Animation::Builder() 243cb93a386Sopenharmony_ci .setPrecompInterceptor(sk_ref_sp(this)) 244cb93a386Sopenharmony_ci .make(static_cast<const char*>(data->data()), data->size()); 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci return anim ? sk_make_sp<ExternalAnimationLayer>(std::move(anim), size) 247cb93a386Sopenharmony_ci : nullptr; 248cb93a386Sopenharmony_ci} 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci} // namespace skottie_utils 251