1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "gm/gm.h" 9cb93a386Sopenharmony_ci#include "include/core/SkColor.h" 10cb93a386Sopenharmony_ci#include "include/utils/SkAnimCodecPlayer.h" 11cb93a386Sopenharmony_ci#include "modules/skottie/include/Skottie.h" 12cb93a386Sopenharmony_ci#include "modules/skottie/include/SkottieProperty.h" 13cb93a386Sopenharmony_ci#include "modules/skottie/utils/SkottieUtils.h" 14cb93a386Sopenharmony_ci#include "modules/skresources/include/SkResources.h" 15cb93a386Sopenharmony_ci#include "tools/Resources.h" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci#include <cmath> 18cb93a386Sopenharmony_ci#include <vector> 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_cinamespace { 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_cistatic constexpr char kWebFontResource[] = "fonts/Roboto-Regular.ttf"; 23cb93a386Sopenharmony_cistatic constexpr char kSkottieResource[] = "skottie/skottie_sample_webfont.json"; 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ci// Mock web font loader which serves a single local font (checked in under resources/). 26cb93a386Sopenharmony_ciclass FakeWebFontProvider final : public skresources::ResourceProvider { 27cb93a386Sopenharmony_cipublic: 28cb93a386Sopenharmony_ci FakeWebFontProvider() 29cb93a386Sopenharmony_ci : fTypeface(SkTypeface::MakeFromData(GetResourceAsData(kWebFontResource))) {} 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ci sk_sp<SkTypeface> loadTypeface(const char[], const char[]) const override { 32cb93a386Sopenharmony_ci return fTypeface; 33cb93a386Sopenharmony_ci } 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ciprivate: 36cb93a386Sopenharmony_ci sk_sp<SkTypeface> fTypeface; 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci using INHERITED = skresources::ResourceProvider; 39cb93a386Sopenharmony_ci}; 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci} // namespace 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ciclass SkottieWebFontGM : public skiagm::GM { 44cb93a386Sopenharmony_cipublic: 45cb93a386Sopenharmony_ciprotected: 46cb93a386Sopenharmony_ci SkString onShortName() override { 47cb93a386Sopenharmony_ci return SkString("skottie_webfont"); 48cb93a386Sopenharmony_ci } 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ci SkISize onISize() override { 51cb93a386Sopenharmony_ci return SkISize::Make(kSize, kSize); 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci void onOnceBeforeDraw() override { 55cb93a386Sopenharmony_ci if (auto stream = GetResourceAsStream(kSkottieResource)) { 56cb93a386Sopenharmony_ci fAnimation = skottie::Animation::Builder() 57cb93a386Sopenharmony_ci .setResourceProvider(sk_make_sp<FakeWebFontProvider>()) 58cb93a386Sopenharmony_ci .make(stream.get()); 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { 63cb93a386Sopenharmony_ci if (!fAnimation) { 64cb93a386Sopenharmony_ci *errorMsg = "No animation"; 65cb93a386Sopenharmony_ci return DrawResult::kFail; 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci auto dest = SkRect::MakeWH(kSize, kSize); 69cb93a386Sopenharmony_ci fAnimation->render(canvas, &dest); 70cb93a386Sopenharmony_ci return DrawResult::kOk; 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci bool onAnimate(double nanos) override { 74cb93a386Sopenharmony_ci if (!fAnimation) { 75cb93a386Sopenharmony_ci return false; 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci const auto duration = fAnimation->duration(); 79cb93a386Sopenharmony_ci fAnimation->seek(std::fmod(1e-9 * nanos, duration) / duration); 80cb93a386Sopenharmony_ci return true; 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ciprivate: 84cb93a386Sopenharmony_ci inline static constexpr SkScalar kSize = 800; 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci sk_sp<skottie::Animation> fAnimation; 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci using INHERITED = skiagm::GM; 89cb93a386Sopenharmony_ci}; 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ciDEF_GM(return new SkottieWebFontGM;) 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ciclass SkottieColorizeGM : public skiagm::GM { 94cb93a386Sopenharmony_cipublic: 95cb93a386Sopenharmony_ci SkottieColorizeGM(const char* name, const char* resource) 96cb93a386Sopenharmony_ci : fName(name) 97cb93a386Sopenharmony_ci , fResource(resource) 98cb93a386Sopenharmony_ci {} 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_ciprotected: 101cb93a386Sopenharmony_ci SkString onShortName() override { 102cb93a386Sopenharmony_ci return SkStringPrintf("skottie_colorize_%s", fName); 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci SkISize onISize() override { 106cb93a386Sopenharmony_ci return SkISize::Make(kSize, kSize); 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci void onOnceBeforeDraw() override { 110cb93a386Sopenharmony_ci if (auto stream = GetResourceAsStream(fResource)) { 111cb93a386Sopenharmony_ci fPropManager = std::make_unique<skottie_utils::CustomPropertyManager>(); 112cb93a386Sopenharmony_ci fAnimation = skottie::Animation::Builder() 113cb93a386Sopenharmony_ci .setPropertyObserver(fPropManager->getPropertyObserver()) 114cb93a386Sopenharmony_ci .make(stream.get()); 115cb93a386Sopenharmony_ci fColorProps = fPropManager->getColorProps(); 116cb93a386Sopenharmony_ci fTextProps = fPropManager->getTextProps(); 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { 121cb93a386Sopenharmony_ci if (!fAnimation) { 122cb93a386Sopenharmony_ci *errorMsg = "No animation"; 123cb93a386Sopenharmony_ci return DrawResult::kFail; 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci auto dest = SkRect::MakeWH(kSize, kSize); 127cb93a386Sopenharmony_ci fAnimation->render(canvas, &dest); 128cb93a386Sopenharmony_ci return DrawResult::kOk; 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci bool onAnimate(double nanos) override { 132cb93a386Sopenharmony_ci if (!fAnimation) { 133cb93a386Sopenharmony_ci return false; 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci const auto duration = fAnimation->duration(); 137cb93a386Sopenharmony_ci fAnimation->seek(std::fmod(1e-9 * nanos, duration) / duration); 138cb93a386Sopenharmony_ci return true; 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci bool onChar(SkUnichar uni) override { 142cb93a386Sopenharmony_ci static constexpr SkColor kColors[] = { 143cb93a386Sopenharmony_ci SK_ColorBLACK, 144cb93a386Sopenharmony_ci SK_ColorRED, 145cb93a386Sopenharmony_ci SK_ColorGREEN, 146cb93a386Sopenharmony_ci SK_ColorYELLOW, 147cb93a386Sopenharmony_ci SK_ColorCYAN, 148cb93a386Sopenharmony_ci }; 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ci if (uni == 'c') { 151cb93a386Sopenharmony_ci fColorIndex = (fColorIndex + 1) % SK_ARRAY_COUNT(kColors); 152cb93a386Sopenharmony_ci for (const auto& prop : fColorProps) { 153cb93a386Sopenharmony_ci fPropManager->setColor(prop, kColors[fColorIndex]); 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci for (const auto& prop : fTextProps) { 156cb93a386Sopenharmony_ci auto txtval = fPropManager->getText(prop); 157cb93a386Sopenharmony_ci txtval.fFillColor = kColors[fColorIndex]; 158cb93a386Sopenharmony_ci fPropManager->setText(prop, txtval); 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci return true; 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci return false; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ciprivate: 167cb93a386Sopenharmony_ci inline static constexpr SkScalar kSize = 800; 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ci const char* fName; 170cb93a386Sopenharmony_ci const char* fResource; 171cb93a386Sopenharmony_ci 172cb93a386Sopenharmony_ci sk_sp<skottie::Animation> fAnimation; 173cb93a386Sopenharmony_ci std::unique_ptr<skottie_utils::CustomPropertyManager> fPropManager; 174cb93a386Sopenharmony_ci std::vector<skottie_utils::CustomPropertyManager::PropKey> fColorProps, 175cb93a386Sopenharmony_ci fTextProps; 176cb93a386Sopenharmony_ci size_t fColorIndex = 0; 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci using INHERITED = skiagm::GM; 179cb93a386Sopenharmony_ci}; 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ciDEF_GM(return new SkottieColorizeGM("color", "skottie/skottie_sample_search.json");) 182cb93a386Sopenharmony_ciDEF_GM(return new SkottieColorizeGM("text" , "skottie/skottie-text-animator-5.json");) 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_ciclass SkottieMultiFrameGM : public skiagm::GM { 185cb93a386Sopenharmony_cipublic: 186cb93a386Sopenharmony_ciprotected: 187cb93a386Sopenharmony_ci SkString onShortName() override { 188cb93a386Sopenharmony_ci return SkString("skottie_multiframe"); 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci SkISize onISize() override { 192cb93a386Sopenharmony_ci return SkISize::Make(kSize, kSize); 193cb93a386Sopenharmony_ci } 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci void onOnceBeforeDraw() override { 196cb93a386Sopenharmony_ci if (auto stream = GetResourceAsStream("skottie/skottie_sample_multiframe.json")) { 197cb93a386Sopenharmony_ci fAnimation = skottie::Animation::Builder() 198cb93a386Sopenharmony_ci .setResourceProvider(sk_make_sp<MultiFrameResourceProvider>()) 199cb93a386Sopenharmony_ci .make(stream.get()); 200cb93a386Sopenharmony_ci fAnimation->seek(0); 201cb93a386Sopenharmony_ci } 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_ci DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { 205cb93a386Sopenharmony_ci if (!fAnimation) { 206cb93a386Sopenharmony_ci *errorMsg = "No animation"; 207cb93a386Sopenharmony_ci return DrawResult::kFail; 208cb93a386Sopenharmony_ci } 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_ci auto dest = SkRect::MakeWH(kSize, kSize); 211cb93a386Sopenharmony_ci fAnimation->render(canvas, &dest); 212cb93a386Sopenharmony_ci return DrawResult::kOk; 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci bool onAnimate(double nanos) override { 216cb93a386Sopenharmony_ci if (!fAnimation) { 217cb93a386Sopenharmony_ci return false; 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci const auto duration = fAnimation->duration(); 221cb93a386Sopenharmony_ci fAnimation->seek(std::fmod(1e-9 * nanos, duration) / duration); 222cb93a386Sopenharmony_ci return true; 223cb93a386Sopenharmony_ci } 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_ciprivate: 226cb93a386Sopenharmony_ci class MultiFrameResourceProvider final : public skresources::ResourceProvider { 227cb93a386Sopenharmony_ci public: 228cb93a386Sopenharmony_ci sk_sp<skresources::ImageAsset> loadImageAsset(const char[], const char[], 229cb93a386Sopenharmony_ci const char[]) const override { 230cb93a386Sopenharmony_ci return skresources::MultiFrameImageAsset::Make( 231cb93a386Sopenharmony_ci GetResourceAsData("images/flightAnim.gif")); 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci }; 234cb93a386Sopenharmony_ci 235cb93a386Sopenharmony_ci inline static constexpr SkScalar kSize = 800; 236cb93a386Sopenharmony_ci 237cb93a386Sopenharmony_ci sk_sp<skottie::Animation> fAnimation; 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_ci using INHERITED = skiagm::GM; 240cb93a386Sopenharmony_ci}; 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_ciDEF_GM(return new SkottieMultiFrameGM;) 243