[skottie] Make animated image support generally available
Consolidate some helpers under skottie_utils, and update all related
tools to support animated images.
TBR=
Change-Id: If08e97143a11d9a414f3230a49ab4284c508b9d0
Reviewed-on: https://skia-review.googlesource.com/c/169342
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index c889c8b..f23716b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1705,6 +1705,7 @@
":tests",
":tool_utils",
"modules/skottie",
+ "modules/skottie:utils",
"modules/sksg",
"//third_party/jsoncpp",
"//third_party/libpng",
@@ -2146,6 +2147,7 @@
":skia",
":tool_utils",
"modules/skottie",
+ "modules/skottie:utils",
"modules/sksg",
"modules/sksg:samples",
"//third_party/imgui",
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index e3774da..14311c4 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -64,6 +64,7 @@
#if defined(SK_ENABLE_SKOTTIE)
#include "Skottie.h"
+ #include "SkottieUtils.h"
#endif
#if defined(SK_XML)
@@ -1193,7 +1194,10 @@
SkottieSrc::SkottieSrc(Path path) : fPath(std::move(path)) {}
Error SkottieSrc::draw(SkCanvas* canvas) const {
- auto animation = skottie::Animation::MakeFromFile(fPath.c_str());
+ auto animation = skottie::Animation::Builder()
+ .setResourceProvider(
+ skottie_utils::FileResourceProvider::Make(SkOSPath::Dirname(fPath.c_str())))
+ .makeFromFile(fPath.c_str());
if (!animation) {
return SkStringPrintf("Unable to parse file: %s", fPath.c_str());
}
diff --git a/modules/skottie/BUILD.gn b/modules/skottie/BUILD.gn
index a572751..1178183 100644
--- a/modules/skottie/BUILD.gn
+++ b/modules/skottie/BUILD.gn
@@ -29,6 +29,25 @@
}
if (defined(is_skia_standalone)) {
+ config("utils_config") {
+ include_dirs = [ "utils" ]
+ }
+ source_set("utils") {
+ if (skia_enable_skottie) {
+ testonly = true
+
+ public_configs = [ ":utils_config" ]
+ configs += [ "../../:skia_private" ]
+ sources = [
+ "utils/SkottieUtils.cpp",
+ ]
+ deps = [
+ ":skottie",
+ "../..:skia",
+ ]
+ }
+ }
+
source_set("tests") {
if (skia_enable_skottie) {
testonly = true
@@ -83,6 +102,7 @@
public_deps = [
":skottie",
+ ":utils",
]
}
@@ -100,6 +120,7 @@
deps = [
":skottie",
+ ":utils",
"../..:gpu_tool_utils",
"../..:skia",
"../..:tool_utils",
diff --git a/modules/skottie/gm/SkottieGM.cpp b/modules/skottie/gm/SkottieGM.cpp
index 6e88837..040b8b3 100644
--- a/modules/skottie/gm/SkottieGM.cpp
+++ b/modules/skottie/gm/SkottieGM.cpp
@@ -13,6 +13,7 @@
#include "SkMakeUnique.h"
#include "Skottie.h"
#include "SkottieProperty.h"
+#include "SkottieUtils.h"
#include <cmath>
#include <vector>
@@ -213,33 +214,11 @@
}
private:
- class MultiFrameImageAsset final : public skottie::ImageAsset {
- public:
- MultiFrameImageAsset() {
- if (auto codec = SkCodec::MakeFromData(GetResourceAsData("images/flightAnim.gif"))) {
- fPlayer = skstd::make_unique<SkAnimCodecPlayer>(std::move(codec));
- }
- }
-
- bool isMultiFrame() override { return fPlayer ? fPlayer->duration() > 0 : false; }
-
- sk_sp<SkImage> getFrame(float t) override {
- if (!fPlayer) {
- return nullptr;
- }
-
- fPlayer->seek(static_cast<uint32_t>(t * 1000));
- return fPlayer->getFrame();
- }
-
- private:
- std::unique_ptr<SkAnimCodecPlayer> fPlayer;
- };
-
class MultiFrameResourceProvider final : public skottie::ResourceProvider {
public:
sk_sp<ImageAsset> loadImageAsset(const char[], const char[]) const override {
- return sk_make_sp<MultiFrameImageAsset>();
+ return skottie_utils::MultiFrameImageAsset::Make(
+ GetResourceAsData("images/flightAnim.gif"));
}
};
diff --git a/modules/skottie/src/Skottie.cpp b/modules/skottie/src/Skottie.cpp
index 792ca05..66aee73 100644
--- a/modules/skottie/src/Skottie.cpp
+++ b/modules/skottie/src/Skottie.cpp
@@ -12,7 +12,6 @@
#include "SkFontMgr.h"
#include "SkImage.h"
#include "SkMakeUnique.h"
-#include "SkOSPath.h"
#include "SkPaint.h"
#include "SkPoint.h"
#include "SkSGColor.h"
@@ -389,58 +388,10 @@
}
sk_sp<Animation> Animation::Builder::makeFromFile(const char path[]) {
- class DirectoryResourceProvider final : public ResourceProvider {
- public:
- explicit DirectoryResourceProvider(SkString dir) : fDir(std::move(dir)) {}
-
- sk_sp<SkData> load(const char resource_path[], const char resource_name[]) const override {
- const auto full_dir = SkOSPath::Join(fDir.c_str(), resource_path),
- full_path = SkOSPath::Join(full_dir.c_str(), resource_name);
- return SkData::MakeFromFileName(full_path.c_str());
- }
-
- sk_sp<ImageAsset> loadImageAsset(const char resource_path[],
- const char resource_name[]) const override {
- auto data = this->load(resource_path, resource_name);
-
- return data
- ? sk_make_sp<StaticImageAsset>(SkImage::MakeFromEncoded(std::move(data)))
- : nullptr;
- }
-
- private:
- class StaticImageAsset final : public ImageAsset {
- public:
- explicit StaticImageAsset(sk_sp<SkImage> image)
- : fImage(std::move(image)) {}
-
- bool isMultiFrame() override { return false; }
-
- sk_sp<SkImage> getFrame(float) override { return fImage; }
-
- private:
- sk_sp<SkImage> fImage;
- };
-
- const SkString fDir;
- };
-
const auto data = SkData::MakeFromFileName(path);
- if (!data)
- return nullptr;
- const auto useLocalProvider = !fResourceProvider;
- if (useLocalProvider) {
- fResourceProvider = sk_make_sp<DirectoryResourceProvider>(SkOSPath::Dirname(path));
- }
-
- auto animation = this->make(static_cast<const char*>(data->data()), data->size());
-
- if (useLocalProvider) {
- fResourceProvider.reset();
- }
-
- return animation;
+ return data ? this->make(static_cast<const char*>(data->data()), data->size())
+ : nullptr;
}
Animation::Animation(std::unique_ptr<sksg::Scene> scene, SkString version, const SkSize& size,
diff --git a/modules/skottie/src/SkottieTool.cpp b/modules/skottie/src/SkottieTool.cpp
index ed394e1..4babf33 100644
--- a/modules/skottie/src/SkottieTool.cpp
+++ b/modules/skottie/src/SkottieTool.cpp
@@ -12,6 +12,7 @@
#include "SkOSFile.h"
#include "SkOSPath.h"
#include "Skottie.h"
+#include "SkottieUtils.h"
#include "SkPictureRecorder.h"
#include "SkStream.h"
#include "SkSurface.h"
@@ -187,6 +188,8 @@
auto anim = skottie::Animation::Builder()
.setLogger(logger)
+ .setResourceProvider(
+ skottie_utils::FileResourceProvider::Make(SkOSPath::Dirname(FLAGS_input[0])))
.makeFromFile(FLAGS_input[0]);
if (!anim) {
SkDebugf("Could not load animation: '%s'.\n", FLAGS_input[0]);
diff --git a/modules/skottie/utils/SkottieUtils.cpp b/modules/skottie/utils/SkottieUtils.cpp
new file mode 100644
index 0000000..d8f39d3
--- /dev/null
+++ b/modules/skottie/utils/SkottieUtils.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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 "SkottieUtils.h"
+
+#include "SkAnimCodecPlayer.h"
+#include "SkData.h"
+#include "SkCodec.h"
+#include "SkImage.h"
+#include "SkMakeUnique.h"
+#include "SkOSFile.h"
+#include "SkOSPath.h"
+
+namespace skottie_utils {
+
+sk_sp<MultiFrameImageAsset> MultiFrameImageAsset::Make(sk_sp<SkData> data) {
+ if (auto codec = SkCodec::MakeFromData(std::move(data))) {
+ return sk_sp<MultiFrameImageAsset>(
+ new MultiFrameImageAsset(skstd::make_unique<SkAnimCodecPlayer>(std::move(codec))));
+ }
+
+ return nullptr;
+}
+
+MultiFrameImageAsset::MultiFrameImageAsset(std::unique_ptr<SkAnimCodecPlayer> player)
+ : fPlayer(std::move(player)) {
+ SkASSERT(fPlayer);
+}
+
+bool MultiFrameImageAsset::isMultiFrame() {
+ return fPlayer->duration() > 0;
+}
+
+sk_sp<SkImage> MultiFrameImageAsset::getFrame(float t) {
+ fPlayer->seek(static_cast<uint32_t>(t * 1000));
+ return fPlayer->getFrame();
+}
+
+sk_sp<FileResourceProvider> FileResourceProvider::Make(SkString base_dir) {
+ return sk_isdir(base_dir.c_str())
+ ? sk_sp<FileResourceProvider>(new FileResourceProvider(std::move(base_dir)))
+ : nullptr;
+}
+
+FileResourceProvider::FileResourceProvider(SkString base_dir) : fDir(std::move(base_dir)) {}
+
+sk_sp<SkData> FileResourceProvider::load(const char resource_path[],
+ const char resource_name[]) const {
+ const auto full_dir = SkOSPath::Join(fDir.c_str() , resource_path),
+ full_path = SkOSPath::Join(full_dir.c_str(), resource_name);
+ return SkData::MakeFromFileName(full_path.c_str());
+}
+
+sk_sp<skottie::ImageAsset> FileResourceProvider::loadImageAsset(const char resource_path[],
+ const char resource_name[]) const {
+ return MultiFrameImageAsset::Make(this->load(resource_path, resource_name));
+}
+
+} // namespace skottie_utils
diff --git a/modules/skottie/utils/SkottieUtils.h b/modules/skottie/utils/SkottieUtils.h
new file mode 100644
index 0000000..06f134a
--- /dev/null
+++ b/modules/skottie/utils/SkottieUtils.h
@@ -0,0 +1,56 @@
+/*
+ * 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 SkottieUtils_DEFINED
+#define SkottieUtils_DEFINED
+
+#include "Skottie.h"
+#include "SkString.h"
+
+#include <memory>
+
+class SkAnimCodecPlayer;
+class SkData;
+class SkImage;
+
+namespace skottie_utils {
+
+class MultiFrameImageAsset final : public skottie::ImageAsset {
+public:
+ static sk_sp<MultiFrameImageAsset> Make(sk_sp<SkData>);
+
+ bool isMultiFrame() override;
+
+ sk_sp<SkImage> getFrame(float t) override;
+
+private:
+ explicit MultiFrameImageAsset(std::unique_ptr<SkAnimCodecPlayer>);
+
+ std::unique_ptr<SkAnimCodecPlayer> fPlayer;
+
+ using INHERITED = skottie::ImageAsset;
+};
+
+class FileResourceProvider final : public skottie::ResourceProvider {
+public:
+ static sk_sp<FileResourceProvider> Make(SkString base_dir);
+
+ sk_sp<SkData> load(const char resource_path[], const char resource_name[]) const override;
+
+ sk_sp<skottie::ImageAsset> loadImageAsset(const char[], const char []) const override;
+
+private:
+ explicit FileResourceProvider(SkString);
+
+ const SkString fDir;
+
+ using INHERITED = skottie::ResourceProvider;
+};
+
+} // namespace skottie_utils
+
+#endif // SkottieUtils_DEFINED
diff --git a/public.bzl b/public.bzl
index 703f400..b360a11 100644
--- a/public.bzl
+++ b/public.bzl
@@ -662,11 +662,14 @@
################################################################################
SKOTTIE_TOOL_INCLUDES = [
+ "modules/skottie/utils",
"tools/flags",
]
SKOTTIE_TOOL_SRCS = [
"modules/skottie/src/SkottieTool.cpp",
+ "modules/skottie/utils/SkottieUtils.cpp",
+ "modules/skottie/utils/SkottieUtils.h",
# TODO(benjaminwagner): Add "flags" target.
"tools/flags/SkCommandLineFlags.cpp",
"tools/flags/SkCommandLineFlags.h",
diff --git a/tools/viewer/SkottieSlide.cpp b/tools/viewer/SkottieSlide.cpp
index 251faaa..ca164fb 100644
--- a/tools/viewer/SkottieSlide.cpp
+++ b/tools/viewer/SkottieSlide.cpp
@@ -11,7 +11,9 @@
#include "SkAnimTimer.h"
#include "SkCanvas.h"
+#include "SkOSPath.h"
#include "Skottie.h"
+#include "SkottieUtils.h"
#include <cmath>
@@ -95,7 +97,11 @@
auto logger = sk_make_sp<Logger>();
skottie::Animation::Builder builder;
- fAnimation = builder.setLogger(logger).makeFromFile(fPath.c_str());
+ fAnimation = builder
+ .setLogger(logger)
+ .setResourceProvider(
+ skottie_utils::FileResourceProvider::Make(SkOSPath::Dirname(fPath.c_str())))
+ .makeFromFile(fPath.c_str());
fAnimationStats = builder.getStats();
fWinSize = SkSize::Make(w, h);
fTimeBase = 0; // force a time reset