• 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 "modules/skottie/include/SkottieProperty.h"
18 #include "modules/sksg/include/SkSGScene.h"
19 #include "src/utils/SkUTF.h"
20 
21 #include <functional>
22 
23 class SkFontMgr;
24 
25 namespace skjson {
26 class ArrayValue;
27 class ObjectValue;
28 class Value;
29 } // namespace skjson
30 
31 namespace sksg {
32 class Color;
33 class Path;
34 class RenderNode;
35 class Transform;
36 } // namespace sksg
37 
38 namespace skottie {
39 
40 class TransformAdapter2D;
41 class TransformAdapter3D;
42 
43 namespace internal {
44 
45 class TextAdapter;
46 
47 using AnimatorScope = sksg::AnimatorList;
48 
49 class AnimationBuilder final : public SkNoncopyable {
50 public:
51     AnimationBuilder(sk_sp<ResourceProvider>, sk_sp<SkFontMgr>, sk_sp<PropertyObserver>,
52                      sk_sp<Logger>, sk_sp<MarkerObserver>,
53                      Animation::Builder::Stats*, const SkSize& size,
54                      float duration, float framerate);
55 
56     std::unique_ptr<sksg::Scene> parse(const skjson::ObjectValue&);
57 
58     struct FontInfo {
59         SkString                  fFamily,
60                                   fStyle;
61         SkScalar                  fAscentPct;
62         sk_sp<SkTypeface>         fTypeface;
63 
64         bool matches(const char family[], const char style[]) const;
65     };
66     const FontInfo* findFont(const SkString& name) const;
67 
68     // This is the workhorse for property binding: depending on whether the property is animated,
69     // it will either apply immediately or instantiate and attach a keyframe animator.
70     template <typename T>
71     bool bindProperty(const skjson::Value&,
72                       std::function<void(const T&)>&&,
73                       const T* default_igore = nullptr) const;
74 
75     template <typename T>
bindProperty(const skjson::Value & jv,std::function<void (const T &)> && apply,const T & default_ignore)76     bool bindProperty(const skjson::Value& jv,
77                       std::function<void(const T&)>&& apply,
78                       const T& default_ignore) const {
79         return this->bindProperty(jv, std::move(apply), &default_ignore);
80     }
81 
82     void log(Logger::Level, const skjson::Value*, const char fmt[], ...) const;
83 
84     sk_sp<sksg::Color> attachColor(const skjson::ObjectValue&, const char prop_name[]) const;
85     sk_sp<sksg::Transform> attachMatrix2D(const skjson::ObjectValue&, sk_sp<sksg::Transform>) const;
86     sk_sp<sksg::Transform> attachMatrix3D(const skjson::ObjectValue&, sk_sp<sksg::Transform>,
87                                           sk_sp<TransformAdapter3D> = nullptr,
88                                           bool precompose_parent = false) const;
89     sk_sp<sksg::RenderNode> attachOpacity(const skjson::ObjectValue&,
90                                           sk_sp<sksg::RenderNode>) const;
91     sk_sp<sksg::Path> attachPath(const skjson::Value&) const;
92 
hasNontrivialBlending()93     bool hasNontrivialBlending() const { return fHasNontrivialBlending; }
94 
95     class AutoScope final {
96     public:
AutoScope(const AnimationBuilder * builder)97         explicit AutoScope(const AnimationBuilder* builder) : AutoScope(builder, AnimatorScope()) {}
98 
AutoScope(const AnimationBuilder * builder,AnimatorScope && scope)99         AutoScope(const AnimationBuilder* builder, AnimatorScope&& scope)
100             : fBuilder(builder)
101             , fCurrentScope(std::move(scope))
102             , fPrevScope(fBuilder->fCurrentAnimatorScope) {
103             fBuilder->fCurrentAnimatorScope = &fCurrentScope;
104         }
105 
release()106         AnimatorScope release() {
107             fBuilder->fCurrentAnimatorScope = fPrevScope;
108             SkDEBUGCODE(fBuilder = nullptr);
109 
110             return std::move(fCurrentScope);
111         }
112 
~AutoScope()113         ~AutoScope() { SkASSERT(!fBuilder); }
114 
115     private:
116         const AnimationBuilder* fBuilder;
117         AnimatorScope           fCurrentScope;
118         AnimatorScope*          fPrevScope;
119     };
120 
121     template <typename T,  typename... Args>
attachDiscardableAdapter(Args &&...args)122     sk_sp<sksg::RenderNode> attachDiscardableAdapter(Args&&... args) const {
123         AutoScope ascope(this);
124         auto adapter = T::Make(std::forward<Args>(args)...);
125         auto adapter_animators = ascope.release();
126 
127         if (!adapter) { return nullptr; }
128 
129         const auto& node = adapter->renderNode();
130         if (adapter_animators.empty()) {
131             // Fire off a synthetic tick to force a single SG sync before discarding the adapter.
132             adapter->tick(0);
133         } else {
134             adapter->setAnimators(std::move(adapter_animators));
135             fCurrentAnimatorScope->push_back(std::move(adapter));
136         }
137 
138         return node;
139     }
140 
141     class AutoPropertyTracker {
142     public:
AutoPropertyTracker(const AnimationBuilder * builder,const skjson::ObjectValue & obj)143         AutoPropertyTracker(const AnimationBuilder* builder, const skjson::ObjectValue& obj)
144             : fBuilder(builder)
145             , fPrevContext(builder->fPropertyObserverContext) {
146             if (fBuilder->fPropertyObserver) {
147                 this->updateContext(builder->fPropertyObserver.get(), obj);
148             }
149         }
150 
~AutoPropertyTracker()151         ~AutoPropertyTracker() {
152             if (fBuilder->fPropertyObserver) {
153                 fBuilder->fPropertyObserverContext = fPrevContext;
154             }
155         }
156     private:
157         void updateContext(PropertyObserver*, const skjson::ObjectValue&);
158 
159         const AnimationBuilder* fBuilder;
160         const char*             fPrevContext;
161     };
162 
163 private:
164     struct AttachLayerContext;
165     struct AttachShapeContext;
166     struct ImageAssetInfo;
167     struct LayerInfo;
168 
169     void parseAssets(const skjson::ArrayValue*);
170     void parseFonts (const skjson::ObjectValue* jfonts,
171                      const skjson::ArrayValue* jchars);
172 
173     void dispatchMarkers(const skjson::ArrayValue*) const;
174 
175     sk_sp<sksg::RenderNode> attachComposition(const skjson::ObjectValue&) const;
176     sk_sp<sksg::RenderNode> attachLayer(const skjson::ObjectValue*,
177                                         AttachLayerContext*) const;
178 
179     sk_sp<sksg::RenderNode> attachBlendMode(const skjson::ObjectValue&,
180                                             sk_sp<sksg::RenderNode>) const;
181 
182     sk_sp<sksg::RenderNode> attachShape(const skjson::ArrayValue*, AttachShapeContext*) const;
183     sk_sp<sksg::RenderNode> attachAssetRef(const skjson::ObjectValue&,
184         const std::function<sk_sp<sksg::RenderNode>(const skjson::ObjectValue&)>&) const;
185     const ImageAssetInfo* loadImageAsset(const skjson::ObjectValue&) const;
186     sk_sp<sksg::RenderNode> attachImageAsset(const skjson::ObjectValue&, LayerInfo*) const;
187 
188     sk_sp<sksg::RenderNode> attachNestedAnimation(const char* name) const;
189 
190     sk_sp<sksg::RenderNode> attachImageLayer  (const skjson::ObjectValue&, LayerInfo*) const;
191     sk_sp<sksg::RenderNode> attachNullLayer   (const skjson::ObjectValue&, LayerInfo*) const;
192     sk_sp<sksg::RenderNode> attachPrecompLayer(const skjson::ObjectValue&, LayerInfo*) const;
193     sk_sp<sksg::RenderNode> attachShapeLayer  (const skjson::ObjectValue&, LayerInfo*) const;
194     sk_sp<sksg::RenderNode> attachSolidLayer  (const skjson::ObjectValue&, LayerInfo*) const;
195     sk_sp<sksg::RenderNode> attachTextLayer   (const skjson::ObjectValue&, LayerInfo*) const;
196 
197     bool dispatchColorProperty(const sk_sp<sksg::Color>&) const;
198     bool dispatchOpacityProperty(const sk_sp<sksg::OpacityEffect>&) const;
199     bool dispatchTextProperty(const sk_sp<TextAdapter>&) const;
200     bool dispatchTransformProperty(const sk_sp<TransformAdapter2D>&) const;
201 
202     // Delay resolving the fontmgr until it is actually needed.
203     struct LazyResolveFontMgr {
LazyResolveFontMgrLazyResolveFontMgr204         LazyResolveFontMgr(sk_sp<SkFontMgr> fontMgr) : fFontMgr(std::move(fontMgr)) {}
205 
getLazyResolveFontMgr206         const sk_sp<SkFontMgr>& get() {
207             if (!fFontMgr) {
208                 fFontMgr = SkFontMgr::RefDefault();
209                 SkASSERT(fFontMgr);
210             }
211             return fFontMgr;
212         }
213 
getMaybeNullLazyResolveFontMgr214         const sk_sp<SkFontMgr>& getMaybeNull() const { return fFontMgr; }
215 
216     private:
217         sk_sp<SkFontMgr> fFontMgr;
218     };
219 
220     sk_sp<ResourceProvider>    fResourceProvider;
221     LazyResolveFontMgr         fLazyFontMgr;
222     sk_sp<PropertyObserver>    fPropertyObserver;
223     sk_sp<Logger>              fLogger;
224     sk_sp<MarkerObserver>      fMarkerObserver;
225     Animation::Builder::Stats* fStats;
226     const SkSize               fSize;
227     const float                fDuration,
228                                fFrameRate;
229     mutable AnimatorScope*     fCurrentAnimatorScope;
230     mutable const char*        fPropertyObserverContext;
231     mutable bool               fHasNontrivialBlending : 1;
232 
233     struct LayerInfo {
234         SkSize      fSize;
235         const float fInPoint,
236                     fOutPoint;
237     };
238 
239     struct AssetInfo {
240         const skjson::ObjectValue* fAsset;
241         mutable bool               fIsAttaching; // Used for cycle detection
242     };
243 
244     struct ImageAssetInfo {
245         sk_sp<ImageAsset> fAsset;
246         SkISize           fSize;
247     };
248 
249     SkTHashMap<SkString, AssetInfo>              fAssets;
250     SkTHashMap<SkString, FontInfo>               fFonts;
251     mutable SkTHashMap<SkString, ImageAssetInfo> fImageAssetCache;
252 
253     using INHERITED = SkNoncopyable;
254 };
255 
256 struct AnimationBuilder::AttachLayerContext {
257     explicit AttachLayerContext(const skjson::ArrayValue&);
258     ~AttachLayerContext();
259 
260     struct TransformRec {
261         sk_sp<sksg::Transform> fTransformNode;
262         AnimatorScope          fTransformScope;
263     };
264 
265     const skjson::ArrayValue&     fLayerList;
266     SkTHashMap<int, TransformRec> fLayerTransformMap;
267     sk_sp<sksg::RenderNode>       fCurrentMatte;
268     sk_sp<sksg::Transform>        fCameraTransform;
269 
270     size_t                        fMotionBlurSamples = 1;
271     float                         fMotionBlurAngle   = 0,
272                                   fMotionBlurPhase   = 0;
273 
274     enum class TransformType { kLayer, kCamera };
275 
276     TransformRec attachLayerTransform(const skjson::ObjectValue& jlayer,
277                                       const AnimationBuilder* abuilder,
278                                       TransformType type = TransformType::kLayer);
279 
280     bool hasMotionBlur(const skjson::ObjectValue& jlayer) const;
281 
282 private:
283     sk_sp<sksg::Transform> attachParentLayerTransform(const skjson::ObjectValue& jlayer,
284                                                       const AnimationBuilder* abuilder,
285                                                       int layer_index);
286 
287     sk_sp<sksg::Transform> attachTransformNode(const skjson::ObjectValue& jlayer,
288                                                const AnimationBuilder* abuilder,
289                                                sk_sp<sksg::Transform> parent_transform,
290                                                TransformType type) const;
291 
292     TransformRec* attachLayerTransformImpl(const skjson::ObjectValue& jlayer,
293                                            const AnimationBuilder* abuilder,
294                                            TransformType type, int layer_index);
295 };
296 
297 } // namespace internal
298 } // namespace skottie
299 
300 #endif // SkottiePriv_DEFINED
301