SVG import: flowed text with a region too large to place is left out with a warning

This commit is contained in:
bflatastic 2026-10-13 09:27:32 +07:00
parent e794c1ac63
commit db85d465c8
2 changed files with 22 additions and 0 deletions

View File

@ -594,6 +594,11 @@ impl Ctx {
obj.xf = parse_transform(r.attribute("transform")) * origin;
let servers = vec![(None, None); obj.runs.len()];
let b = obj.xf.transform_rect_bbox(frame);
// A size, place or transform past what numbers hold (`width="1e999"`) has no frame to set type in.
if ![b.x0, b.y0, b.x1, b.y1].iter().all(|v| v.is_finite()) {
warnings.push(format!("{label}: flowed text (flowRoot) with a region too large to place was left out"));
return None;
}
let marker = Rect::new(b.x0, b.y0, b.x1.max(b.x0 + 1.0), b.y1.max(b.y0 + 1.0));
let name = t.attribute("id").unwrap_or("").to_string();
Some((PendingText { name, obj, servers, paints: 0, non_scaling: false, under: None, marker }, Vec::new()))

View File

@ -612,3 +612,20 @@ fn flowed_text_becomes_area_type() {
assert!(close(t.runs[0].style.size * t.xf.determinant().abs().sqrt(), 16.0, 1e-6));
assert!(w.iter().any(|w| w.contains("flowRoot")), "{w:?}");
}
/// Flowed text that can't be read is left out with a warning each, and never stops the import: no
/// region, a region too large for numbers, a flowRoot inside a flowRoot (read once, as the outer one).
#[test]
fn flowed_text_that_cannot_be_read_is_reported() {
let (d, w) = import_with_report(&svg(
r#"<flowRoot id="none"><flowPara>No region</flowPara></flowRoot>
<flowRoot id="huge"><flowRegion><rect width="1e999" height="10"/></flowRegion><flowPara>Huge</flowPara></flowRoot>
<flowRoot id="far"><flowRegion><rect x="1e308" width="1e308" height="10" transform="scale(1e308)"/></flowRegion><flowPara>Far</flowPara></flowRoot>
<flowRoot id="outer"><flowRegion><rect width="50" height="50"/></flowRegion><flowPara>Outer</flowPara><flowRoot><flowRegion><rect width="5" height="5"/></flowRegion><flowPara>inner</flowPara></flowRoot></flowRoot>"#,
))
.unwrap();
assert_eq!(only_text(&d).plain_text(), "Outer\ninner");
for id in ["none", "huge", "far"] {
assert!(w.iter().any(|w| w.contains(id) && w.contains("flowRoot")), "{id}: {w:?}");
}
}