• 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 SkottieUtils_DEFINED
9 #define SkottieUtils_DEFINED
10 
11 #include "include/core/SkColor.h"
12 #include "include/core/SkString.h"
13 #include "include/private/SkTHash.h"
14 #include "modules/skottie/include/Skottie.h"
15 #include "modules/skottie/include/SkottieProperty.h"
16 
17 #include <memory>
18 #include <string>
19 #include <unordered_map>
20 #include <vector>
21 
22 class SkAnimCodecPlayer;
23 class SkData;
24 class SkImage;
25 
26 namespace skottie_utils {
27 
28 class MultiFrameImageAsset final : public skottie::ImageAsset {
29 public:
30     /**
31     * By default, images are decoded on-the-fly, at rasterization time.
32     * Large images may cause jank as decoding is expensive (and can thrash internal caches).
33     *
34     * Pass |predecode| true to force-decode all images upfront, at the cost of potentially more RAM
35     * and slower animation build times.
36     */
37     static sk_sp<MultiFrameImageAsset> Make(sk_sp<SkData>, bool predecode = false);
38 
39     bool isMultiFrame() override;
40 
41     sk_sp<SkImage> getFrame(float t) override;
42 
43 private:
44     explicit MultiFrameImageAsset(std::unique_ptr<SkAnimCodecPlayer>, bool predecode);
45 
46     std::unique_ptr<SkAnimCodecPlayer> fPlayer;
47     bool                               fPreDecode;
48 
49     using INHERITED = skottie::ImageAsset;
50 };
51 
52 class FileResourceProvider final : public skottie::ResourceProvider {
53 public:
54     static sk_sp<FileResourceProvider> Make(SkString base_dir);
55 
56     sk_sp<SkData> load(const char resource_path[], const char resource_name[]) const override;
57 
58     sk_sp<skottie::ImageAsset> loadImageAsset(const char[], const char[],
59                                               const char[]) const override;
60 
61 private:
62     explicit FileResourceProvider(SkString);
63 
64     const SkString fDir;
65 
66     using INHERITED = skottie::ResourceProvider;
67 };
68 
69 /**
70  * CustomPropertyManager implements a property management scheme where color/opacity/transform
71  * attributes are grouped and manipulated by name (one-to-many mapping).
72  *
73  *   - setters apply the value to all properties in a named group
74  *
75  *   - getters return all the managed property groups, and the first value within each of them
76  *     (unchecked assumption: all properties within the same group have the same value)
77  *
78  * Attach to an Animation::Builder using the utility methods below to intercept properties and
79  * markers at build time.
80  */
81 class CustomPropertyManager final {
82 public:
83     CustomPropertyManager();
84     ~CustomPropertyManager();
85 
86     using PropKey = std::string;
87 
88     std::vector<PropKey> getColorProps() const;
89     skottie::ColorPropertyValue getColor(const PropKey&) const;
90     bool setColor(const PropKey&, const skottie::ColorPropertyValue&);
91 
92     std::vector<PropKey> getOpacityProps() const;
93     skottie::OpacityPropertyValue getOpacity(const PropKey&) const;
94     bool setOpacity(const PropKey&, const skottie::OpacityPropertyValue&);
95 
96     std::vector<PropKey> getTransformProps() const;
97     skottie::TransformPropertyValue getTransform(const PropKey&) const;
98     bool setTransform(const PropKey&, const skottie::TransformPropertyValue&);
99 
100     struct MarkerInfo {
101         std::string name;
102         float       t0, t1;
103     };
markers()104     const std::vector<MarkerInfo>& markers() const { return fMarkers; }
105 
106     // Returns a property observer to be attached to an animation builder.
107     sk_sp<skottie::PropertyObserver> getPropertyObserver() const;
108 
109     // Returns a marker observer to be attached to an animation builder.
110     sk_sp<skottie::MarkerObserver> getMarkerObserver() const;
111 
112 private:
113     class PropertyInterceptor;
114     class MarkerInterceptor;
115 
acceptKey(const char * name)116     static std::string acceptKey(const char* name) {
117         static constexpr char kPrefix = '$';
118 
119         return (name[0] == kPrefix && name[1] != '\0')
120             ? std::string(name + 1)
121             : std::string();
122     }
123 
124     sk_sp<PropertyInterceptor> fPropertyInterceptor;
125     sk_sp<MarkerInterceptor>   fMarkerInterceptor;
126 
127     template <typename T>
128     using PropGroup = std::vector<std::unique_ptr<T>>;
129 
130     template <typename T>
131     using PropMap = std::unordered_map<PropKey, PropGroup<T>>;
132 
133     template <typename T>
134     std::vector<PropKey> getProps(const PropMap<T>& container) const;
135 
136     template <typename V, typename T>
137     V get(const PropKey&, const PropMap<T>& container) const;
138 
139     template <typename V, typename T>
140     bool set(const PropKey&, const V&, const PropMap<T>& container);
141 
142     PropMap<skottie::ColorPropertyHandle>     fColorMap;
143     PropMap<skottie::OpacityPropertyHandle>   fOpacityMap;
144     PropMap<skottie::TransformPropertyHandle> fTransformMap;
145     std::vector<MarkerInfo>                   fMarkers;
146 };
147 
148 } // namespace skottie_utils
149 
150 #endif // SkottieUtils_DEFINED
151