#3108 review: behind-text and in-front-of-text floats don't grow the row

FredApps' review: the row-growth loop counted every non-inline object, so a
page-anchored logo or watermark behind a cell's text would stretch its row to
the object's bottom edge - contradicting table.rs (behind-text frames count
for vertical alignment but don't increase the row's flow height) and Word.
Only floats that take part in the text flow (Square, Tight, Through,
TopAndBottom) grow the row now, the same classification layout already uses
elsewhere for "takes part in wrapping".

New test: a 300pt behind-text and a 300pt in-front-of-text picture each leave
the row at its text height; it fails with the old condition. The existing
Square-wrap tests and cell_frame_centres_empty still pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Opus 5.5 committed 2026-10-22 08:36:05 +08:00
1 parent 25fb9b93f8
commit 29540d03c3
2 files changed
+30 -3

No files matched your search

+5 -3
View File
@@ -1178,8 +1178,10 @@ fn layout_box(
let mut excl: Vec<WrapArea> = Vec::new();
// Areas of the box's floating tables, which other floating tables may have to avoid.
let mut float_tables: Vec<Rect> = Vec::new();
// Deepest a floating picture or shape reaches, so the box (a table cell especially) grows
// to hold it instead of letting it hang past the box's own bottom edge (#3108).
// Deepest a floating picture or shape that takes part in the text flow reaches, so the box
// (a table cell especially) grows to hold it instead of letting it hang past the box's own
// bottom edge (#3108). Behind-text and in-front-of-text objects don't: a page-anchored logo or
// watermark behind a cell's text must not stretch its row (see `align_h` in table.rs).
let mut float_objects_bottom = 0.0f32;
let mut table_areas = Vec::new();
let mut page_table_wraps = Vec::new();
@@ -1287,7 +1289,7 @@ fn layout_box(
let (back, front) = place_objects(ctx, story, &path, p, &pl, (0, pl.lines.len()), (0.0, y + lead), &at, &floats, depth);
for placed in back.iter().chain(front.iter()) {
if let Placed::Object { rect, spin, wrap, .. } = placed
&& *wrap != Wrap::Inline
&& !matches!(wrap, Wrap::Inline | Wrap::BehindText | Wrap::InFrontOfText)
{
float_objects_bottom = float_objects_bottom.max(spin.bounds(*rect).bottom());
}
+25
View File
@@ -5038,6 +5038,31 @@ fn a_rotated_floating_picture_grows_the_row_by_its_rotated_extent() {
);
}
/// #3108 review: only floats that take part in the text flow grow the row. A behind-text (or
/// in-front-of-text) picture taller than the cell's text leaves the row at the text's height, as
/// in Word — a page-anchored logo or watermark behind a cell must not stretch its row.
#[test]
fn a_behind_or_in_front_of_text_picture_in_a_cell_leaves_the_row_alone() {
use wordcraft_doc::para::{Anchor, Float, Wrap};
let row_gap = |wrap: Wrap| {
let mut t = Table::new(1, 1, 468.0);
let mut cp = wordcraft_doc::Paragraph::with_text("Caption", Default::default());
let picture = Float { wrap, h_rel: Anchor::Margin, v_rel: Anchor::Margin, x: 0.0, y: 0.0, ..Default::default() };
cp.insert_object(0, rect_shape(200.0, 300.0, picture), &Default::default()).unwrap();
t.rows[0].cells[0].blocks = vec![wordcraft_doc::para_block(cp)];
let mut d = Document::from_text("Below the table");
d.insert_block(StoryRef::Body, &Path::top(0), wordcraft_doc::Block::Table(t)).unwrap();
let l = lay(&d);
let [(_, row_y, _)] = para_at(&l, &[0, 0, 0, 0])[..] else { panic!("cell text line missing") };
let [(_, below_y, _)] = para_at(&l, &[1])[..] else { panic!("line after the table missing") };
below_y - row_y
};
for wrap in [Wrap::BehindText, Wrap::InFrontOfText] {
let gap = row_gap(wrap);
assert!(gap < 60.0, "{wrap:?}: text after the table is {gap}pt below the cell's text; the 300pt picture grew the row");
}
}
#[test]
fn autofit_sizes_columns_by_their_content() {
let text = |s: &str| wordcraft_doc::para_block(wordcraft_doc::Paragraph::with_text(s, Default::default()));