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/SkRefCnt.h" 12 #include "include/core/SkScalar.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 // TODO(kjlubick) update clients and then remove the following: 19 #include "include/core/SkFontMgr.h" // IWYU pragma: keep 20 #include "modules/skottie/include/ExternalLayer.h" // IWYU pragma: keep 21 #include "modules/skottie/include/SkottieProperty.h" // IWYU pragma: keep 22 #include "modules/skottie/include/SlotManager.h" // IWYU pragma: keep 23 24 #include <cstddef> 25 #include <cstdint> 26 #include <vector> 27 28 class SkCanvas; 29 class SkStream; 30 struct SkRect; 31 32 namespace sksg { 33 34 class InvalidationController; 35 class RenderNode; 36 37 } // namespace sksg 38 39 namespace SkShapers { class Factory; } 40 41 namespace skottie { 42 43 namespace internal { class Animator; } 44 45 using ImageAsset = skresources::ImageAsset; 46 using ResourceProvider = skresources::ResourceProvider; 47 48 /** 49 * A Logger subclass can be used to receive Animation::Builder parsing errors and warnings. 50 */ 51 class SK_API Logger : public SkRefCnt { 52 public: 53 enum class Level { 54 kWarning, 55 kError, 56 }; 57 58 virtual void log(Level, const char message[], const char* json = nullptr) = 0; 59 }; 60 61 // Evaluates AE expressions. 62 template <class T> 63 class SK_API ExpressionEvaluator : public SkRefCnt { 64 public: 65 // Evaluate the expression at the current time. 66 virtual T evaluate(float t) = 0; 67 }; 68 69 /** 70 * Creates ExpressionEvaluators to evaluate AE expressions and return the results. 71 */ 72 class SK_API ExpressionManager : public SkRefCnt { 73 public: 74 virtual sk_sp<ExpressionEvaluator<float>> createNumberExpressionEvaluator( 75 const char expression[]) = 0; 76 77 virtual sk_sp<ExpressionEvaluator<SkString>> createStringExpressionEvaluator( 78 const char expression[]) = 0; 79 80 virtual sk_sp<ExpressionEvaluator<std::vector<float>>> createArrayExpressionEvaluator( 81 const char expression[]) = 0; 82 }; 83 84 /** 85 * Interface for receiving AE composition markers at Animation build time. 86 */ 87 class SK_API MarkerObserver : public SkRefCnt { 88 public: 89 // t0,t1 are in the Animation::seek() domain. 90 virtual void onMarker(const char name[], float t0, float t1) = 0; 91 }; 92 93 class SK_API Animation : public SkNVRefCnt<Animation> { 94 public: 95 class SK_API Builder final { 96 public: 97 enum Flags : uint32_t { 98 kDeferImageLoading = 0x01, // Normally, all static image frames are resolved at 99 // load time via ImageAsset::getFrame(0). With this flag, 100 // frames are only resolved when needed, at seek() time. 101 kPreferEmbeddedFonts = 0x02, // Attempt to use the embedded fonts (glyph paths, 102 // normally used as fallback) over native Skia typefaces. 103 }; 104 105 explicit Builder(uint32_t flags = 0); 106 Builder(const Builder&); 107 Builder(Builder&&); 108 ~Builder(); 109 110 struct Stats { 111 float fTotalLoadTimeMS = 0, // Total animation instantiation time. 112 fJsonParseTimeMS = 0, // Time spent building a JSON DOM. 113 fSceneParseTimeMS = 0; // Time spent constructing the animation scene graph. 114 size_t fJsonSize = 0, // Input JSON size. 115 fAnimatorCount = 0; // Number of dynamically animated properties. 116 }; 117 118 /** 119 * Returns various animation build stats. 120 * 121 * @return Stats (see above). 122 */ getStats()123 const Stats& getStats() const { return fStats; } 124 125 /** 126 * Specify a loader for external resources (images, etc.). 127 */ 128 Builder& setResourceProvider(sk_sp<ResourceProvider>); 129 130 /** 131 * Specify a font manager for loading animation fonts. 132 */ 133 Builder& setFontManager(sk_sp<SkFontMgr>); 134 135 /** 136 * Specify a PropertyObserver to receive callbacks during parsing. 137 * 138 * See SkottieProperty.h for more details. 139 * 140 */ 141 Builder& setPropertyObserver(sk_sp<PropertyObserver>); 142 143 /** 144 * Register a Logger with this builder. 145 */ 146 Builder& setLogger(sk_sp<Logger>); 147 148 /** 149 * Register a MarkerObserver with this builder. 150 */ 151 Builder& setMarkerObserver(sk_sp<MarkerObserver>); 152 153 /** 154 * Register a precomp layer interceptor. 155 * This allows substituting precomp layers with custom/externally managed content. 156 */ 157 Builder& setPrecompInterceptor(sk_sp<PrecompInterceptor>); 158 159 /** 160 * Registers an ExpressionManager to evaluate AE expressions. 161 * If unspecified, expressions in the animation JSON will be ignored. 162 */ 163 Builder& setExpressionManager(sk_sp<ExpressionManager>); 164 165 /** 166 * Registers a factory to be used when shaping text. 167 * If unspecified, text will be shaped with primitive shaping. 168 * See //modules/skshaper/utils/FactoryHelpers.h 169 */ 170 Builder& setTextShapingFactory(sk_sp<SkShapers::Factory>); 171 172 /** 173 * Animation factories. 174 */ 175 sk_sp<Animation> make(SkStream*); 176 sk_sp<Animation> make(const char* data, size_t length); 177 sk_sp<Animation> makeFromFile(const char path[]); 178 179 /** 180 * Get handle for SlotManager after animation is built. 181 */ getSlotManager()182 const sk_sp<SlotManager>& getSlotManager() const {return fSlotManager;} 183 184 private: 185 const uint32_t fFlags; 186 187 sk_sp<ResourceProvider> fResourceProvider; 188 sk_sp<SkFontMgr> fFontMgr; 189 sk_sp<PropertyObserver> fPropertyObserver; 190 sk_sp<Logger> fLogger; 191 sk_sp<MarkerObserver > fMarkerObserver; 192 sk_sp<PrecompInterceptor> fPrecompInterceptor; 193 sk_sp<ExpressionManager> fExpressionManager; 194 sk_sp<SkShapers::Factory> fShapingFactory; 195 sk_sp<SlotManager> fSlotManager; 196 Stats fStats; 197 }; 198 199 /** 200 * Animation factories. 201 * 202 * Use the Builder helper above for more options/control. 203 */ 204 static sk_sp<Animation> Make(const char* data, size_t length); 205 static sk_sp<Animation> Make(SkStream*); 206 static sk_sp<Animation> MakeFromFile(const char path[]); 207 208 ~Animation(); 209 210 enum RenderFlag : uint32_t { 211 // When rendering into a known transparent buffer, clients can pass 212 // this flag to avoid some unnecessary compositing overhead for 213 // animations using layer blend modes. 214 kSkipTopLevelIsolation = 0x01, 215 // By default, content is clipped to the intrinsic animation 216 // bounds (as determined by its size). If this flag is set, 217 // then the animation can draw outside of the bounds. 218 kDisableTopLevelClipping = 0x02, 219 }; 220 using RenderFlags = uint32_t; 221 222 /** 223 * Draws the current animation frame. 224 * 225 * It is undefined behavior to call render() on a newly created Animation 226 * before specifying an initial frame via one of the seek() variants. 227 * 228 * @param canvas destination canvas 229 * @param dst optional destination rect 230 * @param flags optional RenderFlags 231 */ 232 void render(SkCanvas* canvas, const SkRect* dst = nullptr) const; 233 void render(SkCanvas* canvas, const SkRect* dst, RenderFlags) const; 234 235 /** 236 * [Deprecated: use one of the other versions.] 237 * 238 * Updates the animation state for |t|. 239 * 240 * @param t normalized [0..1] frame selector (0 -> first frame, 1 -> final frame) 241 * @param ic optional invalidation controller (dirty region tracking) 242 * 243 */ 244 void seek(SkScalar t, sksg::InvalidationController* ic = nullptr) { 245 this->seekFrameTime(t * this->duration(), ic); 246 } 247 248 /** 249 * Update the animation state to match |t|, specified as a frame index 250 * i.e. relative to duration() * fps(). 251 * 252 * Fractional values are allowed and meaningful - e.g. 253 * 254 * 0.0 -> first frame 255 * 1.0 -> second frame 256 * 0.5 -> halfway between first and second frame 257 */ 258 void seekFrame(double t, sksg::InvalidationController* ic = nullptr); 259 260 /** Update the animation state to match t, specifed in frame time 261 * i.e. relative to duration(). 262 */ 263 void seekFrameTime(double t, sksg::InvalidationController* = nullptr); 264 265 /** 266 * Returns the animation duration in seconds. 267 */ duration()268 double duration() const { return fDuration; } 269 270 /** 271 * Returns the animation frame rate (frames / second). 272 */ fps()273 double fps() const { return fFPS; } 274 275 /** 276 * Animation in point, in frame index units. 277 */ inPoint()278 double inPoint() const { return fInPoint; } 279 280 /** 281 * Animation out point, in frame index units. 282 */ outPoint()283 double outPoint() const { return fOutPoint; } 284 version()285 const SkString& version() const { return fVersion; } size()286 const SkSize& size() const { return fSize; } 287 288 private: 289 enum Flags : uint32_t { 290 kRequiresTopLevelIsolation = 1 << 0, // Needs to draw into a layer due to layer blending. 291 }; 292 293 Animation(sk_sp<sksg::RenderNode>, 294 std::vector<sk_sp<internal::Animator>>&&, 295 SkString ver, const SkSize& size, 296 double inPoint, double outPoint, double duration, double fps, uint32_t flags); 297 298 const sk_sp<sksg::RenderNode> fSceneRoot; 299 const std::vector<sk_sp<internal::Animator>> fAnimators; 300 const SkString fVersion; 301 const SkSize fSize; 302 const double fInPoint, 303 fOutPoint, 304 fDuration, 305 fFPS; 306 const uint32_t fFlags; 307 308 using INHERITED = SkNVRefCnt<Animation>; 309 }; 310 311 } // namespace skottie 312 313 #endif // Skottie_DEFINED 314