diff --git a/crates/xfa/src/layout.rs b/crates/xfa/src/layout.rs index 39841c469..a5dd72a79 100644 --- a/crates/xfa/src/layout.rs +++ b/crates/xfa/src/layout.rs @@ -691,7 +691,10 @@ impl Layouter<'_> { if b.fill().is_none() && b.visible_edges() == [false; 4] { return Ok(()); } - let (_, end, _) = self.cursor(); + let (area, end, _) = self.cursor(); + // The bottom margin stays in the content area, as at a break; content that itself runs + // past it keeps the border round it. + let end = end.min(area.bottom()).max(end - f.margin.bottom); let page = self.pages.len().saturating_sub(1); if !self.on_area(&f.part) { f.lost = true; diff --git a/crates/xfa/src/tests.rs b/crates/xfa/src/tests.rs index aabfe175d..f20bb94ee 100644 --- a/crates/xfa/src/tests.rs +++ b/crates/xfa/src/tests.rs @@ -2096,6 +2096,13 @@ fn a_flowed_subform_is_drawn_with_its_border_under_its_content() { let f19 = form.pages[1].items.iter().find_map(|i| if let Item::Widget(w) = i { (w.name == "f19").then_some(w.rect) } else { None }).unwrap(); assert!((f19.y - 43.2).abs() < 0.01, "the second part starts after the top margin: {}", f19.y); assert!(form.warnings.is_empty(), "{:?}", form.warnings); + // A bottom margin that would run past the content area stops at its edge: 39 quarter-inch + // fields end at 738, and 0.4in more would reach 766.8, past 756. + let quarter: String = (0..39).map(|i| format!(r#""#)).collect(); + let low = format!(r#"{quarter}"#); + let form = lay(&low); + let edge = form.pages[0].items.iter().find_map(|i| if let Item::Fill { rect, .. } = i { Some(rect.bottom()) } else { None }).unwrap(); + assert!((edge - 756.0).abs() < 0.01, "the box ends at the content area's bottom: {edge}"); // The margins come back without a border too. let bare = format!(r#"{many}"#); let form = lay(&bare);