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 | |
21 | class SkCanvas; |
22 | struct SkRect; |
23 | class SkStream; |
24 | |
25 | namespace skjson { class ObjectValue; } |
26 | |
27 | namespace sksg { |
28 | |
29 | class InvalidationController; |
30 | class Scene; |
31 | |
32 | } // namespace sksg |
33 | |
34 | namespace skottie { |
35 | |
36 | namespace internal { class Animator; } |
37 | |
38 | using ImageAsset = skresources::ImageAsset; |
39 | using ResourceProvider = skresources::ResourceProvider; |
40 | |
41 | class PropertyObserver; |
42 | |
43 | /** |
44 | * A Logger subclass can be used to receive Animation::Builder parsing errors and warnings. |
45 | */ |
46 | class SK_API Logger : public SkRefCnt { |
47 | public: |
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 | */ |
59 | class SK_API MarkerObserver : public SkRefCnt { |
60 | public: |
61 | // t0,t1 are in the Animation::seek() domain. |
62 | virtual void onMarker(const char name[], float t0, float t1) = 0; |
63 | }; |
64 | |
65 | class SK_API Animation : public SkNVRefCnt<Animation> { |
66 | public: |
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 | |
214 | private: |
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 | |