1 /* 2 * Copyright 2018 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 SkottiePriv_DEFINED 9 #define SkottiePriv_DEFINED 10 11 #include "Skottie.h" 12 13 #include "SkFontStyle.h" 14 #include "SkottieProperty.h" 15 #include "SkSGScene.h" 16 #include "SkString.h" 17 #include "SkTHash.h" 18 #include "SkTypeface.h" 19 #include "SkUTF.h" 20 21 #include <functional> 22 23 class SkFontMgr; 24 25 namespace skjson { 26 class ArrayValue; 27 class ObjectValue; 28 class Value; 29 } // namespace skjson 30 31 namespace sksg { 32 class Color; 33 class Path; 34 class RenderNode; 35 class Transform; 36 } // namespace sksg 37 38 namespace skottie { 39 40 namespace internal { 41 42 using AnimatorScope = sksg::AnimatorList; 43 44 class AnimationBuilder final : public SkNoncopyable { 45 public: 46 AnimationBuilder(sk_sp<ResourceProvider>, sk_sp<SkFontMgr>, sk_sp<PropertyObserver>, 47 sk_sp<Logger>, sk_sp<MarkerObserver>, 48 Animation::Builder::Stats*, float duration, float framerate); 49 50 std::unique_ptr<sksg::Scene> parse(const skjson::ObjectValue&); 51 52 sk_sp<SkTypeface> findFont(const SkString& name) const; 53 54 // This is the workhorse for property binding: depending on whether the property is animated, 55 // it will either apply immediately or instantiate and attach a keyframe animator. 56 template <typename T> 57 bool bindProperty(const skjson::Value&, 58 AnimatorScope*, 59 std::function<void(const T&)>&&, 60 const T* default_igore = nullptr) const; 61 62 template <typename T> bindProperty(const skjson::Value & jv,AnimatorScope * ascope,std::function<void (const T &)> && apply,const T & default_ignore)63 bool bindProperty(const skjson::Value& jv, 64 AnimatorScope* ascope, 65 std::function<void(const T&)>&& apply, 66 const T& default_ignore) const { 67 return this->bindProperty(jv, ascope, std::move(apply), &default_ignore); 68 } 69 70 void log(Logger::Level, const skjson::Value*, const char fmt[], ...) const; 71 72 sk_sp<sksg::Color> attachColor(const skjson::ObjectValue&, AnimatorScope*, 73 const char prop_name[]) const; 74 sk_sp<sksg::Transform> attachMatrix2D(const skjson::ObjectValue&, AnimatorScope*, 75 sk_sp<sksg::Transform>) const; 76 sk_sp<sksg::Transform> attachMatrix3D(const skjson::ObjectValue&, AnimatorScope*, 77 sk_sp<sksg::Transform>) const; 78 sk_sp<sksg::RenderNode> attachOpacity(const skjson::ObjectValue&, AnimatorScope*, 79 sk_sp<sksg::RenderNode>) const; 80 sk_sp<sksg::Path> attachPath(const skjson::Value&, AnimatorScope*) const; 81 hasNontrivialBlending()82 bool hasNontrivialBlending() const { return fHasNontrivialBlending; } 83 84 private: 85 struct AttachLayerContext; 86 struct AttachShapeContext; 87 struct ImageAssetInfo; 88 struct LayerInfo; 89 90 void parseAssets(const skjson::ArrayValue*); 91 void parseFonts (const skjson::ObjectValue* jfonts, 92 const skjson::ArrayValue* jchars); 93 94 void dispatchMarkers(const skjson::ArrayValue*) const; 95 96 sk_sp<sksg::RenderNode> attachComposition(const skjson::ObjectValue&, AnimatorScope*) const; 97 sk_sp<sksg::RenderNode> attachLayer(const skjson::ObjectValue*, AttachLayerContext*) const; 98 sk_sp<sksg::RenderNode> attachLayerEffects(const skjson::ArrayValue& jeffects, AnimatorScope*, 99 sk_sp<sksg::RenderNode>) const; 100 101 sk_sp<sksg::RenderNode> attachBlendMode(const skjson::ObjectValue&, 102 sk_sp<sksg::RenderNode>) const; 103 104 sk_sp<sksg::RenderNode> attachShape(const skjson::ArrayValue*, AttachShapeContext*) const; 105 sk_sp<sksg::RenderNode> attachAssetRef(const skjson::ObjectValue&, AnimatorScope*, 106 const std::function<sk_sp<sksg::RenderNode>(const skjson::ObjectValue&, 107 AnimatorScope* ctx)>&) const; 108 const ImageAssetInfo* loadImageAsset(const skjson::ObjectValue&) const; 109 sk_sp<sksg::RenderNode> attachImageAsset(const skjson::ObjectValue&, const LayerInfo&, 110 AnimatorScope*) const; 111 112 sk_sp<sksg::RenderNode> attachNestedAnimation(const char* name, AnimatorScope* ascope) const; 113 114 sk_sp<sksg::RenderNode> attachImageLayer (const skjson::ObjectValue&, const LayerInfo&, 115 AnimatorScope*) const; 116 sk_sp<sksg::RenderNode> attachNullLayer (const skjson::ObjectValue&, const LayerInfo&, 117 AnimatorScope*) const; 118 sk_sp<sksg::RenderNode> attachPrecompLayer(const skjson::ObjectValue&, const LayerInfo&, 119 AnimatorScope*) const; 120 sk_sp<sksg::RenderNode> attachShapeLayer (const skjson::ObjectValue&, const LayerInfo&, 121 AnimatorScope*) const; 122 sk_sp<sksg::RenderNode> attachSolidLayer (const skjson::ObjectValue&, const LayerInfo&, 123 AnimatorScope*) const; 124 sk_sp<sksg::RenderNode> attachTextLayer (const skjson::ObjectValue&, const LayerInfo&, 125 AnimatorScope*) const; 126 127 bool dispatchColorProperty(const sk_sp<sksg::Color>&) const; 128 bool dispatchOpacityProperty(const sk_sp<sksg::OpacityEffect>&) const; 129 bool dispatchTransformProperty(const sk_sp<TransformAdapter2D>&) const; 130 131 // Delay resolving the fontmgr until it is actually needed. 132 struct LazyResolveFontMgr { LazyResolveFontMgrLazyResolveFontMgr133 LazyResolveFontMgr(sk_sp<SkFontMgr> fontMgr) : fFontMgr(std::move(fontMgr)) {} 134 getLazyResolveFontMgr135 const sk_sp<SkFontMgr>& get() { 136 if (!fFontMgr) { 137 fFontMgr = SkFontMgr::RefDefault(); 138 SkASSERT(fFontMgr); 139 } 140 return fFontMgr; 141 } 142 getMaybeNullLazyResolveFontMgr143 const sk_sp<SkFontMgr>& getMaybeNull() const { return fFontMgr; } 144 145 private: 146 sk_sp<SkFontMgr> fFontMgr; 147 }; 148 149 class AutoPropertyTracker { 150 public: AutoPropertyTracker(const AnimationBuilder * builder,const skjson::ObjectValue & obj)151 AutoPropertyTracker(const AnimationBuilder* builder, const skjson::ObjectValue& obj) 152 : fBuilder(builder) 153 , fPrevContext(builder->fPropertyObserverContext) { 154 if (fBuilder->fPropertyObserver) { 155 this->updateContext(builder->fPropertyObserver.get(), obj); 156 } 157 } 158 ~AutoPropertyTracker()159 ~AutoPropertyTracker() { 160 if (fBuilder->fPropertyObserver) { 161 fBuilder->fPropertyObserverContext = fPrevContext; 162 } 163 } 164 private: 165 void updateContext(PropertyObserver*, const skjson::ObjectValue&); 166 167 const AnimationBuilder* fBuilder; 168 const char* fPrevContext; 169 }; 170 171 sk_sp<ResourceProvider> fResourceProvider; 172 LazyResolveFontMgr fLazyFontMgr; 173 sk_sp<PropertyObserver> fPropertyObserver; 174 sk_sp<Logger> fLogger; 175 sk_sp<MarkerObserver> fMarkerObserver; 176 Animation::Builder::Stats* fStats; 177 const float fDuration, 178 fFrameRate; 179 mutable const char* fPropertyObserverContext; 180 mutable bool fHasNontrivialBlending : 1; 181 182 183 struct LayerInfo { 184 float fInPoint, 185 fOutPoint; 186 }; 187 188 struct AssetInfo { 189 const skjson::ObjectValue* fAsset; 190 mutable bool fIsAttaching; // Used for cycle detection 191 }; 192 193 struct FontInfo { 194 SkString fFamily, 195 fStyle; 196 SkScalar fAscent; 197 sk_sp<SkTypeface> fTypeface; 198 199 bool matches(const char family[], const char style[]) const; 200 }; 201 202 struct ImageAssetInfo { 203 sk_sp<ImageAsset> fAsset; 204 SkISize fSize; 205 }; 206 207 SkTHashMap<SkString, AssetInfo> fAssets; 208 SkTHashMap<SkString, FontInfo> fFonts; 209 mutable SkTHashMap<SkString, ImageAssetInfo> fImageAssetCache; 210 211 using INHERITED = SkNoncopyable; 212 }; 213 214 } // namespace internal 215 } // namespace skottie 216 217 #endif // SkottiePriv_DEFINED 218