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 #include "gm.h" 9 #include "Resources.h" 10 #include "SkAnimCodecPlayer.h" 11 #include "SkAnimTimer.h" 12 #include "SkColor.h" 13 #include "SkMakeUnique.h" 14 #include "Skottie.h" 15 #include "SkottieProperty.h" 16 #include "SkottieUtils.h" 17 18 #include <cmath> 19 #include <vector> 20 21 using namespace skottie; 22 23 namespace { 24 25 static constexpr char kWebFontResource[] = "fonts/Roboto-Regular.ttf"; 26 static constexpr char kSkottieResource[] = "skottie/skottie_sample_webfont.json"; 27 28 // Dummy web font loader which serves a single local font (checked in under resources/). 29 class FakeWebFontProvider final : public ResourceProvider { 30 public: FakeWebFontProvider()31 FakeWebFontProvider() : fFontData(GetResourceAsData(kWebFontResource)) {} 32 loadFont(const char[],const char[]) const33 sk_sp<SkData> loadFont(const char[], const char[]) const override { 34 return fFontData; 35 } 36 37 private: 38 sk_sp<SkData> fFontData; 39 40 using INHERITED = ResourceProvider; 41 }; 42 43 } // namespace 44 45 class SkottieWebFontGM : public skiagm::GM { 46 public: 47 protected: onShortName()48 SkString onShortName() override { 49 return SkString("skottie_webfont"); 50 } 51 onISize()52 SkISize onISize() override { 53 return SkISize::Make(kSize, kSize); 54 } 55 onOnceBeforeDraw()56 void onOnceBeforeDraw() override { 57 if (auto stream = GetResourceAsStream(kSkottieResource)) { 58 fAnimation = Animation::Builder() 59 .setResourceProvider(sk_make_sp<FakeWebFontProvider>()) 60 .make(stream.get()); 61 } 62 } 63 onDraw(SkCanvas * canvas)64 void onDraw(SkCanvas* canvas) override { 65 if (!fAnimation) { 66 return; 67 } 68 69 auto dest = SkRect::MakeWH(kSize, kSize); 70 fAnimation->render(canvas, &dest); 71 } 72 onAnimate(const SkAnimTimer & timer)73 bool onAnimate(const SkAnimTimer& timer) override { 74 if (!fAnimation) { 75 return false; 76 } 77 78 const auto duration = fAnimation->duration(); 79 fAnimation->seek(std::fmod(timer.secs(), duration) / duration); 80 return true; 81 } 82 83 private: 84 static constexpr SkScalar kSize = 800; 85 86 sk_sp<Animation> fAnimation; 87 88 using INHERITED = skiagm::GM; 89 }; 90 91 DEF_GM(return new SkottieWebFontGM;) 92 93 using namespace skottie_utils; 94 95 class SkottieColorizeGM : public skiagm::GM { 96 protected: onShortName()97 SkString onShortName() override { 98 return SkString("skottie_colorize"); 99 } 100 onISize()101 SkISize onISize() override { 102 return SkISize::Make(kSize, kSize); 103 } 104 onOnceBeforeDraw()105 void onOnceBeforeDraw() override { 106 if (auto stream = GetResourceAsStream("skottie/skottie_sample_search.json")) { 107 fPropManager = skstd::make_unique<CustomPropertyManager>(); 108 fAnimation = Animation::Builder() 109 .setPropertyObserver(fPropManager->getPropertyObserver()) 110 .make(stream.get()); 111 fColors = fPropManager->getColorProps(); 112 } 113 } 114 onDraw(SkCanvas * canvas)115 void onDraw(SkCanvas* canvas) override { 116 if (!fAnimation) { 117 return; 118 } 119 120 auto dest = SkRect::MakeWH(kSize, kSize); 121 fAnimation->render(canvas, &dest); 122 } 123 onAnimate(const SkAnimTimer & timer)124 bool onAnimate(const SkAnimTimer& timer) override { 125 if (!fAnimation) { 126 return false; 127 } 128 129 const auto duration = fAnimation->duration(); 130 fAnimation->seek(std::fmod(timer.secs(), duration) / duration); 131 return true; 132 } 133 onHandleKey(SkUnichar uni)134 bool onHandleKey(SkUnichar uni) override { 135 static constexpr SkColor kColors[] = { 136 SK_ColorBLACK, 137 SK_ColorRED, 138 SK_ColorGREEN, 139 SK_ColorYELLOW, 140 SK_ColorCYAN, 141 }; 142 143 if (uni == 'c') { 144 fColorIndex = (fColorIndex + 1) % SK_ARRAY_COUNT(kColors); 145 for (const auto& prop : fColors) { 146 fPropManager->setColor(prop, kColors[fColorIndex]); 147 } 148 return true; 149 } 150 151 return false; 152 } 153 154 private: 155 static constexpr SkScalar kSize = 800; 156 157 sk_sp<Animation> fAnimation; 158 std::unique_ptr<CustomPropertyManager> fPropManager; 159 std::vector<CustomPropertyManager::PropKey> fColors; 160 size_t fColorIndex = 0; 161 162 using INHERITED = skiagm::GM; 163 }; 164 165 DEF_GM(return new SkottieColorizeGM;) 166 167 class SkottieMultiFrameGM : public skiagm::GM { 168 public: 169 protected: onShortName()170 SkString onShortName() override { 171 return SkString("skottie_multiframe"); 172 } 173 onISize()174 SkISize onISize() override { 175 return SkISize::Make(kSize, kSize); 176 } 177 onOnceBeforeDraw()178 void onOnceBeforeDraw() override { 179 if (auto stream = GetResourceAsStream("skottie/skottie_sample_multiframe.json")) { 180 fAnimation = Animation::Builder() 181 .setResourceProvider(sk_make_sp<MultiFrameResourceProvider>()) 182 .make(stream.get()); 183 } 184 } 185 onDraw(SkCanvas * canvas)186 void onDraw(SkCanvas* canvas) override { 187 if (!fAnimation) { 188 return; 189 } 190 191 auto dest = SkRect::MakeWH(kSize, kSize); 192 fAnimation->render(canvas, &dest); 193 } 194 onAnimate(const SkAnimTimer & timer)195 bool onAnimate(const SkAnimTimer& timer) override { 196 if (!fAnimation) { 197 return false; 198 } 199 200 const auto duration = fAnimation->duration(); 201 fAnimation->seek(std::fmod(timer.secs(), duration) / duration); 202 return true; 203 } 204 205 private: 206 class MultiFrameResourceProvider final : public skottie::ResourceProvider { 207 public: loadImageAsset(const char[],const char[]) const208 sk_sp<ImageAsset> loadImageAsset(const char[], const char[]) const override { 209 return skottie_utils::MultiFrameImageAsset::Make( 210 GetResourceAsData("images/flightAnim.gif")); 211 } 212 }; 213 214 static constexpr SkScalar kSize = 800; 215 216 sk_sp<Animation> fAnimation; 217 218 using INHERITED = skiagm::GM; 219 }; 220 221 DEF_GM(return new SkottieMultiFrameGM;) 222