summaryrefslogtreecommitdiff
path: root/crates/typst-layout/src/pages/finalize.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-10-27 19:04:55 +0100
committerGitHub <noreply@github.com>2024-10-27 18:04:55 +0000
commitbe7cfc85d08c545abfac08098b7b33b4bd71f37e (patch)
treef4137fa2aaa57babae1f7603a9b2ed7e688f43d8 /crates/typst-layout/src/pages/finalize.rs
parentb8034a343831e8609aec2ec81eb7eeda57aa5d81 (diff)
Split out four new crates (#5302)
Diffstat (limited to 'crates/typst-layout/src/pages/finalize.rs')
-rw-r--r--crates/typst-layout/src/pages/finalize.rs73
1 files changed, 73 insertions, 0 deletions
diff --git a/crates/typst-layout/src/pages/finalize.rs b/crates/typst-layout/src/pages/finalize.rs
new file mode 100644
index 00000000..8df6cb16
--- /dev/null
+++ b/crates/typst-layout/src/pages/finalize.rs
@@ -0,0 +1,73 @@
+use typst_library::diag::SourceResult;
+use typst_library::engine::Engine;
+use typst_library::introspection::{ManualPageCounter, Tag};
+use typst_library::layout::{Frame, FrameItem, Page, Point};
+
+use super::LayoutedPage;
+
+/// Piece together the inner page frame and the marginals. We can only do this
+/// at the very end because inside/outside margins require knowledge of the
+/// physical page number, which is unknown during parallel layout.
+pub fn finalize(
+ engine: &mut Engine,
+ counter: &mut ManualPageCounter,
+ tags: &mut Vec<Tag>,
+ LayoutedPage {
+ inner,
+ mut margin,
+ binding,
+ two_sided,
+ header,
+ footer,
+ background,
+ foreground,
+ fill,
+ numbering,
+ }: LayoutedPage,
+) -> SourceResult<Page> {
+ // If two sided, left becomes inside and right becomes outside.
+ // Thus, for left-bound pages, we want to swap on even pages and
+ // for right-bound pages, we want to swap on odd pages.
+ if two_sided && binding.swap(counter.physical()) {
+ std::mem::swap(&mut margin.left, &mut margin.right);
+ }
+
+ // Create a frame for the full page.
+ let mut frame = Frame::hard(inner.size() + margin.sum_by_axis());
+
+ // Add tags.
+ for tag in tags.drain(..) {
+ frame.push(Point::zero(), FrameItem::Tag(tag));
+ }
+
+ // Add the "before" marginals. The order in which we push things here is
+ // important as it affects the relative ordering of introspectable elements
+ // and thus how counters resolve.
+ if let Some(background) = background {
+ frame.push_frame(Point::zero(), background);
+ }
+ if let Some(header) = header {
+ frame.push_frame(Point::with_x(margin.left), header);
+ }
+
+ // Add the inner contents.
+ frame.push_frame(Point::new(margin.left, margin.top), inner);
+
+ // Add the "after" marginals.
+ if let Some(footer) = footer {
+ let y = frame.height() - footer.height();
+ frame.push_frame(Point::new(margin.left, y), footer);
+ }
+ if let Some(foreground) = foreground {
+ frame.push_frame(Point::zero(), foreground);
+ }
+
+ // Apply counter updates from within the page to the manual page counter.
+ counter.visit(engine, &frame)?;
+
+ // Get this page's number and then bump the counter for the next page.
+ let number = counter.logical();
+ counter.step();
+
+ Ok(Page { frame, fill, numbering, number })
+}