Flutter Engine
The Flutter Engine
SkottieUtils.cpp
Go to the documentation of this file.
1/*
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
9
10#include "include/core/SkData.h"
11#include "include/core/SkRect.h"
12#include "include/core/SkSize.h"
16
17#include <cstring>
18#include <utility>
19
20class SkCanvas;
21
22namespace skottie_utils {
23
25public:
26 explicit PropertyInterceptor(CustomPropertyManager* mgr) : fMgr(mgr) {}
27
28 void onColorProperty(const char node_name[],
30 const auto key = fMgr->acceptKey(node_name, ".Color");
31 if (!key.empty()) {
32 fMgr->fColorMap[key].push_back(c());
33 }
34 }
35
36 void onOpacityProperty(const char node_name[],
38 const auto key = fMgr->acceptKey(node_name, ".Opacity");
39 if (!key.empty()) {
40 fMgr->fOpacityMap[key].push_back(o());
41 }
42 }
43
44 void onTransformProperty(const char node_name[],
46 const auto key = fMgr->acceptKey(node_name, ".Transform");
47 if (!key.empty()) {
48 fMgr->fTransformMap[key].push_back(t());
49 }
50 }
51
52 void onTextProperty(const char node_name[],
54 const auto key = fMgr->acceptKey(node_name, ".Text");
55 if (!key.empty()) {
56 fMgr->fTextMap[key].push_back(t());
57 }
58 }
59
60 void onEnterNode(const char node_name[], PropertyObserver::NodeType node_type) override {
61 if (node_name == nullptr) {
62 return;
63 }
64 fMgr->fCurrentNode =
65 fMgr->fCurrentNode.empty() ? node_name : fMgr->fCurrentNode + "." + node_name;
66 }
67
68 void onLeavingNode(const char node_name[], PropertyObserver::NodeType node_type) override {
69 if (node_name == nullptr) {
70 return;
71 }
72 auto length = strlen(node_name);
73 fMgr->fCurrentNode =
74 fMgr->fCurrentNode.length() > length
75 ? fMgr->fCurrentNode.substr(
76 0, fMgr->fCurrentNode.length() - strlen(node_name) - 1)
77 : "";
78 }
79
80private:
82};
83
85public:
86 explicit MarkerInterceptor(CustomPropertyManager* mgr) : fMgr(mgr) {}
87
88 void onMarker(const char name[], float t0, float t1) override {
89 // collect all markers
90 fMgr->fMarkers.push_back({ std::string(name), t0, t1 });
91 }
92
93private:
95};
96
98 : fMode(mode)
99 , fPrefix(prefix ? prefix : "$")
100 , fPropertyInterceptor(sk_make_sp<PropertyInterceptor>(this))
101 , fMarkerInterceptor(sk_make_sp<MarkerInterceptor>(this)) {}
102
104
105std::string CustomPropertyManager::acceptKey(const char* name, const char* suffix) const {
106 if (!SkStrStartsWith(name, fPrefix.c_str())) {
107 return std::string();
108 }
109
110 return fMode == Mode::kCollapseProperties
111 ? std::string(name)
112 : fCurrentNode + suffix;
113}
114
116 return fPropertyInterceptor;
117}
118
120 return fMarkerInterceptor;
121}
122
123template <typename T>
124std::vector<CustomPropertyManager::PropKey>
125CustomPropertyManager::getProps(const PropMap<T>& container) const {
126 std::vector<PropKey> props;
127
128 for (const auto& prop_list : container) {
129 SkASSERT(!prop_list.second.empty());
130 props.push_back(prop_list.first);
131 }
132
133 return props;
134}
135
136template <typename V, typename T>
137V CustomPropertyManager::get(const PropKey& key, const PropMap<T>& container) const {
138 auto prop_group = container.find(key);
139
140 return prop_group == container.end()
141 ? V()
142 : prop_group->second.front()->get();
143}
144
145template <typename T>
146std::unique_ptr<T> CustomPropertyManager::getHandle(const PropKey& key,
147 size_t index,
148 const PropMap<T>& container) const {
149 auto prop_group = container.find(key);
150
151 if (prop_group == container.end() || index >= prop_group->second.size()) {
152 return nullptr;
153 }
154
155 return std::make_unique<T>(*prop_group->second[index]);
156}
157
158template <typename V, typename T>
159bool CustomPropertyManager::set(const PropKey& key, const V& val, const PropMap<T>& container) {
160 auto prop_group = container.find(key);
161
162 if (prop_group == container.end()) {
163 return false;
164 }
165
166 for (auto& handle : prop_group->second) {
167 handle->set(val);
168 }
169
170 return true;
171}
172
173std::vector<CustomPropertyManager::PropKey>
175 return this->getProps(fColorMap);
176}
177
179 return this->get<skottie::ColorPropertyValue>(key, fColorMap);
180}
181
182std::unique_ptr<skottie::ColorPropertyHandle>
184 return this->getHandle(key, index, fColorMap);
185}
186
188 return this->set(key, c, fColorMap);
189}
190
191std::vector<CustomPropertyManager::PropKey>
193 return this->getProps(fOpacityMap);
194}
195
197 return this->get<skottie::OpacityPropertyValue>(key, fOpacityMap);
198}
199
200std::unique_ptr<skottie::OpacityPropertyHandle>
202 return this->getHandle(key, index, fOpacityMap);
203}
204
206 return this->set(key, o, fOpacityMap);
207}
208
209std::vector<CustomPropertyManager::PropKey>
211 return this->getProps(fTransformMap);
212}
213
215 return this->get<skottie::TransformPropertyValue>(key, fTransformMap);
216}
217
218std::unique_ptr<skottie::TransformPropertyHandle>
220 return this->getHandle(key, index, fTransformMap);
221}
222
225 return this->set(key, t, fTransformMap);
226}
227
228std::vector<CustomPropertyManager::PropKey>
230 return this->getProps(fTextMap);
231}
232
234 return this->get<skottie::TextPropertyValue>(key, fTextMap);
235}
236
237std::unique_ptr<skottie::TextPropertyHandle>
239 return this->getHandle(key, index, fTextMap);
240}
241
243 return this->set(key, o, fTextMap);
244}
245
246namespace {
247
248class ExternalAnimationLayer final : public skottie::ExternalLayer {
249public:
250 ExternalAnimationLayer(sk_sp<skottie::Animation> anim, const SkSize& size)
251 : fAnimation(std::move(anim))
252 , fSize(size) {}
253
254private:
255 void render(SkCanvas* canvas, double t) override {
256 fAnimation->seekFrameTime(t);
257
258 // The main animation will layer-isolate if needed - we don't want the nested animation
259 // to override that decision.
260 const auto flags = skottie::Animation::RenderFlag::kSkipTopLevelIsolation;
261 const auto dst_rect = SkRect::MakeSize(fSize);
262 fAnimation->render(canvas, &dst_rect, flags);
263 }
264
265 const sk_sp<skottie::Animation> fAnimation;
266 const SkSize fSize;
267};
268
269} // namespace
270
273 const char prefixp[])
274 : fResourceProvider(std::move(rprovider))
275 , fPrefix(prefixp) {}
276
278
279sk_sp<skottie::ExternalLayer> ExternalAnimationPrecompInterceptor::onLoadPrecomp(
280 const char[], const char name[], const SkSize& size) {
281 if (0 != strncmp(name, fPrefix.c_str(), fPrefix.size())) {
282 return nullptr;
283 }
284
285 auto data = fResourceProvider->load("", name + fPrefix.size());
286 if (!data) {
287 return nullptr;
288 }
289
290 auto anim = skottie::Animation::Builder()
291 .setPrecompInterceptor(sk_ref_sp(this))
292 .setResourceProvider(fResourceProvider)
293 .make(static_cast<const char*>(data->data()), data->size());
294
295 return anim ? sk_make_sp<ExternalAnimationLayer>(std::move(anim), size)
296 : nullptr;
297}
298
299} // namespace skottie_utils
#define SkASSERT(cond)
Definition: SkAssert.h:116
sk_sp< T > sk_make_sp(Args &&... args)
Definition: SkRefCnt.h:371
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
static bool SkStrStartsWith(const char string[], const char prefixStr[])
Definition: SkString.h:26
size_t size() const
Definition: SkString.h:131
const char * c_str() const
Definition: SkString.h:133
void seekFrameTime(double t, sksg::InvalidationController *=nullptr)
Definition: Skottie.cpp:530
void render(SkCanvas *canvas, const SkRect *dst=nullptr) const
Definition: Skottie.cpp:482
std::function< std::unique_ptr< T >()> LazyHandle
void onMarker(const char name[], float t0, float t1) override
void onTextProperty(const char node_name[], const LazyHandle< skottie::TextPropertyHandle > &t) override
void onTransformProperty(const char node_name[], const LazyHandle< skottie::TransformPropertyHandle > &t) override
void onOpacityProperty(const char node_name[], const LazyHandle< skottie::OpacityPropertyHandle > &o) override
void onLeavingNode(const char node_name[], PropertyObserver::NodeType node_type) override
void onColorProperty(const char node_name[], const LazyHandle< skottie::ColorPropertyHandle > &c) override
void onEnterNode(const char node_name[], PropertyObserver::NodeType node_type) override
sk_sp< skottie::MarkerObserver > getMarkerObserver() const
bool setOpacity(const PropKey &, const skottie::OpacityPropertyValue &)
skottie::ColorPropertyValue getColor(const PropKey &) const
bool setTransform(const PropKey &, const skottie::TransformPropertyValue &)
std::unique_ptr< skottie::OpacityPropertyHandle > getOpacityHandle(const PropKey &, size_t) const
bool setColor(const PropKey &, const skottie::ColorPropertyValue &)
bool setText(const PropKey &, const skottie::TextPropertyValue &)
std::vector< PropKey > getColorProps() const
std::unique_ptr< skottie::TextPropertyHandle > getTextHandle(const PropKey &, size_t index) const
skottie::TransformPropertyValue getTransform(const PropKey &) const
std::unique_ptr< skottie::TransformPropertyHandle > getTransformHandle(const PropKey &, size_t) const
std::unique_ptr< skottie::ColorPropertyHandle > getColorHandle(const PropKey &, size_t) const
std::vector< PropKey > getTextProps() const
skottie::TextPropertyValue getText(const PropKey &) const
std::vector< PropKey > getOpacityProps() const
sk_sp< skottie::PropertyObserver > getPropertyObserver() const
std::vector< PropKey > getTransformProps() const
CustomPropertyManager(Mode=Mode::kNamespacedProperties, const char *prefix=nullptr)
skottie::OpacityPropertyValue getOpacity(const PropKey &) const
ExternalAnimationPrecompInterceptor(sk_sp< skresources::ResourceProvider >, const char prefix[])
virtual sk_sp< SkData > load(const char[], const char[]) const
Definition: SkResources.h:156
FlutterSemanticsFlag flags
size_t length
T __attribute__((ext_vector_type(N))) V
DlVertices::Builder Builder
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
def render(idl_node, indent_str=' ')
Definition: idlrenderer.py:9
float OpacityPropertyValue
SkColor ColorPropertyValue
Definition: ref_ptr.h:256
#define V(name)
Definition: raw_object.h:125
static constexpr SkRect MakeSize(const SkSize &size)
Definition: SkRect.h:633
Definition: SkSize.h:52
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
SkBlendMode fMode
Definition: xfermodes.cpp:52