From 5a59bb48216352d04f78c9a9392ca7cef280d7b2 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 18 Nov 2021 12:50:28 +0100 Subject: Page fill --- src/eval/template.rs | 9 ++++++--- src/library/page.rs | 26 +++++++++++++++++++++++--- src/library/shape.rs | 1 + src/style/mod.rs | 3 +++ 4 files changed, 33 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/eval/template.rs b/src/eval/template.rs index 7801dc79..307bff2a 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 a5935002..6642de16 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 7c543958..d0df5f48 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 9cf2de07..4588163b 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, } } } -- cgit v1.2.3