From e1558268f9b813ca6b789909075603eb8dc22af9 Mon Sep 17 00:00:00 2001 From: Beiri22 Date: Wed, 30 Aug 2023 12:58:16 +0200 Subject: [PATCH] Introduce second variant of Ignorant Behaviour and prevent weak page breaks at basically empty pages (#1929) --- crates/typst-library/src/layout/mod.rs | 2 +- crates/typst-library/src/layout/spacing.rs | 4 +-- crates/typst-library/src/meta/metadata.rs | 2 +- crates/typst-library/src/shared/behave.rs | 14 +++++----- crates/typst/src/model/content.rs | 2 +- crates/typst/src/model/realize.rs | 4 ++- tests/ref/layout/pagebreak-empty.png | Bin 0 -> 18958 bytes tests/typ/layout/pagebreak-empty.typ | 30 +++++++++++++++++++++ 8 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 tests/ref/layout/pagebreak-empty.png create mode 100644 tests/typ/layout/pagebreak-empty.typ diff --git a/crates/typst-library/src/layout/mod.rs b/crates/typst-library/src/layout/mod.rs index ce728ccb7..3334d5aa3 100644 --- a/crates/typst-library/src/layout/mod.rs +++ b/crates/typst-library/src/layout/mod.rs @@ -467,7 +467,7 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> { fn interrupt_page(&mut self, styles: Option>) -> SourceResult<()> { self.interrupt_par()?; let Some(doc) = &mut self.doc else { return Ok(()) }; - if !self.flow.0.is_empty() || (doc.keep_next && styles.is_some()) { + if !self.flow.0.is_basically_empty() || (doc.keep_next && styles.is_some()) { let (flow, shared) = mem::take(&mut self.flow).0.finish(); let styles = if shared == StyleChain::default() { styles.unwrap_or_default() diff --git a/crates/typst-library/src/layout/spacing.rs b/crates/typst-library/src/layout/spacing.rs index 950f024f8..69a5d952a 100644 --- a/crates/typst-library/src/layout/spacing.rs +++ b/crates/typst-library/src/layout/spacing.rs @@ -63,7 +63,7 @@ impl Behave for HElem { } else if self.weak(StyleChain::default()) { Behaviour::Weak(1) } else { - Behaviour::Ignorant + Behaviour::Invisible } } @@ -158,7 +158,7 @@ impl Behave for VElem { } else if self.weakness(StyleChain::default()) > 0 { Behaviour::Weak(self.weakness(StyleChain::default())) } else { - Behaviour::Ignorant + Behaviour::Invisible } } diff --git a/crates/typst-library/src/meta/metadata.rs b/crates/typst-library/src/meta/metadata.rs index ed0d19864..89d1409a9 100644 --- a/crates/typst-library/src/meta/metadata.rs +++ b/crates/typst-library/src/meta/metadata.rs @@ -38,6 +38,6 @@ impl Show for MetadataElem { impl Behave for MetadataElem { fn behaviour(&self) -> Behaviour { - Behaviour::Ignorant + Behaviour::Invisible } } diff --git a/crates/typst-library/src/shared/behave.rs b/crates/typst-library/src/shared/behave.rs index 6a1aa1274..471daa189 100644 --- a/crates/typst-library/src/shared/behave.rs +++ b/crates/typst-library/src/shared/behave.rs @@ -34,10 +34,9 @@ impl<'a> BehavedBuilder<'a> { /// probably collapse. pub fn is_basically_empty(&self) -> bool { self.builder.is_empty() - && self - .staged - .iter() - .all(|(_, behaviour, _)| matches!(behaviour, Behaviour::Weak(_))) + && self.staged.iter().all(|(_, behaviour, _)| { + matches!(behaviour, Behaviour::Weak(_) | Behaviour::Invisible) + }) } /// Push an item into the sequence. @@ -74,7 +73,7 @@ impl<'a> BehavedBuilder<'a> { self.builder.push(elem, styles); self.last = interaction; } - Behaviour::Ignorant => { + Behaviour::Ignorant | Behaviour::Invisible => { self.staged.push((elem, interaction, styles)); } } @@ -95,7 +94,10 @@ impl<'a> BehavedBuilder<'a> { /// false. fn flush(&mut self, supportive: bool) { for (item, interaction, styles) in self.staged.drain(..) { - if supportive || interaction == Behaviour::Ignorant { + if supportive + || interaction == Behaviour::Ignorant + || interaction == Behaviour::Invisible + { self.builder.push(item, styles); } } diff --git a/crates/typst/src/model/content.rs b/crates/typst/src/model/content.rs index f1600f251..6541ab6b4 100644 --- a/crates/typst/src/model/content.rs +++ b/crates/typst/src/model/content.rs @@ -610,7 +610,7 @@ pub struct MetaElem { impl Behave for MetaElem { fn behaviour(&self) -> Behaviour { - Behaviour::Ignorant + Behaviour::Invisible } } diff --git a/crates/typst/src/model/realize.rs b/crates/typst/src/model/realize.rs index 01c46b818..3e683d3e6 100644 --- a/crates/typst/src/model/realize.rs +++ b/crates/typst/src/model/realize.rs @@ -214,8 +214,10 @@ pub enum Behaviour { /// An element that destroys adjacent weak elements. Destructive, /// An element that does not interact at all with other elements, having the - /// same effect as if it didn't exist. + /// same effect as if it didn't exist, but has a visual representation. Ignorant, + /// An element that does not have a visual representation. + Invisible, } /// Guards content against being affected by the same show rule multiple times. diff --git a/tests/ref/layout/pagebreak-empty.png b/tests/ref/layout/pagebreak-empty.png new file mode 100644 index 0000000000000000000000000000000000000000..412c4e8d659b8156ae9cb163d2657bd7e294d19d GIT binary patch literal 18958 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