Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to rendering a text in nested SVG #740

Open
yanorei32 opened this issue Apr 15, 2024 · 7 comments
Open

Failed to rendering a text in nested SVG #740

yanorei32 opened this issue Apr 15, 2024 · 7 comments
Labels

Comments

@yanorei32
Copy link

yanorei32 commented Apr 15, 2024

I wrote are two SVGs and I nested those and I got a blank image unexpectedly.

Is this a bug...? (Sorry. I can't classify that problem as bug, unimplemented feature, undefined behaviour or something else, because I'm not an expert of SVG specification.)

Version: 0.41.0
OS: Windows 11 23H2 22631.3447 (x86_64) and Arch Linux.

I got a same results in --use-fonts-dir option.

Text containing SVG (child.svg)

Works expectedly if this file only.
This file just needs to contain a text element.
But I wrote some elements and attributes for visiblity.

Note: I choose a Noto Sans but this problem is occured too in any system fonts.

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
	<rect x="25" y="25" width="25" height="25" fill="red" />
	<text
		x="50" y="50" dominant-baseline="middle" text-anchor="middle"
		font-size="25" font-family="Noto Sans"
		fill="black"
	>
		Hello
	</text>
</svg>

Rendered Image (child.svg):

resvg child.svg child.png

child

Parent SVG (parent.svg)

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
	<image x="0" y="0" width="100" height="100" href="child.svg" />
</svg>

Rendered Image (parent.svg):

resvg parent.svg parent.png

Actually behaviour (parent.svg)

parent

and I got warning:

Warning (in usvg::text::layout:1115): No match for '"Noto Sans"' font-family.

Expected behaviour (parent.svg)

Completly same as child.svg in this case.

@RazrFalcon
Copy link
Collaborator

RazrFalcon commented Apr 15, 2024

Yes, we're loading fonts only when the main SVG has text nodes. We do not check referenced SVGs.
Will fix.

For now, simply add a single empty text element to the main SVG and it will fix the issue.

@RazrFalcon RazrFalcon added the bug label Apr 15, 2024
@yanorei32
Copy link
Author

Amazing! Thank you for very fast reply!
I confirmed that solution is works and that completely avoid this problem.
I hope this problem will be fixed in future.

@LaurenzV
Copy link
Contributor

Yes, we're loading fonts only when the main SVG has text nodes. We do not check referenced SVGs.

Didn't I fix this in #675? Apparently I didn't...

@LaurenzV
Copy link
Contributor

LaurenzV commented Apr 15, 2024

Oh... It's because resvg has it's own logic for checking if there are text nodes... So it works in tests but not in the CLI:

https://github.com/RazrFalcon/resvg/blob/ec1627fb73ecf4f3d91f5b2283cf8b89ec6c83c3/crates/resvg/src/main.rs#L84-L86

That's gonna be tricky to change though if we want to do it inside the resvg CLI...

Maybe it's best to just always initialize the fontdb?

@RazrFalcon
Copy link
Collaborator

Maybe it's best to just always initialize the fontdb?

That's pretty slow. Even on a macbook with a hot cache it's like 10-20ms.
It could easily take 100-500ms on an average hardware.

The issue here is that before, text flattening was done after parsing, not during. So before we were checking for usvg::Text nodes, not text XML elements.

This is partially related to #710 , as we have to add a callback to text flattening. I haven't thought about it much yet.

The only "solution" so far is to have some public, intermediate tree representation. One between usvg::parser::svgtree and usvg::Tree.
This way we wouldn't have to do everything in one go, which has it's own limitations (paint servers resolving) and complicates code quite a bit (text flattening). But it would have a small performance hit.
Basically, instead of modifying usvg::Tree and passing it to resvg, we would allow modifying of this new tree, which then be converted into usvg::Tree.
And we already do roxmltree -> svgtree -> usvg::Tree ...

@LaurenzV
Copy link
Contributor

That will be a lot of trees then. :p But I've also had thoughts about whether there should be some additional intermediate representation...

@RazrFalcon
Copy link
Collaborator

While intermediate representations do reduce performance a bit, they do simplify the code and logic quite a lot.
The hard part is to find the right boundaries for each representation.

My goal is to keep usvg::Tree read-only with all of the SVG complexity removed and all metadata calculated (bboxes, etc).
For the caller, SVG should look like a simple list of layers. And as you already know, it's ridiculously hard to do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants