• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
209     struct AttachLayerContext;
210     struct AttachShapeContext;
211     struct FootageAssetInfo;
212     struct LayerInfo;
213 
214     void parseAssets(const skjson::ArrayValue*);
215 
216     // Return true iff all fonts were resolved.
217     bool resolveNativeTypefaces();
218     bool resolveEmbeddedTypefaces(const skjson::ArrayValue& jchars);
219 
220     void dispatchMarkers(const skjson::ArrayValue*) const;
221 
222     sk_sp<sksg::RenderNode> attachBlendMode(const skjson::ObjectValue&,
223                                             sk_sp<sksg::RenderNode>) const;
224 
225     sk_sp<sksg::RenderNode> attachShape(const skjson::ArrayValue*, AttachShapeContext*,
226                                         bool suppress_draws = false) const;
227     const FootageAssetInfo* loadFootageAsset(const skjson::ObjectValue&) const;
228     sk_sp<sksg::RenderNode> attachFootageAsset(const skjson::ObjectValue&, LayerInfo*) const;
229 
230     sk_sp<sksg::RenderNode> attachExternalPrecompLayer(const skjson::ObjectValue&,
231                                                        const LayerInfo&) const;
232 
233     sk_sp<sksg::RenderNode> attachFootageLayer(const skjson::ObjectValue&, LayerInfo*) const;
234     sk_sp<sksg::RenderNode> attachNullLayer   (const skjson::ObjectValue&, LayerInfo*) const;
235     sk_sp<sksg::RenderNode> attachPrecompLayer(const skjson::ObjectValue&, LayerInfo*) const;
236     sk_sp<sksg::RenderNode> attachShapeLayer  (const skjson::ObjectValue&, LayerInfo*) const;
237     sk_sp<sksg::RenderNode> attachSolidLayer  (const skjson::ObjectValue&, LayerInfo*) const;
238     sk_sp<sksg::RenderNode> attachTextLayer   (const skjson::ObjectValue&, LayerInfo*) const;
239     sk_sp<sksg::RenderNode> attachAudioLayer  (const skjson::ObjectValue&, LayerInfo*) const;
240 
241     sk_sp<ResourceProvider>      fResourceProvider;
242     sk_sp<SkFontMgr>             fFontMgr;
243     sk_sp<PropertyObserver>      fPropertyObserver;
244     sk_sp<Logger>                fLogger;
245     sk_sp<MarkerObserver>        fMarkerObserver;
246     sk_sp<PrecompInterceptor>    fPrecompInterceptor;
247     sk_sp<ExpressionManager>     fExpressionManager;
248     sk_sp<SkShapers::Factory>    fShapingFactory;
249     sk_sp<SceneGraphRevalidator> fRevalidator;
250     sk_sp<SlotManager>           fSlotManager;
251     Animation::Builder::Stats*   fStats;
252     const SkSize                 fCompSize;
253     const float                  fDuration,
254                                  fFrameRate;
255     const uint32_t               fFlags;
256     mutable AnimatorScope*       fCurrentAnimatorScope;
257     mutable const char*          fPropertyObserverContext = nullptr;
258     mutable bool                 fHasNontrivialBlending : 1;
259 
260     struct LayerInfo {
261         SkSize      fSize;
262         const float fInPoint,
263                     fOutPoint;
264     };
265 
266     struct AssetInfo {
267         const skjson::ObjectValue* fAsset;
268         mutable bool               fIsAttaching; // Used for cycle detection
269     };
270 
271     struct FootageAssetInfo {
272         sk_sp<ImageAsset> fAsset;
273         SkISize           fSize;
274     };
275 
276     class ScopedAssetRef {
277     public:
278         ScopedAssetRef(const AnimationBuilder* abuilder, const skjson::ObjectValue& jlayer);
279 
~ScopedAssetRef()280         ~ScopedAssetRef() {
281             if (fInfo) {
282                 fInfo->fIsAttaching = false;
283             }
284         }
285 
286         explicit operator bool() const { return !!fInfo; }
287 
288         const skjson::ObjectValue& operator*() const { return *fInfo->fAsset; }
289 
290     private:
291         const AssetInfo* fInfo = nullptr;
292     };
293 
294     skia_private::THashMap<SkString, AssetInfo>                fAssets;
295     skia_private::THashMap<SkString, FontInfo>                 fFonts;
296     sk_sp<CustomFont::GlyphCompMapper>                         fCustomGlyphMapper;
297     mutable skia_private::THashMap<SkString, FootageAssetInfo> fImageAssetCache;
298 
299     // Handle to "slots" JSON Object, used to grab slot values while building
300     const skjson::ObjectValue* fSlotsRoot;
301 
302     using INHERITED = SkNoncopyable;
303 };
304 
305 } // namespace internal
306 } // namespace skottie
307 
308 #endif // SkottiePriv_DEFINED
309