Convert px/unitless SVG root size to mm when a viewBox is present (#1749)

Found while testing crates/io/src/svg_read.rs:576-593 (parse_length_mm), used at 605-612 (viewport)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-10-24 01:49:44 -04:00
committed by GitHub
co-authored by Claude Haiku 5.5
parent 7d2fbd959a
commit f686a595e6
2 changed files with 21 additions and 2 deletions
+9 -2
View File
@@ -620,8 +620,15 @@ fn viewport(e: &BytesStart) -> Result<Mat3> {
_ => None,
}
});
let w_mm = attr(e, b"width").as_deref().and_then(parse_length_mm);
let h_mm = attr(e, b"height").as_deref().and_then(parse_length_mm);
// A bare or `px` root size is in CSS pixels, not millimetres.
let root_mm = |name: &[u8]| {
let raw = attr(e, name)?;
let mm = parse_length_mm(&raw)?;
let unit = raw.trim().trim_start_matches(|c: char| c.is_ascii_digit() || matches!(c, '.' | '-' | '+' | 'e' | 'E')).trim();
Some(if matches!(unit, "" | "px") { mm * 25.4 / 96.0 } else { mm })
};
let w_mm = root_mm(b"width");
let h_mm = root_mm(b"height");
let unit = match (vb, w_mm, h_mm) {
(Some((_, _, vw, _)), Some(w), _) if w > 0.0 => w / vw,
(Some((_, _, _, vh)), _, Some(h)) if h > 0.0 => h / vh,
+12
View File
@@ -2274,6 +2274,18 @@ fn svg_viewbox_scaling_and_mm_units() {
assert!((c.center.x - 10.0).abs() < 1e-9 && (c.center.y - 5.0).abs() < 1e-9, "{c:?}");
}
#[test]
fn svg_viewbox_with_px_or_unitless_root_size_uses_reference_pixel() {
for w in ["800", "800px"] {
let svg = format!(
r#"<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="600" viewBox="0 0 400 300"><line x1="0" y1="0" x2="400" y2="0"/></svg>"#
);
let d = read(svg.as_bytes(), "vb.svg").unwrap();
let l = first(&d, |k| if let EntityKind::Line(l) = k { Some(l.clone()) } else { None });
assert!((l.b.x - 800.0 * 25.4 / 96.0).abs() < 1e-9, "{w}: {l:?}");
}
}
#[test]
fn svg_inkscape_layers_are_kept() {
let svg = format!(