1/*
2 * Copyright 2017 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
8#ifndef Skottie_DEFINED
9#define Skottie_DEFINED
10
11#include "include/core/SkFontMgr.h"
12#include "include/core/SkRefCnt.h"
13#include "include/core/SkSize.h"
14#include "include/core/SkString.h"
15#include "include/core/SkTypes.h"
16#include "modules/skresources/include/SkResources.h"
17
18#include <memory>
19#include <vector>
20
21class SkCanvas;
22struct SkRect;
23class SkStream;
24
25namespace skjson { class ObjectValue; }
26
27namespace sksg {
28
29class InvalidationController;
30class Scene;
31
32} // namespace sksg
33
34namespace skottie {
35
36namespace internal { class Animator; }
37
38using ImageAsset = skresources::ImageAsset;
39using ResourceProvider = skresources::ResourceProvider;
40
41class PropertyObserver;
42
43/**
44 * A Logger subclass can be used to receive Animation::Builder parsing errors and warnings.
45 */
46class SK_API Logger : public SkRefCnt {
47public:
48 enum class Level {
49 kWarning,
50 kError,
51 };
52
53 virtual void log(Level, const char message[], const char* json = nullptr);
54};
55
56/**
57 * Interface for receiving AE composition markers at Animation build time.
58 */
59class SK_API MarkerObserver : public SkRefCnt {
60public:
61 // t0,t1 are in the Animation::seek() domain.
62 virtual void onMarker(const char name[], float t0, float t1) = 0;
63};
64
65class SK_API Animation : public SkNVRefCnt<Animation> {
66public:
67 class Builder final {
68 public:
69 enum Flags : uint32_t {
70 kDeferImageLoading = 0x01, // Normally, all static image frames are resolved at
71 // load time via ImageAsset::getFrame(0). With this flag,
72 // frames are only resolved when needed, at seek() time.
73 };
74
75 explicit Builder(uint32_t flags = 0);
76 ~Builder();
77
78 struct Stats {
79 float fTotalLoadTimeMS = 0, // Total animation instantiation time.
80 fJsonParseTimeMS = 0, // Time spent building a JSON DOM.
81 fSceneParseTimeMS = 0; // Time spent constructing the animation scene graph.
82 size_t fJsonSize = 0, // Input JSON size.
83 fAnimatorCount = 0; // Number of dynamically animated properties.
84 };
85
86 /**
87 * Returns various animation build stats.
88 *
89 * @return Stats (see above).
90 */
91 const Stats& getStats() const { return fStats; }
92
93 /**
94 * Specify a loader for external resources (images, etc.).
95 */
96 Builder& setResourceProvider(sk_sp<ResourceProvider>);
97
98 /**
99 * Specify a font manager for loading animation fonts.
100 */
101 Builder& setFontManager(sk_sp<SkFontMgr>);
102
103 /**
104 * Specify a PropertyObserver to receive callbacks during parsing.
105 *
106 * See SkottieProperty.h for more details.
107 *
108 */
109 Builder& setPropertyObserver(sk_sp<PropertyObserver>);
110
111 /**
112 * Register a Logger with this builder.
113 */
114 Builder& setLogger(sk_sp<Logger>);
115
116 /**
117 * Register a MarkerObserver with this builder.
118 */
119 Builder& setMarkerObserver(sk_sp<MarkerObserver>);
120
121 /**
122 * Animation factories.
123 */
124 sk_sp<Animation> make(SkStream*);
125 sk_sp<Animation> make(const char* data, size_t length);
126 sk_sp<Animation> makeFromFile(const char path[]);
127
128 private:
129 const uint32_t fFlags;
130
131 sk_sp<ResourceProvider> fResourceProvider;
132 sk_sp<SkFontMgr> fFontMgr;
133 sk_sp<PropertyObserver> fPropertyObserver;
134 sk_sp<Logger> fLogger;
135 sk_sp<MarkerObserver> fMarkerObserver;
136 Stats fStats;
137 };
138
139 /**
140 * Animation factories.
141 *
142 * Use the Builder helper above for more options/control.
143 */
144 static sk_sp<Animation> Make(const char* data, size_t length);
145 static sk_sp<Animation> Make(SkStream*);
146 static sk_sp<Animation> MakeFromFile(const char path[]);
147
148 ~Animation();
149
150 enum RenderFlag : uint32_t {
151 // When rendering into a known transparent buffer, clients can pass
152 // this flag to avoid some unnecessary compositing overhead for
153 // animations using layer blend modes.
154 kSkipTopLevelIsolation = 0x01,
155 };
156 using RenderFlags = uint32_t;
157
158 /**
159 * Draws the current animation frame.
160 *
161 * It is undefined behavior to call render() on a newly created Animation
162 * before specifying an initial frame via one of the seek() variants.
163 *
164 * @param canvas destination canvas
165 * @param dst optional destination rect
166 * @param flags optional RenderFlags
167 */
168 void render(SkCanvas* canvas, const SkRect* dst = nullptr) const;
169 void render(SkCanvas* canvas, const SkRect* dst, RenderFlags) const;
170
171 /**
172 * [Deprecated: use one of the other versions.]
173 *
174 * Updates the animation state for |t|.
175 *
176 * @param t normalized [0..1] frame selector (0 -> first frame, 1 -> final frame)
177 * @param ic optional invalidation controller (dirty region tracking)
178 *
179 */
180 void seek(SkScalar t, sksg::InvalidationController* ic = nullptr) {
181 this->seekFrameTime(t * this->duration(), ic);
182 }
183
184 /**
185 * Update the animation state to match |t|, specified as a frame index
186 * i.e. relative to duration() * fps().
187 *
188 * Fractional values are allowed and meaningful - e.g.
189 *
190 * 0.0 -> first frame
191 * 1.0 -> second frame
192 * 0.5 -> halfway between first and second frame
193 */
194 void seekFrame(double t, sksg::InvalidationController* ic = nullptr);
195
196 /** Update the animation state to match t, specifed in frame time
197 * i.e. relative to duration().
198 */
199 void seekFrameTime(double t, sksg::InvalidationController* = nullptr);
200
201 /**
202 * Returns the animation duration in seconds.
203 */
204 double duration() const { return fDuration; }
205
206 /**
207 * Returns the animation frame rate (frames / second).
208 */
209 double fps() const { return fFPS; }
210
211 const SkString& version() const { return fVersion; }
212 const SkSize& size() const { return fSize; }
213
214private:
215 enum Flags : uint32_t {
216 kRequiresTopLevelIsolation = 1 << 0, // Needs to draw into a layer due to layer blending.
217 };
218
219 Animation(std::unique_ptr<sksg::Scene>,
220 std::vector<sk_sp<internal::Animator>>&&,
221 SkString ver, const SkSize& size,
222 double inPoint, double outPoint, double duration, double fps, uint32_t flags);
223
224 const std::unique_ptr<sksg::Scene> fScene;
225 const std::vector<sk_sp<internal::Animator>> fAnimators;
226 const SkString fVersion;
227 const SkSize fSize;
228 const double fInPoint,
229 fOutPoint,
230 fDuration,
231 fFPS;
232 const uint32_t fFlags;
233
234 typedef SkNVRefCnt<Animation> INHERITED;
235};
236
237} // namespace skottie
238
239#endif // Skottie_DEFINED
240