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