mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Small fixes for table line priority in headers/footers (#3602)
This commit is contained in:
parent
c29db5f27e
commit
288f7da4d0
@ -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 {
|
||||
&[]
|
||||
|
@ -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) =
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 17 KiB |
Binary file not shown.
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 41 KiB |
@ -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]
|
||||
)
|
||||
)
|
||||
|
@ -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]
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user