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