aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUILD.gn1
-rw-r--r--dm/DMSrcSink.cpp4
-rw-r--r--experimental/skotty/Skotty.cpp79
-rw-r--r--experimental/skotty/Skotty.h15
-rw-r--r--experimental/sksg/SkSGImage.cpp29
-rw-r--r--experimental/sksg/SkSGImage.h49
-rw-r--r--tools/viewer/SkottySlide.cpp4
-rw-r--r--tools/viewer/SkottySlide2.cpp6
8 files changed, 167 insertions, 20 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 4a1433f215..0dee148caf 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1379,6 +1379,7 @@ if (skia_enable_tools) {
"experimental/sksg/SkSGEffectNode.cpp",
"experimental/sksg/SkSGGeometryNode.cpp",
"experimental/sksg/SkSGGroup.cpp",
+ "experimental/sksg/SkSGImage.cpp",
"experimental/sksg/SkSGInvalidationController.cpp",
"experimental/sksg/SkSGNode.cpp",
"experimental/sksg/SkSGPaintNode.cpp",
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 55b54f520b..1685dcbe96 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -1320,9 +1320,7 @@ Name DDLSKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
SkottySrc::SkottySrc(Path path)
: fName(SkOSPath::Basename(path.c_str())) {
- auto stream = SkStream::MakeFromFile(path.c_str());
- fAnimation = skotty::Animation::Make(stream.get());
-
+ fAnimation = skotty::Animation::MakeFromFile(path.c_str());
if (!fAnimation) {
return;
}
diff --git a/experimental/skotty/Skotty.cpp b/experimental/skotty/Skotty.cpp
index b331547316..077640b695 100644
--- a/experimental/skotty/Skotty.cpp
+++ b/experimental/skotty/Skotty.cpp
@@ -12,14 +12,17 @@
#include "SkottyPriv.h"
#include "SkottyProperties.h"
#include "SkData.h"
+#include "SkImage.h"
#include "SkMakeUnique.h"
+#include "SkOSPath.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkPoint.h"
#include "SkSGColor.h"
#include "SkSGDraw.h"
-#include "SkSGInvalidationController.h"
#include "SkSGGroup.h"
+#include "SkSGImage.h"
+#include "SkSGInvalidationController.h"
#include "SkSGMerge.h"
#include "SkSGPath.h"
#include "SkSGRect.h"
@@ -42,6 +45,7 @@ namespace {
using AssetMap = SkTHashMap<SkString, const Json::Value*>;
struct AttachContext {
+ const ResourceProvider& fResources;
const AssetMap& fAssets;
SkTArray<std::unique_ptr<AnimatorBase>>& fAnimators;
};
@@ -550,11 +554,43 @@ sk_sp<sksg::RenderNode> AttachSolidLayer(const Json::Value& layer, AttachContext
return nullptr;
}
-sk_sp<sksg::RenderNode> AttachImageLayer(const Json::Value& layer, AttachContext*) {
+sk_sp<sksg::RenderNode> AttachImageAsset(const Json::Value& jimage, AttachContext* ctx) {
+ SkASSERT(jimage.isObject());
+
+ const auto name = ParseString(jimage["p"], ""),
+ path = ParseString(jimage["u"], "");
+ if (name.isEmpty())
+ return nullptr;
+
+ // TODO: plumb resource paths explicitly to ResourceProvider?
+ const auto resName = path.isEmpty() ? name : SkOSPath::Join(path.c_str(), name.c_str());
+ const auto resStream = ctx->fResources.openStream(resName.c_str());
+ if (!resStream || !resStream->hasLength()) {
+ LOG("!! Could not load image resource: %s\n", resName.c_str());
+ return nullptr;
+ }
+
+ // TODO: non-intrisic image sizing
+ return sksg::Image::Make(
+ SkImage::MakeFromEncoded(SkData::MakeFromStream(resStream.get(), resStream->getLength())));
+}
+
+sk_sp<sksg::RenderNode> AttachImageLayer(const Json::Value& layer, AttachContext* ctx) {
SkASSERT(layer.isObject());
- LOG("?? Image layer stub\n");
- return nullptr;
+ auto refId = ParseString(layer["refId"], "");
+ if (refId.isEmpty()) {
+ LOG("!! Image layer missing refId\n");
+ return nullptr;
+ }
+
+ const auto* jimage = ctx->fAssets.find(refId);
+ if (!jimage) {
+ LOG("!! Image asset not found: '%s'\n", refId.c_str());
+ return nullptr;
+ }
+
+ return AttachImageAsset(**jimage, ctx);
}
sk_sp<sksg::RenderNode> AttachNullLayer(const Json::Value& layer, AttachContext*) {
@@ -699,7 +735,7 @@ sk_sp<sksg::RenderNode> AttachComposition(const Json::Value& comp, AttachContext
} // namespace
-std::unique_ptr<Animation> Animation::Make(SkStream* stream) {
+std::unique_ptr<Animation> Animation::Make(SkStream* stream, const ResourceProvider& res) {
if (!stream->hasLength()) {
// TODO: handle explicit buffering?
LOG("!! cannot parse streaming content\n");
@@ -733,10 +769,37 @@ std::unique_ptr<Animation> Animation::Make(SkStream* stream) {
return nullptr;
}
- return std::unique_ptr<Animation>(new Animation(std::move(version), size, fps, json));
+ return std::unique_ptr<Animation>(new Animation(res, std::move(version), size, fps, json));
+}
+
+std::unique_ptr<Animation> Animation::MakeFromFile(const char path[], const ResourceProvider* res) {
+ class DirectoryResourceProvider final : public ResourceProvider {
+ public:
+ explicit DirectoryResourceProvider(SkString dir) : fDir(std::move(dir)) {}
+
+ std::unique_ptr<SkStream> openStream(const char resource[]) const override {
+ const auto resPath = SkOSPath::Join(fDir.c_str(), resource);
+ return SkStream::MakeFromFile(resPath.c_str());
+ }
+
+ private:
+ const SkString fDir;
+ };
+
+ const auto jsonStream = SkStream::MakeFromFile(path);
+ if (!jsonStream)
+ return nullptr;
+
+ std::unique_ptr<ResourceProvider> defaultProvider;
+ if (!res) {
+ defaultProvider = skstd::make_unique<DirectoryResourceProvider>(SkOSPath::Dirname(path));
+ }
+
+ return Make(jsonStream.get(), res ? *res : *defaultProvider);
}
-Animation::Animation(SkString version, const SkSize& size, SkScalar fps, const Json::Value& json)
+Animation::Animation(const ResourceProvider& resources,
+ SkString version, const SkSize& size, SkScalar fps, const Json::Value& json)
: fVersion(std::move(version))
, fSize(size)
, fFrameRate(fps)
@@ -752,7 +815,7 @@ Animation::Animation(SkString version, const SkSize& size, SkScalar fps, const J
assets.set(ParseString(asset["id"], ""), &asset);
}
- AttachContext ctx = { assets, fAnimators };
+ AttachContext ctx = { resources, assets, fAnimators };
fDom = AttachComposition(json, &ctx);
LOG("** Attached %d animators\n", fAnimators.count());
diff --git a/experimental/skotty/Skotty.h b/experimental/skotty/Skotty.h
index d02dc8d3ab..ebd103d60c 100644
--- a/experimental/skotty/Skotty.h
+++ b/experimental/skotty/Skotty.h
@@ -29,9 +29,18 @@ namespace skotty {
class AnimatorBase;
+class ResourceProvider : public SkNoncopyable {
+public:
+ virtual ~ResourceProvider() = default;
+
+ virtual std::unique_ptr<SkStream> openStream(const char resource[]) const = 0;
+};
+
class Animation : public SkNoncopyable {
public:
- static std::unique_ptr<Animation> Make(SkStream*);
+ static std::unique_ptr<Animation> Make(SkStream*, const ResourceProvider&);
+ static std::unique_ptr<Animation> MakeFromFile(const char path[],
+ const ResourceProvider* = nullptr);
~Animation();
@@ -48,7 +57,9 @@ public:
void setShowInval(bool show) { fShowInval = show; }
private:
- Animation(SkString ver, const SkSize& size, SkScalar fps, const Json::Value&);
+ Animation(const ResourceProvider&,
+ SkString ver, const SkSize& size, SkScalar fps,
+ const Json::Value&);
SkString fVersion;
SkSize fSize;
diff --git a/experimental/sksg/SkSGImage.cpp b/experimental/sksg/SkSGImage.cpp
new file mode 100644
index 0000000000..a0c3a759dc
--- /dev/null
+++ b/experimental/sksg/SkSGImage.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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 "SkSGImage.h"
+
+#include "SkCanvas.h"
+#include "SkImage.h"
+
+namespace sksg {
+
+Image::Image(sk_sp<SkImage> image) : fImage(std::move(image)) {}
+
+void Image::onRender(SkCanvas* canvas) const {
+ SkPaint paint;
+ paint.setAntiAlias(fAntiAlias);
+ paint.setFilterQuality(fQuality);
+
+ canvas->drawImage(fImage, 0, 0);
+}
+
+SkRect Image::onRevalidate(InvalidationController*, const SkMatrix& ctm) {
+ return SkRect::Make(fImage->bounds());
+}
+
+} // namespace sksg
diff --git a/experimental/sksg/SkSGImage.h b/experimental/sksg/SkSGImage.h
new file mode 100644
index 0000000000..7d17a50aaa
--- /dev/null
+++ b/experimental/sksg/SkSGImage.h
@@ -0,0 +1,49 @@
+/*
+ * 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 SkSGImage_DEFINED
+#define SkSGImage_DEFINED
+
+#include "SkSGRenderNode.h"
+
+#include "SkFilterQuality.h"
+
+class SkImage;
+
+namespace sksg {
+
+/**
+ * Concrete rendering node, wrapping an SkImage.
+ *
+ */
+class Image final : public RenderNode {
+public:
+ static sk_sp<Image> Make(sk_sp<SkImage> image) {
+ return image ? sk_sp<Image>(new Image(std::move(image))) : nullptr;
+ }
+
+ SG_ATTRIBUTE(Quality , SkFilterQuality, fQuality )
+ SG_ATTRIBUTE(AntiAlias, bool , fAntiAlias)
+
+protected:
+ explicit Image(sk_sp<SkImage>);
+
+ void onRender(SkCanvas*) const override;
+
+ SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
+
+private:
+ const sk_sp<SkImage> fImage;
+ SkFilterQuality fQuality = kLow_SkFilterQuality;
+ bool fAntiAlias = true;
+
+ typedef RenderNode INHERITED;
+};
+
+} // namespace sksg
+
+#endif // SkSGImage_DEFINED
diff --git a/tools/viewer/SkottySlide.cpp b/tools/viewer/SkottySlide.cpp
index 6e3608c904..a26acf6172 100644
--- a/tools/viewer/SkottySlide.cpp
+++ b/tools/viewer/SkottySlide.cpp
@@ -10,7 +10,6 @@
#include "SkAnimTimer.h"
#include "SkCanvas.h"
#include "Skotty.h"
-#include "SkStream.h"
SkottySlide::SkottySlide(const SkString& name, const SkString& path)
: fPath(path) {
@@ -18,8 +17,7 @@ SkottySlide::SkottySlide(const SkString& name, const SkString& path)
}
void SkottySlide::load(SkScalar, SkScalar) {
- auto stream = SkStream::MakeFromFile(fPath.c_str());
- fAnimation = skotty::Animation::Make(stream.get());
+ fAnimation = skotty::Animation::MakeFromFile(fPath.c_str());
fTimeBase = 0; // force a time reset
if (fAnimation) {
diff --git a/tools/viewer/SkottySlide2.cpp b/tools/viewer/SkottySlide2.cpp
index 7e76693a9a..180c7ad411 100644
--- a/tools/viewer/SkottySlide2.cpp
+++ b/tools/viewer/SkottySlide2.cpp
@@ -42,10 +42,8 @@ void SkottySlide2::load(SkScalar, SkScalar) {
SkOSFile::Iter iter(fPath.c_str(), "json");
while (iter.next(&name)) {
SkString path = SkOSPath::Join(fPath.c_str(), name.c_str());
- if (auto stream = SkStream::MakeFromFile(path.c_str())) {
- if (auto anim = skotty::Animation::Make(stream.get())) {
- fAnims.push_back(Rec(std::move(anim))).fName = name;
- }
+ if (auto anim = skotty::Animation::MakeFromFile(path.c_str())) {
+ fAnims.push_back(Rec(std::move(anim))).fName = name;
}
}
}