Skip to content

Commit fabe160

Browse files
committed
usvg/parser: fix width/height computation when only one is specified
In case only one of the height/width attributes are set and we have a viewBox, we currently report an incorrect size: the height/width that is set and 100% of the viewbox's attribute for the other attribute. This is incorrect, and we should instead compute the missing attribute value from the specified one and the viewBox' aspect ratio, like was done by #715. I have validated that this fixes servo's servo/servo#41273 Signed-off-by: Simon Martin <simon@nasilyan.com>
1 parent b3c7f58 commit fabe160

2 files changed

Lines changed: 44 additions & 1 deletion

File tree

‎crates/usvg/src/parser/converter.rs‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,18 @@ fn resolve_svg_size(svg: &SvgNode, opt: &Options) -> (Result<Size, Error>, bool)
540540
svg.convert_user_length(AId::Height, &state, def)
541541
};
542542

543-
Size::from_wh(w, h)
543+
// If only one of height/width is not specified, its value should be
544+
// computed from the other and the viewbox' aspect ratio.
545+
match (svg.attribute::<Length>(AId::Width), svg.attribute::<Length>(AId::Height)) {
546+
(Some(_), None) => {
547+
Size::from_wh(w, vbox.height() * w / vbox.width())
548+
},
549+
(None, Some(_)) => {
550+
Size::from_wh(vbox.width() * h / vbox.height(), h)
551+
},
552+
(_, _) => Size::from_wh(w, h),
553+
}
554+
544555
} else {
545556
Size::from_wh(
546557
svg.convert_user_length(AId::Width, &state, def),

‎crates/usvg/tests/parser.rs‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,38 @@ fn size_detection_5() {
217217
assert_eq!(tree.size(), usvg::Size::from_wh(100.0, 100.0).unwrap());
218218
}
219219

220+
#[test]
221+
fn size_detection_6() {
222+
let svg =
223+
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10' width='30'/>";
224+
let tree = usvg::Tree::from_str(&svg, &usvg::Options::default()).unwrap();
225+
assert_eq!(tree.size(), usvg::Size::from_wh(30.0, 30.0).unwrap());
226+
}
227+
228+
#[test]
229+
fn size_detection_7() {
230+
let svg =
231+
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 20' width='30'/>";
232+
let tree = usvg::Tree::from_str(&svg, &usvg::Options::default()).unwrap();
233+
assert_eq!(tree.size(), usvg::Size::from_wh(30.0, 60.0).unwrap());
234+
}
235+
236+
#[test]
237+
fn size_detection_8() {
238+
let svg =
239+
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10' height='30'/>";
240+
let tree = usvg::Tree::from_str(&svg, &usvg::Options::default()).unwrap();
241+
assert_eq!(tree.size(), usvg::Size::from_wh(30.0, 30.0).unwrap());
242+
}
243+
244+
#[test]
245+
fn size_detection_9() {
246+
let svg =
247+
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 20' height='30'/>";
248+
let tree = usvg::Tree::from_str(&svg, &usvg::Options::default()).unwrap();
249+
assert_eq!(tree.size(), usvg::Size::from_wh(15.0, 30.0).unwrap());
250+
}
251+
220252
#[test]
221253
fn invalid_size_1() {
222254
let svg = "<svg width='0' height='0' viewBox='0 0 10 20' xmlns='http://www.w3.org/2000/svg'/>";

0 commit comments

Comments
 (0)