Skip to content

fix SVG preserveAspectRatio="none" handling for <symbol>/<use> - #9261

Merged
davepagurek merged 4 commits into
processing:mainfrom
Danyccsf:fix-svg-preserve-aspect-ratio-none
Oct 12, 2026
Merged

davepagurek merged 4 commits into
processing:mainfrom
Danyccsf:fix-svg-preserve-aspect-ratio-none

Conversation

@Danyccsf

@Danyccsf Danyccsf commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Resolves #9257

Description

This PR fixes SVG import handling of preserveAspectRatio="none" when a <use> element references a <symbol> with a viewBox.

Previously, the SVG importer always applied uniform scaling using the default xMidYMid meet behavior, even when the referenced symbol explicitly specified preserveAspectRatio="none". This caused symbols to retain their proportions instead of stretching to the dimensions specified by <use>.

Changes

  • Respect preserveAspectRatio="none" when a <use> element references a <symbol> with a viewBox.
  • Apply independent X and Y scaling instead of the default uniform scaling in this case.
  • Account for non-zero viewBox origins when applying the transform.
  • Preserve the existing default xMidYMid meet behavior and leave the fallback behavior for other values unchanged.
  • Add unit tests for non-uniform scaling and non-zero viewBox origins.
  • Add a visual regression test comparing default meet behavior with none, including an SVG fixture and reference screenshot.

Testing

  • SVG importer unit tests passed (94/94).
  • New visual regression test passed in Chromium.
  • Confirmed that the visual test passes when comparing its output against the saved reference screenshot.
  • Visually inspected the screenshot to verify the difference between uniform and non-uniform scaling.
  • Lint completed with no errors (18 existing warnings).

Screenshots of the change

Added a visual regression screenshot under:

test/unit/visual/screenshots/svg/SVG Import - defs and use/symbol preserveAspectRatio none/000.png

The screenshot compares two SVG symbols:

  • Top: Default xMidYMid meet behavior, preserving the symbol's proportions.
  • Bottom: preserveAspectRatio="none", stretching the symbol horizontally to fill its viewport.

Scope and follow-up considerations

  • This PR focuses on the none value for referenced SVG symbols.
  • Other alignment values and slice are not implemented by this change. Supporting them would require additional alignment parsing and transformation logic, with viewport clipping considerations for slice.
  • Broader support could be addressed in a follow-up issue or PR, depending on maintainer feedback.

PR Checklist

  • npm run lint passes
  • [Inline reference] is included / updated
  • [Unit tests] are included / updated
  • Visual regression test is included / updated

@p5-bot

p5-bot Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

@davepagurek davepagurek left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is looking good! Do you think we could add some visual tests so it's easier to verify the output?

I also was looking at https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/preserveAspectRatio to see what other options there are than none. Do you have a sense of what it might take to fully cover this attribute and whether that's worth adding?

@Danyccsf

Danyccsf commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

This is looking good! Do you think we could add some visual tests so it's easier to verify the output?

I also was looking at https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/preserveAspectRatio to see what other options there are than none. Do you have a sense of what it might take to fully cover this attribute and whether that's worth adding?

Thanks, Dave! I appreciate the feedback.

I'll look into the existing visual testing setup and add appropriate visual coverage for this case.

I'll also review the other preserveAspectRatio options and assess the scope of supporting them, so we can decide whether they belong in this PR or would be better handled separately.

I'll follow up with my findings!

@Danyccsf

Danyccsf commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

This is looking good! Do you think we could add some visual tests so it's easier to verify the output?

I also was looking at https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/preserveAspectRatio to see what other options there are than none. Do you have a sense of what it might take to fully cover this attribute and whether that's worth adding?

Thanks for the feedback, Dave!

I've pushed a visual regression test comparing the default xMidYMid meet behavior with preserveAspectRatio="none" for a symbol referenced through <use>. The test passes locally in Chromium, and I've inspected the generated screenshot to verify the difference in scaling.

I also looked into the other preserveAspectRatio values. The current visitUse() implementation handles none and otherwise applies the default centered meet transformation.

Supporting the other alignment options appears relatively straightforward by parsing the alignment values and adjusting the translation offsets. Supporting slice would also require investigating viewport clipping. Fully covering the attribute across applicable SVG elements would involve a broader review of the importer.

I think that broader support would be worthwhile, but my preference would be to keep this PR focused on none and handle the remaining options in a follow-up issue or PR. Would that approach make sense to you?

@perminder-17 perminder-17 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good to me!

@davepagurek

Copy link
Copy Markdown
Contributor

I think that broader support would be worthwhile, but my preference would be to keep this PR focused on none and handle the remaining options in a follow-up issue or PR. Would that approach make sense to you?

Sounds good! Feel free to open another issue if you're interested.

@davepagurek davepagurek left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good to me too, thanks!

@davepagurek
davepagurek merged commit ecfd981 into processing:main Oct 12, 2026
4 checks passed
@davepagurek

Copy link
Copy Markdown
Contributor

@all-contributors please add @Danyccsf for bug, code

@allcontributors

Copy link
Copy Markdown
Contributor

@davepagurek

I've put up a pull request to add @Danyccsf! 🎉

@Danyccsf

Copy link
Copy Markdown
Contributor Author

I think that broader support would be worthwhile, but my preference would be to keep this PR focused on none and handle the remaining options in a follow-up issue or PR. Would that approach make sense to you?

Sounds good! Feel free to open another issue if you're interested.

Hi Dave,
Thanks again for your feedback on PR #9261!
Following our discussion about additional preserveAspectRatio values, I investigated the alignment behavior and reproduced an issue with xMinYMin meet.
A local regression test confirmed that the SVG importer applies a horizontal translation of 50 instead of the expected 0.
I've documented the finding in a follow-up issue: #9287.
I'm planning to investigate the remaining meet alignment options as a potential follow-up contribution, while keeping slice behavior separate for now.
Thanks again for your guidance!

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.

[p5.js 2.0+ Bug Report]: SVG importer does not respect preserveAspectRatio="none" for <symbol>/<use>

3 participants