/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkottiePriv_DEFINED #define SkottiePriv_DEFINED #include "Skottie.h" #include "SkFontStyle.h" #include "SkottieProperty.h" #include "SkSGScene.h" #include "SkString.h" #include "SkTHash.h" #include "SkTypeface.h" #include "SkUTF.h" #include class SkFontMgr; namespace skjson { class ArrayValue; class ObjectValue; class Value; } // namespace skjson namespace sksg { class Color; class Path; class RenderNode; class Transform; } // namespace sksg namespace skottie { namespace internal { using AnimatorScope = sksg::AnimatorList; class AnimationBuilder final : public SkNoncopyable { public: AnimationBuilder(sk_sp, sk_sp, sk_sp, sk_sp, sk_sp, Animation::Builder::Stats*, float duration, float framerate); std::unique_ptr parse(const skjson::ObjectValue&); sk_sp findFont(const SkString& name) const; // This is the workhorse for property binding: depending on whether the property is animated, // it will either apply immediately or instantiate and attach a keyframe animator. template bool bindProperty(const skjson::Value&, AnimatorScope*, std::function&&, const T* default_igore = nullptr) const; template bool bindProperty(const skjson::Value& jv, AnimatorScope* ascope, std::function&& apply, const T& default_ignore) const { return this->bindProperty(jv, ascope, std::move(apply), &default_ignore); } void log(Logger::Level, const skjson::Value*, const char fmt[], ...) const; sk_sp attachColor(const skjson::ObjectValue&, AnimatorScope*, const char prop_name[]) const; sk_sp attachMatrix2D(const skjson::ObjectValue&, AnimatorScope*, sk_sp) const; sk_sp attachMatrix3D(const skjson::ObjectValue&, AnimatorScope*, sk_sp) const; sk_sp attachOpacity(const skjson::ObjectValue&, AnimatorScope*, sk_sp) const; sk_sp attachPath(const skjson::Value&, AnimatorScope*) const; private: struct AttachLayerContext; struct AttachShapeContext; struct ImageAssetInfo; struct LayerInfo; void parseAssets(const skjson::ArrayValue*); void parseFonts (const skjson::ObjectValue* jfonts, const skjson::ArrayValue* jchars); void dispatchMarkers(const skjson::ArrayValue*) const; sk_sp attachComposition(const skjson::ObjectValue&, AnimatorScope*) const; sk_sp attachLayer(const skjson::ObjectValue*, AttachLayerContext*) const; sk_sp attachLayerEffects(const skjson::ArrayValue& jeffects, AnimatorScope*, sk_sp) const; sk_sp attachShape(const skjson::ArrayValue*, AttachShapeContext*) const; sk_sp attachAssetRef(const skjson::ObjectValue&, AnimatorScope*, const std::function(const skjson::ObjectValue&, AnimatorScope* ctx)>&) const; const ImageAssetInfo* loadImageAsset(const skjson::ObjectValue&) const; sk_sp attachImageAsset(const skjson::ObjectValue&, const LayerInfo&, AnimatorScope*) const; sk_sp attachNestedAnimation(const char* name, AnimatorScope* ascope) const; sk_sp attachImageLayer (const skjson::ObjectValue&, const LayerInfo&, AnimatorScope*) const; sk_sp attachNullLayer (const skjson::ObjectValue&, const LayerInfo&, AnimatorScope*) const; sk_sp attachPrecompLayer(const skjson::ObjectValue&, const LayerInfo&, AnimatorScope*) const; sk_sp attachShapeLayer (const skjson::ObjectValue&, const LayerInfo&, AnimatorScope*) const; sk_sp attachSolidLayer (const skjson::ObjectValue&, const LayerInfo&, AnimatorScope*) const; sk_sp attachTextLayer (const skjson::ObjectValue&, const LayerInfo&, AnimatorScope*) const; bool dispatchColorProperty(const sk_sp&) const; bool dispatchOpacityProperty(const sk_sp&) const; bool dispatchTransformProperty(const sk_sp&) const; // Delay resolving the fontmgr until it is actually needed. struct LazyResolveFontMgr { LazyResolveFontMgr(sk_sp fontMgr) : fFontMgr(std::move(fontMgr)) {} const sk_sp& get() { if (!fFontMgr) { fFontMgr = SkFontMgr::RefDefault(); SkASSERT(fFontMgr); } return fFontMgr; } const sk_sp& getMaybeNull() const { return fFontMgr; } private: sk_sp fFontMgr; }; class AutoPropertyTracker { public: AutoPropertyTracker(const AnimationBuilder* builder, const skjson::ObjectValue& obj) : fBuilder(builder) , fPrevContext(builder->fPropertyObserverContext) { if (fBuilder->fPropertyObserver) { this->updateContext(builder->fPropertyObserver.get(), obj); } } ~AutoPropertyTracker() { if (fBuilder->fPropertyObserver) { fBuilder->fPropertyObserverContext = fPrevContext; } } private: void updateContext(PropertyObserver*, const skjson::ObjectValue&); const AnimationBuilder* fBuilder; const char* fPrevContext; }; sk_sp fResourceProvider; LazyResolveFontMgr fLazyFontMgr; sk_sp fPropertyObserver; sk_sp fLogger; sk_sp fMarkerObserver; Animation::Builder::Stats* fStats; const float fDuration, fFrameRate; mutable const char* fPropertyObserverContext; struct LayerInfo { float fInPoint, fOutPoint; }; struct AssetInfo { const skjson::ObjectValue* fAsset; mutable bool fIsAttaching; // Used for cycle detection }; struct FontInfo { SkString fFamily, fStyle; SkScalar fAscent; sk_sp fTypeface; bool matches(const char family[], const char style[]) const; }; struct ImageAssetInfo { sk_sp fAsset; SkISize fSize; }; SkTHashMap fAssets; SkTHashMap fFonts; mutable SkTHashMap fImageAssetCache; using INHERITED = SkNoncopyable; }; } // namespace internal } // namespace skottie #endif // SkottiePriv_DEFINED