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