• 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 "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