1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2017 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h" 9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h" 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMgr.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/include/Skottie.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/include/SkottieProperty.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/utils/SkottieUtils.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skresources/include/SkResources.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/include/SkShaper_factory.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/utils/FactoryHelpers.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h" 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker #include <cmath> 22*c8dee2aaSAndroid Build Coastguard Worker #include <vector> 23*c8dee2aaSAndroid Build Coastguard Worker 24*c8dee2aaSAndroid Build Coastguard Worker namespace { 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker static constexpr char kWebFontResource[] = "fonts/Roboto-Regular.ttf"; 27*c8dee2aaSAndroid Build Coastguard Worker static constexpr char kSkottieResource[] = "skottie/skottie_sample_webfont.json"; 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Worker // Mock web font loader which serves a single local font (checked in under resources/). 30*c8dee2aaSAndroid Build Coastguard Worker class FakeWebFontProvider final : public skresources::ResourceProvider { 31*c8dee2aaSAndroid Build Coastguard Worker public: FakeWebFontProvider()32*c8dee2aaSAndroid Build Coastguard Worker FakeWebFontProvider() : fTypeface(ToolUtils::CreateTypefaceFromResource(kWebFontResource)) {} 33*c8dee2aaSAndroid Build Coastguard Worker loadTypeface(const char[],const char[]) const34*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> loadTypeface(const char[], const char[]) const override { 35*c8dee2aaSAndroid Build Coastguard Worker return fTypeface; 36*c8dee2aaSAndroid Build Coastguard Worker } 37*c8dee2aaSAndroid Build Coastguard Worker 38*c8dee2aaSAndroid Build Coastguard Worker private: 39*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> fTypeface; 40*c8dee2aaSAndroid Build Coastguard Worker 41*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = skresources::ResourceProvider; 42*c8dee2aaSAndroid Build Coastguard Worker }; 43*c8dee2aaSAndroid Build Coastguard Worker 44*c8dee2aaSAndroid Build Coastguard Worker } // namespace 45*c8dee2aaSAndroid Build Coastguard Worker 46*c8dee2aaSAndroid Build Coastguard Worker class SkottieExternalPropsGM : public skiagm::GM { 47*c8dee2aaSAndroid Build Coastguard Worker public: 48*c8dee2aaSAndroid Build Coastguard Worker protected: getName() const49*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("skottie_external_props"); } 50*c8dee2aaSAndroid Build Coastguard Worker getISize()51*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(kSize, kSize); } 52*c8dee2aaSAndroid Build Coastguard Worker onOnceBeforeDraw()53*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override { 54*c8dee2aaSAndroid Build Coastguard Worker if (auto stream = GetResourceAsStream(kSkottieResource)) { 55*c8dee2aaSAndroid Build Coastguard Worker fPropManager = std::make_unique<skottie_utils::CustomPropertyManager>(); 56*c8dee2aaSAndroid Build Coastguard Worker fAnimation = skottie::Animation::Builder() 57*c8dee2aaSAndroid Build Coastguard Worker .setFontManager(ToolUtils::TestFontMgr()) 58*c8dee2aaSAndroid Build Coastguard Worker .setResourceProvider(sk_make_sp<FakeWebFontProvider>()) 59*c8dee2aaSAndroid Build Coastguard Worker .setPropertyObserver(fPropManager->getPropertyObserver()) 60*c8dee2aaSAndroid Build Coastguard Worker .setTextShapingFactory(SkShapers::BestAvailable()) 61*c8dee2aaSAndroid Build Coastguard Worker .make(stream.get()); 62*c8dee2aaSAndroid Build Coastguard Worker } 63*c8dee2aaSAndroid Build Coastguard Worker } 64*c8dee2aaSAndroid Build Coastguard Worker onDraw(SkCanvas * canvas,SkString * errorMsg)65*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { 66*c8dee2aaSAndroid Build Coastguard Worker if (!fAnimation) { 67*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = "No animation"; 68*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kFail; 69*c8dee2aaSAndroid Build Coastguard Worker } 70*c8dee2aaSAndroid Build Coastguard Worker 71*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < 4; ++i) { 72*c8dee2aaSAndroid Build Coastguard Worker this->update_props(i); 73*c8dee2aaSAndroid Build Coastguard Worker auto dest = SkRect::MakeWH(kSize/2, kSize/2).makeOffset(kSize * (i & 1) / 2, 74*c8dee2aaSAndroid Build Coastguard Worker kSize * (i & 2) / 4); 75*c8dee2aaSAndroid Build Coastguard Worker fAnimation->render(canvas, &dest); 76*c8dee2aaSAndroid Build Coastguard Worker } 77*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk; 78*c8dee2aaSAndroid Build Coastguard Worker } 79*c8dee2aaSAndroid Build Coastguard Worker onAnimate(double nanos)80*c8dee2aaSAndroid Build Coastguard Worker bool onAnimate(double nanos) override { 81*c8dee2aaSAndroid Build Coastguard Worker if (!fAnimation) { 82*c8dee2aaSAndroid Build Coastguard Worker return false; 83*c8dee2aaSAndroid Build Coastguard Worker } 84*c8dee2aaSAndroid Build Coastguard Worker 85*c8dee2aaSAndroid Build Coastguard Worker const auto duration = fAnimation->duration(); 86*c8dee2aaSAndroid Build Coastguard Worker fAnimation->seek(std::fmod(1e-9 * nanos, duration) / duration); 87*c8dee2aaSAndroid Build Coastguard Worker return true; 88*c8dee2aaSAndroid Build Coastguard Worker } 89*c8dee2aaSAndroid Build Coastguard Worker 90*c8dee2aaSAndroid Build Coastguard Worker private: update_props(size_t i)91*c8dee2aaSAndroid Build Coastguard Worker void update_props(size_t i) { 92*c8dee2aaSAndroid Build Coastguard Worker 93*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(i < 4); 94*c8dee2aaSAndroid Build Coastguard Worker if (!i) { 95*c8dee2aaSAndroid Build Coastguard Worker return; 96*c8dee2aaSAndroid Build Coastguard Worker } 97*c8dee2aaSAndroid Build Coastguard Worker 98*c8dee2aaSAndroid Build Coastguard Worker static constexpr struct { 99*c8dee2aaSAndroid Build Coastguard Worker const char* txt_string; 100*c8dee2aaSAndroid Build Coastguard Worker SkColor txt_color, 101*c8dee2aaSAndroid Build Coastguard Worker solid_color; 102*c8dee2aaSAndroid Build Coastguard Worker float transform_scale; 103*c8dee2aaSAndroid Build Coastguard Worker } gTests[] = { 104*c8dee2aaSAndroid Build Coastguard Worker { "update #1", SK_ColorRED , SK_ColorYELLOW, 100.f }, 105*c8dee2aaSAndroid Build Coastguard Worker { "update #2", SK_ColorGREEN , SK_ColorBLUE , 50.f }, 106*c8dee2aaSAndroid Build Coastguard Worker { "update #3", SK_ColorMAGENTA, SK_ColorCYAN , 150.f }, 107*c8dee2aaSAndroid Build Coastguard Worker }; 108*c8dee2aaSAndroid Build Coastguard Worker 109*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(i - 1 < std::size(gTests)); 110*c8dee2aaSAndroid Build Coastguard Worker const auto& tst = gTests[i - 1]; 111*c8dee2aaSAndroid Build Coastguard Worker 112*c8dee2aaSAndroid Build Coastguard Worker for (const auto& prop : fPropManager->getColorProps()) { 113*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(fPropManager->setColor(prop, tst.solid_color)); 114*c8dee2aaSAndroid Build Coastguard Worker } 115*c8dee2aaSAndroid Build Coastguard Worker 116*c8dee2aaSAndroid Build Coastguard Worker for (const auto& prop : fPropManager->getTransformProps()) { 117*c8dee2aaSAndroid Build Coastguard Worker auto t = fPropManager->getTransform(prop); 118*c8dee2aaSAndroid Build Coastguard Worker t.fScale = {tst.transform_scale, tst.transform_scale}; 119*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(fPropManager->setTransform(prop, t)); 120*c8dee2aaSAndroid Build Coastguard Worker } 121*c8dee2aaSAndroid Build Coastguard Worker 122*c8dee2aaSAndroid Build Coastguard Worker for (const auto& prop : fPropManager->getTextProps()) { 123*c8dee2aaSAndroid Build Coastguard Worker auto txt = fPropManager->getText(prop); 124*c8dee2aaSAndroid Build Coastguard Worker txt.fText.set(tst.txt_string); 125*c8dee2aaSAndroid Build Coastguard Worker txt.fFillColor = tst.txt_color; 126*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(fPropManager->setText(prop, txt)); 127*c8dee2aaSAndroid Build Coastguard Worker } 128*c8dee2aaSAndroid Build Coastguard Worker } 129*c8dee2aaSAndroid Build Coastguard Worker 130*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr SkScalar kSize = 800; 131*c8dee2aaSAndroid Build Coastguard Worker 132*c8dee2aaSAndroid Build Coastguard Worker sk_sp<skottie::Animation> fAnimation; 133*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<skottie_utils::CustomPropertyManager> fPropManager; 134*c8dee2aaSAndroid Build Coastguard Worker 135*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = skiagm::GM; 136*c8dee2aaSAndroid Build Coastguard Worker }; 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new SkottieExternalPropsGM;) 139