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

feat: Render referenced elements in use tags #238

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

theminecoder
Copy link

<use> elements lists to reference another element by id. This enables the codebase to render such element when rasterising.

I am aware this is not completely to spec in regards to x,y,width,height but this does the base job for when transforms are at play, which is what my current case exposes. I may look into that in another pr

@meyfa meyfa changed the title Correctly render referenced elements in use tagss feat: Render referenced elements in use tags Nov 6, 2024
Copy link
Owner

@meyfa meyfa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! I've left some ideas to further improve this.

The most important thing I would like to have is a check for cycles. Currently, the <use> tag could even reference itself, or reference a parent node, which would cause infinite recursion.

What makes this complicated are cases like:

<use id="foo" href="#bar" />
<use id="bar" href="#foo" />

One solution I can think of would be:

  • Store an array of SVGUse elements on the SVGRasterizer (initially empty)
  • At the beginning of SVGUse::rasterize(), check if $this is part of the array; if yes, return; if no, add it to the array, and continue as usual.
  • At the end of SVGUse::rasterize(), remove $this from the array.

src/Nodes/Structures/SVGUse.php Outdated Show resolved Hide resolved
$element = $this->getHref();
if(empty($element)) return;

/** @var SVGDocumentFragment $root */
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this doc comment

Suggested change
/** @var SVGDocumentFragment $root */

src/Nodes/Structures/SVGUse.php Outdated Show resolved Hide resolved
do {
$root = $this->getParent();
} while ($root->getParent() != null);
$element = $root->getElementById(substr($element, strpos($element, "#") + 1 ?: 0));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Please avoid reusing variables, especially when the type changes ($element was string before this line, but is now a node object). Maybe rename the string variable to $href to reduce confusion.
  2. strpos($element, "#") + 1 ?: 0 is problematic - if the string is not found, strpos returns false, and false + 1 makes little sense.

However, it seems to me that the href always has to start with #, and so this can (and should) be rewritten:

  • At the start of the function, if $href does not start with #, return.
  • Otherwise, remove the first character, and use that for getElementById.

Sources: https://www.w3.org/TR/SVG11/struct.html#UseElement

@meyfa meyfa linked an issue Nov 6, 2024 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for <use> elements
2 participants