xref: /aosp_15_r20/external/skia/modules/skottie/src/SkottiePriv.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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