Rendering SVG with multiple use of same path

482 views
Skip to first unread message

Pierre Alma

unread,
Oct 3, 2022, 10:52:58 AM10/3/22
to skia-discuss
Hi,

I render SVG with Skia and I need to render many time the same path in one image. I would like this path to be defined only once in the SVG file and referenced many time with a transformation (to lighten the file).

The resulting SVG would be something like
<defs>
<g id="part1">
<path ... />
</g>
</defs>
<g>
<use xlink:href="#part1" transform="matrix(1,0,0,1,0,0)" />
<use xlink:href="#part1" transform="matrix(1,0,0,1,122,18) rotate(90)" />
...
</g>

Could I do that with SkSVG and how?

Thank you,
Pierre

Ben Wagner

unread,
Oct 3, 2022, 11:20:22 AM10/3/22
to skia-d...@googlegroups.com
This should work. See [0] for where in the code this `xlink:href` IRI
is parsed. It is then used by other methods in `SkSVGUse.cpp` as
`fHref` to draw the thing referenced. The transforms are parsed at [1]
and should also be parsed and applied properly.

[0] https://skia.googlesource.com/skia/+/85b2c7da6d444216e317661c79552f1fdd1359cd/modules/svg/src/SkSVGUse.cpp#24
[1] https://skia.googlesource.com/skia/+/85b2c7da6d444216e317661c79552f1fdd1359cd/modules/svg/src/SkSVGAttributeParser.cpp#661
> --
> You received this message because you are subscribed to the Google Groups "skia-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to skia-discuss...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/skia-discuss/17306721-be6a-4349-9848-7a332905920cn%40googlegroups.com.

Pierre Alma

unread,
Oct 11, 2022, 11:24:48 AM10/11/22
to skia-discuss
Thank you for your answer.

From what I understand, SkSVGUse stores a reference to another SVG node. When onRender or onAsPath is called we render this node or this path.

I would like however to output SVG files with such "use" tags.

Example code
    SkFILEStream svgStream(inpath);
    sk_sp<SkSVGDOM> dom = SkSVGDOM::MakeFromStream(svgStream);
    const auto wStream = std::make_shared<SkFILEWStream>(outpath);
    auto canvas = SkSVGCanvas::Make(SkRect::MakeWH(500, 500), wStream.get());
    dom->render(canvas.get());
    wStream->flush();

   
If <inpath> file is as described in my first message, <outpath> file does not contains "use" tag anymore, paths are copied. Would there be a way to keep these "use" that make svg files a lot more compact?

Ben Wagner

unread,
Oct 11, 2022, 12:07:28 PM10/11/22
to skia-d...@googlegroups.com
Ah, you're describing using the SkSVGCanvas to create an SVG document,
as opposed to using SkSVG to parse an SVG document and draw it to
pixels. Unfortunately SkSVGCanvas is less used and maintained than
SkSVG. In particular SkSVGDevice (which does the actual work for
SkSVGCanvas) simply streams out the SVG XML as draw calls are made. It
does not create a DOM which could then be later analyzed for
duplicates which could be grouped. Doing so would probably require
restructuring the way the current SkSVGCanvas works. So at the moment
there isn't any simple way to have the output use "use" in any useful
way.
> To view this discussion on the web visit https://groups.google.com/d/msgid/skia-discuss/c2c451d6-9d44-4a66-8aa2-a316b1121c89n%40googlegroups.com.

Pierre Alma

unread,
Oct 17, 2022, 4:36:21 AM10/17/22
to skia-discuss
That's clear, thank you for your answer.
Reply all
Reply to author
Forward
0 new messages