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 "modules/skottie/include/SkottieProperty.h" 17 #include "modules/skottie/src/animator/Animator.h" 18 #include "modules/skottie/src/text/Font.h" 19 #include "modules/sksg/include/SkSGScene.h" 20 #include "src/base/SkUTF.h" 21 #include "src/core/SkTHash.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 CustomFont::Builder fCustomFontBuilder; 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 SK_PRINTF_LIKE(4, 5); 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 CustomFont; 184 friend class LayerBuilder; 185 186 struct AttachLayerContext; 187 struct AttachShapeContext; 188 struct FootageAssetInfo; 189 struct LayerInfo; 190 191 void parseAssets(const skjson::ArrayValue*); 192 void parseFonts (const skjson::ObjectValue* jfonts, 193 const skjson::ArrayValue* jchars); 194 195 // Return true iff all fonts were resolved. 196 bool resolveNativeTypefaces(); 197 bool resolveEmbeddedTypefaces(const skjson::ArrayValue& jchars); 198 199 void dispatchMarkers(const skjson::ArrayValue*) const; 200 201 sk_sp<sksg::RenderNode> attachBlendMode(const skjson::ObjectValue&, 202 sk_sp<sksg::RenderNode>) const; 203 204 sk_sp<sksg::RenderNode> attachShape(const skjson::ArrayValue*, AttachShapeContext*, 205 bool suppress_draws = false) const; 206 const FootageAssetInfo* loadFootageAsset(const skjson::ObjectValue&) const; 207 sk_sp<sksg::RenderNode> attachFootageAsset(const skjson::ObjectValue&, LayerInfo*) const; 208 209 sk_sp<sksg::RenderNode> attachExternalPrecompLayer(const skjson::ObjectValue&, 210 const LayerInfo&) const; 211 212 sk_sp<sksg::RenderNode> attachFootageLayer(const skjson::ObjectValue&, LayerInfo*) const; 213 sk_sp<sksg::RenderNode> attachNullLayer (const skjson::ObjectValue&, LayerInfo*) const; 214 sk_sp<sksg::RenderNode> attachPrecompLayer(const skjson::ObjectValue&, LayerInfo*) const; 215 sk_sp<sksg::RenderNode> attachShapeLayer (const skjson::ObjectValue&, LayerInfo*) const; 216 sk_sp<sksg::RenderNode> attachSolidLayer (const skjson::ObjectValue&, LayerInfo*) const; 217 sk_sp<sksg::RenderNode> attachTextLayer (const skjson::ObjectValue&, LayerInfo*) const; 218 sk_sp<sksg::RenderNode> attachAudioLayer (const skjson::ObjectValue&, LayerInfo*) const; 219 220 // Delay resolving the fontmgr until it is actually needed. 221 struct LazyResolveFontMgr { LazyResolveFontMgrLazyResolveFontMgr222 LazyResolveFontMgr(sk_sp<SkFontMgr> fontMgr) : fFontMgr(std::move(fontMgr)) {} 223 getLazyResolveFontMgr224 const sk_sp<SkFontMgr>& get() { 225 if (!fFontMgr) { 226 fFontMgr = SkFontMgr::RefDefault(); 227 SkASSERT(fFontMgr); 228 } 229 return fFontMgr; 230 } 231 getMaybeNullLazyResolveFontMgr232 const sk_sp<SkFontMgr>& getMaybeNull() const { return fFontMgr; } 233 234 private: 235 sk_sp<SkFontMgr> fFontMgr; 236 }; 237 238 sk_sp<ResourceProvider> fResourceProvider; 239 LazyResolveFontMgr fLazyFontMgr; 240 sk_sp<PropertyObserver> fPropertyObserver; 241 sk_sp<Logger> fLogger; 242 sk_sp<MarkerObserver> fMarkerObserver; 243 sk_sp<PrecompInterceptor> fPrecompInterceptor; 244 sk_sp<ExpressionManager> fExpressionManager; 245 Animation::Builder::Stats* fStats; 246 const SkSize fCompSize; 247 const float fDuration, 248 fFrameRate; 249 const uint32_t fFlags; 250 mutable AnimatorScope* fCurrentAnimatorScope; 251 mutable const char* fPropertyObserverContext; 252 mutable bool fHasNontrivialBlending : 1; 253 254 struct LayerInfo { 255 SkSize fSize; 256 const float fInPoint, 257 fOutPoint; 258 }; 259 260 struct AssetInfo { 261 const skjson::ObjectValue* fAsset; 262 mutable bool fIsAttaching; // Used for cycle detection 263 }; 264 265 struct FootageAssetInfo { 266 sk_sp<ImageAsset> fAsset; 267 SkISize fSize; 268 }; 269 270 class ScopedAssetRef { 271 public: 272 ScopedAssetRef(const AnimationBuilder* abuilder, const skjson::ObjectValue& jlayer); 273 ~ScopedAssetRef()274 ~ScopedAssetRef() { 275 if (fInfo) { 276 fInfo->fIsAttaching = false; 277 } 278 } 279 280 explicit operator bool() const { return !!fInfo; } 281 282 const skjson::ObjectValue& operator*() const { return *fInfo->fAsset; } 283 284 private: 285 const AssetInfo* fInfo = nullptr; 286 }; 287 288 SkTHashMap<SkString, AssetInfo> fAssets; 289 SkTHashMap<SkString, FontInfo> fFonts; 290 sk_sp<CustomFont::GlyphCompMapper> fCustomGlyphMapper; 291 mutable SkTHashMap<SkString, FootageAssetInfo> fImageAssetCache; 292 293 using INHERITED = SkNoncopyable; 294 }; 295 296 } // namespace internal 297 } // namespace skottie 298 299 #endif // SkottiePriv_DEFINED 300