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 "modules/skottie/include/Skottie.h" 12 13 #include "include/core/SkFontStyle.h" 14 #include "include/core/SkString.h" 15 #include "include/core/SkTypeface.h" 16 #include "include/private/SkTHash.h" 17 #include "include/utils/SkCustomTypeface.h" 18 #include "modules/skottie/include/SkottieProperty.h" 19 #include "modules/skottie/src/animator/Animator.h" 20 #include "modules/sksg/include/SkSGScene.h" 21 #include "src/utils/SkUTF.h" 22 23 #include <vector> 24 25 class SkFontMgr; 26 27 namespace skjson { 28 class ArrayValue; 29 class ObjectValue; 30 class Value; 31 } // namespace skjson 32 33 namespace sksg { 34 class Color; 35 class Path; 36 class RenderNode; 37 class Transform; 38 } // namespace sksg 39 40 namespace skottie { 41 namespace internal { 42 43 // Close-enough to AE. 44 static constexpr float kBlurSizeToSigma = 0.3f; 45 46 class TextAdapter; 47 class TransformAdapter2D; 48 class TransformAdapter3D; 49 50 using AnimatorScope = std::vector<sk_sp<Animator>>; 51 52 class AnimationBuilder final : public SkNoncopyable { 53 public: 54 AnimationBuilder(sk_sp<ResourceProvider>, sk_sp<SkFontMgr>, sk_sp<PropertyObserver>, 55 sk_sp<Logger>, sk_sp<MarkerObserver>, sk_sp<PrecompInterceptor>, 56 sk_sp<ExpressionManager>, 57 Animation::Builder::Stats*, const SkSize& comp_size, 58 float duration, float framerate, uint32_t flags); 59 60 struct AnimationInfo { 61 std::unique_ptr<sksg::Scene> fScene; 62 AnimatorScope fAnimators; 63 }; 64 65 AnimationInfo parse(const skjson::ObjectValue&); 66 67 struct FontInfo { 68 SkString fFamily, 69 fStyle, 70 fPath; 71 SkScalar fAscentPct; 72 sk_sp<SkTypeface> fTypeface; 73 SkCustomTypefaceBuilder fCustomBuilder; 74 75 bool matches(const char family[], const char style[]) const; 76 }; 77 const FontInfo* findFont(const SkString& name) const; 78 79 void log(Logger::Level, const skjson::Value*, const char fmt[], ...) const; 80 81 sk_sp<sksg::Transform> attachMatrix2D(const skjson::ObjectValue&, sk_sp<sksg::Transform>, 82 bool auto_orient = false) const; 83 sk_sp<sksg::Transform> attachMatrix3D(const skjson::ObjectValue&, sk_sp<sksg::Transform>, 84 bool auto_orient = false) const; 85 86 sk_sp<sksg::Transform> attachCamera(const skjson::ObjectValue& jlayer, 87 const skjson::ObjectValue& jtransform, 88 sk_sp<sksg::Transform>, 89 const SkSize&) const; 90 91 sk_sp<sksg::RenderNode> attachOpacity(const skjson::ObjectValue&, 92 sk_sp<sksg::RenderNode>) const; 93 sk_sp<sksg::Path> attachPath(const skjson::Value&) const; 94 hasNontrivialBlending()95 bool hasNontrivialBlending() const { return fHasNontrivialBlending; } 96 97 class AutoScope final { 98 public: AutoScope(const AnimationBuilder * builder)99 explicit AutoScope(const AnimationBuilder* builder) : AutoScope(builder, AnimatorScope()) {} 100 AutoScope(const AnimationBuilder * builder,AnimatorScope && scope)101 AutoScope(const AnimationBuilder* builder, AnimatorScope&& scope) 102 : fBuilder(builder) 103 , fCurrentScope(std::move(scope)) 104 , fPrevScope(fBuilder->fCurrentAnimatorScope) { 105 fBuilder->fCurrentAnimatorScope = &fCurrentScope; 106 } 107 release()108 AnimatorScope release() { 109 fBuilder->fCurrentAnimatorScope = fPrevScope; 110 SkDEBUGCODE(fBuilder = nullptr); 111 112 return std::move(fCurrentScope); 113 } 114 ~AutoScope()115 ~AutoScope() { SkASSERT(!fBuilder); } 116 117 private: 118 const AnimationBuilder* fBuilder; 119 AnimatorScope fCurrentScope; 120 AnimatorScope* fPrevScope; 121 }; 122 123 template <typename T> attachDiscardableAdapter(sk_sp<T> adapter)124 void attachDiscardableAdapter(sk_sp<T> adapter) const { 125 if (adapter->isStatic()) { 126 // Fire off a synthetic tick to force a single SG sync before discarding. 127 adapter->seek(0); 128 } else { 129 fCurrentAnimatorScope->push_back(std::move(adapter)); 130 } 131 } 132 133 template <typename T, typename... Args> 134 auto attachDiscardableAdapter(Args&&... args) const -> 135 typename std::decay<decltype(T::Make(std::forward<Args>(args)...)->node())>::type 136 { 137 using NodeType = 138 typename std::decay<decltype(T::Make(std::forward<Args>(args)...)->node())>::type; 139 140 NodeType node; 141 if (auto adapter = T::Make(std::forward<Args>(args)...)) { 142 node = adapter->node(); 143 this->attachDiscardableAdapter(std::move(adapter)); 144 } 145 return node; 146 } 147 148 class AutoPropertyTracker { 149 public: AutoPropertyTracker(const AnimationBuilder * builder,const skjson::ObjectValue & obj,const PropertyObserver::NodeType node_type)150 AutoPropertyTracker(const AnimationBuilder* builder, const skjson::ObjectValue& obj, const PropertyObserver::NodeType node_type) 151 : fBuilder(builder) 152 , fPrevContext(builder->fPropertyObserverContext), fNodeType(node_type) { 153 if (fBuilder->fPropertyObserver) { 154 auto observer = builder->fPropertyObserver.get(); 155 this->updateContext(observer, obj); 156 observer->onEnterNode(fBuilder->fPropertyObserverContext, fNodeType); 157 } 158 } 159 ~AutoPropertyTracker()160 ~AutoPropertyTracker() { 161 if (fBuilder->fPropertyObserver) { 162 fBuilder->fPropertyObserver->onLeavingNode(fBuilder->fPropertyObserverContext, fNodeType); 163 fBuilder->fPropertyObserverContext = fPrevContext; 164 } 165 } 166 private: 167 void updateContext(PropertyObserver*, const skjson::ObjectValue&); 168 169 const AnimationBuilder* fBuilder; 170 const char* fPrevContext; 171 const PropertyObserver::NodeType fNodeType; 172 }; 173 174 bool dispatchColorProperty(const sk_sp<sksg::Color>&) const; 175 bool dispatchOpacityProperty(const sk_sp<sksg::OpacityEffect>&) const; 176 bool dispatchTextProperty(const sk_sp<TextAdapter>&) const; 177 bool dispatchTransformProperty(const sk_sp<TransformAdapter2D>&) const; 178 179 sk_sp<ExpressionManager> expression_manager() const; 180 181 private: 182 friend class CompositionBuilder; 183 friend class LayerBuilder; 184 185 struct AttachLayerContext; 186 struct AttachShapeContext; 187 struct FootageAssetInfo; 188 struct LayerInfo; 189 190 void parseAssets(const skjson::ArrayValue*); 191 void parseFonts (const skjson::ObjectValue* jfonts, 192 const skjson::ArrayValue* jchars); 193 194 // Return true iff all fonts were resolved. 195 bool resolveNativeTypefaces(); 196 bool resolveEmbeddedTypefaces(const skjson::ArrayValue& jchars); 197 198 void dispatchMarkers(const skjson::ArrayValue*) const; 199 200 sk_sp<sksg::RenderNode> attachBlendMode(const skjson::ObjectValue&, 201 sk_sp<sksg::RenderNode>) const; 202 203 sk_sp<sksg::RenderNode> attachShape(const skjson::ArrayValue*, AttachShapeContext*, 204 bool suppress_draws = false) const; 205 const FootageAssetInfo* loadFootageAsset(const skjson::ObjectValue&) const; 206 sk_sp<sksg::RenderNode> attachFootageAsset(const skjson::ObjectValue&, LayerInfo*) const; 207 208 sk_sp<sksg::RenderNode> attachExternalPrecompLayer(const skjson::ObjectValue&, 209 const LayerInfo&) const; 210 211 sk_sp<sksg::RenderNode> attachFootageLayer(const skjson::ObjectValue&, LayerInfo*) const; 212 sk_sp<sksg::RenderNode> attachNullLayer (const skjson::ObjectValue&, LayerInfo*) const; 213 sk_sp<sksg::RenderNode> attachPrecompLayer(const skjson::ObjectValue&, LayerInfo*) const; 214 sk_sp<sksg::RenderNode> attachShapeLayer (const skjson::ObjectValue&, LayerInfo*) const; 215 sk_sp<sksg::RenderNode> attachSolidLayer (const skjson::ObjectValue&, LayerInfo*) const; 216 sk_sp<sksg::RenderNode> attachTextLayer (const skjson::ObjectValue&, LayerInfo*) const; 217 sk_sp<sksg::RenderNode> attachAudioLayer (const skjson::ObjectValue&, LayerInfo*) const; 218 219 // Delay resolving the fontmgr until it is actually needed. 220 struct LazyResolveFontMgr { LazyResolveFontMgrLazyResolveFontMgr221 LazyResolveFontMgr(sk_sp<SkFontMgr> fontMgr) : fFontMgr(std::move(fontMgr)) {} 222 getLazyResolveFontMgr223 const sk_sp<SkFontMgr>& get() { 224 if (!fFontMgr) { 225 fFontMgr = SkFontMgr::RefDefault(); 226 SkASSERT(fFontMgr); 227 } 228 return fFontMgr; 229 } 230 getMaybeNullLazyResolveFontMgr231 const sk_sp<SkFontMgr>& getMaybeNull() const { return fFontMgr; } 232 233 private: 234 sk_sp<SkFontMgr> fFontMgr; 235 }; 236 237 sk_sp<ResourceProvider> fResourceProvider; 238 LazyResolveFontMgr fLazyFontMgr; 239 sk_sp<PropertyObserver> fPropertyObserver; 240 sk_sp<Logger> fLogger; 241 sk_sp<MarkerObserver> fMarkerObserver; 242 sk_sp<PrecompInterceptor> fPrecompInterceptor; 243 sk_sp<ExpressionManager> fExpressionManager; 244 Animation::Builder::Stats* fStats; 245 const SkSize fCompSize; 246 const float fDuration, 247 fFrameRate; 248 const uint32_t fFlags; 249 mutable AnimatorScope* fCurrentAnimatorScope; 250 mutable const char* fPropertyObserverContext; 251 mutable bool fHasNontrivialBlending : 1; 252 253 struct LayerInfo { 254 SkSize fSize; 255 const float fInPoint, 256 fOutPoint; 257 }; 258 259 struct AssetInfo { 260 const skjson::ObjectValue* fAsset; 261 mutable bool fIsAttaching; // Used for cycle detection 262 }; 263 264 struct FootageAssetInfo { 265 sk_sp<ImageAsset> fAsset; 266 SkISize fSize; 267 }; 268 269 class ScopedAssetRef { 270 public: 271 ScopedAssetRef(const AnimationBuilder* abuilder, const skjson::ObjectValue& jlayer); 272 ~ScopedAssetRef()273 ~ScopedAssetRef() { 274 if (fInfo) { 275 fInfo->fIsAttaching = false; 276 } 277 } 278 279 operator bool() const { return !!fInfo; } 280 281 const skjson::ObjectValue& operator*() const { return *fInfo->fAsset; } 282 283 private: 284 const AssetInfo* fInfo = nullptr; 285 }; 286 287 SkTHashMap<SkString, AssetInfo> fAssets; 288 SkTHashMap<SkString, FontInfo> fFonts; 289 mutable SkTHashMap<SkString, FootageAssetInfo> fImageAssetCache; 290 291 using INHERITED = SkNoncopyable; 292 }; 293 294 } // namespace internal 295 } // namespace skottie 296 297 #endif // SkottiePriv_DEFINED 298