diff --git a/src/eval/template.rs b/src/eval/template.rs index 7801dc799..307bff2a2 100644 --- a/src/eval/template.rs +++ b/src/eval/template.rs @@ -6,7 +6,7 @@ use std::ops::{Add, AddAssign}; use std::rc::Rc; use crate::diag::StrResult; -use crate::geom::{Align, Dir, GenAxis, Length, Linear, Sides, Size}; +use crate::geom::{Align, Dir, GenAxis, Length, Linear, Paint, Sides, Size}; use crate::layout::{Layout, PackedNode}; use crate::library::{ Decoration, DocumentNode, FlowChild, FlowNode, PageNode, ParChild, ParNode, @@ -384,6 +384,7 @@ impl Builder { struct PageBuilder { size: Size, padding: Sides, + fill: Option, hard: bool, } @@ -392,15 +393,17 @@ impl PageBuilder { Self { size: style.page.size, padding: style.page.margins(), + fill: style.page.fill, hard, } } fn build(self, child: FlowNode, keep: bool) -> Option { - let Self { size, padding, hard } = self; + let Self { size, padding, fill, hard } = self; (!child.children.is_empty() || (keep && hard)).then(|| PageNode { - size, child: child.pack().padded(padding), + size, + fill, }) } } diff --git a/src/library/page.rs b/src/library/page.rs index a5935002b..6642de166 100644 --- a/src/library/page.rs +++ b/src/library/page.rs @@ -18,6 +18,7 @@ pub fn page(ctx: &mut EvalContext, args: &mut Args) -> TypResult { let right = args.named("right")?; let bottom = args.named("bottom")?; let flip = args.named("flip")?; + let fill = args.named("fill")?; ctx.template.modify(move |style| { let page = style.page_mut(); @@ -60,6 +61,10 @@ pub fn page(ctx: &mut EvalContext, args: &mut Args) -> TypResult { if flip.unwrap_or(false) { std::mem::swap(&mut page.size.w, &mut page.size.h); } + + if let Some(fill) = fill { + page.fill = Some(Paint::Color(fill)); + } }); ctx.template.pagebreak(false); @@ -77,10 +82,12 @@ pub fn pagebreak(_: &mut EvalContext, _: &mut Args) -> TypResult { /// Layouts its children onto one or multiple pages. #[derive(Debug, Hash)] pub struct PageNode { - /// The size of the page. - pub size: Size, /// The node that produces the actual pages. pub child: PackedNode, + /// The size of the page. + pub size: Size, + /// The background fill. + pub fill: Option, } impl PageNode { @@ -90,6 +97,19 @@ impl PageNode { // that axis. let expand = self.size.to_spec().map(Length::is_finite); let regions = Regions::repeat(self.size, self.size, expand); - self.child.layout(ctx, ®ions).into_iter().map(|c| c.item).collect() + + // Layout the child. + let mut frames: Vec<_> = + self.child.layout(ctx, ®ions).into_iter().map(|c| c.item).collect(); + + // Add background fill if requested. + if let Some(fill) = self.fill { + for frame in &mut frames { + let element = Element::Geometry(Geometry::Rect(frame.size), fill); + Rc::make_mut(frame).prepend(Point::zero(), element) + } + } + + frames } } diff --git a/src/library/shape.rs b/src/library/shape.rs index 7c543958b..d0df5f480 100644 --- a/src/library/shape.rs +++ b/src/library/shape.rs @@ -131,6 +131,7 @@ impl Layout for ShapeNode { frames = node.layout(ctx, &pod); } + // TODO: What if there are multiple or no frames? // Extract the frame. Rc::take(frames.into_iter().next().unwrap().item) } else { diff --git a/src/style/mod.rs b/src/style/mod.rs index 9cf2de073..4588163bd 100644 --- a/src/style/mod.rs +++ b/src/style/mod.rs @@ -71,6 +71,8 @@ pub struct PageStyle { /// The amount of white space on each side of the page. If a side is set to /// `None`, the default for the paper class is used. pub margins: Sides>, + /// The background fill of the page. + pub fill: Option, } impl PageStyle { @@ -93,6 +95,7 @@ impl Default for PageStyle { class: paper.class(), size: paper.size(), margins: Sides::splat(None), + fill: None, } } } diff --git a/tests/ref/layout/page.png b/tests/ref/layout/page.png index 75ad00d12..dae3d4882 100644 Binary files a/tests/ref/layout/page.png and b/tests/ref/layout/page.png differ diff --git a/tests/typ/layout/page.typ b/tests/typ/layout/page.typ index 1d2fdb622..9bb3097d7 100644 --- a/tests/typ/layout/page.typ +++ b/tests/typ/layout/page.typ @@ -2,15 +2,15 @@ --- // Set width and height. -#page(width: 120pt, height: 120pt) +#page(width: 80pt, height: 80pt) [#page(width: 40pt) High] [#page(height: 40pt) Wide] // Set all margins at once. [ - #page(margins: 30pt) - #align(top, left)[TL] - #align(bottom, right)[BR] + #page(margins: 5pt) + #place(top, left)[TL] + #place(bottom, right)[BR] ] // Set individual margins. @@ -26,15 +26,10 @@ // Flipped predefined paper. [#page(paper: "a11", flip: true) Flipped A11] -// Flipped custom page size. -#page(width: 40pt, height: 120pt) -#page(flip: true) -Wide - --- // Test a combination of pages with bodies and normal content. -#page(height: 50pt) +#page(width: 80pt, height: 30pt) [#page() First] [#page() Second] @@ -43,4 +38,9 @@ Wide Fourth [#page(height: 25pt)] Sixth -[#page() Seventh and last] +[#page() Seventh] + +--- +#page(width: 80pt, height: 40pt, fill: eastern) +#font(15pt, "Roboto", fill: white, smallcaps: true) +Typst