Home | History | Annotate | Download | only in gm
      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:
     31     FakeWebFontProvider() : fFontData(GetResourceAsData(kWebFontResource)) {}
     32 
     33     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:
     48     SkString onShortName() override {
     49         return SkString("skottie_webfont");
     50     }
     51 
     52     SkISize onISize() override {
     53         return SkISize::Make(kSize, kSize);
     54     }
     55 
     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 
     64     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
     65         if (!fAnimation) {
     66             *errorMsg = "No animation";
     67             return DrawResult::kFail;
     68         }
     69 
     70         auto dest = SkRect::MakeWH(kSize, kSize);
     71         fAnimation->render(canvas, &dest);
     72         return DrawResult::kOk;
     73     }
     74 
     75     bool onAnimate(const SkAnimTimer& timer) override {
     76         if (!fAnimation) {
     77             return false;
     78         }
     79 
     80         const auto duration = fAnimation->duration();
     81         fAnimation->seek(std::fmod(timer.secs(), duration) / duration);
     82         return true;
     83     }
     84 
     85 private:
     86     static constexpr SkScalar kSize = 800;
     87 
     88     sk_sp<Animation> fAnimation;
     89 
     90     using INHERITED = skiagm::GM;
     91 };
     92 
     93 DEF_GM(return new SkottieWebFontGM;)
     94 
     95 using namespace skottie_utils;
     96 
     97 class SkottieColorizeGM : public skiagm::GM {
     98 protected:
     99     SkString onShortName() override {
    100         return SkString("skottie_colorize");
    101     }
    102 
    103     SkISize onISize() override {
    104         return SkISize::Make(kSize, kSize);
    105     }
    106 
    107     void onOnceBeforeDraw() override {
    108         if (auto stream = GetResourceAsStream("skottie/skottie_sample_search.json")) {
    109             fPropManager = skstd::make_unique<CustomPropertyManager>();
    110             fAnimation   = Animation::Builder()
    111                               .setPropertyObserver(fPropManager->getPropertyObserver())
    112                               .make(stream.get());
    113             fColors      = fPropManager->getColorProps();
    114         }
    115     }
    116 
    117     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
    118         if (!fAnimation) {
    119             *errorMsg = "No animation";
    120             return DrawResult::kFail;
    121         }
    122 
    123         auto dest = SkRect::MakeWH(kSize, kSize);
    124         fAnimation->render(canvas, &dest);
    125         return DrawResult::kOk;
    126     }
    127 
    128     bool onAnimate(const SkAnimTimer& timer) override {
    129         if (!fAnimation) {
    130             return false;
    131         }
    132 
    133         const auto duration = fAnimation->duration();
    134         fAnimation->seek(std::fmod(timer.secs(), duration) / duration);
    135         return true;
    136     }
    137 
    138     bool onHandleKey(SkUnichar uni) override {
    139         static constexpr SkColor kColors[] = {
    140             SK_ColorBLACK,
    141             SK_ColorRED,
    142             SK_ColorGREEN,
    143             SK_ColorYELLOW,
    144             SK_ColorCYAN,
    145         };
    146 
    147         if (uni == 'c') {
    148             fColorIndex = (fColorIndex + 1) % SK_ARRAY_COUNT(kColors);
    149             for (const auto& prop : fColors) {
    150                 fPropManager->setColor(prop, kColors[fColorIndex]);
    151             }
    152             return true;
    153         }
    154 
    155         return false;
    156     }
    157 
    158 private:
    159     static constexpr SkScalar kSize = 800;
    160 
    161     sk_sp<Animation>                            fAnimation;
    162     std::unique_ptr<CustomPropertyManager>      fPropManager;
    163     std::vector<CustomPropertyManager::PropKey> fColors;
    164     size_t                                      fColorIndex = 0;
    165 
    166     using INHERITED = skiagm::GM;
    167 };
    168 
    169 DEF_GM(return new SkottieColorizeGM;)
    170 
    171 class SkottieMultiFrameGM : public skiagm::GM {
    172 public:
    173 protected:
    174     SkString onShortName() override {
    175         return SkString("skottie_multiframe");
    176     }
    177 
    178     SkISize onISize() override {
    179         return SkISize::Make(kSize, kSize);
    180     }
    181 
    182     void onOnceBeforeDraw() override {
    183         if (auto stream = GetResourceAsStream("skottie/skottie_sample_multiframe.json")) {
    184             fAnimation = Animation::Builder()
    185                             .setResourceProvider(sk_make_sp<MultiFrameResourceProvider>())
    186                             .make(stream.get());
    187         }
    188     }
    189 
    190     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
    191         if (!fAnimation) {
    192             *errorMsg = "No animation";
    193             return DrawResult::kFail;
    194         }
    195 
    196         auto dest = SkRect::MakeWH(kSize, kSize);
    197         fAnimation->render(canvas, &dest);
    198         return DrawResult::kOk;
    199     }
    200 
    201     bool onAnimate(const SkAnimTimer& timer) override {
    202         if (!fAnimation) {
    203             return false;
    204         }
    205 
    206         const auto duration = fAnimation->duration();
    207         fAnimation->seek(std::fmod(timer.secs(), duration) / duration);
    208         return true;
    209     }
    210 
    211 private:
    212     class MultiFrameResourceProvider final : public skottie::ResourceProvider {
    213     public:
    214         sk_sp<ImageAsset> loadImageAsset(const char[], const char[]) const override {
    215             return skottie_utils::MultiFrameImageAsset::Make(
    216                         GetResourceAsData("images/flightAnim.gif"));
    217         }
    218     };
    219 
    220     static constexpr SkScalar kSize = 800;
    221 
    222     sk_sp<Animation> fAnimation;
    223 
    224     using INHERITED = skiagm::GM;
    225 };
    226 
    227 DEF_GM(return new SkottieMultiFrameGM;)
    228