Layout: align behind-text cell pictures (#1871) (#1871)

Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
Fin WarmanandBrandon Thomas authored and GitHub committed 2026-10-18 09:56:19 -04:00
1 parent d4a3292834
commit 4dcd4749ca
3 files changed
+51 -2

No files matched your search

+12 -2
View File
@@ -673,10 +673,20 @@ pub fn layout_table(ctx: &mut Ctx, story: StoryRef, t: &Table, path: &[u32], ava
{
items.push(Placed::Fill { rect, color: f });
}
// Behind-text frames count towards vertical alignment even without inline content.
// They do not increase the row's flow height.
let align_h = c
.items
.iter()
.filter_map(|item| match item {
Placed::Object { rect, wrap: wordcraft_doc::para::Wrap::BehindText, .. } => Some(rect.bottom()),
_ => None,
})
.fold(c.h, f32::max);
let mut dy = match c.valign {
VAlign::Top => 0.0,
VAlign::Center => ((span_h - c.h) / 2.0).max(0.0),
VAlign::Bottom => (span_h - c.h).max(0.0),
VAlign::Center => ((span_h - align_h) / 2.0).max(0.0),
VAlign::Bottom => (span_h - align_h).max(0.0),
};
let end = (c.vmerge != VMerge::Continue && c.turned.is_none()).then_some(c.end + dy);
let mut cell_items = c.items;
+35
View File
@@ -7803,3 +7803,38 @@ fn kept_prefix_stays_together() {
t.rows.insert(1, middle);
assert_eq!(row_keep_pages(&d), [1, 1, 2], "an oversized follower cannot separate an already placed kept prefix");
}
/// Word and Adobe: a behind-text frame participates in a cell's vertical alignment,
/// even when its anchor paragraph has no inline picture (synthetic two-cell probe).
#[test]
fn cell_frame_centres_empty() {
use wordcraft_doc::para::{Anchor, Float, Wrap};
use wordcraft_doc::props::{HeightRule, VAlign};
let mut d = Document::new();
let mut t = Table::new(1, 2, 468.0);
t.rows[0].props.height = Some(182.5);
t.rows[0].props.height_rule = HeightRule::Exact;
for (ci, cell) in t.rows[0].cells.iter_mut().enumerate() {
cell.props.valign = Some(VAlign::Center);
cell.props.margins = Some([0.0; 4]);
let mut p = wordcraft_doc::Paragraph::with_text("", Default::default());
p.props.space_before = Some(0.0);
p.props.space_after = Some(0.0);
let float = Float { wrap: Wrap::BehindText, h_rel: Anchor::Column, v_rel: Anchor::Paragraph, y: -12.75, ..Default::default() };
p.insert_object(0, picture(231.0, 180.75, float), &Default::default()).unwrap();
if ci == 0 {
p.insert_object(p.text.len(), picture(207.0, 155.25, Default::default()), &Default::default()).unwrap();
}
cell.blocks = vec![wordcraft_doc::para_block(p)];
}
d.insert_block(StoryRef::Body, &Path::top(0), wordcraft_doc::Block::Table(t)).unwrap();
let l = lay(&d);
let frames: Vec<_> = l.pages[0]
.items
.iter()
.filter_map(|item| if let Placed::Object { rect, wrap: Wrap::BehindText, .. } = item { Some(rect) } else { None })
.collect();
assert_eq!(frames.len(), 2);
assert!((frames[0].y - frames[1].y).abs() < 0.01, "frames must align: {frames:?}");
assert!((frames[0].y - 66.5).abs() < 0.5, "Word frame top: {frames:?}");
}
+4
View File
@@ -182,6 +182,9 @@ and save, in raster output and in PDF. Synthetic controls cover red rectangles,
connectors. Custom lists are capped at 64 pairs; painted spans are bounded to 0.01–20000 pt.
Theme-inherited dash styles, line caps, ink and open freeform strokes are not covered by this change.
When content exceeds a preferred column width, AutoFit donors lose equal widths until they reach their content minima. Original synthetic Word probes cover donor reductions; cached field refresh and wrapping remain separate gaps.
Behind-text pictures in table cells participate in centre and bottom vertical alignment without increasing row flow height.
## Revision history
| Date | Change | Summary |
@@ -201,6 +204,7 @@ When content exceeds a preferred column width, AutoFit donors lose equal widths
| 2026-10-16 | trivial | Hint-reliant CJK fonts execute TrueType contour assembly; Windows DFKai-SB no longer loses strokes. Synthetic local-font regression; no font binaries bundled. |
| 2026-10-16 | trivial | `w:autoSpaceDE` and `w:autoSpaceDN` are laid out: a quarter em between Asian text and Latin text or digits (#2358) |
| 2026-10-16 | trivial | AutoFit donors lose equal widths, bounded by content minima |
| 2026-10-16 | trivial | Behind-text pictures in table cells participate in centre and bottom vertical alignment without increasing row flow height. |
| 2026-10-14 | trivial | Row table border exceptions draw without leaking into other rows |
| 2026-10-14 | trivial | Consistent cell widths override a stale table grid |
| 2026-10-14 | trivial | Paragraphs inside complex-field instructions take no flow height; empty result paragraphs keep their line. |