Skip to content

Re-resolve viewport-dependent lengths for viewBox-less SVG against the used size - #642

Open
nicoburns wants to merge 1 commit into
devin/1786151607-block-replaced-sizingfrom
devin/1786155474-svg-viewport-reresolution
Open

Re-resolve viewport-dependent lengths for viewBox-less SVG against the used size#642
nicoburns wants to merge 1 commit into
devin/1786151607-block-replaced-sizingfrom
devin/1786155474-svg-viewport-reresolution

Conversation

@nicoburns

@nicoburns nicoburns commented Aug 8, 2026

Copy link
Copy Markdown
Member

Summary

Stacked on #634. An SVG with a viewBox scales to its CSS box (object-fit contain, unchanged). An SVG without one cannot be scaled: its percentage lengths must instead re-resolve against the element's used size.

SvgImageData now retains the SVG source, and tree_for_viewport(w, h) re-parses it with the root width/height attributes replaced by the used content-box size (cached per size; usvg has no API to override the root viewport after parsing, hence set_root_svg_size_attrs rewriting the root tag):

// draw_svg
let svg = svg.tree_for_viewport(zoom.unzoom(width / scale), zoom.unzoom(height / scale));

The viewport is re-resolved in unzoomed CSS px so the existing object-fit transform applies zoom/HiDPI scaling to 1:1 content (keeps css/css-viewport/zoom/svg-path.html passing). Fixes e.g. css/CSS2/normal-flow/block-replaced-height-006.xht and css/css-transforms/{scale,rotate,skewX,skewY}/svg-*, where viewBox-less SVG content was previously object-fit scaled against usvg's fallback size.

Link to Devin session: https://dioxus.staging.devinenterprise.com/sessions/51256d0b440341bd874c6dc59e138478
Requested by: @nicoburns

WPT results

79 newly passing, 5 newly failing (net +74).

Full diff (84 changed tests)
+ Fail => Pass css/CSS2/backgrounds/background-001.xht
+ Fail => Pass css/CSS2/backgrounds/background-002.xht
+ Fail => Pass css/CSS2/backgrounds/background-003.xht
+ Fail => Pass css/CSS2/backgrounds/background-006.xht
+ Fail => Pass css/CSS2/backgrounds/background-007.xht
+ Fail => Pass css/CSS2/backgrounds/background-008.xht
+ Fail => Pass css/CSS2/backgrounds/background-009.xht
+ Fail => Pass css/CSS2/backgrounds/background-010.xht
+ Fail => Pass css/CSS2/backgrounds/background-014.xht
+ Fail => Pass css/CSS2/backgrounds/background-018.xht
+ Fail => Pass css/CSS2/backgrounds/background-022.xht
+ Fail => Pass css/CSS2/backgrounds/background-087.xht
+ Fail => Pass css/CSS2/backgrounds/background-182.xht
+ Fail => Pass css/CSS2/backgrounds/background-328.xht
+ Fail => Pass css/CSS2/backgrounds/background-329.xht
- Pass => Fail css/CSS2/backgrounds/background-attachment-applies-to-007.xht
- Pass => Fail css/CSS2/backgrounds/background-attachment-applies-to-009.xht
- Pass => Fail css/CSS2/backgrounds/background-attachment-applies-to-012.xht
- Pass => Fail css/CSS2/backgrounds/background-attachment-applies-to-013.xht
- Pass => Fail css/CSS2/backgrounds/background-attachment-applies-to-014.xht
+ Fail => Pass css/CSS2/backgrounds/background-image-cover-002.xht
+ Fail => Pass css/CSS2/backgrounds/background-image-cover-004.xht
+ Fail => Pass css/CSS2/backgrounds/background-image-cover-attachment-001.xht
+ Fail => Pass css/CSS2/backgrounds/background-image-transparency-001.xht
+ Fail => Pass css/CSS2/backgrounds/background-repeat-001.xht
+ Fail => Pass css/CSS2/backgrounds/background-repeat-002.xht
+ Fail => Pass css/CSS2/backgrounds/background-repeat-003.xht
+ Fail => Pass css/CSS2/backgrounds/background-repeat-005.xht
+ Fail => Pass css/CSS2/borders/border-bottom-width-003.xht
+ Fail => Pass css/CSS2/borders/border-bottom-width-025.xht
+ Fail => Pass css/CSS2/borders/border-bottom-width-058.xht
+ Fail => Pass css/CSS2/borders/border-bottom-width-069.xht
+ Fail => Pass css/CSS2/borders/border-bottom-width-080.xht
+ Fail => Pass css/CSS2/borders/border-top-width-003.xht
+ Fail => Pass css/CSS2/borders/border-top-width-025.xht
+ Fail => Pass css/CSS2/borders/border-top-width-058.xht
+ Fail => Pass css/CSS2/borders/border-top-width-069.xht
+ Fail => Pass css/CSS2/borders/border-top-width-080.xht
+ Fail => Pass css/CSS2/borders/border-width-shorthand-001.xht
+ Fail => Pass css/CSS2/borders/border-width-shorthand-002.xht
+ Fail => Pass css/CSS2/borders/border-width-shorthand-003.xht
+ Fail => Pass css/CSS2/borders/border-width-shorthand-004.xht
+ Fail => Pass css/CSS2/floats-clear/float-replaced-width-011.xht
+ Fail => Pass css/CSS2/inline-svg-100-percent-in-body.html
+ Fail => Pass css/CSS2/inline-svg-intrinsic-size-100-percent-2.html
+ Fail => Pass css/CSS2/normal-flow/block-replaced-width-006.xht
+ Fail => Pass css/CSS2/normal-flow/inline-block-replaced-width-006.xht
+ Fail => Pass css/CSS2/normal-flow/inline-replaced-width-006.xht
+ Fail => Pass css/CSS2/positioning/absolute-replaced-width-006.xht
+ Fail => Pass css/CSS2/positioning/absolute-replaced-width-013.xht
+ Fail => Pass css/CSS2/positioning/absolute-replaced-width-020.xht
+ Fail => Pass css/CSS2/positioning/absolute-replaced-width-027.xht
+ Fail => Pass css/CSS2/positioning/absolute-replaced-width-034.xht
+ Fail => Pass css/CSS2/positioning/absolute-replaced-width-037.xht
+ Fail => Pass css/CSS2/positioning/absolute-replaced-width-051.xht
+ Fail => Pass css/CSS2/positioning/absolute-replaced-width-069.xht
+ Fail => Pass css/CSS2/positioning/absolute-replaced-width-076.xht
+ Fail => Pass css/css-borders/corner-shape/corner-shape-svg-border.html
+ Fail => Pass css/css-images/object-position-svg-001i.html
+ Fail => Pass css/css-images/object-position-svg-002i.html
+ Fail => Pass css/css-transforms/css-skew-002.html
+ Fail => Pass css/css-transforms/gradientTransform/svg-gradientTransform-combination-001.html
+ Fail => Pass css/css-transforms/group/svg-transform-group-008.html
+ Fail => Pass css/css-transforms/group/svg-transform-group-009.html
+ Fail => Pass css/css-transforms/group/svg-transform-group-011.html
+ Fail => Pass css/css-transforms/group/svg-transform-nested-008.html
+ Fail => Pass css/css-transforms/group/svg-transform-nested-013.html
+ Fail => Pass css/css-transforms/group/svg-transform-nested-014.html
+ Fail => Pass css/css-transforms/group/svg-transform-nested-018.html
+ Fail => Pass css/css-transforms/group/svg-transform-nested-021.html
+ Fail => Pass css/css-transforms/group/svg-transform-nested-029.html
+ Fail => Pass css/css-transforms/scale/svg-scale-006.html
+ Fail => Pass css/css-transforms/scale/svg-scale-007.html
+ Fail => Pass css/css-transforms/skewX/svg-skewx-001.html
+ Fail => Pass css/css-transforms/skewX/svg-skewx-006.html
+ Fail => Pass css/css-transforms/skewX/svg-skewx-011.html
+ Fail => Pass css/css-transforms/skewX/svg-skewx-016.html
+ Fail => Pass css/css-transforms/skewX/svg-skewx-021.html
+ Fail => Pass css/css-transforms/skewY/svg-skewy-001.html
+ Fail => Pass css/css-transforms/skewY/svg-skewy-006.html
+ Fail => Pass css/css-transforms/skewY/svg-skewy-011.html
+ Fail => Pass css/css-transforms/skewY/svg-skewy-016.html
+ Fail => Pass css/css-transforms/skewY/svg-skewy-021.html
+ Fail => Pass css/css-transforms/translate/svg-translate-with-units.html

Generated by the WPT workflow.

@nicoburns nicoburns self-assigned this Aug 8, 2026
@staging-devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@staging-devin-ai-integration
staging-devin-ai-integration Bot force-pushed the devin/1786155474-svg-viewport-reresolution branch from da8d27c to 48f2111 Compare August 8, 2026 02:34
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.

1 participant