• 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 "include/private/SkTHash.h"
17 #include "include/utils/SkCustomTypeface.h"
18 #include "modules/skottie/include/SkottieProperty.h"
19 #include "modules/skottie/src/animator/Animator.h"
20 #include "modules/sksg/include/SkSGScene.h"
21 #include "src/utils/SkUTF.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                      Animation::Builder::Stats*, const SkSize& comp_size,
57                      float duration, float framerate, uint32_t flags);
58 
59     struct AnimationInfo {
60         std::unique_ptr<sksg::Scene> fScene;
61         AnimatorScope                fAnimators;
62     };
63 
64     AnimationInfo parse(const skjson::ObjectValue&);
65 
66     struct FontInfo {
67         SkString                fFamily,
68                                 fStyle,
69                                 fPath;
70         SkScalar                fAscentPct;
71         sk_sp<SkTypeface>       fTypeface;
72         SkCustomTypefaceBuilder fCustomBuilder;
73 
74         bool matches(const char family[], const char style[]) const;
75     };
76     const FontInfo* findFont(const SkString& name) const;
77 
78     void log(Logger::Level, const skjson::Value*, const char fmt[], ...) const;
79 
80     sk_sp<sksg::Transform> attachMatrix2D(const skjson::ObjectValue&, sk_sp<sksg::Transform>,
81                                           bool auto_orient = false) const;
82     sk_sp<sksg::Transform> attachMatrix3D(const skjson::ObjectValue&, sk_sp<sksg::Transform>,
83                                           bool auto_orient = false) const;
84 
85     sk_sp<sksg::Transform> attachCamera(const skjson::ObjectValue& jlayer,
86                                         const skjson::ObjectValue& jtransform,
87                                         sk_sp<sksg::Transform>,
88                                         const SkSize&) const;
89 
90     sk_sp<sksg::RenderNode> attachOpacity(const skjson::ObjectValue&,
91                                           sk_sp<sksg::RenderNode>) const;
92     sk_sp<sksg::Path> attachPath(const skjson::Value&) const;
93 
hasNontrivialBlending()94     bool hasNontrivialBlending() const { return fHasNontrivialBlending; }
95 
96     class AutoScope final {
97     public:
AutoScope(const AnimationBuilder * builder)98         explicit AutoScope(const AnimationBuilder* builder) : AutoScope(builder, AnimatorScope()) {}
99 
AutoScope(const AnimationBuilder * builder,AnimatorScope && scope)100         AutoScope(const AnimationBuilder* builder, AnimatorScope&& scope)
101             : fBuilder(builder)
102             , fCurrentScope(std::move(scope))
103             , fPrevScope(fBuilder->fCurrentAnimatorScope) {
104             fBuilder->fCurrentAnimatorScope = &fCurrentScope;
105         }
106 
release()107         AnimatorScope release() {
108             fBuilder->fCurrentAnimatorScope = fPrevScope;
109             SkDEBUGCODE(fBuilder = nullptr);
110 
111             return std::move(fCurrentScope);
112         }
113 
~AutoScope()114         ~AutoScope() { SkASSERT(!fBuilder); }
115 
116     private:
117         const AnimationBuilder* fBuilder;
118         AnimatorScope           fCurrentScope;
119         AnimatorScope*          fPrevScope;
120     };
121 
122     template <typename T>
attachDiscardableAdapter(sk_sp<T> adapter)123     void attachDiscardableAdapter(sk_sp<T> adapter) const {
124         if (adapter->isStatic()) {
125             // Fire off a synthetic tick to force a single SG sync before discarding.
126             adapter->seek(0);
127         } else {
128             fCurrentAnimatorScope->push_back(std::move(adapter));
129         }
130     }
131 
132     template <typename T, typename... Args>
133     auto attachDiscardableAdapter(Args&&... args) const ->
134         typename std::decay<decltype(T::Make(std::forward<Args>(args)...)->node())>::type
135     {
136         using NodeType =
137         typename std::decay<decltype(T::Make(std::forward<Args>(args)...)->node())>::type;
138 
139         NodeType node;
140         if (auto adapter = T::Make(std::forward<Args>(args)...)) {
141             node = adapter->node();
142             this->attachDiscardableAdapter(std::move(adapter));
143         }
144         return node;
145     }
146 
147     class AutoPropertyTracker {
148     public:
AutoPropertyTracker(const AnimationBuilder * builder,const skjson::ObjectValue & obj)149         AutoPropertyTracker(const AnimationBuilder* builder, const skjson::ObjectValue& obj)
150             : fBuilder(builder)
151             , fPrevContext(builder->fPropertyObserverContext) {
152             if (fBuilder->fPropertyObserver) {
153                 auto observer = builder->fPropertyObserver.get();
154                 this->updateContext(observer, obj);
155                 observer->onEnterNode(fBuilder->fPropertyObserverContext);
156             }
157         }
158 
~AutoPropertyTracker()159         ~AutoPropertyTracker() {
160             if (fBuilder->fPropertyObserver) {
161                 fBuilder->fPropertyObserver->onLeavingNode(fBuilder->fPropertyObserverContext);
162                 fBuilder->fPropertyObserverContext = fPrevContext;
163             }
164         }
165     private:
166         void updateContext(PropertyObserver*, const skjson::ObjectValue&);
167 
168         const AnimationBuilder* fBuilder;
169         const char*             fPrevContext;
170     };
171 
172     bool dispatchColorProperty(const sk_sp<sksg::Color>&) const;
173     bool dispatchOpacityProperty(const sk_sp<sksg::OpacityEffect>&) const;
174     bool dispatchTextProperty(const sk_sp<TextAdapter>&) const;
175     bool dispatchTransformProperty(const sk_sp<TransformAdapter2D>&) const;
176 
177 private:
178     friend class CompositionBuilder;
179     friend class LayerBuilder;
180 
181     struct AttachLayerContext;
182     struct AttachShapeContext;
183     struct FootageAssetInfo;
184     struct LayerInfo;
185 
186     void parseAssets(const skjson::ArrayValue*);
187     void parseFonts (const skjson::ObjectValue* jfonts,
188                      const skjson::ArrayValue* jchars);
189 
190     // Return true iff all fonts were resolved.
191     bool resolveNativeTypefaces();
192     bool resolveEmbeddedTypefaces(const skjson::ArrayValue& jchars);
193 
194     void dispatchMarkers(const skjson::ArrayValue*) const;
195 
196     sk_sp<sksg::RenderNode> attachBlendMode(const skjson::ObjectValue&,
197                                             sk_sp<sksg::RenderNode>) const;
198 
199     sk_sp<sksg::RenderNode> attachShape(const skjson::ArrayValue*, AttachShapeContext*,
200                                         bool suppress_draws = false) const;
201     const FootageAssetInfo* loadFootageAsset(const skjson::ObjectValue&) const;
202     sk_sp<sksg::RenderNode> attachFootageAsset(const skjson::ObjectValue&, LayerInfo*) const;
203 
204     sk_sp<sksg::RenderNode> attachExternalPrecompLayer(const skjson::ObjectValue&,
205                                                        const LayerInfo&) const;
206 
207     sk_sp<sksg::RenderNode> attachFootageLayer(const skjson::ObjectValue&, LayerInfo*) const;
208     sk_sp<sksg::RenderNode> attachNullLayer   (const skjson::ObjectValue&, LayerInfo*) const;
209     sk_sp<sksg::RenderNode> attachPrecompLayer(const skjson::ObjectValue&, LayerInfo*) const;
210     sk_sp<sksg::RenderNode> attachShapeLayer  (const skjson::ObjectValue&, LayerInfo*) const;
211     sk_sp<sksg::RenderNode> attachSolidLayer  (const skjson::ObjectValue&, LayerInfo*) const;
212     sk_sp<sksg::RenderNode> attachTextLayer   (const skjson::ObjectValue&, LayerInfo*) const;
213     sk_sp<sksg::RenderNode> attachAudioLayer  (const skjson::ObjectValue&, LayerInfo*) const;
214 
215     // Delay resolving the fontmgr until it is actually needed.
216     struct LazyResolveFontMgr {
LazyResolveFontMgrLazyResolveFontMgr217         LazyResolveFontMgr(sk_sp<SkFontMgr> fontMgr) : fFontMgr(std::move(fontMgr)) {}
218 
getLazyResolveFontMgr219         const sk_sp<SkFontMgr>& get() {
220             if (!fFontMgr) {
221                 fFontMgr = SkFontMgr::RefDefault();
222                 SkASSERT(fFontMgr);
223             }
224             return fFontMgr;
225         }
226 
getMaybeNullLazyResolveFontMgr227         const sk_sp<SkFontMgr>& getMaybeNull() const { return fFontMgr; }
228 
229     private:
230         sk_sp<SkFontMgr> fFontMgr;
231     };
232 
233     sk_sp<ResourceProvider>    fResourceProvider;
234     LazyResolveFontMgr         fLazyFontMgr;
235     sk_sp<PropertyObserver>    fPropertyObserver;
236     sk_sp<Logger>              fLogger;
237     sk_sp<MarkerObserver>      fMarkerObserver;
238     sk_sp<PrecompInterceptor>  fPrecompInterceptor;
239     Animation::Builder::Stats* fStats;
240     const SkSize               fCompSize;
241     const float                fDuration,
242                                fFrameRate;
243     const uint32_t             fFlags;
244     mutable AnimatorScope*     fCurrentAnimatorScope;
245     mutable const char*        fPropertyObserverContext;
246     mutable bool               fHasNontrivialBlending : 1;
247 
248     struct LayerInfo {
249         SkSize      fSize;
250         const float fInPoint,
251                     fOutPoint;
252     };
253 
254     struct AssetInfo {
255         const skjson::ObjectValue* fAsset;
256         mutable bool               fIsAttaching; // Used for cycle detection
257     };
258 
259     struct FootageAssetInfo {
260         sk_sp<ImageAsset> fAsset;
261         SkISize           fSize;
262     };
263 
264     class ScopedAssetRef {
265     public:
266         ScopedAssetRef(const AnimationBuilder* abuilder, const skjson::ObjectValue& jlayer);
267 
~ScopedAssetRef()268         ~ScopedAssetRef() {
269             if (fInfo) {
270                 fInfo->fIsAttaching = false;
271             }
272         }
273 
274         operator bool() const { return !!fInfo; }
275 
276         const skjson::ObjectValue& operator*() const { return *fInfo->fAsset; }
277 
278     private:
279         const AssetInfo* fInfo = nullptr;
280     };
281 
282     SkTHashMap<SkString, AssetInfo>                fAssets;
283     SkTHashMap<SkString, FontInfo>                 fFonts;
284     mutable SkTHashMap<SkString, FootageAssetInfo> fImageAssetCache;
285 
286     using INHERITED = SkNoncopyable;
287 };
288 
289 } // namespace internal
290 } // namespace skottie
291 
292 #endif // SkottiePriv_DEFINED
293