[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
This commit is contained in:
parent
be362774f9
commit
e1baa7c105
@ -651,16 +651,21 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use intrinsic size? make tunable via flag?
|
sk_sp<SkSVGDOM> svgDom = SkSVGDOM::MakeFromStream(stream);
|
||||||
static const SkSize kContainerSize = SkSize::Make(128, 128);
|
|
||||||
sk_sp<SkSVGDOM> svgDom = SkSVGDOM::MakeFromStream(stream, kContainerSize);
|
|
||||||
if (!svgDom) {
|
if (!svgDom) {
|
||||||
SkDebugf("Could not parse %s.\n", path);
|
SkDebugf("Could not parse %s.\n", path);
|
||||||
return nullptr;
|
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;
|
SkPictureRecorder recorder;
|
||||||
svgDom->render(recorder.beginRecording(kContainerSize.width(), kContainerSize.height()));
|
svgDom->render(recorder.beginRecording(svgDom->containerSize().width(),
|
||||||
|
svgDom->containerSize().height()));
|
||||||
return recorder.finishRecordingAsPicture();
|
return recorder.finishRecordingAsPicture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1043,11 +1043,12 @@ Error SVGSrc::draw(SkCanvas* canvas) const {
|
|||||||
return SkStringPrintf("Unable to open file: %s", fPath.c_str());
|
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) {
|
if (!dom) {
|
||||||
return SkStringPrintf("Unable to parse file: %s", fPath.c_str());
|
return SkStringPrintf("Unable to parse file: %s", fPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dom->setContainerSize(kSVGSize);
|
||||||
dom->render(canvas);
|
dom->render(canvas);
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
@ -384,26 +384,29 @@ sk_sp<SkSVGNode> construct_svg_node(const SkDOM& dom, const ConstructionContext&
|
|||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
SkSVGDOM::SkSVGDOM(const SkSize& containerSize)
|
SkSVGDOM::SkSVGDOM()
|
||||||
: fContainerSize(containerSize) {
|
: fContainerSize(SkSize::Make(0, 0)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkSVGDOM> SkSVGDOM::MakeFromDOM(const SkDOM& xmlDom, const SkSize& containerSize) {
|
sk_sp<SkSVGDOM> SkSVGDOM::MakeFromDOM(const SkDOM& xmlDom) {
|
||||||
sk_sp<SkSVGDOM> dom = sk_make_sp<SkSVGDOM>(containerSize);
|
sk_sp<SkSVGDOM> dom = sk_make_sp<SkSVGDOM>();
|
||||||
|
|
||||||
ConstructionContext ctx(&dom->fIDMapper);
|
ConstructionContext ctx(&dom->fIDMapper);
|
||||||
dom->fRoot = construct_svg_node(xmlDom, ctx, xmlDom.getRootNode());
|
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;
|
return dom;
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkSVGDOM> SkSVGDOM::MakeFromStream(SkStream& svgStream, const SkSize& containerSize) {
|
sk_sp<SkSVGDOM> SkSVGDOM::MakeFromStream(SkStream& svgStream) {
|
||||||
SkDOM xmlDom;
|
SkDOM xmlDom;
|
||||||
if (!xmlDom.build(svgStream)) {
|
if (!xmlDom.build(svgStream)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeFromDOM(xmlDom, containerSize);
|
return MakeFromDOM(xmlDom);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkSVGDOM::render(SkCanvas* canvas) const {
|
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) {
|
void SkSVGDOM::setContainerSize(const SkSize& containerSize) {
|
||||||
// TODO: inval
|
// TODO: inval
|
||||||
fContainerSize = containerSize;
|
fContainerSize = containerSize;
|
||||||
|
@ -20,18 +20,22 @@ class SkSVGNode;
|
|||||||
|
|
||||||
class SkSVGDOM : public SkRefCnt {
|
class SkSVGDOM : public SkRefCnt {
|
||||||
public:
|
public:
|
||||||
SkSVGDOM(const SkSize& containerSize);
|
SkSVGDOM();
|
||||||
~SkSVGDOM() = default;
|
~SkSVGDOM() = default;
|
||||||
|
|
||||||
static sk_sp<SkSVGDOM> MakeFromDOM(const SkDOM&, const SkSize& containerSize);
|
static sk_sp<SkSVGDOM> MakeFromDOM(const SkDOM&);
|
||||||
static sk_sp<SkSVGDOM> MakeFromStream(SkStream&, const SkSize& containerSize);
|
static sk_sp<SkSVGDOM> MakeFromStream(SkStream&);
|
||||||
|
|
||||||
|
const SkSize& containerSize() const;
|
||||||
void setContainerSize(const SkSize&);
|
void setContainerSize(const SkSize&);
|
||||||
|
|
||||||
void setRoot(sk_sp<SkSVGNode>);
|
void setRoot(sk_sp<SkSVGNode>);
|
||||||
|
|
||||||
void render(SkCanvas*) const;
|
void render(SkCanvas*) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SkSize intrinsicSize() const;
|
||||||
|
|
||||||
SkSize fContainerSize;
|
SkSize fContainerSize;
|
||||||
sk_sp<SkSVGNode> fRoot;
|
sk_sp<SkSVGNode> fRoot;
|
||||||
SkSVGIDMapper fIDMapper;
|
SkSVGIDMapper fIDMapper;
|
||||||
|
@ -95,3 +95,15 @@ void SkSVGSVG::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
|
|||||||
this->INHERITED::onSetAttribute(attr, 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));
|
||||||
|
}
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include "SkSVGTypes.h"
|
#include "SkSVGTypes.h"
|
||||||
#include "SkTLazy.h"
|
#include "SkTLazy.h"
|
||||||
|
|
||||||
|
class SkSVGLengthContext;
|
||||||
|
|
||||||
class SkSVGSVG : public SkSVGContainer {
|
class SkSVGSVG : public SkSVGContainer {
|
||||||
public:
|
public:
|
||||||
virtual ~SkSVGSVG() = default;
|
virtual ~SkSVGSVG() = default;
|
||||||
@ -24,6 +26,8 @@ public:
|
|||||||
void setHeight(const SkSVGLength&);
|
void setHeight(const SkSVGLength&);
|
||||||
void setViewBox(const SkSVGViewBoxType&);
|
void setViewBox(const SkSVGViewBoxType&);
|
||||||
|
|
||||||
|
SkSize intrinsicSize(const SkSVGLengthContext&) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onPrepareToRender(SkSVGRenderContext*) const override;
|
bool onPrepareToRender(SkSVGRenderContext*) const override;
|
||||||
|
|
||||||
|
@ -35,7 +35,10 @@ protected:
|
|||||||
return;
|
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 {
|
void onDrawContent(SkCanvas* canvas) override {
|
||||||
|
@ -136,7 +136,8 @@ protected:
|
|||||||
// Handle everything in a normalized 1x1 space.
|
// Handle everything in a normalized 1x1 space.
|
||||||
root->setViewBox(SkSVGViewBoxType(SkRect::MakeWH(1, 1)));
|
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));
|
fDom->setRoot(std::move(root));
|
||||||
|
|
||||||
// Off we go.
|
// Off we go.
|
||||||
|
Loading…
Reference in New Issue
Block a user