From daa5f9e9f5dc2bd3816ce46bb68f1ac5844ed933 Mon Sep 17 00:00:00 2001 From: PgBiel <9021226+PgBiel@users.noreply.github.com> Date: Thu, 15 May 2025 20:34:23 -0300 Subject: [PATCH] pending repeating headers at the top are also "repeats" For "may_progress" purposes. This avoids an unnecessary additional region break due to them being considered as "non-repeating" before. --- crates/typst-layout/src/grid/layouter.rs | 8 ++++++-- crates/typst-layout/src/grid/repeated.rs | 16 ++++++++++++++++ .../grid-header-and-rowspan-contiguous-2.png | Bin 869 -> 815 bytes ...o-large-repeating-orphan-before-relative.png | Bin 491 -> 437 bytes 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/crates/typst-layout/src/grid/layouter.rs b/crates/typst-layout/src/grid/layouter.rs index 9db5657a4..5b35ca8fe 100644 --- a/crates/typst-layout/src/grid/layouter.rs +++ b/crates/typst-layout/src/grid/layouter.rs @@ -76,10 +76,14 @@ pub(super) struct Current { /// The initial size of the current region before we started subtracting. pub(super) initial: Size, /// The height of the region after repeated headers were placed and footers - /// prepared. + /// prepared. This also includes pending repeating headers from the start, + /// even if they were not repeated yet, since they will be repeated in the + /// next region anyway (bar orphan prevention). /// /// This is used to quickly tell if any additional space in the region has - /// been occupied since then. + /// been occupied since then, meaning that additional space will become + /// available after a region break (see + /// [`GridLayouter::may_progress_with_repeats`]). pub(super) initial_after_repeats: Abs, /// Whether `layouter.regions.may_progress()` was `true` at the top of the /// region. diff --git a/crates/typst-layout/src/grid/repeated.rs b/crates/typst-layout/src/grid/repeated.rs index 81ac48d1a..fbfa5dbc6 100644 --- a/crates/typst-layout/src/grid/repeated.rs +++ b/crates/typst-layout/src/grid/repeated.rs @@ -329,7 +329,12 @@ impl<'a> GridLayouter<'a> { self.current.repeated_header_rows = self.current.lrows.len(); self.current.initial_after_repeats = self.regions.size.y; + let mut has_non_repeated_pending_header = false; for header in self.pending_headers { + if matches!(header, Repeatable::NotRepeated(_)) { + self.current.initial_after_repeats = self.regions.size.y; + has_non_repeated_pending_header = true; + } let header_height = self.layout_header_rows(header.unwrap(), engine, disambiguator, false)?; if matches!(header, Repeatable::Repeated(_)) { @@ -338,6 +343,10 @@ impl<'a> GridLayouter<'a> { } } + if !has_non_repeated_pending_header { + self.current.initial_after_repeats = self.regions.size.y; + } + if !may_progress { // Flush pending headers immediately, as placing them again later // won't help. @@ -396,6 +405,8 @@ impl<'a> GridLayouter<'a> { self.current.lrows_orphan_snapshot = Some(self.current.lrows.len()); } + let mut at_top = self.regions.size.y == self.current.initial_after_repeats; + self.unbreakable_rows_left += total_header_row_count(headers.iter().map(Repeatable::unwrap)); @@ -412,6 +423,11 @@ impl<'a> GridLayouter<'a> { if !short_lived && matches!(header, Repeatable::Repeated(_)) { self.current.repeating_header_height += header_height; self.current.repeating_header_heights.push(header_height); + if at_top { + self.current.initial_after_repeats = self.regions.size.y; + } + } else { + at_top = false; } } diff --git a/tests/ref/grid-header-and-rowspan-contiguous-2.png b/tests/ref/grid-header-and-rowspan-contiguous-2.png index 555b952b3732b78af1caa91c494f7923ad893265..29bc411d1cbf611682cb463daed918d201d3b788 100644 GIT binary patch delta 706 zcmaFLww`T*7&qe)4rT@hhNDO2q9!UT*C!+-OqehsK0cnEoqgZFeYLfPEJNf#>I;lH#Rm#Mn?Yo_wV4rgFQVx z&z?QIbLWn?w|8)G@YSnV)6&vr%$Ok~BNH7R-QVBO#l=-vSeTTQbmq*NEnBvfl$3aR zc}dqxOaJ}*S4Bl7KR-V!D@#mFtgEYwjg4*1nl&seETyHT;^N|8zkYRfbY(LnajKjzu!~*BFFAAr}O>)D2Go) zn;b7%3TvK!J=eTHUzFsrI$8JX@x?V!wSSHF)z}Iz zPJFlj@@nyqX~{BwPw>XiySJzG@vp7gHy?VJzq?nr=iig8G7Gso`t$6orG7qi=T|

od-iNTKE9VPUphNG$H&J{m@pwBA%UHpy|%X2!NEaKPtVoW_3PKKYu2n`V`Iz9 z%M%wD|M&0T!Gj0Ay}keb{VOdk?d9bqCMK4Zm6e~LucD%ol$3Pl%o#2&uEN4X85x=2 z;NUG=wnRrq&zLbIEiJ95r{~U{J0&G0&z?Q&@9&R{jJ$gFYH4Yyva&J@3rkm5S7T%2 z;>C+OIXN$1zWn&{V_sffMn=XjU%te~#tI1u#l*x!L`1Z=w}1Qgjfsh=s;cV5i4#kg zE@fq9b#Za|`0?Y57cW#*Rm;oE_wC!q!^2ZiQBhM<EaktaqI1!lX;f|B-$R{H)Am}oLV_AUE{OJvn`qzmiXSe^M7l@kxP*cw~B*So}V3S z)}L~+JNah3$EA0#x2)c@>XiNdl2Yr7YpQE1o_(n(e(o}JUGm$Eu&Mg<-1kV%=_v_) zddS|~e(n1Gay9Wxe@cxarS+KQ+e>0hN*6dZ)>d@=?&tI-e z-`M}_=W3686P0HDt=M@f`|S2-Yva~WeG??#n|Afq)72mU9X|fTzv#YS_`0L3djq#9 zo7d!hcyn;>=YF}g_Vf4lmH&Tt>aqIGhdW9)?HkV~=Jkmw2*<))4>4;4#0O_yLwtbh(tq_8rtEv9&bs|QeDZbwo-7?` ecm%l|$#)88Sd_k4vjv!J7(8A5T-G@yGywqrvy5{9 diff --git a/tests/ref/grid-subheaders-too-large-repeating-orphan-before-relative.png b/tests/ref/grid-subheaders-too-large-repeating-orphan-before-relative.png index 9688c438792a9d9fb2f2500ec25063561ae8d1b0..dfcac850083b082e6eccff867e8662f64f74244d 100644 GIT binary patch delta 424 zcmV;Z0ayO(1GNK?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 S0TxRD0000qobpShKA71OL>+9>FprDG1itOy{?d|Q>*4Dwn!A3?#TYpLr<$6YySuyg_V(!L=;7hv*x1;E zgM-o0(ZY3U zWN~wQcQ1$N{o_Fn)xl>>4z=Xh>x&HHiTGQ{rv&y}_$-Ux}~r@&Fi; zF(f0*kc=T2Lo$YB02q=nBx6X%kc=T2L$b}BtPv(mm@r|&gb5QSOqeiX!T`2o1@Wpi Uuj-tkGXMYp07*qoM6N<$g5n