From fc5858c98256b32eca798a0df1bf96f426416bd2 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 8 Oct 2024 15:13:14 +0200 Subject: [PATCH] Allow sticky blocks to be breakable (#5161) --- crates/typst/src/layout/container.rs | 2 -- crates/typst/src/layout/flow/collect.rs | 4 +++- crates/typst/src/layout/flow/distribute.rs | 8 ++++---- tests/ref/block-sticky-breakable.png | Bin 0 -> 405 bytes tests/suite/layout/container.typ | 6 ++++++ 5 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 tests/ref/block-sticky-breakable.png diff --git a/crates/typst/src/layout/container.rs b/crates/typst/src/layout/container.rs index 996ef6c99..9fdef0be4 100644 --- a/crates/typst/src/layout/container.rs +++ b/crates/typst/src/layout/container.rs @@ -422,8 +422,6 @@ pub struct BlockElem { /// This is, by default, set on heading blocks to prevent orphaned headings /// at the bottom of the page. /// - /// Marking a block as sticky makes it unbreakable. - /// /// ```example /// >>> #set page(height: 140pt) /// // Disable stickiness of headings. diff --git a/crates/typst/src/layout/flow/collect.rs b/crates/typst/src/layout/flow/collect.rs index 9fc64f067..a477c3347 100644 --- a/crates/typst/src/layout/flow/collect.rs +++ b/crates/typst/src/layout/flow/collect.rs @@ -189,7 +189,7 @@ impl<'a> Collector<'a, '_, '_> { self.output.push(spacing(elem.above(styles))); - if !breakable || sticky || fr.is_some() { + if !breakable || fr.is_some() { self.output.push(Child::Single(self.boxed(SingleChild { align, sticky, @@ -203,6 +203,7 @@ impl<'a> Collector<'a, '_, '_> { let alone = self.children.len() == 1; self.output.push(Child::Multi(self.boxed(MultiChild { align, + sticky, alone, elem, styles, @@ -375,6 +376,7 @@ fn layout_single_impl( #[derive(Debug)] pub struct MultiChild<'a> { pub align: Axes, + pub sticky: bool, alone: bool, elem: &'a Packed, styles: StyleChain<'a>, diff --git a/crates/typst/src/layout/flow/distribute.rs b/crates/typst/src/layout/flow/distribute.rs index 65516ccd8..a30b71bac 100644 --- a/crates/typst/src/layout/flow/distribute.rs +++ b/crates/typst/src/layout/flow/distribute.rs @@ -247,7 +247,7 @@ impl<'a, 'b> Distributor<'a, 'b, '_, '_, '_> { // Lay out the block. let (frame, spill) = multi.layout(self.composer.engine, self.regions)?; - self.frame(frame, multi.align, false, true)?; + self.frame(frame, multi.align, multi.sticky, true)?; // If the block didn't fully fit into the current region, save it into // the `spill` and finish the region. @@ -292,9 +292,9 @@ impl<'a, 'b> Distributor<'a, 'b, '_, '_, '_> { breakable: bool, ) -> FlowResult<()> { if sticky { - // If the frame is sticky and we haven't remember a preceding sticky - // element, make a checkpoint which we can restore should we end on - // this sticky element. + // If the frame is sticky and we haven't remembered a preceding + // sticky element, make a checkpoint which we can restore should we + // end on this sticky element. if self.stickable && self.sticky.is_none() { self.sticky = Some(self.snapshot()); } diff --git a/tests/ref/block-sticky-breakable.png b/tests/ref/block-sticky-breakable.png new file mode 100644 index 0000000000000000000000000000000000000000..91287a7e67a25882fb9b7957b026a60404d5aa09 GIT binary patch literal 405 zcmeAS@N?(olHy`uVBq!ia0vp^6+m3c0VEi%2k%EaktaqI1scx~rGnd2XA z87dj{1jNgZ%I+?Dd+z9|Q+u7Pe+KJKxiaarC*SNT^{bOz&rapm^-AxxTDomg(POX6 ze5tNH&ueTrUe|2ih45-wSw%3+Y5`cyR21awy*$pP4cik0W-6o z*!!T792=?Uow@cJla^e^i+4_ z4^GB!)(nq(7}ArY-KTSPBphsFUpn@ZRp^hD=AqL+4<4?#ZEXA=q@TB8?ZUTHznC++=}+kYC-lIe;U%}wo{0(v zi+?^y+|OMhrJ6IRcd1dDFQXvHA8Bo;`ySgEJqU_^STm1NnP