diff options
author | Florin Malita <fmalita@chromium.org> | 2017-10-11 14:02:11 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-10-11 18:21:37 +0000 |
commit | 6a69c053ff244a11ae41002bfc09b54a5dc9ec68 (patch) | |
tree | a64fe55a386cf1a8a974855680d9e3832b0b06f5 /experimental/svg/model | |
parent | c9472af8585be3c12691b968b667cde3ca83cae4 (diff) |
[SVGDom] Initial <use> support
https://www.w3.org/TR/SVG/struct.html#UseElement
Change-Id: Id85c2648255dcd4763bf11c7bdb8b1490286f1e4
Reviewed-on: https://skia-review.googlesource.com/58260
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'experimental/svg/model')
-rw-r--r-- | experimental/svg/model/SkSVGContainer.h | 2 | ||||
-rw-r--r-- | experimental/svg/model/SkSVGDOM.cpp | 2 | ||||
-rw-r--r-- | experimental/svg/model/SkSVGNode.h | 3 | ||||
-rw-r--r-- | experimental/svg/model/SkSVGUse.cpp | 86 | ||||
-rw-r--r-- | experimental/svg/model/SkSVGUse.h | 47 |
5 files changed, 138 insertions, 2 deletions
diff --git a/experimental/svg/model/SkSVGContainer.h b/experimental/svg/model/SkSVGContainer.h index 3a6841f3ad..cf0d4d37d2 100644 --- a/experimental/svg/model/SkSVGContainer.h +++ b/experimental/svg/model/SkSVGContainer.h @@ -33,4 +33,4 @@ private: typedef SkSVGTransformableNode INHERITED; }; -#endif // SkSVGSVG_DEFINED +#endif // SkSVGContainer_DEFINED diff --git a/experimental/svg/model/SkSVGDOM.cpp b/experimental/svg/model/SkSVGDOM.cpp index 6625e21705..7d6b0b75cd 100644 --- a/experimental/svg/model/SkSVGDOM.cpp +++ b/experimental/svg/model/SkSVGDOM.cpp @@ -27,6 +27,7 @@ #include "SkSVGStop.h" #include "SkSVGSVG.h" #include "SkSVGTypes.h" +#include "SkSVGUse.h" #include "SkSVGValue.h" #include "SkTSearch.h" @@ -335,6 +336,7 @@ SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = { { "rect" , []() -> sk_sp<SkSVGNode> { return SkSVGRect::Make(); }}, { "stop" , []() -> sk_sp<SkSVGNode> { return SkSVGStop::Make(); }}, { "svg" , []() -> sk_sp<SkSVGNode> { return SkSVGSVG::Make(); }}, + { "use" , []() -> sk_sp<SkSVGNode> { return SkSVGUse::Make(); }}, }; struct ConstructionContext { diff --git a/experimental/svg/model/SkSVGNode.h b/experimental/svg/model/SkSVGNode.h index e6567134c8..c0190c4b0c 100644 --- a/experimental/svg/model/SkSVGNode.h +++ b/experimental/svg/model/SkSVGNode.h @@ -32,7 +32,8 @@ enum class SkSVGTag { kRadialGradient, kRect, kStop, - kSvg + kSvg, + kUse }; class SkSVGNode : public SkRefCnt { diff --git a/experimental/svg/model/SkSVGUse.cpp b/experimental/svg/model/SkSVGUse.cpp new file mode 100644 index 0000000000..b98909f8b4 --- /dev/null +++ b/experimental/svg/model/SkSVGUse.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSVGUse.h" + +#include "SkCanvas.h" +#include "SkSVGRenderContext.h" +#include "SkSVGValue.h" + +SkSVGUse::SkSVGUse() : INHERITED(SkSVGTag::kUse) {} + +void SkSVGUse::appendChild(sk_sp<SkSVGNode>) { + SkDebugf("cannot append child nodes to this element.\n"); +} + +void SkSVGUse::setHref(const SkSVGStringType& href) { + fHref = href; +} + +void SkSVGUse::setX(const SkSVGLength& x) { + fX = x; +} + +void SkSVGUse::setY(const SkSVGLength& y) { + fY = y; +} + +void SkSVGUse::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) { + switch (attr) { + case SkSVGAttribute::kHref: + if (const auto* href = v.as<SkSVGStringValue>()) { + this->setHref(*href); + } + break; + case SkSVGAttribute::kX: + if (const auto* x = v.as<SkSVGLengthValue>()) { + this->setX(*x); + } + break; + case SkSVGAttribute::kY: + if (const auto* y = v.as<SkSVGLengthValue>()) { + this->setY(*y); + } + break; + default: + this->INHERITED::onSetAttribute(attr, v); + } +} + +bool SkSVGUse::onPrepareToRender(SkSVGRenderContext* ctx) const { + if (fHref.value().isEmpty() || !INHERITED::onPrepareToRender(ctx)) { + return false; + } + + if (fX.value() || fY.value()) { + // Restored when the local SkSVGRenderContext leaves scope. + ctx->canvas()->save(); + ctx->canvas()->translate(fX.value(), fY.value()); + } + + // TODO: width/height override for <svg> targets. + + return true; +} + +void SkSVGUse::onRender(const SkSVGRenderContext& ctx) const { + const auto* ref = ctx.findNodeById(fHref); + if (!ref) { + return; + } + + ref->render(ctx); +} + +SkPath SkSVGUse::onAsPath(const SkSVGRenderContext& ctx) const { + const auto* ref = ctx.findNodeById(fHref); + if (!ref) { + return SkPath(); + } + + return ref->asPath(ctx); +} diff --git a/experimental/svg/model/SkSVGUse.h b/experimental/svg/model/SkSVGUse.h new file mode 100644 index 0000000000..4ae17e64bc --- /dev/null +++ b/experimental/svg/model/SkSVGUse.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkSVGUse_DEFINED +#define SkSVGUse_DEFINED + +#include "SkSVGTransformableNode.h" +#include "SkSVGTypes.h" + +/** + * Implements support for <use> (reference) elements. + * (https://www.w3.org/TR/SVG/struct.html#UseElement) + */ +class SkSVGUse final : public SkSVGTransformableNode { +public: + ~SkSVGUse() override = default; + + static sk_sp<SkSVGUse> Make() { return sk_sp<SkSVGUse>(new SkSVGUse()); } + + void appendChild(sk_sp<SkSVGNode>) override; + + void setHref(const SkSVGStringType&); + void setX(const SkSVGLength&); + void setY(const SkSVGLength&); + +protected: + void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override; + + bool onPrepareToRender(SkSVGRenderContext*) const override; + void onRender(const SkSVGRenderContext&) const override; + SkPath onAsPath(const SkSVGRenderContext&) const override; + +private: + SkSVGUse(); + + SkSVGStringType fHref; + SkSVGLength fX = SkSVGLength(0); + SkSVGLength fY = SkSVGLength(0); + + typedef SkSVGTransformableNode INHERITED; +}; + +#endif // SkSVGUse_DEFINED |