diff options
author | Florin Malita <fmalita@chromium.org> | 2018-01-08 12:51:12 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-01-08 18:11:31 +0000 |
commit | 493280782430b76251145cfb7d78d6d33b65c1d1 (patch) | |
tree | 14973ee0898f4b193664a34e16c551a846509bbd | |
parent | 7b7d9b374d62c4be5d439a3a1dd761b9ef4b3052 (diff) |
[skotty,sksg] Initial image support
TBR=
Change-Id: Ib3c918b1d746e4f190ae05708681f2d5519afdb2
Reviewed-on: https://skia-review.googlesource.com/91980
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
-rw-r--r-- | BUILD.gn | 1 | ||||
-rw-r--r-- | dm/DMSrcSink.cpp | 4 | ||||
-rw-r--r-- | experimental/skotty/Skotty.cpp | 79 | ||||
-rw-r--r-- | experimental/skotty/Skotty.h | 15 | ||||
-rw-r--r-- | experimental/sksg/SkSGImage.cpp | 29 | ||||
-rw-r--r-- | experimental/sksg/SkSGImage.h | 49 | ||||
-rw-r--r-- | tools/viewer/SkottySlide.cpp | 4 | ||||
-rw-r--r-- | tools/viewer/SkottySlide2.cpp | 6 |
8 files changed, 167 insertions, 20 deletions
@@ -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; } } } |