diff options
| author | Laurenz <laurmaedje@gmail.com> | 2024-10-27 19:04:55 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-27 18:04:55 +0000 |
| commit | be7cfc85d08c545abfac08098b7b33b4bd71f37e (patch) | |
| tree | f4137fa2aaa57babae1f7603a9b2ed7e688f43d8 /crates/typst-layout/src/pages/finalize.rs | |
| parent | b8034a343831e8609aec2ec81eb7eeda57aa5d81 (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.rs | 73 |
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 }) +} |
