From 365bf47db64dc2ab88e7649548e9ab64b6644eda Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 06:08:48 -0500 Subject: [PATCH] Expose bounded SVG root dimensions --- crates/svg/src/tree.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/svg/src/tree.rs b/crates/svg/src/tree.rs index 0352fa022..9cb004d89 100644 --- a/crates/svg/src/tree.rs +++ b/crates/svg/src/tree.rs @@ -134,6 +134,24 @@ pub fn parse_text(svg: &str, limits: &Limits, options: &usvg::Options<'_>) -> Re usvg::Tree::from_xmltree(&xml, options).map_err(|e| Error::Parse(e.to_string())) } +/// Read the root SVG's unitless width and height without constructing a rendering tree. +/// +/// Lengths with units, percentages, missing dimensions, and non-SVG roots return `Ok(None)`; +/// malformed or over-limit XML returns the same bounded parsing error as [`parse_text`]. +pub fn root_unitless_size(svg: &str, limits: &Limits) -> Result, Error> { + let xml = checked(svg, limits)?; + let root = xml.root_element(); + if root.tag_name().name() != "svg" { + return Ok(None); + } + let Some((width, height)) = + root.attribute("width").and_then(|value| value.parse::().ok()).zip(root.attribute("height").and_then(|value| value.parse::().ok())) + else { + return Ok(None); + }; + Ok(Some((width, height))) +} + /// Every check on SVG text, cheapest first; the XML it parses to on the way. fn checked<'s>(svg: &'s str, limits: &Limits) -> Result, Error> { let preflight_limits = crate::preflight::Limits {