From 288f7da4d08ede7583e920cab0ac126506d92d3e Mon Sep 17 00:00:00 2001 From: PgBiel <9021226+PgBiel@users.noreply.github.com> Date: Mon, 11 Mar 2024 07:24:51 -0300 Subject: [PATCH] Small fixes for table line priority in headers/footers (#3602) --- crates/typst/src/layout/grid/layout.rs | 66 ++++++++++++++++++------- crates/typst/src/layout/grid/lines.rs | 4 +- tests/ref/layout/grid-footers-5.png | Bin 5769 -> 17228 bytes tests/ref/layout/grid-headers-4.png | Bin 36452 -> 41733 bytes tests/typ/layout/grid-footers-5.typ | 13 +++++ tests/typ/layout/grid-headers-4.typ | 41 +++++++++++++++ 6 files changed, 105 insertions(+), 19 deletions(-) diff --git a/crates/typst/src/layout/grid/layout.rs b/crates/typst/src/layout/grid/layout.rs index 354e6814d..772c107e8 100644 --- a/crates/typst/src/layout/grid/layout.rs +++ b/crates/typst/src/layout/grid/layout.rs @@ -1731,21 +1731,44 @@ impl<'a> GridLayouter<'a> { }) .unwrap_or(LinePosition::Before); + // FIXME: In the future, directly specify in 'self.rrows' when + // we place a repeated header rather than its original rows. + // That would let us remove most of those verbose checks, both + // in 'lines.rs' and here. Those checks also aren't fully + // accurate either, since they will also trigger when some rows + // have been removed between the header and what's below it. + let is_under_repeated_header = self + .grid + .header + .as_ref() + .and_then(Repeatable::as_repeated) + .zip(prev_y) + .is_some_and(|(header, prev_y)| { + // Note: 'y == header.end' would mean we're right below + // the NON-REPEATED header, so that case should return + // false. + prev_y < header.end && y > header.end + }); + // If some grid rows were omitted between the previous resolved // row and the current one, we ensure lines below the previous // row don't "disappear" and are considered, albeit with less // priority. However, don't do this when we're below a header, // as it must have more priority instead of less, so it is - // chained later instead of before. + // chained later instead of before. The exception is when the + // last row in the header is removed, in which case we append + // both the lines under the row above us and also (later) the + // lines under the header's (removed) last row. let prev_lines = prev_y .filter(|prev_y| { prev_y + 1 != y - && !self - .grid - .header - .as_ref() - .and_then(Repeatable::as_repeated) - .is_some_and(|header| prev_y + 1 == header.end) + && (!is_under_repeated_header + || self + .grid + .header + .as_ref() + .and_then(Repeatable::as_repeated) + .is_some_and(|header| prev_y + 1 != header.end)) }) .map(|prev_y| get_hlines_at(prev_y + 1)) .unwrap_or(&[]); @@ -1765,15 +1788,16 @@ impl<'a> GridLayouter<'a> { &[] }; - // The header lines, if any, will correspond to the lines under - // the previous row, so they function similarly to 'prev_lines'. - let expected_header_line_position = expected_prev_line_position; + let mut expected_header_line_position = LinePosition::Before; let header_hlines = if let Some((Repeatable::Repeated(header), prev_y)) = self.grid.header.as_ref().zip(prev_y) { - if prev_y + 1 != y - && prev_y + 1 == header.end - && !self.grid.has_gutter + if is_under_repeated_header + && (!self.grid.has_gutter + || matches!( + self.grid.rows[prev_y], + Sizing::Rel(length) if length.is_zero() + )) { // For lines below a header, give priority to the // lines originally below the header rather than @@ -1783,10 +1807,18 @@ impl<'a> GridLayouter<'a> { // lines being normally laid out then will be // precisely the lines below the header. // - // Additionally, we don't append header lines when - // gutter is enabled, since, in that case, there will - // be a gutter row between header and content, so no - // lines should overlap. + // Additionally, we don't repeat lines above the row + // below the header when gutter is enabled, since, in + // that case, there will be a gutter row between header + // and content, so no lines should overlap. The + // exception is when the gutter at the end of the + // header has a size of zero, which happens when only + // column-gutter is specified, for example. In that + // case, we still repeat the line under the gutter. + expected_header_line_position = expected_line_position( + header.end, + header.end == self.grid.rows.len(), + ); get_hlines_at(header.end) } else { &[] diff --git a/crates/typst/src/layout/grid/lines.rs b/crates/typst/src/layout/grid/lines.rs index 1249c3e95..c976da2d7 100644 --- a/crates/typst/src/layout/grid/lines.rs +++ b/crates/typst/src/layout/grid/lines.rs @@ -547,7 +547,7 @@ pub(super) fn hline_stroke_at_column( // Ensure the row above us is a repeated header. // FIXME: Make this check more robust when headers at arbitrary // positions are added. - local_top_y + 1 == header.end && y != header.end + local_top_y < header.end && y > header.end }); // Prioritize the footer's top stroke as well where applicable. @@ -559,7 +559,7 @@ pub(super) fn hline_stroke_at_column( // Ensure the row below us is a repeated footer. // FIXME: Make this check more robust when footers at arbitrary // positions are added. - local_top_y.unwrap_or(0) + 1 != footer.start && y == footer.start + local_top_y.unwrap_or(0) + 1 < footer.start && y >= footer.start }); let (prioritized_cell_stroke, deprioritized_cell_stroke) = diff --git a/tests/ref/layout/grid-footers-5.png b/tests/ref/layout/grid-footers-5.png index b58ed2669ce24914088fd7ea38d82899f59fcc62..0cfd2d66857ffc2de43e233d0880a67f06a76b62 100644 GIT binary patch literal 17228 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 literal 5769 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 diff --git a/tests/ref/layout/grid-headers-4.png b/tests/ref/layout/grid-headers-4.png index e60877d833722452eb6a7f492d32687574b47938..be6080f7414211a0fa3fd8a254bd509aa07e3698 100644 GIT binary patch delta 6307 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 delta 1396 zcmZ{kdrVVj7>7%BwaSr8tZ+&|rvYt1<=_Q@0bRLF0f7!7QUoa!TLdRnaH3Mq))wkI zhDe9hR)mSTK@}{lD$!P?7QvRAtlTLwuEMy90g=mg5MzvH$@y}U_mA((@5%FfQ>xH? zSJ4?JhFCfljY6R=)!BEWQ0X>OE6D}8dwOiZs%VeF3x_EU?pNbBVndOq8<%Sm40_=9 z8>fiT(w)1b*WVqgy-tY^2=uUhkQZi2*lH)8IYcyzD1lB zDnGa9td$GEH&se$PwkJlG6(B&#>U1HoVuEtR&XMpFlS%&_vLh`BBiCb3JVJ*5)P>` zf{?A&YPIKQ#ujE7H3KKcb@HWY_25)t;Ba4!028fB?|Iqu`|8vcs|+ggTJ6# znVC^D^xh8M{SNL3C=7&Q_^6|uU1LXwKJrXPnp!54#ShkXl`;Go3Fc`laCv8j1%*&>&;ex(Fkp5|=<*1M8R_qT)^FHp!6oj*aQZh_%PI|*kOaw8W zzx3$j=hc_D`xFH53@q3rX*gc@@T`DZO)rB8-vb+6llDUiXU-^*tH_<8cfs?KmXi4L zP}f`@X)+Q7!9Pk$i057p^(c9!wnqTYW>to|-(*|x#Pn##vr|ka#6=I;(0`7$FVR>vzu~B7#PxcZ=Me>431Drm6x}`Ww-G6Em_h(bv%Df@yfS=zM7-+sl zIcS}g**`Qy0QfkiV5`3y*2TpotG~K>f9XSJ4;tVbC|g^DopSt&f${D~@Z{gBfm*RU z_Q9F)4d&)tQe!P}??hMopU0YpwUUeGj+tqVb2H=NvX~%y@%C&rR9$b^nXvAEN(L{_ zm9XO|Ulmy%nu;(O8Xk^`ju!5X)0HvmspP-FU3Di6ftHf+xR{ub(kL$)t+%1U2npnljX;Xp+uPf%V8tFgRui=osR@sC zDH6ovXGgTK1nH+b+jeOpblr8lt<);VZ|kAeAZ`xT)!r_uiQ=m^1N?<&cTVZ)CH}mspqwO-^ zgGbBSJlJ!1Z!ibrEM zUSAUC646qSOEmfVbJdoGwFGZGqGecmWxoGj!b64<4PIG~=^a2;E6U5$&!gCl%Ki@{ CsDC5? diff --git a/tests/typ/layout/grid-footers-5.typ b/tests/typ/layout/grid-footers-5.typ index db2489fd9..874fcd2e4 100644 --- a/tests/typ/layout/grid-footers-5.typ +++ b/tests/typ/layout/grid-footers-5.typ @@ -26,3 +26,16 @@ gutter: 3pt, table.footer[a][b][c] ) + +--- +// Test footer stroke priority edge case +#set page(height: 10em) +#table( + columns: 2, + stroke: black, + ..(table.cell(stroke: aqua)[d],) * 8, + table.footer( + table.cell(rowspan: 2, colspan: 2)[a], + [c], [d] + ) +) diff --git a/tests/typ/layout/grid-headers-4.typ b/tests/typ/layout/grid-headers-4.typ index 13fd41dd1..6ede601c2 100644 --- a/tests/typ/layout/grid-headers-4.typ +++ b/tests/typ/layout/grid-headers-4.typ @@ -56,3 +56,44 @@ ), [a\ b] ) + +--- +// Test header stroke priority edge case (last header row removed) +#set page(height: 8em) +#table( + columns: 2, + stroke: black, + gutter: (auto, 3pt), + table.header( + [c], [d], + ), + ..(table.cell(stroke: aqua)[d],) * 8, +) + +--- +// Yellow line should be kept here +#set text(6pt) +#table( + column-gutter: 3pt, + inset: 1pt, + table.header( + [a], + table.hline(stroke: yellow), + ), + table.cell(rowspan: 2)[b] +) + +--- +// Red line should be kept here +#set page(height: 6em) +#set text(6pt) +#table( + column-gutter: 3pt, + inset: 1pt, + table.header( + table.hline(stroke: red, position: bottom), + [a], + ), + [a], + table.cell(stroke: aqua)[b] +)