From 1d217e4019aa865970fb18c9771d007a3615929c Mon Sep 17 00:00:00 2001 From: PgBiel <9021226+PgBiel@users.noreply.github.com> Date: Tue, 6 May 2025 03:55:34 -0300 Subject: [PATCH] allow skipping from non-repeated header on lack of space Can lead to orphans, but without enough space, anything goes. --- crates/typst-layout/src/grid/layouter.rs | 13 +++++-------- crates/typst-layout/src/grid/repeated.rs | 4 ++-- crates/typst-layout/src/grid/rowspans.rs | 11 +++++------ ...rge-non-repeating-orphan-before-relative.png | Bin 437 -> 542 bytes 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/crates/typst-layout/src/grid/layouter.rs b/crates/typst-layout/src/grid/layouter.rs index 75cf16995..8ebe59123 100644 --- a/crates/typst-layout/src/grid/layouter.rs +++ b/crates/typst-layout/src/grid/layouter.rs @@ -1376,14 +1376,13 @@ impl<'a> GridLayouter<'a> { // endlessly repeated) when subtracting header and footer height. // // See 'check_for_unbreakable_rows' as for why we're using - // 'header_height' to predict header height and not - // 'repeating_header_height'. + // 'repeating_header_height' to predict header height. let height = frame.height(); while self.unbreakable_rows_left == 0 && !self.regions.size.y.fits(height) && may_progress_with_offset( self.regions, - self.current.header_height + self.current.footer_height, + self.current.repeating_header_height + self.current.footer_height, ) { self.finish_region(engine, false)?; @@ -1571,11 +1570,9 @@ impl<'a> GridLayouter<'a> { && self.current.lrows.is_empty() && may_progress_with_offset( self.regions, - // This header height isn't doing much as we just - // confirmed that there are no headers in this region, - // but let's keep it here for correctness. It will add - // zero anyway. - self.current.header_height + self.current.footer_height, + // Don't sum header height as we just confirmed that there + // are no headers in this region. + self.current.footer_height, ); let mut laid_out_footer_start = None; diff --git a/crates/typst-layout/src/grid/repeated.rs b/crates/typst-layout/src/grid/repeated.rs index 54f5cda7c..5b2be228b 100644 --- a/crates/typst-layout/src/grid/repeated.rs +++ b/crates/typst-layout/src/grid/repeated.rs @@ -377,7 +377,7 @@ impl<'a> GridLayouter<'a> { // 'header_height == repeating_header_height' here // (there won't be any pending headers at this point, other // than the ones we are about to place). - self.current.header_height + self.current.footer_height, + self.current.repeating_header_height + self.current.footer_height, ) { // Note that, after the first region skip, the new headers will go @@ -393,7 +393,7 @@ impl<'a> GridLayouter<'a> { && self.current.lrows_orphan_snapshot.is_none() && may_progress_with_offset( self.regions, - self.current.header_height + self.current.footer_height, + self.current.repeating_header_height + self.current.footer_height, ); if should_snapshot { diff --git a/crates/typst-layout/src/grid/rowspans.rs b/crates/typst-layout/src/grid/rowspans.rs index 3ffd71518..9cbae6fe8 100644 --- a/crates/typst-layout/src/grid/rowspans.rs +++ b/crates/typst-layout/src/grid/rowspans.rs @@ -258,12 +258,11 @@ impl GridLayouter<'_> { while !self.regions.size.y.fits(row_group.height) && may_progress_with_offset( self.regions, - // Note that we consider that the exact same headers and footers will be - // added if we skip like this (blocking other rows from being laid out) - // due to orphan/widow prevention, which explains the usage of - // 'header_height' (include non-repeating but pending headers) rather - // than 'repeating_header_height'. - self.current.header_height + self.current.footer_height, + // Use 'repeating_header_height' (ignoring the height of + // non-repeated headers) to allow skipping if the + // non-repeated header is too large. It will become an + // orphan, but when there is no space left, anything goes. + self.current.repeating_header_height + self.current.footer_height, ) { self.finish_region(engine, false)?; diff --git a/tests/ref/grid-subheaders-too-large-non-repeating-orphan-before-relative.png b/tests/ref/grid-subheaders-too-large-non-repeating-orphan-before-relative.png index dfcac850083b082e6eccff867e8662f64f74244d..324787b2506342de1630d9dc2c013971d0d701d8 100644 GIT binary patch delta 530 zcmV+t0`2{^1D*ts7k{A$0{{R3JBy140002+P)t-s|Ns90002BZJo@_j{{H@>qoX7w zB>epR($dmwY;5=U_t)3gg@uKNhK7oYib+XH?Ck7-fPl!z$cc%G+1c6c?d{gq*5u^m zRaI3>OG_>;E-)}Ke0+R_goL1=po4>h*x1(SBC>3`|z=;-M7_V&BGyT-=G z!otG!_4VcDCdl;^LZ`ntpzMM@L7rw6x95&9$|)p`oFl zpPxoXM!~_s>gwvRudng(@pg80?(XheTU$y>N-r-jjg5`Y&d%N4-R9=zva+%vAt8*6 zjP&&My}iBt{eS)cK{ox_9CQEx0O?6YK~#9!?b=6j!T=CN(YA#woJfv1;hb~M#>QkJ z?tdG09Dy#ue;4>wvzbi`0Me}|i=^9;$u!{+$;`+joNa5e#93K1>en}Nh!3xB<1hoT@7k^L)0{{R3N_KX3@$vDmudh;4Qka;S z>+9>{;^KaOewUY*oSdBL>FJG)jpgO#Gcz;w_4UHS!p6qNr+=rXySuxZnwo%sfcEzG z=;-L-;o;cW*n@+E(b3UKNl7p;FnoM`+1c5NiHYp&?CtIC*4EaFii(AWg~-Ur&d$!) z*VoD_MKv2r(vS4_9D6Fu;3M;Iz!XXMPtgylgE3B}He8(Hs5Lc^x S0TxRD0000