• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google LLC
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 SkResources_DEFINED
9 #define SkResources_DEFINED
10 
11 #include "include/core/SkData.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/core/SkString.h"
14 #include "include/core/SkTypes.h"
15 #include "include/private/SkMutex.h"
16 #include "include/private/SkTHash.h"
17 
18 #include <memory>
19 
20 class SkAnimCodecPlayer;
21 class SkImage;
22 
23 namespace skresources {
24 
25 /**
26  * Image asset proxy interface.
27  */
28 class SK_API ImageAsset : public SkRefCnt {
29 public:
30     /**
31      * Returns true if the image asset is animated.
32      */
33     virtual bool isMultiFrame() = 0;
34 
35     /**
36      * Returns the SkImage for a given frame.
37      *
38      * If the image asset is static, getImage() is only called once, at animation load time.
39      * Otherwise, this gets invoked every time the animation time is adjusted (on every seek).
40      *
41      * Embedders should cache and serve the same SkImage whenever possible, for efficiency.
42      *
43      * @param t   Frame time code, in seconds, relative to the image layer timeline origin
44      *            (in-point).
45      */
46     virtual sk_sp<SkImage> getFrame(float t) = 0;
47 };
48 
49 class MultiFrameImageAsset final : public ImageAsset {
50 public:
51     /**
52     * By default, images are decoded on-the-fly, at rasterization time.
53     * Large images may cause jank as decoding is expensive (and can thrash internal caches).
54     *
55     * Pass |predecode| true to force-decode all images upfront, at the cost of potentially more RAM
56     * and slower animation build times.
57     */
58     static sk_sp<MultiFrameImageAsset> Make(sk_sp<SkData>, bool predecode = false);
59 
60     bool isMultiFrame() override;
61 
62     sk_sp<SkImage> getFrame(float t) override;
63 
64 private:
65     explicit MultiFrameImageAsset(std::unique_ptr<SkAnimCodecPlayer>, bool predecode);
66 
67     std::unique_ptr<SkAnimCodecPlayer> fPlayer;
68     bool                               fPreDecode;
69 
70     using INHERITED = ImageAsset;
71 };
72 
73 /**
74  * ResourceProvider is an interface that lets rich-content modules defer loading of external
75  * resources (images, fonts, etc.) to embedding clients.
76  */
77 class SK_API ResourceProvider : public SkRefCnt {
78 public:
79     /**
80      * Load a generic resource (currently only nested animations) specified by |path| + |name|,
81      * and return as an SkData.
82      */
load(const char[],const char[])83     virtual sk_sp<SkData> load(const char[] /* resource_path */,
84                                const char[] /* resource_name */) const {
85         return nullptr;
86     }
87 
88     /**
89      * Load an image asset specified by |path| + |name|, and returns the corresponding
90      * ImageAsset proxy.
91      */
loadImageAsset(const char[],const char[],const char[])92     virtual sk_sp<ImageAsset> loadImageAsset(const char[] /* resource_path */,
93                                              const char[] /* resource_name */,
94                                              const char[] /* resource_id   */) const {
95         return nullptr;
96     }
97 
98     /**
99      * Load an external font and return as SkData.
100      *
101      * @param name  font name    ("fName" Lottie property)
102      * @param url   web font URL ("fPath" Lottie property)
103      *
104      * -- Note --
105      *
106      *   This mechanism assumes monolithic fonts (single data blob).  Some web font providers may
107      *   serve multiple font blobs, segmented for various unicode ranges, depending on user agent
108      *   capabilities (woff, woff2).  In that case, the embedder would need to advertise no user
109      *   agent capabilities when fetching the URL, in order to receive full font data.
110      */
loadFont(const char[],const char[])111     virtual sk_sp<SkData> loadFont(const char[] /* name */,
112                                    const char[] /* url  */) const {
113         return nullptr;
114     }
115 };
116 
117 class FileResourceProvider final : public ResourceProvider {
118 public:
119     static sk_sp<FileResourceProvider> Make(SkString base_dir, bool predecode = false);
120 
121     sk_sp<SkData> load(const char resource_path[], const char resource_name[]) const override;
122 
123     sk_sp<ImageAsset> loadImageAsset(const char[], const char[], const char[]) const override;
124 
125 private:
126     FileResourceProvider(SkString, bool);
127 
128     const SkString fDir;
129     const bool     fPredecode;
130 
131     using INHERITED = ResourceProvider;
132 };
133 
134 class ResourceProviderProxyBase : public ResourceProvider {
135 protected:
136     explicit ResourceProviderProxyBase(sk_sp<ResourceProvider>);
137 
138     sk_sp<SkData> load(const char[], const char[]) const override;
139     sk_sp<ImageAsset> loadImageAsset(const char[], const char[], const char[]) const override;
140     sk_sp<SkData> loadFont(const char[], const char[]) const override;
141 
142 private:
143     const sk_sp<ResourceProvider> fProxy;
144 };
145 
146 class CachingResourceProvider final : public ResourceProviderProxyBase {
147 public:
Make(sk_sp<ResourceProvider> rp)148     static sk_sp<CachingResourceProvider> Make(sk_sp<ResourceProvider> rp) {
149         return rp ? sk_sp<CachingResourceProvider>(new CachingResourceProvider(std::move(rp)))
150                   : nullptr;
151     }
152 
153 private:
154     explicit CachingResourceProvider(sk_sp<ResourceProvider>);
155 
156     sk_sp<ImageAsset> loadImageAsset(const char[], const char[], const char[]) const override;
157 
158     mutable SkMutex                                 fMutex;
159     mutable SkTHashMap<SkString, sk_sp<ImageAsset>> fImageCache;
160 
161     using INHERITED = ResourceProviderProxyBase;
162 };
163 
164 class DataURIResourceProviderProxy final : public ResourceProviderProxyBase {
165 public:
166     static sk_sp<DataURIResourceProviderProxy> Make(sk_sp<ResourceProvider> rp,
167                                                     bool predecode = false);
168 
169 private:
170     DataURIResourceProviderProxy(sk_sp<ResourceProvider>, bool);
171 
172     sk_sp<ImageAsset> loadImageAsset(const char[], const char[], const char[]) const override;
173 
174     const bool fPredecode;
175 
176     using INHERITED = ResourceProviderProxyBase;
177 };
178 
179 } // namespace skresources
180 
181 #endif // SkResources_DEFINED
182