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/skottie/include/ExternalLayer.h" 17 #include "modules/skottie/include/SkottieProperty.h" 18 #include "modules/skresources/include/SkResources.h" 19 20 #include <memory> 21 #include <vector> 22 23 class SkCanvas; 24 struct SkRect; 25 class SkStream; 26 27 namespace skjson { class ObjectValue; } 28 29 namespace sksg { 30 31 class InvalidationController; 32 class Scene; 33 34 } // namespace sksg 35 36 namespace skottie { 37 38 namespace internal { class Animator; } 39 40 using ImageAsset = skresources::ImageAsset; 41 using ResourceProvider = skresources::ResourceProvider; 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 kPreferEmbeddedFonts = 0x02, // Attempt to use the embedded fonts (glyph paths, 74 // normally used as fallback) over native Skia typefaces. 75 }; 76 77 explicit Builder(uint32_t flags = 0); 78 ~Builder(); 79 80 struct Stats { 81 float fTotalLoadTimeMS = 0, // Total animation instantiation time. 82 fJsonParseTimeMS = 0, // Time spent building a JSON DOM. 83 fSceneParseTimeMS = 0; // Time spent constructing the animation scene graph. 84 size_t fJsonSize = 0, // Input JSON size. 85 fAnimatorCount = 0; // Number of dynamically animated properties. 86 }; 87 88 /** 89 * Returns various animation build stats. 90 * 91 * @return Stats (see above). 92 */ getStats()93 const Stats& getStats() const { return fStats; } 94 95 /** 96 * Specify a loader for external resources (images, etc.). 97 */ 98 Builder& setResourceProvider(sk_sp<ResourceProvider>); 99 100 /** 101 * Specify a font manager for loading animation fonts. 102 */ 103 Builder& setFontManager(sk_sp<SkFontMgr>); 104 105 /** 106 * Specify a PropertyObserver to receive callbacks during parsing. 107 * 108 * See SkottieProperty.h for more details. 109 * 110 */ 111 Builder& setPropertyObserver(sk_sp<PropertyObserver>); 112 113 /** 114 * Register a Logger with this builder. 115 */ 116 Builder& setLogger(sk_sp<Logger>); 117 118 /** 119 * Register a MarkerObserver with this builder. 120 */ 121 Builder& setMarkerObserver(sk_sp<MarkerObserver>); 122 123 /** 124 * Register a precomp layer interceptor. 125 * This allows substituting precomp layers with custom/externally managed content. 126 */ 127 Builder& setPrecompInterceptor(sk_sp<PrecompInterceptor>); 128 129 /** 130 * Animation factories. 131 */ 132 sk_sp<Animation> make(SkStream*); 133 sk_sp<Animation> make(const char* data, size_t length); 134 sk_sp<Animation> makeFromFile(const char path[]); 135 136 private: 137 const uint32_t fFlags; 138 139 sk_sp<ResourceProvider> fResourceProvider; 140 sk_sp<SkFontMgr> fFontMgr; 141 sk_sp<PropertyObserver> fPropertyObserver; 142 sk_sp<Logger> fLogger; 143 sk_sp<MarkerObserver > fMarkerObserver; 144 sk_sp<PrecompInterceptor> fPrecompInterceptor; 145 Stats fStats; 146 }; 147 148 /** 149 * Animation factories. 150 * 151 * Use the Builder helper above for more options/control. 152 */ 153 static sk_sp<Animation> Make(const char* data, size_t length); 154 static sk_sp<Animation> Make(SkStream*); 155 static sk_sp<Animation> MakeFromFile(const char path[]); 156 157 ~Animation(); 158 159 enum RenderFlag : uint32_t { 160 // When rendering into a known transparent buffer, clients can pass 161 // this flag to avoid some unnecessary compositing overhead for 162 // animations using layer blend modes. 163 kSkipTopLevelIsolation = 0x01, 164 // By default, content is clipped to the intrinsic animation 165 // bounds (as determined by its size). If this flag is set, 166 // then the animation can draw outside of the bounds. 167 kDisableTopLevelClipping = 0x02, 168 }; 169 using RenderFlags = uint32_t; 170 171 /** 172 * Draws the current animation frame. 173 * 174 * It is undefined behavior to call render() on a newly created Animation 175 * before specifying an initial frame via one of the seek() variants. 176 * 177 * @param canvas destination canvas 178 * @param dst optional destination rect 179 * @param flags optional RenderFlags 180 */ 181 void render(SkCanvas* canvas, const SkRect* dst = nullptr) const; 182 void render(SkCanvas* canvas, const SkRect* dst, RenderFlags) const; 183 184 /** 185 * [Deprecated: use one of the other versions.] 186 * 187 * Updates the animation state for |t|. 188 * 189 * @param t normalized [0..1] frame selector (0 -> first frame, 1 -> final frame) 190 * @param ic optional invalidation controller (dirty region tracking) 191 * 192 */ 193 void seek(SkScalar t, sksg::InvalidationController* ic = nullptr) { 194 this->seekFrameTime(t * this->duration(), ic); 195 } 196 197 /** 198 * Update the animation state to match |t|, specified as a frame index 199 * i.e. relative to duration() * fps(). 200 * 201 * Fractional values are allowed and meaningful - e.g. 202 * 203 * 0.0 -> first frame 204 * 1.0 -> second frame 205 * 0.5 -> halfway between first and second frame 206 */ 207 void seekFrame(double t, sksg::InvalidationController* ic = nullptr); 208 209 /** Update the animation state to match t, specifed in frame time 210 * i.e. relative to duration(). 211 */ 212 void seekFrameTime(double t, sksg::InvalidationController* = nullptr); 213 214 /** 215 * Returns the animation duration in seconds. 216 */ duration()217 double duration() const { return fDuration; } 218 219 /** 220 * Returns the animation frame rate (frames / second). 221 */ fps()222 double fps() const { return fFPS; } 223 224 /** 225 * Animation in point, in frame index units. 226 */ inPoint()227 double inPoint() const { return fInPoint; } 228 229 /** 230 * Animation out point, in frame index units. 231 */ outPoint()232 double outPoint() const { return fOutPoint; } 233 version()234 const SkString& version() const { return fVersion; } size()235 const SkSize& size() const { return fSize; } 236 237 private: 238 enum Flags : uint32_t { 239 kRequiresTopLevelIsolation = 1 << 0, // Needs to draw into a layer due to layer blending. 240 }; 241 242 Animation(std::unique_ptr<sksg::Scene>, 243 std::vector<sk_sp<internal::Animator>>&&, 244 SkString ver, const SkSize& size, 245 double inPoint, double outPoint, double duration, double fps, uint32_t flags); 246 247 const std::unique_ptr<sksg::Scene> fScene; 248 const std::vector<sk_sp<internal::Animator>> fAnimators; 249 const SkString fVersion; 250 const SkSize fSize; 251 const double fInPoint, 252 fOutPoint, 253 fDuration, 254 fFPS; 255 const uint32_t fFlags; 256 257 using INHERITED = SkNVRefCnt<Animation>; 258 }; 259 260 } // namespace skottie 261 262 #endif // Skottie_DEFINED 263