From 4365e18454af4f8f53fe1198182cb5dc8f3d628e Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 26 Aug 2024 19:17:58 +0200 Subject: [PATCH] Improve realization and page layout (#4840) --- crates/typst-utils/src/lib.rs | 35 + crates/typst/src/eval/rules.rs | 4 +- crates/typst/src/foundations/content.rs | 2 +- crates/typst/src/foundations/styles.rs | 289 +++++- crates/typst/src/introspection/counter.rs | 2 +- .../typst/src/introspection/introspector.rs | 13 +- crates/typst/src/introspection/mod.rs | 74 +- crates/typst/src/introspection/tag.rs | 111 +++ crates/typst/src/layout/flow.rs | 833 ++++++++++++------ crates/typst/src/layout/inline/collect.rs | 2 +- crates/typst/src/layout/inline/mod.rs | 3 +- crates/typst/src/layout/page.rs | 148 +++- crates/typst/src/layout/place.rs | 2 +- crates/typst/src/math/ctx.rs | 3 +- crates/typst/src/math/fragment.rs | 9 + crates/typst/src/math/mod.rs | 29 +- crates/typst/src/model/par.rs | 4 +- crates/typst/src/realize/arenas.rs | 9 +- crates/typst/src/realize/behaviour.rs | 182 +--- crates/typst/src/realize/mod.rs | 698 +++++++-------- crates/typst/src/realize/process.rs | 28 +- tests/ref/counter-page-between-pages.png | Bin 0 -> 299 bytes .../counter-page-footer-before-set-page.png | Bin 0 -> 535 bytes tests/ref/counter-page-footer-only-update.png | Bin 0 -> 205 bytes .../counter-page-header-before-set-page.png | Bin 0 -> 551 bytes tests/ref/counter-page-header-only-update.png | Bin 0 -> 131 bytes tests/ref/issue-1833-locate-place.png | Bin 0 -> 136 bytes .../ref/issue-1886-locate-after-metadata.png | Bin 0 -> 830 bytes tests/ref/issue-2326-context-set-page.png | Bin 0 -> 676 bytes tests/ref/issue-2841-pagebreak-to-weak.png | Bin 0 -> 391 bytes .../ref/issue-4029-locate-after-pagebreak.png | Bin 0 -> 698 bytes ...ue-4029-locate-after-par-and-pagebreak.png | Bin 0 -> 785 bytes tests/ref/issue-4029-locate-after-spacing.png | Bin 0 -> 706 bytes tests/ref/issue-4363-set-page-after-tag.png | Bin 0 -> 278 bytes tests/ref/list-item-styling.png | Bin 0 -> 1459 bytes tests/ref/list-items-context.png | Bin 0 -> 382 bytes tests/ref/locate-between-pages.png | Bin 0 -> 231 bytes tests/ref/page-marginal-style-context.png | Bin 0 -> 348 bytes tests/ref/page-marginal-style-empty.png | Bin 0 -> 152 bytes tests/ref/page-marginal-style-page-call.png | Bin 0 -> 300 bytes ...ginal-style-shared-initial-interaction.png | Bin 0 -> 504 bytes ...arginal-style-show-rule-with-page-call.png | Bin 0 -> 1514 bytes ...arginal-style-show-rule-with-pagebreak.png | Bin 0 -> 716 bytes ...marginal-style-show-rule-with-set-page.png | Bin 0 -> 727 bytes tests/ref/page-marginal-style-show-rule.png | Bin 0 -> 716 bytes ...ginal-style-text-call-around-page-call.png | Bin 0 -> 529 bytes ...ginal-style-text-call-around-pagebreak.png | Bin 0 -> 510 bytes ...rginal-style-text-call-around-set-page.png | Bin 0 -> 531 bytes .../page-marginal-style-text-call-code.png | Bin 0 -> 473 bytes tests/ref/page-marginal-style-text-call.png | Bin 0 -> 473 bytes .../page-marginal-style-text-set-first.png | Bin 0 -> 457 bytes tests/ref/page-marginal-style-text-set.png | Bin 0 -> 457 bytes tests/suite/introspection/counter.typ | 40 + tests/suite/introspection/locate.typ | 90 ++ tests/suite/layout/page.typ | 111 +++ tests/suite/layout/pagebreak.typ | 9 + tests/suite/model/list.typ | 10 + 57 files changed, 1710 insertions(+), 1030 deletions(-) create mode 100644 crates/typst/src/introspection/tag.rs create mode 100644 tests/ref/counter-page-between-pages.png create mode 100644 tests/ref/counter-page-footer-before-set-page.png create mode 100644 tests/ref/counter-page-footer-only-update.png create mode 100644 tests/ref/counter-page-header-before-set-page.png create mode 100644 tests/ref/counter-page-header-only-update.png create mode 100644 tests/ref/issue-1833-locate-place.png create mode 100644 tests/ref/issue-1886-locate-after-metadata.png create mode 100644 tests/ref/issue-2326-context-set-page.png create mode 100644 tests/ref/issue-2841-pagebreak-to-weak.png create mode 100644 tests/ref/issue-4029-locate-after-pagebreak.png create mode 100644 tests/ref/issue-4029-locate-after-par-and-pagebreak.png create mode 100644 tests/ref/issue-4029-locate-after-spacing.png create mode 100644 tests/ref/issue-4363-set-page-after-tag.png create mode 100644 tests/ref/list-item-styling.png create mode 100644 tests/ref/list-items-context.png create mode 100644 tests/ref/locate-between-pages.png create mode 100644 tests/ref/page-marginal-style-context.png create mode 100644 tests/ref/page-marginal-style-empty.png create mode 100644 tests/ref/page-marginal-style-page-call.png create mode 100644 tests/ref/page-marginal-style-shared-initial-interaction.png create mode 100644 tests/ref/page-marginal-style-show-rule-with-page-call.png create mode 100644 tests/ref/page-marginal-style-show-rule-with-pagebreak.png create mode 100644 tests/ref/page-marginal-style-show-rule-with-set-page.png create mode 100644 tests/ref/page-marginal-style-show-rule.png create mode 100644 tests/ref/page-marginal-style-text-call-around-page-call.png create mode 100644 tests/ref/page-marginal-style-text-call-around-pagebreak.png create mode 100644 tests/ref/page-marginal-style-text-call-around-set-page.png create mode 100644 tests/ref/page-marginal-style-text-call-code.png create mode 100644 tests/ref/page-marginal-style-text-call.png create mode 100644 tests/ref/page-marginal-style-text-set-first.png create mode 100644 tests/ref/page-marginal-style-text-set.png diff --git a/crates/typst-utils/src/lib.rs b/crates/typst-utils/src/lib.rs index 831b2374c..79d4bb09b 100644 --- a/crates/typst-utils/src/lib.rs +++ b/crates/typst-utils/src/lib.rs @@ -106,6 +106,18 @@ impl OptionExt for Option { /// Extra methods for [`[T]`](slice). pub trait SliceExt { + /// Returns a slice with all matching elements from the start of the slice + /// removed. + fn trim_start_matches(&self, f: F) -> &[T] + where + F: FnMut(&T) -> bool; + + /// Returns a slice with all matching elements from the end of the slice + /// removed. + fn trim_end_matches(&self, f: F) -> &[T] + where + F: FnMut(&T) -> bool; + /// Split a slice into consecutive runs with the same key and yield for /// each such run the key and the slice of elements with that key. fn group_by_key(&self, f: F) -> GroupByKey<'_, T, F> @@ -115,6 +127,29 @@ pub trait SliceExt { } impl SliceExt for [T] { + fn trim_start_matches(&self, mut f: F) -> &[T] + where + F: FnMut(&T) -> bool, + { + let len = self.len(); + let mut i = 0; + while i < len && f(&self[i]) { + i += 1; + } + &self[i..] + } + + fn trim_end_matches(&self, mut f: F) -> &[T] + where + F: FnMut(&T) -> bool, + { + let mut i = self.len(); + while i > 0 && f(&self[i - 1]) { + i -= 1; + } + &self[..i] + } + fn group_by_key(&self, f: F) -> GroupByKey<'_, T, F> { GroupByKey { slice: self, f } } diff --git a/crates/typst/src/eval/rules.rs b/crates/typst/src/eval/rules.rs index f5d7da178..61fee84a1 100644 --- a/crates/typst/src/eval/rules.rs +++ b/crates/typst/src/eval/rules.rs @@ -24,7 +24,7 @@ impl Eval for ast::SetRule<'_> { }) .at(target.span())?; let args = self.args().eval(vm)?.spanned(self.span()); - Ok(target.set(&mut vm.engine, args)?.spanned(self.span())) + Ok(target.set(&mut vm.engine, args)?.spanned(self.span()).liftable()) } } @@ -46,6 +46,6 @@ impl Eval for ast::ShowRule<'_> { expr => expr.eval(vm)?.cast::().at(span)?, }; - Ok(Recipe { span, selector, transform }) + Ok(Recipe::new(selector, transform, span)) } } diff --git a/crates/typst/src/foundations/content.rs b/crates/typst/src/foundations/content.rs index 656049dd5..b9d1b1897 100644 --- a/crates/typst/src/foundations/content.rs +++ b/crates/typst/src/foundations/content.rs @@ -369,7 +369,7 @@ impl Content { context: Tracked, recipe: Recipe, ) -> SourceResult { - if recipe.selector.is_none() { + if recipe.selector().is_none() { recipe.apply(engine, context, self) } else { Ok(self.styled(recipe)) diff --git a/crates/typst/src/foundations/styles.rs b/crates/typst/src/foundations/styles.rs index 55bb348a0..e74a16499 100644 --- a/crates/typst/src/foundations/styles.rs +++ b/crates/typst/src/foundations/styles.rs @@ -93,6 +93,11 @@ impl Styles { self.0.iter().map(|style| &**style) } + /// Iterate over the contained styles. + pub fn as_slice(&self) -> &[LazyHash