diff options
author | fmalita <fmalita@chromium.org> | 2016-09-14 12:04:30 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-09-14 12:04:30 -0700 |
commit | e1baa7c105dad0f301ce34e5d6d1aa329334ef8c (patch) | |
tree | c79b25d4ed835bffccd2cbac9a6da433f1e51245 | |
parent | be362774f9b9e8964544a579281603ed995e6e5a (diff) |
[SVGDom] Expose intrinsic size info
* expose intrinsic size info on <svg> nodes.
* tweak the SkSVGDOM constructor to no longer take an container size
param, but instead default to intrinsic size
* update clients to call SkSVGDOM::setContainerSize() explicitly, when
needed
R=robertphillips@google.com,stephana@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2345533002
Review-Url: https://codereview.chromium.org/2345533002
-rw-r--r-- | bench/nanobench.cpp | 13 | ||||
-rw-r--r-- | dm/DMSrcSink.cpp | 3 | ||||
-rw-r--r-- | experimental/svg/model/SkSVGDOM.cpp | 29 | ||||
-rw-r--r-- | experimental/svg/model/SkSVGDOM.h | 10 | ||||
-rw-r--r-- | experimental/svg/model/SkSVGSVG.cpp | 12 | ||||
-rw-r--r-- | experimental/svg/model/SkSVGSVG.h | 4 | ||||
-rw-r--r-- | samplecode/SampleSVGFile.cpp | 5 | ||||
-rw-r--r-- | samplecode/SampleSVGPong.cpp | 3 |
8 files changed, 63 insertions, 16 deletions
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp index ef22deeb42..ca403f50de 100644 --- a/bench/nanobench.cpp +++ b/bench/nanobench.cpp @@ -651,16 +651,21 @@ public: return nullptr; } - // TODO: use intrinsic size? make tunable via flag? - static const SkSize kContainerSize = SkSize::Make(128, 128); - sk_sp<SkSVGDOM> svgDom = SkSVGDOM::MakeFromStream(stream, kContainerSize); + sk_sp<SkSVGDOM> svgDom = SkSVGDOM::MakeFromStream(stream); if (!svgDom) { SkDebugf("Could not parse %s.\n", path); return nullptr; } + // Use the intrinsic SVG size if available, otherwise fall back to a default value. + static const SkSize kDefaultContainerSize = SkSize::Make(128, 128); + if (svgDom->containerSize().isEmpty()) { + svgDom->setContainerSize(kDefaultContainerSize); + } + SkPictureRecorder recorder; - svgDom->render(recorder.beginRecording(kContainerSize.width(), kContainerSize.height())); + svgDom->render(recorder.beginRecording(svgDom->containerSize().width(), + svgDom->containerSize().height())); return recorder.finishRecordingAsPicture(); } diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index 0c7de850b7..0cdb70e933 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -1043,11 +1043,12 @@ Error SVGSrc::draw(SkCanvas* canvas) const { return SkStringPrintf("Unable to open file: %s", fPath.c_str()); } - sk_sp<SkSVGDOM> dom = SkSVGDOM::MakeFromStream(stream, kSVGSize); + sk_sp<SkSVGDOM> dom = SkSVGDOM::MakeFromStream(stream); if (!dom) { return SkStringPrintf("Unable to parse file: %s", fPath.c_str()); } + dom->setContainerSize(kSVGSize); dom->render(canvas); return ""; diff --git a/experimental/svg/model/SkSVGDOM.cpp b/experimental/svg/model/SkSVGDOM.cpp index f467c5e6d0..c9745f1730 100644 --- a/experimental/svg/model/SkSVGDOM.cpp +++ b/experimental/svg/model/SkSVGDOM.cpp @@ -384,26 +384,29 @@ sk_sp<SkSVGNode> construct_svg_node(const SkDOM& dom, const ConstructionContext& } // anonymous namespace -SkSVGDOM::SkSVGDOM(const SkSize& containerSize) - : fContainerSize(containerSize) { +SkSVGDOM::SkSVGDOM() + : fContainerSize(SkSize::Make(0, 0)) { } -sk_sp<SkSVGDOM> SkSVGDOM::MakeFromDOM(const SkDOM& xmlDom, const SkSize& containerSize) { - sk_sp<SkSVGDOM> dom = sk_make_sp<SkSVGDOM>(containerSize); +sk_sp<SkSVGDOM> SkSVGDOM::MakeFromDOM(const SkDOM& xmlDom) { + sk_sp<SkSVGDOM> dom = sk_make_sp<SkSVGDOM>(); ConstructionContext ctx(&dom->fIDMapper); dom->fRoot = construct_svg_node(xmlDom, ctx, xmlDom.getRootNode()); + // Reset the default container size to match the intrinsic SVG size. + dom->setContainerSize(dom->intrinsicSize()); + return dom; } -sk_sp<SkSVGDOM> SkSVGDOM::MakeFromStream(SkStream& svgStream, const SkSize& containerSize) { +sk_sp<SkSVGDOM> SkSVGDOM::MakeFromStream(SkStream& svgStream) { SkDOM xmlDom; if (!xmlDom.build(svgStream)) { return nullptr; } - return MakeFromDOM(xmlDom, containerSize); + return MakeFromDOM(xmlDom); } void SkSVGDOM::render(SkCanvas* canvas) const { @@ -416,6 +419,20 @@ void SkSVGDOM::render(SkCanvas* canvas) const { } } +SkSize SkSVGDOM::intrinsicSize() const { + if (!fRoot || fRoot->tag() != SkSVGTag::kSvg) { + return SkSize::Make(0, 0); + } + + // Intrinsic sizes are never relative, so the viewport size is irrelevant. + const SkSVGLengthContext lctx(SkSize::Make(0, 0)); + return static_cast<const SkSVGSVG*>(fRoot.get())->intrinsicSize(lctx); +} + +const SkSize& SkSVGDOM::containerSize() const { + return fContainerSize; +} + void SkSVGDOM::setContainerSize(const SkSize& containerSize) { // TODO: inval fContainerSize = containerSize; diff --git a/experimental/svg/model/SkSVGDOM.h b/experimental/svg/model/SkSVGDOM.h index 9c59b7c561..8904c1799d 100644 --- a/experimental/svg/model/SkSVGDOM.h +++ b/experimental/svg/model/SkSVGDOM.h @@ -20,18 +20,22 @@ class SkSVGNode; class SkSVGDOM : public SkRefCnt { public: - SkSVGDOM(const SkSize& containerSize); + SkSVGDOM(); ~SkSVGDOM() = default; - static sk_sp<SkSVGDOM> MakeFromDOM(const SkDOM&, const SkSize& containerSize); - static sk_sp<SkSVGDOM> MakeFromStream(SkStream&, const SkSize& containerSize); + static sk_sp<SkSVGDOM> MakeFromDOM(const SkDOM&); + static sk_sp<SkSVGDOM> MakeFromStream(SkStream&); + const SkSize& containerSize() const; void setContainerSize(const SkSize&); + void setRoot(sk_sp<SkSVGNode>); void render(SkCanvas*) const; private: + SkSize intrinsicSize() const; + SkSize fContainerSize; sk_sp<SkSVGNode> fRoot; SkSVGIDMapper fIDMapper; diff --git a/experimental/svg/model/SkSVGSVG.cpp b/experimental/svg/model/SkSVGSVG.cpp index 13f18043c0..592992760a 100644 --- a/experimental/svg/model/SkSVGSVG.cpp +++ b/experimental/svg/model/SkSVGSVG.cpp @@ -95,3 +95,15 @@ void SkSVGSVG::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) { this->INHERITED::onSetAttribute(attr, v); } } + +// https://www.w3.org/TR/SVG/coords.html#IntrinsicSizing +SkSize SkSVGSVG::intrinsicSize(const SkSVGLengthContext& lctx) const { + // Percentage values do not provide an intrinsic size. + if (fWidth.unit() == SkSVGLength::Unit::kPercentage || + fHeight.unit() == SkSVGLength::Unit::kPercentage) { + return SkSize::Make(0, 0); + } + + return SkSize::Make(lctx.resolve(fWidth, SkSVGLengthContext::LengthType::kHorizontal), + lctx.resolve(fHeight, SkSVGLengthContext::LengthType::kVertical)); +} diff --git a/experimental/svg/model/SkSVGSVG.h b/experimental/svg/model/SkSVGSVG.h index ae4787cac3..675c83351f 100644 --- a/experimental/svg/model/SkSVGSVG.h +++ b/experimental/svg/model/SkSVGSVG.h @@ -12,6 +12,8 @@ #include "SkSVGTypes.h" #include "SkTLazy.h" +class SkSVGLengthContext; + class SkSVGSVG : public SkSVGContainer { public: virtual ~SkSVGSVG() = default; @@ -24,6 +26,8 @@ public: void setHeight(const SkSVGLength&); void setViewBox(const SkSVGViewBoxType&); + SkSize intrinsicSize(const SkSVGLengthContext&) const; + protected: bool onPrepareToRender(SkSVGRenderContext*) const override; diff --git a/samplecode/SampleSVGFile.cpp b/samplecode/SampleSVGFile.cpp index a4b5b34d7d..61a6be73d6 100644 --- a/samplecode/SampleSVGFile.cpp +++ b/samplecode/SampleSVGFile.cpp @@ -35,7 +35,10 @@ protected: return; } - fDom = SkSVGDOM::MakeFromDOM(xmlDom, SkSize::Make(this->width(), this->height())); + fDom = SkSVGDOM::MakeFromDOM(xmlDom); + if (fDom) { + fDom->setContainerSize(SkSize::Make(this->width(), this->height())); + } } void onDrawContent(SkCanvas* canvas) override { diff --git a/samplecode/SampleSVGPong.cpp b/samplecode/SampleSVGPong.cpp index be107b64dc..590ec1824b 100644 --- a/samplecode/SampleSVGPong.cpp +++ b/samplecode/SampleSVGPong.cpp @@ -136,7 +136,8 @@ protected: // Handle everything in a normalized 1x1 space. root->setViewBox(SkSVGViewBoxType(SkRect::MakeWH(1, 1))); - fDom = sk_sp<SkSVGDOM>(new SkSVGDOM(SkSize::Make(this->width(), this->height()))); + fDom = sk_sp<SkSVGDOM>(new SkSVGDOM()); + fDom->setContainerSize(SkSize::Make(this->width(), this->height())); fDom->setRoot(std::move(root)); // Off we go. |