simplify Repeatable, keep only deref

This commit is contained in:
PgBiel 2025-06-10 02:54:07 -03:00
parent 75a4cfb2e4
commit 8cde2d4f17
3 changed files with 29 additions and 39 deletions

View File

@ -274,13 +274,14 @@ impl<'a> GridLayouter<'a> {
pub fn layout(mut self, engine: &mut Engine) -> SourceResult<Fragment> { pub fn layout(mut self, engine: &mut Engine) -> SourceResult<Fragment> {
self.measure_columns(engine)?; self.measure_columns(engine)?;
if let Some(footer) = self.grid.footer.as_ref().and_then(Repeatable::as_repeated) if let Some(footer) = &self.grid.footer {
{ if footer.repeated {
// Ensure rows in the first region will be aware of the possible // Ensure rows in the first region will be aware of the
// presence of the footer. // possible presence of the footer.
self.prepare_footer(footer, engine, 0)?; self.prepare_footer(footer, engine, 0)?;
self.regions.size.y -= self.current.footer_height; self.regions.size.y -= self.current.footer_height;
self.current.initial_after_repeats = self.regions.size.y; self.current.initial_after_repeats = self.regions.size.y;
}
} }
let mut y = 0; let mut y = 0;
@ -297,10 +298,8 @@ impl<'a> GridLayouter<'a> {
} }
} }
if let Some(footer) = if let Some(footer) = &self.grid.footer {
self.grid.footer.as_ref().and_then(Repeatable::as_repeated) if footer.repeated && y >= footer.start {
{
if y >= footer.start {
if y == footer.start { if y == footer.start {
self.layout_footer(footer, engine, self.finished.len())?; self.layout_footer(footer, engine, self.finished.len())?;
self.flush_orphans(); self.flush_orphans();
@ -1573,9 +1572,7 @@ impl<'a> GridLayouter<'a> {
let mut laid_out_footer_start = None; let mut laid_out_footer_start = None;
if !footer_would_be_widow { if !footer_would_be_widow {
if let Some(footer) = if let Some(footer) = &self.grid.footer {
self.grid.footer.as_ref().and_then(Repeatable::as_repeated)
{
// Don't layout the footer if it would be alone with the header // Don't layout the footer if it would be alone with the header
// in the page (hence the widow check), and don't layout it // in the page (hence the widow check), and don't layout it
// twice (check below). // twice (check below).
@ -1583,7 +1580,9 @@ impl<'a> GridLayouter<'a> {
// TODO(subfooters): this check can be replaced by a vector of // TODO(subfooters): this check can be replaced by a vector of
// repeating footers in the future, and/or some "pending // repeating footers in the future, and/or some "pending
// footers" vector for footers we're about to place. // footers" vector for footers we're about to place.
if self.current.lrows.iter().all(|row| row.index() < footer.start) { if footer.repeated
&& self.current.lrows.iter().all(|row| row.index() < footer.start)
{
laid_out_footer_start = Some(footer.start); laid_out_footer_start = Some(footer.start);
self.layout_footer(footer, engine, self.finished.len())?; self.layout_footer(footer, engine, self.finished.len())?;
} }

View File

@ -1,3 +1,5 @@
use std::ops::Deref;
use typst_library::diag::SourceResult; use typst_library::diag::SourceResult;
use typst_library::engine::Engine; use typst_library::engine::Engine;
use typst_library::layout::grid::resolve::{Footer, Header, Repeatable}; use typst_library::layout::grid::resolve::{Footer, Header, Repeatable};
@ -205,7 +207,7 @@ impl<'a> GridLayouter<'a> {
self.repeating_headers self.repeating_headers
.iter() .iter()
.copied() .copied()
.chain(self.pending_headers.iter().map(Repeatable::unwrap)), .chain(self.pending_headers.iter().map(Repeatable::deref)),
&self.regions, &self.regions,
engine, engine,
disambiguator, disambiguator,
@ -254,7 +256,7 @@ impl<'a> GridLayouter<'a> {
total_header_row_count(self.repeating_headers.iter().copied()); total_header_row_count(self.repeating_headers.iter().copied());
let pending_header_rows = let pending_header_rows =
total_header_row_count(self.pending_headers.iter().map(Repeatable::unwrap)); total_header_row_count(self.pending_headers.iter().map(Repeatable::deref));
// Group of headers is unbreakable. // Group of headers is unbreakable.
// Thus, no risk of 'finish_region' being recursively called from // Thus, no risk of 'finish_region' being recursively called from
@ -326,7 +328,7 @@ impl<'a> GridLayouter<'a> {
has_non_repeated_pending_header = true; has_non_repeated_pending_header = true;
} }
let header_height = let header_height =
self.layout_header_rows(header.unwrap(), engine, disambiguator, false)?; self.layout_header_rows(header, engine, disambiguator, false)?;
if header.repeated { if header.repeated {
self.current.repeating_header_height += header_height; self.current.repeating_header_height += header_height;
self.current.repeating_header_heights.push(header_height); self.current.repeating_header_heights.push(header_height);
@ -364,7 +366,7 @@ impl<'a> GridLayouter<'a> {
// for upcoming regions, we will have to consider repeating headers as // for upcoming regions, we will have to consider repeating headers as
// well. // well.
let header_height = self.simulate_header_height( let header_height = self.simulate_header_height(
headers.iter().map(Repeatable::unwrap), headers.iter().map(Repeatable::deref),
&self.regions, &self.regions,
engine, engine,
0, 0,
@ -398,11 +400,10 @@ impl<'a> GridLayouter<'a> {
let mut at_top = self.regions.size.y == self.current.initial_after_repeats; let mut at_top = self.regions.size.y == self.current.initial_after_repeats;
self.unbreakable_rows_left += self.unbreakable_rows_left +=
total_header_row_count(headers.iter().map(Repeatable::unwrap)); total_header_row_count(headers.iter().map(Repeatable::deref));
for header in headers { for header in headers {
let header_height = let header_height = self.layout_header_rows(header, engine, 0, false)?;
self.layout_header_rows(header.unwrap(), engine, 0, false)?;
// Only store this header height if it is actually going to // Only store this header height if it is actually going to
// become a pending header. Otherwise, pretend it's not a // become a pending header. Otherwise, pretend it's not a

View File

@ -1,5 +1,5 @@
use std::num::{NonZeroU32, NonZeroUsize}; use std::num::{NonZeroU32, NonZeroUsize};
use std::ops::{Deref, Range}; use std::ops::{Deref, DerefMut, Range};
use std::sync::Arc; use std::sync::Arc;
use ecow::eco_format; use ecow::eco_format;
@ -485,21 +485,13 @@ impl<T> Deref for Repeatable<T> {
} }
} }
impl<T> Repeatable<T> { impl<T> DerefMut for Repeatable<T> {
/// Gets the value inside this repeatable, regardless of whether fn deref_mut(&mut self) -> &mut Self::Target {
/// it repeats.
#[inline]
pub fn unwrap(&self) -> &T {
&self.inner
}
/// Gets the value inside this repeatable, regardless of whether
/// it repeats (mutably).
#[inline]
pub fn unwrap_mut(&mut self) -> &mut T {
&mut self.inner &mut self.inner
} }
}
impl<T> Repeatable<T> {
/// Returns `Some` if the value is repeated, `None` otherwise. /// Returns `Some` if the value is repeated, `None` otherwise.
#[inline] #[inline]
pub fn as_repeated(&self) -> Option<&T> { pub fn as_repeated(&self) -> Option<&T> {
@ -1606,7 +1598,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
conflicts conflicts
}) })
{ {
conflicting_header.unwrap_mut().short_lived = true; conflicting_header.short_lived = true;
} }
headers.push(Repeatable { inner: data, repeated: row_group.repeat }); headers.push(Repeatable { inner: data, repeated: row_group.repeat });
@ -1825,7 +1817,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
consecutive_header_start = h.range.start; consecutive_header_start = h.range.start;
at_the_end at_the_end
}) { }) {
header_at_the_end.unwrap_mut().short_lived = true; header_at_the_end.short_lived = true;
} }
// Repeat the gutter below a header (hence why we don't // Repeat the gutter below a header (hence why we don't
@ -1833,8 +1825,6 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
// Don't do this if there are no rows under the header. // Don't do this if there are no rows under the header.
if has_gutter { if has_gutter {
for header in &mut *headers { for header in &mut *headers {
let header = header.unwrap_mut();
// Index of first y is doubled, as each row before it // Index of first y is doubled, as each row before it
// receives a gutter row below. // receives a gutter row below.
header.range.start *= 2; header.range.start *= 2;