diff --git a/crates/typst/src/layout/grid/layout.rs b/crates/typst/src/layout/grid/layout.rs index 772c107e8..20b2ddc8f 100644 --- a/crates/typst/src/layout/grid/layout.rs +++ b/crates/typst/src/layout/grid/layout.rs @@ -646,6 +646,8 @@ impl CellGrid { ResolvableGridItem::Cell(cell) => cell, }; let cell_span = cell.span(); + let colspan = cell.colspan(styles).get(); + let rowspan = cell.rowspan(styles).get(); // Let's calculate the cell's final position based on its // requested position. let resolved_index = { @@ -654,6 +656,8 @@ impl CellGrid { resolve_cell_position( cell_x, cell_y, + colspan, + rowspan, &resolved_cells, &mut auto_index, min_auto_index, @@ -663,8 +667,6 @@ impl CellGrid { }; let x = resolved_index % c; let y = resolved_index / c; - let colspan = cell.colspan(styles).get(); - let rowspan = cell.rowspan(styles).get(); if colspan > c - x { bail!( @@ -1284,9 +1286,12 @@ impl CellGrid { /// positioning. Useful with headers: if a cell in a header has automatic /// positioning, it should start at the header's first row, and not at the end /// of the previous row. +#[allow(clippy::too_many_arguments)] fn resolve_cell_position( cell_x: Smart, cell_y: Smart, + colspan: usize, + rowspan: usize, resolved_cells: &[Option], auto_index: &mut usize, min_auto_index: usize, @@ -1316,7 +1321,18 @@ fn resolve_cell_position( // Ensure the next cell with automatic position will be // placed after this one (maybe not immediately after). - *auto_index = resolved_index + 1; + // + // The calculation below also affects the position of the upcoming + // automatically-positioned lines. + *auto_index = if colspan == columns { + // The cell occupies all columns, so no cells can be placed + // after it until all of its rows have been spanned. + resolved_index + colspan * rowspan + } else { + // The next cell will have to be placed at least after its + // spanned columns. + resolved_index + colspan + }; Ok(resolved_index) } diff --git a/tests/ref/layout/grid-stroke.png b/tests/ref/layout/grid-stroke.png index 409d10f10..e9f9b0615 100644 Binary files a/tests/ref/layout/grid-stroke.png and b/tests/ref/layout/grid-stroke.png differ diff --git a/tests/typ/layout/grid-stroke.typ b/tests/typ/layout/grid-stroke.typ index 9d01e1cd1..7a01b52d6 100644 --- a/tests/typ/layout/grid-stroke.typ +++ b/tests/typ/layout/grid-stroke.typ @@ -288,6 +288,19 @@ table.hline(stroke: blue, start: 1, end: 2), ) +--- +// - Vline should be placed after the colspan. +// - Hline should be placed under the full-width rowspan. +#table( + columns: 3, + rows: 1.25em, + inset: 1pt, + stroke: none, + table.cell(colspan: 2)[a], table.vline(stroke: red), table.hline(stroke: blue), [b], + [c], [d], [e], + table.cell(colspan: 3, rowspan: 2)[a], table.vline(stroke: blue), table.hline(stroke: red) +) + --- // Error: 8:3-8:32 cannot place horizontal line at the 'bottom' position of the bottom border (y = 2) // Hint: 8:3-8:32 set the line's position to 'top' or place it at a smaller 'y' index