diff options
Diffstat (limited to 'tools/viewer')
-rw-r--r-- | tools/viewer/SlideDir.cpp | 189 | ||||
-rw-r--r-- | tools/viewer/SlideDir.h | 53 | ||||
-rw-r--r-- | tools/viewer/Viewer.cpp | 14 |
3 files changed, 254 insertions, 2 deletions
diff --git a/tools/viewer/SlideDir.cpp b/tools/viewer/SlideDir.cpp new file mode 100644 index 0000000000..23f1a219f1 --- /dev/null +++ b/tools/viewer/SlideDir.cpp @@ -0,0 +1,189 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SlideDir.h" + +#include "SkAnimTimer.h" +#include "SkCanvas.h" +#include "SkMakeUnique.h" +#include "SkSGColor.h" +#include "SkSGDraw.h" +#include "SkSGGroup.h" +#include "SkSGRenderNode.h" +#include "SkSGScene.h" +#include "SkSGText.h" +#include "SkSGTransform.h" +#include "SkTypeface.h" + +namespace { + +static constexpr float kAspectRatio = 1.5f; +static constexpr float kLabelSize = 12.0f; +static constexpr SkSize kPadding = { 12.0f, 24.0f }; + +class SlideAdapter final : public sksg::RenderNode { +public: + explicit SlideAdapter(sk_sp<Slide> slide) + : fSlide(std::move(slide)) { + SkASSERT(fSlide); + } + + std::unique_ptr<sksg::Animator> makeForwardingAnimator() { + // Trivial sksg::Animator -> skottie::Animation tick adapter + class ForwardingAnimator final : public sksg::Animator { + public: + explicit ForwardingAnimator(sk_sp<SlideAdapter> adapter) + : fAdapter(std::move(adapter)) {} + + protected: + void onTick(float t) override { + fAdapter->tick(SkScalarRoundToInt(t)); + } + + private: + sk_sp<SlideAdapter> fAdapter; + }; + + return skstd::make_unique<ForwardingAnimator>(sk_ref_sp(this)); + } + +protected: + SkRect onRevalidate(sksg::InvalidationController* ic, const SkMatrix& ctm) override { + const auto isize = fSlide->getDimensions(); + return SkRect::MakeIWH(isize.width(), isize.height()); + } + + void onRender(SkCanvas* canvas) const override { + fSlide->draw(canvas); + } + +private: + void tick(SkMSec t) { + fSlide->animate(SkAnimTimer(0, t * 1e6, SkAnimTimer::kRunning_State)); + this->invalidate(); + } + + const sk_sp<Slide> fSlide; + + using INHERITED = sksg::RenderNode; +}; + +} // namespace + +struct SlideDir::Rec { + sk_sp<sksg::Matrix> fMatrix; + SkRect fRect; +}; + +SlideDir::SlideDir(const SkString& name, SkTArray<sk_sp<Slide>, true>&& slides, int columns) + : fSlides(std::move(slides)) + , fColumns(columns) { + fName = name; +} + +static sk_sp<sksg::RenderNode> MakeLabel(const SkString& txt, const SkRect& dst) { + auto text = sksg::Text::Make(nullptr, txt); + text->setFlags(SkPaint::kAntiAlias_Flag); + text->setSize(kLabelSize); + text->setAlign(SkPaint::kCenter_Align); + text->setPosition(SkPoint::Make(dst.centerX(), dst.bottom())); + + return sksg::Draw::Make(std::move(text), sksg::Color::Make(SK_ColorBLACK)); +} + +void SlideDir::load(SkScalar winWidth, SkScalar winHeight) { + // Build a global scene using transformed animation fragments: + // + // [Group(root)] + // [Transform] + // [Group] + // [AnimationWrapper] + // [Draw] + // [Text] + // [Color] + // [Transform] + // [Group] + // [AnimationWrapper] + // [Draw] + // [Text] + // [Color] + // ... + // + + fSize = SkSize::Make(winWidth, winHeight).toCeil(); + + const auto cellWidth = winWidth / fColumns, + cellHeight = cellWidth / kAspectRatio; + + sksg::AnimatorList sceneAnimators; + auto root = sksg::Group::Make(); + + for (int i = 0; i < fSlides.count(); ++i) { + const auto& slide = fSlides[i]; + slide->load(winWidth, winHeight); + + const auto slideSize = slide->getDimensions(); + const auto cell = SkRect::MakeXYWH(cellWidth * (i % fColumns), + cellHeight * (i / fColumns), + cellWidth, + cellHeight), + slideRect = cell.makeInset(kPadding.width(), kPadding.height()); + + auto matrix = sksg::Matrix::Make( + SkMatrix::MakeRectToRect(SkRect::MakeIWH(slideSize.width(), slideSize.height()), + slideRect, + SkMatrix::kCenter_ScaleToFit)); + + auto adapter = sk_make_sp<SlideAdapter>(slide); + auto slideGrp = sksg::Group::Make(); + slideGrp->addChild(sksg::Transform::Make(adapter, matrix)); + slideGrp->addChild(MakeLabel(slide->getName(), cell)); + + sceneAnimators.push_back(adapter->makeForwardingAnimator()); + root->addChild(std::move(slideGrp)); + + fRecs.push_back({ matrix, slideRect }); + } + + fScene = sksg::Scene::Make(std::move(root), std::move(sceneAnimators)); +} + +void SlideDir::unload() { + for (const auto& slide : fSlides) { + slide->unload(); + } + + fRecs.reset(); + fScene.reset(); + fTimeBase = 0; +} + +SkISize SlideDir::getDimensions() const { + return fSize; +} + +void SlideDir::draw(SkCanvas* canvas) { + fScene->render(canvas); +} + +bool SlideDir::animate(const SkAnimTimer& timer) { + if (fTimeBase == 0) { + // Reset the animation time. + fTimeBase = timer.msec(); + } + fScene->animate(timer.msec() - fTimeBase); + + return true; +} + +bool SlideDir::onChar(SkUnichar c) { + return false; +} + +bool SlideDir::onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState, uint32_t modifiers) { + return false; +} diff --git a/tools/viewer/SlideDir.h b/tools/viewer/SlideDir.h new file mode 100644 index 0000000000..a4c5f6da0a --- /dev/null +++ b/tools/viewer/SlideDir.h @@ -0,0 +1,53 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SlideDir_DEFINED +#define SlideDir_DEFINED + +#include "Slide.h" + +#include "SkTArray.h" + +class SkString; + +namespace sksg { class Scene; } + +class SlideDir final : public Slide { +public: + SlideDir(const SkString& name, SkTArray<sk_sp<Slide>, true>&&, + int columns = kDefaultColumnCount); + +protected: + void load(SkScalar winWidth, SkScalar winHeight) override; + void unload() override; + + SkISize getDimensions() const override; + + void draw(SkCanvas*) override; + bool animate(const SkAnimTimer&) override; + + bool onChar(SkUnichar) override; + bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState, uint32_t modifiers) override; + +private: + static constexpr int kDefaultColumnCount = 4; + + struct Rec; + + const SkTArray<sk_sp<Slide>, true> fSlides; + const int fColumns; + + SkTArray<Rec, true> fRecs; + std::unique_ptr<sksg::Scene> fScene; + + SkISize fSize = SkISize::MakeEmpty(); + SkMSec fTimeBase = 0; + + using INHERITED = Slide; +}; + +#endif // SlideDir_DEFINED diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp index 2a58f2dc62..92741fea97 100644 --- a/tools/viewer/Viewer.cpp +++ b/tools/viewer/Viewer.cpp @@ -13,6 +13,7 @@ #include "SampleSlide.h" #include "SkottieSlide.h" #include "SKPSlide.h" +#include "SlideDir.h" #include "GrContext.h" #include "SkCanvas.h" @@ -556,14 +557,23 @@ void Viewer::initSlides() { for (const auto& json : FLAGS_jsons) { fSlides.push_back(sk_make_sp<SkottieSlide2>(json)); + SkTArray<sk_sp<Slide>, true> dirSlides; + SkOSFile::Iter it(json.c_str(), ".json"); SkString jsonName; while (it.next(&jsonName)) { if (SkCommandLineFlags::ShouldSkip(FLAGS_match, jsonName.c_str())) { continue; } - fSlides.push_back(sk_make_sp<SkottieSlide>(jsonName, SkOSPath::Join(json.c_str(), - jsonName.c_str()))); + auto slide = sk_make_sp<SkottieSlide>(jsonName, SkOSPath::Join(json.c_str(), + jsonName.c_str())); + dirSlides.push_back(slide); + fSlides.push_back(std::move(slide)); + } + + if (!dirSlides.empty()) { + fSlides.push_back(sk_make_sp<SlideDir>(SkStringPrintf("skottie-dir[%s]", json.c_str()), + std::move(dirSlides))); } } } |