1 /* 2 * Copyright 2017 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 Skottie_DEFINED 9 #define Skottie_DEFINED 10 11 #include "SkFontMgr.h" 12 #include "SkRefCnt.h" 13 #include "SkSize.h" 14 #include "SkString.h" 15 #include "SkTypes.h" 16 17 #include <memory> 18 19 class SkCanvas; 20 class SkData; 21 class SkImage; 22 struct SkRect; 23 class SkStream; 24 25 namespace skjson { class ObjectValue; } 26 27 namespace sksg { class Scene; } 28 29 namespace skottie { 30 31 class PropertyObserver; 32 33 /** 34 * Image asset proxy interface. 35 */ 36 class SK_API ImageAsset : public SkRefCnt { 37 public: 38 /** 39 * Returns true if the image asset is animated. 40 */ 41 virtual bool isMultiFrame() = 0; 42 43 /** 44 * Returns the SkImage for a given frame. 45 * 46 * If the image asset is static, getImage() is only called once, at animation load time. 47 * Otherwise, this gets invoked every time the animation time is adjusted (on every seek). 48 * 49 * Embedders should cache and serve the same SkImage whenever possible, for efficiency. 50 * 51 * @param t Frame time code, in seconds, relative to the image layer timeline origin 52 * (in-point). 53 */ 54 virtual sk_sp<SkImage> getFrame(float t) = 0; 55 }; 56 57 /** 58 * ResourceProvider allows Skottie embedders to control loading of external 59 * Skottie resources -- e.g. images, fonts, nested animations. 60 */ 61 class SK_API ResourceProvider : public SkRefCnt { 62 public: 63 /** 64 * Load a generic resource (currently only nested animations) specified by |path| + |name|, 65 * and return as an SkData. 66 */ 67 virtual sk_sp<SkData> load(const char resource_path[], 68 const char resource_name[]) const; 69 70 /** 71 * Load an image asset specified by |path| + |name|, and returns the corresponding 72 * ImageAsset proxy. 73 */ 74 virtual sk_sp<ImageAsset> loadImageAsset(const char resource_path[], 75 const char resource_name[]) const; 76 77 /** 78 * Load an external font and return as SkData. 79 * 80 * @param name font name ("fName" Lottie property) 81 * @param url web font URL ("fPath" Lottie property) 82 * 83 * -- Note -- 84 * 85 * This mechanism assumes monolithic fonts (single data blob). Some web font providers may 86 * serve multiple font blobs, segmented for various unicode ranges, depending on user agent 87 * capabilities (woff, woff2). In that case, the embedder would need to advertise no user 88 * agent capabilities when fetching the URL, in order to receive full font data. 89 */ 90 virtual sk_sp<SkData> loadFont(const char name[], const char url[]) const; 91 }; 92 93 /** 94 * A Logger subclass can be used to receive Animation::Builder parsing errors and warnings. 95 */ 96 class SK_API Logger : public SkRefCnt { 97 public: 98 enum class Level { 99 kWarning, 100 kError, 101 }; 102 103 virtual void log(Level, const char message[], const char* json = nullptr); 104 }; 105 106 /** 107 * Interface for receiving AE composition markers at Animation build time. 108 */ 109 class SK_API MarkerObserver : public SkRefCnt { 110 public: 111 // t0,t1 are in the Animation::seek() domain. 112 virtual void onMarker(const char name[], float t0, float t1) = 0; 113 }; 114 115 class SK_API Animation : public SkNVRefCnt<Animation> { 116 public: 117 118 class Builder final { 119 public: 120 Builder(); 121 ~Builder(); 122 123 struct Stats { 124 float fTotalLoadTimeMS = 0, // Total animation instantiation time. 125 fJsonParseTimeMS = 0, // Time spent building a JSON DOM. 126 fSceneParseTimeMS = 0; // Time spent constructing the animation scene graph. 127 size_t fJsonSize = 0, // Input JSON size. 128 fAnimatorCount = 0; // Number of dynamically animated properties. 129 }; 130 131 /** 132 * Returns various animation build stats. 133 * 134 * @return Stats (see above). 135 */ getStats()136 const Stats& getStats() const { return fStats; } 137 138 /** 139 * Specify a loader for external resources (images, etc.). 140 */ 141 Builder& setResourceProvider(sk_sp<ResourceProvider>); 142 143 /** 144 * Specify a font manager for loading animation fonts. 145 */ 146 Builder& setFontManager(sk_sp<SkFontMgr>); 147 148 /** 149 * Specify a PropertyObserver to receive callbacks during parsing. 150 * 151 * See SkottieProperty.h for more details. 152 * 153 */ 154 Builder& setPropertyObserver(sk_sp<PropertyObserver>); 155 156 /** 157 * Register a Logger with this builder. 158 */ 159 Builder& setLogger(sk_sp<Logger>); 160 161 /** 162 * Register a MarkerObserver with this builder. 163 */ 164 Builder& setMarkerObserver(sk_sp<MarkerObserver>); 165 166 /** 167 * Animation factories. 168 */ 169 sk_sp<Animation> make(SkStream*); 170 sk_sp<Animation> make(const char* data, size_t length); 171 sk_sp<Animation> makeFromFile(const char path[]); 172 173 private: 174 sk_sp<ResourceProvider> fResourceProvider; 175 sk_sp<SkFontMgr> fFontMgr; 176 sk_sp<PropertyObserver> fPropertyObserver; 177 sk_sp<Logger> fLogger; 178 sk_sp<MarkerObserver> fMarkerObserver; 179 Stats fStats; 180 }; 181 182 /** 183 * Animation factories. 184 * 185 * Use the Builder helper above for more options/control. 186 */ 187 static sk_sp<Animation> Make(const char* data, size_t length); 188 static sk_sp<Animation> Make(SkStream*); 189 static sk_sp<Animation> MakeFromFile(const char path[]); 190 191 ~Animation(); 192 193 enum RenderFlag : uint32_t { 194 // When rendering into a known transparent buffer, clients can pass 195 // this flag to avoid some unnecessary compositing overhead for 196 // animations using layer blend modes. 197 kSkipTopLevelIsolation = 0x01, 198 }; 199 using RenderFlags = uint32_t; 200 201 /** 202 * Draws the current animation frame. 203 * 204 * @param canvas destination canvas 205 * @param dst optional destination rect 206 * @param flags optional RenderFlags 207 */ 208 void render(SkCanvas* canvas, const SkRect* dst = nullptr) const; 209 void render(SkCanvas* canvas, const SkRect* dst, RenderFlags) const; 210 211 /** 212 * Updates the animation state for |t|. 213 * 214 * @param t normalized [0..1] frame selector (0 -> first frame, 1 -> final frame) 215 * 216 */ 217 void seek(SkScalar t); 218 219 /** 220 * Returns the animation duration in seconds. 221 */ duration()222 SkScalar duration() const { return fDuration; } 223 version()224 const SkString& version() const { return fVersion; } size()225 const SkSize& size() const { return fSize; } 226 227 void setShowInval(bool show); 228 229 private: 230 enum Flags : uint32_t { 231 kRequiresTopLevelIsolation = 1 << 0, // Needs to draw into a layer due to layer blending. 232 }; 233 234 Animation(std::unique_ptr<sksg::Scene>, SkString ver, const SkSize& size, 235 SkScalar inPoint, SkScalar outPoint, SkScalar duration, uint32_t flags = 0); 236 237 std::unique_ptr<sksg::Scene> fScene; 238 const SkString fVersion; 239 const SkSize fSize; 240 const SkScalar fInPoint, 241 fOutPoint, 242 fDuration; 243 const uint32_t fFlags; 244 245 typedef SkNVRefCnt<Animation> INHERITED; 246 }; 247 248 } // namespace skottie 249 250 #endif // Skottie_DEFINED 251