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