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