mirror of
https://github.com/typst/typst
synced 2025-07-16 00:52:54 +08:00
use footer.range like header.range
This commit is contained in:
parent
bd7e403a6d
commit
183f47ecc0
@ -320,11 +320,11 @@ impl<'a> GridLayouter<'a> {
|
|||||||
if let [next_footer, other_footers @ ..] = self.upcoming_footers {
|
if let [next_footer, other_footers @ ..] = self.upcoming_footers {
|
||||||
// TODO(subfooters): effective range (consider gutter before
|
// TODO(subfooters): effective range (consider gutter before
|
||||||
// if it was removed)
|
// if it was removed)
|
||||||
if next_footer.range().contains(&y) {
|
if next_footer.range.contains(&y) {
|
||||||
self.upcoming_footers = other_footers;
|
self.upcoming_footers = other_footers;
|
||||||
self.place_new_footer(engine, next_footer)?;
|
self.place_new_footer(engine, next_footer)?;
|
||||||
self.flush_orphans();
|
self.flush_orphans();
|
||||||
y = next_footer.end;
|
y = next_footer.range.end;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1719,8 +1719,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
//
|
//
|
||||||
// TODO(subfooters): use effective range
|
// TODO(subfooters): use effective range
|
||||||
// (what about the gutter?).
|
// (what about the gutter?).
|
||||||
!footer.range().contains(&y)
|
!footer.range.contains(&y) || footer.range.contains(&rowspan.y)
|
||||||
|| footer.range().contains(&rowspan.y)
|
|
||||||
}))
|
}))
|
||||||
&& (rowspan.y + rowspan.rowspan < y + 1
|
&& (rowspan.y + rowspan.rowspan < y + 1
|
||||||
|| rowspan.y + rowspan.rowspan == y + 1 && is_last)
|
|| rowspan.y + rowspan.rowspan == y + 1 && is_last)
|
||||||
|
@ -521,9 +521,9 @@ pub fn hline_stroke_at_column(
|
|||||||
// Ensure the row below us is a repeated footer.
|
// Ensure the row below us is a repeated footer.
|
||||||
// FIXME: Make this check more robust when footers at arbitrary
|
// FIXME: Make this check more robust when footers at arbitrary
|
||||||
// positions are added.
|
// positions are added.
|
||||||
footer.end == grid.rows.len()
|
footer.range.end == grid.rows.len()
|
||||||
&& local_top_y.unwrap_or(0) + 1 < footer.start
|
&& local_top_y.unwrap_or(0) + 1 < footer.range.start
|
||||||
&& y >= footer.start
|
&& y >= footer.range.start
|
||||||
});
|
});
|
||||||
|
|
||||||
let (prioritized_cell_stroke, deprioritized_cell_stroke) =
|
let (prioritized_cell_stroke, deprioritized_cell_stroke) =
|
||||||
|
@ -493,7 +493,7 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// Placing a non-short-lived repeating footer, so it must be
|
// Placing a non-short-lived repeating footer, so it must be
|
||||||
// the latest one in the repeating footers vector.
|
// the latest one in the repeating footers vector.
|
||||||
let latest_repeating_footer = self.repeating_footers.pop().unwrap();
|
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 =
|
let expected_footer_height =
|
||||||
self.current.repeating_footer_heights.pop().unwrap();
|
self.current.repeating_footer_heights.pop().unwrap();
|
||||||
@ -660,12 +660,12 @@ impl<'a> GridLayouter<'a> {
|
|||||||
engine: &mut Engine,
|
engine: &mut Engine,
|
||||||
disambiguator: usize,
|
disambiguator: usize,
|
||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
let footer_len = footer.end - footer.start;
|
let footer_len = footer.range.end - footer.range.start;
|
||||||
self.unbreakable_rows_left += footer_len;
|
self.unbreakable_rows_left += footer_len;
|
||||||
|
|
||||||
// TODO(subfooters): also consider omitted gutter before the footer
|
// TODO(subfooters): also consider omitted gutter before the footer
|
||||||
// when there is a header right before it taking it.
|
// 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(
|
self.layout_row_with_state(
|
||||||
y,
|
y,
|
||||||
engine,
|
engine,
|
||||||
@ -694,8 +694,8 @@ impl<'a> GridLayouter<'a> {
|
|||||||
// assume that the amount of unbreakable rows following the first row
|
// assume that the amount of unbreakable rows following the first row
|
||||||
// in the footer will be precisely the rows in the footer.
|
// in the footer will be precisely the rows in the footer.
|
||||||
self.simulate_unbreakable_row_group(
|
self.simulate_unbreakable_row_group(
|
||||||
footer.start,
|
footer.range.start,
|
||||||
Some(footer.end - footer.start),
|
Some(footer.range.end - footer.range.start),
|
||||||
regions,
|
regions,
|
||||||
engine,
|
engine,
|
||||||
disambiguator,
|
disambiguator,
|
||||||
|
@ -447,24 +447,14 @@ pub struct Header {
|
|||||||
/// A repeatable grid footer. Stops at the last row.
|
/// A repeatable grid footer. Stops at the last row.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Footer {
|
pub struct Footer {
|
||||||
/// The first row included in this footer.
|
/// The range of rows included in this footer.
|
||||||
pub start: usize,
|
pub range: Range<usize>,
|
||||||
/// The index after the last row included in this footer.
|
|
||||||
pub end: usize,
|
|
||||||
/// The footer's level.
|
/// The footer's level.
|
||||||
///
|
///
|
||||||
/// Used similarly to header level.
|
/// Used similarly to header level.
|
||||||
pub level: u32,
|
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).
|
/// A possibly repeatable grid child (header or footer).
|
||||||
///
|
///
|
||||||
/// It still exists even when not repeatable, but must not have additional
|
/// 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
|
// Only check if the footer is at the end later, once we know
|
||||||
// the final amount of rows.
|
// the final amount of rows.
|
||||||
let data = Footer {
|
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
|
// is gutter, but only once all cells have been analyzed
|
||||||
// and the header's and footer's exact boundaries are
|
// and the header's and footer's exact boundaries are
|
||||||
// known. That is because the gutter row immediately
|
// known. That is because the gutter row immediately
|
||||||
// before the footer might not be included as part of
|
// before the footer might not be included as part of
|
||||||
// the footer if it is contained within the header.
|
// the footer if it is contained within the header.
|
||||||
start: group_range.start,
|
range: group_range,
|
||||||
end: group_range.end,
|
|
||||||
level: row_group.repeatable_level.get(),
|
level: row_group.repeatable_level.get(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1818,11 +1807,11 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
|
|||||||
// TODO: interleaved headers and footers?
|
// TODO: interleaved headers and footers?
|
||||||
let mut first_end_footer = row_amount;
|
let mut first_end_footer = row_amount;
|
||||||
for end_footer in footers.iter().rev() {
|
for end_footer in footers.iter().rev() {
|
||||||
if end_footer.end != first_end_footer {
|
if end_footer.range.end != first_end_footer {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
first_end_footer = end_footer.start;
|
first_end_footer = end_footer.range.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut consecutive_header_start = first_end_footer;
|
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);
|
let last_header_end = headers.last().map(|header| header.range.end);
|
||||||
|
|
||||||
// Convert the footer's start index to post-gutter coordinates.
|
// Convert the footer's start index to post-gutter coordinates.
|
||||||
footer.start *= 2;
|
footer.range.start *= 2;
|
||||||
|
|
||||||
// TODO: this probably has to change
|
// TODO: this probably has to change
|
||||||
// Include the gutter right before the footer, unless there is
|
// Include the gutter right before the footer, unless there is
|
||||||
// none, or the gutter is already included in the header (no
|
// none, or the gutter is already included in the header (no
|
||||||
// rows between the header and the footer).
|
// rows between the header and the footer).
|
||||||
if last_header_end != Some(footer.start) {
|
if last_header_end != Some(footer.range.start) {
|
||||||
footer.start = footer.start.saturating_sub(1);
|
footer.range.start = footer.range.start.saturating_sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adapt footer end but DO NOT include the gutter below it,
|
// 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
|
// It also keeps us within the total amount of rows, so we
|
||||||
// don't need to '.min()' later.
|
// 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 {
|
if !at_least_one_cell {
|
||||||
// TODO: short-lived (and remove this?)
|
// TODO: short-lived (and remove this?)
|
||||||
@ -2101,7 +2090,7 @@ fn check_for_conflicting_cell_row(
|
|||||||
|
|
||||||
if footers
|
if footers
|
||||||
.iter()
|
.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!(
|
bail!(
|
||||||
"cell would conflict with footer spanning the same position";
|
"cell would conflict with footer spanning the same position";
|
||||||
@ -2335,11 +2324,11 @@ fn find_next_available_position(
|
|||||||
*next_header += 1;
|
*next_header += 1;
|
||||||
} else if let Some(footer) = footers
|
} else if let Some(footer) = footers
|
||||||
.get(*next_footer)
|
.get(*next_footer)
|
||||||
.filter(|footer| resolved_index >= footer.start * columns)
|
.filter(|footer| resolved_index >= footer.range.start * columns)
|
||||||
{
|
{
|
||||||
// Skip footer, for the same reason.
|
// Skip footer, for the same reason.
|
||||||
if resolved_index < footer.end * columns {
|
if resolved_index < footer.range.end * columns {
|
||||||
resolved_index = footer.end * columns;
|
resolved_index = footer.range.end * columns;
|
||||||
|
|
||||||
if skip_rows {
|
if skip_rows {
|
||||||
resolved_index += initial_index % columns;
|
resolved_index += initial_index % columns;
|
||||||
|
@ -303,8 +303,8 @@ fn show_cellgrid_html(grid: CellGrid, styles: StyleChain) -> Content {
|
|||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.take_while(|ft| {
|
.take_while(|ft| {
|
||||||
let is_consecutive = ft.end == consecutive_footer_start;
|
let is_consecutive = ft.range.end == consecutive_footer_start;
|
||||||
consecutive_footer_start = ft.start;
|
consecutive_footer_start = ft.range.start;
|
||||||
|
|
||||||
is_consecutive
|
is_consecutive
|
||||||
})
|
})
|
||||||
@ -313,7 +313,7 @@ fn show_cellgrid_html(grid: CellGrid, styles: StyleChain) -> Content {
|
|||||||
if footers_at_end > 0 {
|
if footers_at_end > 0 {
|
||||||
let last_mid_table_footer = grid.footers.len() - footers_at_end;
|
let last_mid_table_footer = grid.footers.len() - footers_at_end;
|
||||||
let removed_footer_rows =
|
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..);
|
let rows = rows.drain(removed_footer_rows..);
|
||||||
|
|
||||||
Some(elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row)))))
|
Some(elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row)))))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user