/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef Skottie_DEFINED #define Skottie_DEFINED #include "include/core/SkFontMgr.h" #include "include/core/SkRefCnt.h" #include "include/core/SkSize.h" #include "include/core/SkString.h" #include "include/core/SkTypes.h" #include "modules/skottie/include/ExternalLayer.h" #include "modules/skottie/include/SkottieProperty.h" #include "modules/skresources/include/SkResources.h" #include #include class SkCanvas; struct SkRect; class SkStream; namespace skjson { class ObjectValue; } namespace sksg { class InvalidationController; class Scene; } // namespace sksg namespace skottie { namespace internal { class Animator; } using ImageAsset = skresources::ImageAsset; using ResourceProvider = skresources::ResourceProvider; /** * A Logger subclass can be used to receive Animation::Builder parsing errors and warnings. */ class SK_API Logger : public SkRefCnt { public: enum class Level { kWarning, kError, }; virtual void log(Level, const char message[], const char* json = nullptr); }; // Evaluates AE expressions. template class SK_API ExpressionEvaluator : public SkRefCnt { public: // Evaluate the expression at the current time. virtual T evaluate(float t) = 0; }; /** * Creates ExpressionEvaluators to evaluate AE expressions and return the results. */ class SK_API ExpressionManager : public SkRefCnt { public: virtual sk_sp> createNumberExpressionEvaluator( const char expression[]) = 0; virtual sk_sp> createStringExpressionEvaluator( const char expression[]) = 0; virtual sk_sp>> createArrayExpressionEvaluator( const char expression[]) = 0; }; /** * Interface for receiving AE composition markers at Animation build time. */ class SK_API MarkerObserver : public SkRefCnt { public: // t0,t1 are in the Animation::seek() domain. virtual void onMarker(const char name[], float t0, float t1) = 0; }; class SK_API Animation : public SkNVRefCnt { public: class SK_API Builder final { public: enum Flags : uint32_t { kDeferImageLoading = 0x01, // Normally, all static image frames are resolved at // load time via ImageAsset::getFrame(0). With this flag, // frames are only resolved when needed, at seek() time. kPreferEmbeddedFonts = 0x02, // Attempt to use the embedded fonts (glyph paths, // normally used as fallback) over native Skia typefaces. }; explicit Builder(uint32_t flags = 0); ~Builder(); struct Stats { float fTotalLoadTimeMS = 0, // Total animation instantiation time. fJsonParseTimeMS = 0, // Time spent building a JSON DOM. fSceneParseTimeMS = 0; // Time spent constructing the animation scene graph. size_t fJsonSize = 0, // Input JSON size. fAnimatorCount = 0; // Number of dynamically animated properties. }; /** * Returns various animation build stats. * * @return Stats (see above). */ const Stats& getStats() const { return fStats; } /** * Specify a loader for external resources (images, etc.). */ Builder& setResourceProvider(sk_sp); /** * Specify a font manager for loading animation fonts. */ Builder& setFontManager(sk_sp); /** * Specify a PropertyObserver to receive callbacks during parsing. * * See SkottieProperty.h for more details. * */ Builder& setPropertyObserver(sk_sp); /** * Register a Logger with this builder. */ Builder& setLogger(sk_sp); /** * Register a MarkerObserver with this builder. */ Builder& setMarkerObserver(sk_sp); /** * Register a precomp layer interceptor. * This allows substituting precomp layers with custom/externally managed content. */ Builder& setPrecompInterceptor(sk_sp); /** * Registers an ExpressionManager to evaluate AE expressions. * If unspecified, expressions in the animation JSON will be ignored. */ Builder& setExpressionManager(sk_sp); /** * Animation factories. */ sk_sp make(SkStream*); sk_sp make(const char* data, size_t length); sk_sp makeFromFile(const char path[]); private: const uint32_t fFlags; sk_sp fResourceProvider; sk_sp fFontMgr; sk_sp fPropertyObserver; sk_sp fLogger; sk_sp fMarkerObserver; sk_sp fPrecompInterceptor; sk_sp fExpressionManager; Stats fStats; }; /** * Animation factories. * * Use the Builder helper above for more options/control. */ static sk_sp Make(const char* data, size_t length); static sk_sp Make(SkStream*); static sk_sp MakeFromFile(const char path[]); ~Animation(); enum RenderFlag : uint32_t { // When rendering into a known transparent buffer, clients can pass // this flag to avoid some unnecessary compositing overhead for // animations using layer blend modes. kSkipTopLevelIsolation = 0x01, // By default, content is clipped to the intrinsic animation // bounds (as determined by its size). If this flag is set, // then the animation can draw outside of the bounds. kDisableTopLevelClipping = 0x02, }; using RenderFlags = uint32_t; /** * Draws the current animation frame. * * It is undefined behavior to call render() on a newly created Animation * before specifying an initial frame via one of the seek() variants. * * @param canvas destination canvas * @param dst optional destination rect * @param flags optional RenderFlags */ void render(SkCanvas* canvas, const SkRect* dst = nullptr) const; void render(SkCanvas* canvas, const SkRect* dst, RenderFlags) const; /** * [Deprecated: use one of the other versions.] * * Updates the animation state for |t|. * * @param t normalized [0..1] frame selector (0 -> first frame, 1 -> final frame) * @param ic optional invalidation controller (dirty region tracking) * */ void seek(SkScalar t, sksg::InvalidationController* ic = nullptr) { this->seekFrameTime(t * this->duration(), ic); } /** * Update the animation state to match |t|, specified as a frame index * i.e. relative to duration() * fps(). * * Fractional values are allowed and meaningful - e.g. * * 0.0 -> first frame * 1.0 -> second frame * 0.5 -> halfway between first and second frame */ void seekFrame(double t, sksg::InvalidationController* ic = nullptr); /** Update the animation state to match t, specifed in frame time * i.e. relative to duration(). */ void seekFrameTime(double t, sksg::InvalidationController* = nullptr); /** * Returns the animation duration in seconds. */ double duration() const { return fDuration; } /** * Returns the animation frame rate (frames / second). */ double fps() const { return fFPS; } /** * Animation in point, in frame index units. */ double inPoint() const { return fInPoint; } /** * Animation out point, in frame index units. */ double outPoint() const { return fOutPoint; } const SkString& version() const { return fVersion; } const SkSize& size() const { return fSize; } private: enum Flags : uint32_t { kRequiresTopLevelIsolation = 1 << 0, // Needs to draw into a layer due to layer blending. }; Animation(std::unique_ptr, std::vector>&&, SkString ver, const SkSize& size, double inPoint, double outPoint, double duration, double fps, uint32_t flags); const std::unique_ptr fScene; const std::vector> fAnimators; const SkString fVersion; const SkSize fSize; const double fInPoint, fOutPoint, fDuration, fFPS; const uint32_t fFlags; using INHERITED = SkNVRefCnt; }; } // namespace skottie #endif // Skottie_DEFINED