aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar fmalita <fmalita@chromium.org>2016-09-14 12:04:30 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-09-14 12:04:30 -0700
commite1baa7c105dad0f301ce34e5d6d1aa329334ef8c (patch)
treec79b25d4ed835bffccd2cbac9a6da433f1e51245
parentbe362774f9b9e8964544a579281603ed995e6e5a (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.cpp13
-rw-r--r--dm/DMSrcSink.cpp3
-rw-r--r--experimental/svg/model/SkSVGDOM.cpp29
-rw-r--r--experimental/svg/model/SkSVGDOM.h10
-rw-r--r--experimental/svg/model/SkSVGSVG.cpp12
-rw-r--r--experimental/svg/model/SkSVGSVG.h4
-rw-r--r--samplecode/SampleSVGFile.cpp5
-rw-r--r--samplecode/SampleSVGPong.cpp3
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.