blob: 14fe0e0e87dca7064f96599781d3a9de7407e5a2 [file] [log] [blame]
Florin Malitaa8316552018-11-09 16:19:44 -05001/*
2 * Copyright 2018 Google Inc.
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "modules/skottie/utils/SkottieUtils.h"
Florin Malitaa8316552018-11-09 16:19:44 -05009
Florin Malitaa8316552018-11-09 16:19:44 -050010namespace skottie_utils {
11
Florin Malita91af8d82018-11-30 16:46:45 -050012class CustomPropertyManager::PropertyInterceptor final : public skottie::PropertyObserver {
13public:
14 explicit PropertyInterceptor(CustomPropertyManager* mgr) : fMgr(mgr) {}
Florin Malita8ac81b72018-11-28 11:39:39 -050015
Florin Malita91af8d82018-11-30 16:46:45 -050016 void onColorProperty(const char node_name[],
17 const LazyHandle<skottie::ColorPropertyHandle>& c) override {
Florin Malita3f45e4b2020-08-20 14:51:41 -040018 const auto key = fMgr->acceptKey(node_name, ".Color");
19 if (!key.empty()) {
20 fMgr->fColorMap[key].push_back(c());
21 }
Florin Malita8ac81b72018-11-28 11:39:39 -050022 }
Florin Malita8ac81b72018-11-28 11:39:39 -050023
Florin Malita91af8d82018-11-30 16:46:45 -050024 void onOpacityProperty(const char node_name[],
25 const LazyHandle<skottie::OpacityPropertyHandle>& o) override {
Florin Malita3f45e4b2020-08-20 14:51:41 -040026 const auto key = fMgr->acceptKey(node_name, ".Opacity");
27 if (!key.empty()) {
28 fMgr->fOpacityMap[key].push_back(o());
29 }
Florin Malita8ac81b72018-11-28 11:39:39 -050030 }
Florin Malita8ac81b72018-11-28 11:39:39 -050031
Florin Malita91af8d82018-11-30 16:46:45 -050032 void onTransformProperty(const char node_name[],
33 const LazyHandle<skottie::TransformPropertyHandle>& t) override {
Florin Malita3f45e4b2020-08-20 14:51:41 -040034 const auto key = fMgr->acceptKey(node_name, ".Transform");
35 if (!key.empty()) {
36 fMgr->fTransformMap[key].push_back(t());
37 }
38 }
39
40 void onTextProperty(const char node_name[],
41 const LazyHandle<skottie::TextPropertyHandle>& t) override {
42 const auto key = fMgr->acceptKey(node_name, ".Text");
43 if (!key.empty()) {
44 fMgr->fTextMap[key].push_back(t());
45 }
Shachar Langbeheimbe28d2e2020-02-11 09:48:50 +020046 }
47
48 void onEnterNode(const char node_name[]) override {
49 fMgr->fCurrentNode =
50 fMgr->fCurrentNode.empty() ? node_name : fMgr->fCurrentNode + "." + node_name;
51 }
52
53 void onLeavingNode(const char node_name[]) override {
54 auto length = strlen(node_name);
55 fMgr->fCurrentNode =
56 fMgr->fCurrentNode.length() > length
57 ? fMgr->fCurrentNode.substr(
58 0, fMgr->fCurrentNode.length() - strlen(node_name) - 1)
59 : "";
Florin Malita8ac81b72018-11-28 11:39:39 -050060 }
Florin Malita8ac81b72018-11-28 11:39:39 -050061
Florin Malita91af8d82018-11-30 16:46:45 -050062private:
63 CustomPropertyManager* fMgr;
64};
65
66class CustomPropertyManager::MarkerInterceptor final : public skottie::MarkerObserver {
67public:
68 explicit MarkerInterceptor(CustomPropertyManager* mgr) : fMgr(mgr) {}
69
70 void onMarker(const char name[], float t0, float t1) override {
Florin Malita3f45e4b2020-08-20 14:51:41 -040071 // collect all markers
72 fMgr->fMarkers.push_back({ std::string(name), t0, t1 });
Florin Malita91af8d82018-11-30 16:46:45 -050073 }
74
75private:
76 CustomPropertyManager* fMgr;
77};
78
Florin Malita3f45e4b2020-08-20 14:51:41 -040079CustomPropertyManager::CustomPropertyManager(Mode mode, const char* prefix)
80 : fMode(mode)
81 , fPrefix(prefix ? prefix : "$")
82 , fPropertyInterceptor(sk_make_sp<PropertyInterceptor>(this))
Florin Malita91af8d82018-11-30 16:46:45 -050083 , fMarkerInterceptor(sk_make_sp<MarkerInterceptor>(this)) {}
Florin Malita8ac81b72018-11-28 11:39:39 -050084
85CustomPropertyManager::~CustomPropertyManager() = default;
86
Florin Malita3f45e4b2020-08-20 14:51:41 -040087std::string CustomPropertyManager::acceptKey(const char* name, const char* suffix) const {
88 if (!SkStrStartsWith(name, fPrefix.c_str())) {
89 return std::string();
90 }
91
92 return fMode == Mode::kCollapseProperties
93 ? std::string(name)
94 : fCurrentNode + suffix;
95}
96
Florin Malita91af8d82018-11-30 16:46:45 -050097sk_sp<skottie::PropertyObserver> CustomPropertyManager::getPropertyObserver() const {
98 return fPropertyInterceptor;
99}
100
101sk_sp<skottie::MarkerObserver> CustomPropertyManager::getMarkerObserver() const {
102 return fMarkerInterceptor;
103}
104
Florin Malita8ac81b72018-11-28 11:39:39 -0500105template <typename T>
106std::vector<CustomPropertyManager::PropKey>
107CustomPropertyManager::getProps(const PropMap<T>& container) const {
108 std::vector<PropKey> props;
109
110 for (const auto& prop_list : container) {
111 SkASSERT(!prop_list.second.empty());
112 props.push_back(prop_list.first);
113 }
114
115 return props;
116}
117
118template <typename V, typename T>
119V CustomPropertyManager::get(const PropKey& key, const PropMap<T>& container) const {
120 auto prop_group = container.find(key);
121
122 return prop_group == container.end()
123 ? V()
124 : prop_group->second.front()->get();
125}
126
127template <typename V, typename T>
128bool CustomPropertyManager::set(const PropKey& key, const V& val, const PropMap<T>& container) {
129 auto prop_group = container.find(key);
130
131 if (prop_group == container.end()) {
132 return false;
133 }
134
135 for (auto& handle : prop_group->second) {
136 handle->set(val);
137 }
138
139 return true;
140}
141
142std::vector<CustomPropertyManager::PropKey>
143CustomPropertyManager::getColorProps() const {
144 return this->getProps(fColorMap);
145}
146
147skottie::ColorPropertyValue CustomPropertyManager::getColor(const PropKey& key) const {
148 return this->get<skottie::ColorPropertyValue>(key, fColorMap);
149}
150
151bool CustomPropertyManager::setColor(const PropKey& key, const skottie::ColorPropertyValue& c) {
152 return this->set(key, c, fColorMap);
153}
154
155std::vector<CustomPropertyManager::PropKey>
156CustomPropertyManager::getOpacityProps() const {
157 return this->getProps(fOpacityMap);
158}
159
160skottie::OpacityPropertyValue CustomPropertyManager::getOpacity(const PropKey& key) const {
161 return this->get<skottie::OpacityPropertyValue>(key, fOpacityMap);
162}
163
164bool CustomPropertyManager::setOpacity(const PropKey& key, const skottie::OpacityPropertyValue& o) {
165 return this->set(key, o, fOpacityMap);
166}
167
168std::vector<CustomPropertyManager::PropKey>
169CustomPropertyManager::getTransformProps() const {
170 return this->getProps(fTransformMap);
171}
172
Florin Malita7c7cd302020-01-16 18:39:44 -0500173skottie::TransformPropertyValue CustomPropertyManager::getTransform(const PropKey& key) const {
174 return this->get<skottie::TransformPropertyValue>(key, fTransformMap);
175}
176
Florin Malita8ac81b72018-11-28 11:39:39 -0500177bool CustomPropertyManager::setTransform(const PropKey& key,
178 const skottie::TransformPropertyValue& t) {
179 return this->set(key, t, fTransformMap);
180}
181
Florin Malita7c7cd302020-01-16 18:39:44 -0500182std::vector<CustomPropertyManager::PropKey>
183CustomPropertyManager::getTextProps() const {
184 return this->getProps(fTextMap);
185}
186
187skottie::TextPropertyValue CustomPropertyManager::getText(const PropKey& key) const {
188 return this->get<skottie::TextPropertyValue>(key, fTextMap);
189}
190
191bool CustomPropertyManager::setText(const PropKey& key, const skottie::TextPropertyValue& o) {
192 return this->set(key, o, fTextMap);
193}
194
Florin Malitafbddfbb2020-05-06 15:55:18 -0400195namespace {
196
197class ExternalAnimationLayer final : public skottie::ExternalLayer {
198public:
199 ExternalAnimationLayer(sk_sp<skottie::Animation> anim, const SkSize& size)
200 : fAnimation(std::move(anim))
201 , fSize(size) {}
202
203private:
204 void render(SkCanvas* canvas, double t) override {
205 fAnimation->seekFrameTime(t);
206
207 const auto dst_rect = SkRect::MakeSize(fSize);
208 fAnimation->render(canvas, &dst_rect);
209 }
210
211 const sk_sp<skottie::Animation> fAnimation;
212 const SkSize fSize;
213};
214
215} // namespace
216
217ExternalAnimationPrecompInterceptor::ExternalAnimationPrecompInterceptor(
218 sk_sp<skresources::ResourceProvider> rprovider,
219 const char prefixp[])
220 : fResourceProvider(std::move(rprovider))
221 , fPrefix(prefixp) {}
222
223ExternalAnimationPrecompInterceptor::~ExternalAnimationPrecompInterceptor() = default;
224
225sk_sp<skottie::ExternalLayer> ExternalAnimationPrecompInterceptor::onLoadPrecomp(
226 const char[], const char name[], const SkSize& size) {
John Stilesc1c3c6d2020-08-15 23:22:53 -0400227 if (0 != strncmp(name, fPrefix.c_str(), fPrefix.size())) {
Florin Malitafbddfbb2020-05-06 15:55:18 -0400228 return nullptr;
229 }
230
231 auto data = fResourceProvider->load("", name + fPrefix.size());
232 if (!data) {
233 return nullptr;
234 }
235
236 auto anim = skottie::Animation::Builder()
237 .setPrecompInterceptor(sk_ref_sp(this))
238 .make(static_cast<const char*>(data->data()), data->size());
239
240 return anim ? sk_make_sp<ExternalAnimationLayer>(std::move(anim), size)
241 : nullptr;
242}
243
Florin Malitaa8316552018-11-09 16:19:44 -0500244} // namespace skottie_utils