SVG import: an Inkscape page whose box can't be placed is skipped

This commit is contained in:
bflatastic 2026-10-13 11:38:40 +07:00
parent ef0ab7ba9d
commit 04bb6d6f27
2 changed files with 13 additions and 2 deletions

View File

@ -296,14 +296,16 @@ fn inkscape_pages(xml: &roxmltree::Document, user: Affine) -> Option<Vec<vectorc
.filter_map(|p| {
let (w, h) = (num(p, "width")?, num(p, "height")?);
let (x, y) = (num(p, "x").unwrap_or(0.0), num(p, "y").unwrap_or(0.0));
(w > 0.0 && h > 0.0).then(|| (p, Rect::new(x, y, x + w, y + h)))
// A box too large to add up or to place (1e308 wide) is no page.
let r = user.transform_rect_bbox(Rect::new(x, y, x + w, y + h));
(w > 0.0 && h > 0.0 && r.is_finite()).then_some((p, r))
})
.take(1000)
.enumerate()
.map(|(i, (p, r))| vectorcraft_doc::Artboard {
id: i as u32 + 1,
name: p.attribute((INKSCAPE, "label")).filter(|l| !l.trim().is_empty()).map_or_else(|| format!("Artboard {}", i + 1), str::to_string),
rect: user.transform_rect_bbox(r),
rect: r,
show_center_mark: false,
show_cross_hairs: false,
})

View File

@ -240,6 +240,15 @@ fn inkscape_pages_become_artboards() {
let d = import_with(svg, &ImportOptions::default()).unwrap().0;
let b: Vec<(String, Rect)> = d.artboards.iter().map(|a| (a.name.clone(), a.rect)).collect();
assert_eq!(b, vec![("Front".to_string(), Rect::new(0.0, 0.0, 200.0, 200.0)), ("Artboard 2".to_string(), Rect::new(240.0, 0.0, 360.0, 300.0))]);
// Hostile boxes (too large to add up, not numbers, negative) are no pages, and at most 1,000 are read.
let pages = r#"<inkscape:page x="1e308" y="0" width="1e308" height="10"/><inkscape:page x="NaN" y="0" width="10" height="10"/><inkscape:page width="inf" height="10"/><inkscape:page width="-5" height="10"/>"#.to_string()
+ &r#"<inkscape:page width="10" height="10"/>"#.repeat(1500);
let hostile = format!(
r#"<svg xmlns="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="50" height="50"><g>{pages}</g></svg>"#
);
let d = import_with(&hostile, &ImportOptions::default()).unwrap().0;
assert_eq!(d.artboards.len(), 1000);
assert!(d.artboards.iter().all(|a| a.rect == Rect::new(0.0, 0.0, 10.0, 10.0)), "{:?}", d.artboards.first());
// A file without pages keeps its one artboard.
let d = import_with(&svg_doc(), &ImportOptions::default()).unwrap().0;
assert_eq!(d.artboards.len(), 1);