From 199bb7c56d91b7c7f7260f6f008c5ab75fd8c8a4 Mon Sep 17 00:00:00 2001 From: PgBiel <9021226+PgBiel@users.noreply.github.com> Date: Sun, 16 Feb 2025 20:09:47 -0300 Subject: [PATCH] skip headers and footers in cells with 'x: ' --- .../typst-library/src/layout/grid/resolve.rs | 45 +++++++++++++++--- tests/ref/grid-header-cell-with-x.png | Bin 0 -> 419 bytes tests/suite/layout/grid/footers.typ | 12 +++++ tests/suite/layout/grid/headers.typ | 11 +++++ 4 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 tests/ref/grid-header-cell-with-x.png diff --git a/crates/typst-library/src/layout/grid/resolve.rs b/crates/typst-library/src/layout/grid/resolve.rs index d79f0ae45..c813197c1 100644 --- a/crates/typst-library/src/layout/grid/resolve.rs +++ b/crates/typst-library/src/layout/grid/resolve.rs @@ -1738,13 +1738,44 @@ fn resolve_cell_position( // 'first_available_row'). Otherwise, start searching at the // first row. let mut resolved_y = first_available_row; - while let Some(Some(_)) = - resolved_cells.get(cell_index(cell_x, resolved_y)?) - { - // Try each row until either we reach an absent position - // (`Some(None)`) or an out of bounds position (`None`), - // in which case we'd create a new row to place this cell in. - resolved_y += 1; + if header.is_some() || footer.is_some() { + // There are row groups, so we have to not only skip + // rows where the requested column is occupied to find the + // first suitable row, but also skip rows belonging to + // headers or footers. + loop { + if let Some(Some(_)) = + resolved_cells.get(cell_index(cell_x, resolved_y)?) + { + // Try each row until either we reach an absent position + // (`Some(None)`) or an out of bounds position (`None`), + // in which case we'd create a new row to place this cell in. + resolved_y += 1; + } else if let Some(header) = + header.filter(|header| resolved_y < header.end) + { + // Skip header + resolved_y = header.end; + } else if let Some((footer_end, _, _)) = + footer.filter(|(end, _, footer)| { + resolved_y >= footer.start && resolved_y < *end + }) + { + // Skip footer + resolved_y = *footer_end; + } else { + break; + } + } + } else { + // No row groups to skip, so only skip a row if the + // requested column is occupied, and find the first row + // where it isn't. + while let Some(Some(_)) = + resolved_cells.get(cell_index(cell_x, resolved_y)?) + { + resolved_y += 1; + } } cell_index(cell_x, resolved_y) } diff --git a/tests/ref/grid-header-cell-with-x.png b/tests/ref/grid-header-cell-with-x.png new file mode 100644 index 0000000000000000000000000000000000000000..659826250b2c258fd7bf7dc9ab843fb84954035b GIT binary patch literal 419 zcmV;U0bKrxP)+Gt{NLp`Rf$ZKR?%;Hgt zsc7-JQv+o2j9d`;Z$I5FK9LV3zBd`t-(ruc&42#?x1qnq8UHIb4~WJ2{}=TRh{ZYo zv+n%=u0?l?Z?sN5^#A|N+})!k*QmwRv)GkO1OqS$Bl9?NX<~78>1zxid;^&mI&Ur?ZyB9PeTTvKAztH|7-Eb0kC+& zs(&?~@BX8+#mAfurT$nH(Be;TAAfpt>EHjC*Kgb%ExCrF#aSUMFaY0dWS(t5O)L)6 z3C95J0mwXs+R->3wRqHG3N8LPd&9?edp z7E@rcznl#QV6{NziIvgB;^S)$V}O|lka^3ljn2Z1T0Cm;sKtZ9VgN}LaL>$~n<)SQ N002ovPDHLkV1mqg%XI(% literal 0 HcmV?d00001 diff --git a/tests/suite/layout/grid/footers.typ b/tests/suite/layout/grid/footers.typ index 422387a62..df7b519ec 100644 --- a/tests/suite/layout/grid/footers.typ +++ b/tests/suite/layout/grid/footers.typ @@ -83,6 +83,18 @@ grid.cell(y: 1)[c], ) +--- grid-footer-cell-with-x --- +#grid( + columns: 2, + stroke: black, + inset: 5pt, + grid.cell(x: 1)[a], + // Error: 3-56 footer must end at the last row + grid.footer(grid.cell(x: 0)[b1], grid.cell(x: 0)[b2]), + // This should skip the footer + grid.cell(x: 1)[c] +) + --- grid-footer-expand --- // Ensure footer properly expands #grid( diff --git a/tests/suite/layout/grid/headers.typ b/tests/suite/layout/grid/headers.typ index 984197174..28f51a214 100644 --- a/tests/suite/layout/grid/headers.typ +++ b/tests/suite/layout/grid/headers.typ @@ -60,6 +60,17 @@ grid.cell(y: 2)[c] ) +--- grid-header-cell-with-x --- +#grid( + columns: 2, + stroke: black, + inset: 5pt, + // grid.cell(x: 1)[a], + grid.header(grid.cell(x: 0)[b1], grid.cell(x: 0)[b2]), + // This should skip the header + grid.cell(x: 1)[c] +) + --- grid-header-last-child --- // When the header is the last grid child, it shouldn't include the gutter row // after it, because there is none.