Clamp negative margins before checking they leave text room (#1941)

Found while testing crates/engine/src/cmd/page.rs:392 (margins) and :424 (margins_fit)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-10-18 04:41:20 -04:00
committed by GitHub
co-authored by Claude Haiku 5.5
parent eff1444f08
commit 6b192f58ce
2 changed files with 22 additions and 6 deletions
+8 -6
View File
@@ -474,7 +474,9 @@ fn margins(s: &mut Session, v: &Value) -> CmdResult {
)
}
};
let gutter = p::f32(v, "gutter");
// Negative margins count as zero before the fit check, so one can't offset another.
let (t, b, l, r) = (t.max(0.0), b.max(0.0), l.max(0.0), r.max(0.0));
let gutter = p::f32(v, "gutter").map(|g| g.max(0.0));
let cur = sect(s);
if !margins_fit((cur.page_w, cur.page_h), (t, b, l, r), gutter.unwrap_or(cur.gutter)) {
return Err(CmdError::Params("margins leave no room for text".into()));
@@ -485,12 +487,12 @@ fn margins(s: &mut Session, v: &Value) -> CmdResult {
s.doc.settings.mirror_margins = on;
}
with_sect(s, |x| {
x.margin_top = t.max(0.0);
x.margin_bottom = b.max(0.0);
x.margin_left = l.max(0.0);
x.margin_right = r.max(0.0);
x.margin_top = t;
x.margin_bottom = b;
x.margin_left = l;
x.margin_right = r;
if let Some(g) = gutter {
x.gutter = g.max(0.0);
x.gutter = g;
}
})
}
+14
View File
@@ -1935,6 +1935,20 @@ fn layout_size_refuses_a_page_its_margins_dont_fit() {
assert_eq!((s.doc.last_section.page_w, s.doc.last_section.page_h), (180.0, 180.0), "exactly 36 pt of room is enough");
}
/// A negative margin (or gutter) counts as zero, so it can't offset an oversized one past the
/// text-room check: `layout.margins` refuses and changes nothing.
#[test]
fn layout_margins_negative_cannot_hide_an_oversized_margin() {
let mut s = s();
run(&mut s, "layout.margins", json!({"preset": "normal"}));
let before = s.doc.last_section.clone();
for v in [json!({"top": 2000, "bottom": -2000}), json!({"left": 2000, "right": -2000}), json!({"left": 600, "right": 0, "gutter": -600})] {
let e = s.run("layout.margins", &v).unwrap_err().to_string();
assert!(e.contains("margins leave no room for text"), "{v}: {e}");
assert_eq!(s.doc.last_section, before, "{v} changes nothing");
}
}
/// #1433: the smallest page there can be (0.1" wide, no margins, set straight through Page
/// Setup's section) still lays out and exports text, a table and two columns.
#[test]