use footer.range like header.range

This commit is contained in:
PgBiel 2025-06-13 01:27:33 -03:00
parent bd7e403a6d
commit 183f47ecc0
5 changed files with 28 additions and 40 deletions

View File

@ -320,11 +320,11 @@ impl<'a> GridLayouter<'a> {
if let [next_footer, other_footers @ ..] = self.upcoming_footers {
// TODO(subfooters): effective range (consider gutter before
// if it was removed)
if next_footer.range().contains(&y) {
if next_footer.range.contains(&y) {
self.upcoming_footers = other_footers;
self.place_new_footer(engine, next_footer)?;
self.flush_orphans();
y = next_footer.end;
y = next_footer.range.end;
continue;
}
@ -1719,8 +1719,7 @@ impl<'a> GridLayouter<'a> {
//
// TODO(subfooters): use effective range
// (what about the gutter?).
!footer.range().contains(&y)
|| footer.range().contains(&rowspan.y)
!footer.range.contains(&y) || footer.range.contains(&rowspan.y)
}))
&& (rowspan.y + rowspan.rowspan < y + 1
|| rowspan.y + rowspan.rowspan == y + 1 && is_last)

View File

@ -521,9 +521,9 @@ pub 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.
footer.end == grid.rows.len()
&& local_top_y.unwrap_or(0) + 1 < footer.start
&& y >= footer.start
footer.range.end == grid.rows.len()
&& local_top_y.unwrap_or(0) + 1 < footer.range.start
&& y >= footer.range.start
});
let (prioritized_cell_stroke, deprioritized_cell_stroke) =

View File

@ -493,7 +493,7 @@ impl<'a> GridLayouter<'a> {
// Placing a non-short-lived repeating footer, so it must be
// the latest one in the repeating footers vector.
let latest_repeating_footer = self.repeating_footers.pop().unwrap();
assert_eq!(latest_repeating_footer.start, footer.start);
assert_eq!(latest_repeating_footer.range.start, footer.range.start);
let expected_footer_height =
self.current.repeating_footer_heights.pop().unwrap();
@ -660,12 +660,12 @@ impl<'a> GridLayouter<'a> {
engine: &mut Engine,
disambiguator: usize,
) -> SourceResult<()> {
let footer_len = footer.end - footer.start;
let footer_len = footer.range.end - footer.range.start;
self.unbreakable_rows_left += footer_len;
// TODO(subfooters): also consider omitted gutter before the footer
// when there is a header right before it taking it.
for y in footer.start..self.grid.rows.len() {
for y in footer.range.start..self.grid.rows.len() {
self.layout_row_with_state(
y,
engine,
@ -694,8 +694,8 @@ impl<'a> GridLayouter<'a> {
// assume that the amount of unbreakable rows following the first row
// in the footer will be precisely the rows in the footer.
self.simulate_unbreakable_row_group(
footer.start,
Some(footer.end - footer.start),
footer.range.start,
Some(footer.range.end - footer.range.start),
regions,
engine,
disambiguator,

View File

@ -447,24 +447,14 @@ pub struct Header {
/// A repeatable grid footer. Stops at the last row.
#[derive(Debug, Clone)]
pub struct Footer {
/// The first row included in this footer.
pub start: usize,
/// The index after the last row included in this footer.
pub end: usize,
/// The range of rows included in this footer.
pub range: Range<usize>,
/// The footer's level.
///
/// Used similarly to header level.
pub level: u32,
}
impl Footer {
/// The footer's range of included rows.
#[inline]
pub fn range(&self) -> Range<usize> {
self.start..self.end
}
}
/// A possibly repeatable grid child (header or footer).
///
/// It still exists even when not repeatable, but must not have additional
@ -1621,14 +1611,13 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
// Only check if the footer is at the end later, once we know
// the final amount of rows.
let data = Footer {
// Later on, we have to correct this number in case there
// Later on, we have to correct this range in case there
// is gutter, but only once all cells have been analyzed
// and the header's and footer's exact boundaries are
// known. That is because the gutter row immediately
// before the footer might not be included as part of
// the footer if it is contained within the header.
start: group_range.start,
end: group_range.end,
range: group_range,
level: row_group.repeatable_level.get(),
};
@ -1818,11 +1807,11 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
// TODO: interleaved headers and footers?
let mut first_end_footer = row_amount;
for end_footer in footers.iter().rev() {
if end_footer.end != first_end_footer {
if end_footer.range.end != first_end_footer {
break;
}
first_end_footer = end_footer.start;
first_end_footer = end_footer.range.start;
}
let mut consecutive_header_start = first_end_footer;
@ -1879,14 +1868,14 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
let last_header_end = headers.last().map(|header| header.range.end);
// Convert the footer's start index to post-gutter coordinates.
footer.start *= 2;
footer.range.start *= 2;
// TODO: this probably has to change
// Include the gutter right before the footer, unless there is
// none, or the gutter is already included in the header (no
// rows between the header and the footer).
if last_header_end != Some(footer.start) {
footer.start = footer.start.saturating_sub(1);
if last_header_end != Some(footer.range.start) {
footer.range.start = footer.range.start.saturating_sub(1);
}
// Adapt footer end but DO NOT include the gutter below it,
@ -1899,7 +1888,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
//
// It also keeps us within the total amount of rows, so we
// don't need to '.min()' later.
footer.end = (2 * footer.end).saturating_sub(1);
footer.range.end = (2 * footer.range.end).saturating_sub(1);
if !at_least_one_cell {
// TODO: short-lived (and remove this?)
@ -2101,7 +2090,7 @@ fn check_for_conflicting_cell_row(
if footers
.iter()
.any(|footer| cell_y < footer.end && cell_y + rowspan > footer.start)
.any(|footer| cell_y < footer.range.end && cell_y + rowspan > footer.range.start)
{
bail!(
"cell would conflict with footer spanning the same position";
@ -2335,11 +2324,11 @@ fn find_next_available_position(
*next_header += 1;
} else if let Some(footer) = footers
.get(*next_footer)
.filter(|footer| resolved_index >= footer.start * columns)
.filter(|footer| resolved_index >= footer.range.start * columns)
{
// Skip footer, for the same reason.
if resolved_index < footer.end * columns {
resolved_index = footer.end * columns;
if resolved_index < footer.range.end * columns {
resolved_index = footer.range.end * columns;
if skip_rows {
resolved_index += initial_index % columns;

View File

@ -303,8 +303,8 @@ fn show_cellgrid_html(grid: CellGrid, styles: StyleChain) -> Content {
.iter()
.rev()
.take_while(|ft| {
let is_consecutive = ft.end == consecutive_footer_start;
consecutive_footer_start = ft.start;
let is_consecutive = ft.range.end == consecutive_footer_start;
consecutive_footer_start = ft.range.start;
is_consecutive
})
@ -313,7 +313,7 @@ fn show_cellgrid_html(grid: CellGrid, styles: StyleChain) -> Content {
if footers_at_end > 0 {
let last_mid_table_footer = grid.footers.len() - footers_at_end;
let removed_footer_rows =
grid.footers.get(last_mid_table_footer).unwrap().start;
grid.footers.get(last_mid_table_footer).unwrap().range.start;
let rows = rows.drain(removed_footer_rows..);
Some(elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row)))))