diff --git a/crates/usvg/src/parser/converter.rs b/crates/usvg/src/parser/converter.rs index 38bdbdbff..09d7c2565 100644 --- a/crates/usvg/src/parser/converter.rs +++ b/crates/usvg/src/parser/converter.rs @@ -540,7 +540,16 @@ fn resolve_svg_size(svg: &SvgNode, opt: &Options) -> (Result, bool) svg.convert_user_length(AId::Height, &state, def) }; - Size::from_wh(w, h) + // If only one of height/width is not specified, its value should be + // computed from the other and the viewbox' aspect ratio. + match ( + svg.attribute::(AId::Width), + svg.attribute::(AId::Height), + ) { + (Some(_), None) => Size::from_wh(w, vbox.height() * w / vbox.width()), + (None, Some(_)) => Size::from_wh(vbox.width() * h / vbox.height(), h), + (_, _) => Size::from_wh(w, h), + } } else { Size::from_wh( svg.convert_user_length(AId::Width, &state, def), diff --git a/crates/usvg/tests/parser.rs b/crates/usvg/tests/parser.rs index d2786d801..17eb4e89e 100644 --- a/crates/usvg/tests/parser.rs +++ b/crates/usvg/tests/parser.rs @@ -217,6 +217,34 @@ fn size_detection_5() { assert_eq!(tree.size(), usvg::Size::from_wh(100.0, 100.0).unwrap()); } +#[test] +fn size_detection_6() { + let svg = ""; + let tree = usvg::Tree::from_str(&svg, &usvg::Options::default()).unwrap(); + assert_eq!(tree.size(), usvg::Size::from_wh(30.0, 30.0).unwrap()); +} + +#[test] +fn size_detection_7() { + let svg = ""; + let tree = usvg::Tree::from_str(&svg, &usvg::Options::default()).unwrap(); + assert_eq!(tree.size(), usvg::Size::from_wh(30.0, 60.0).unwrap()); +} + +#[test] +fn size_detection_8() { + let svg = ""; + let tree = usvg::Tree::from_str(&svg, &usvg::Options::default()).unwrap(); + assert_eq!(tree.size(), usvg::Size::from_wh(30.0, 30.0).unwrap()); +} + +#[test] +fn size_detection_9() { + let svg = ""; + let tree = usvg::Tree::from_str(&svg, &usvg::Options::default()).unwrap(); + assert_eq!(tree.size(), usvg::Size::from_wh(15.0, 30.0).unwrap()); +} + #[test] fn invalid_size_1() { let svg = "";