Page fill

This commit is contained in:
Laurenz 2021-11-18 12:50:28 +01:00
parent b2e6a29789
commit 5a59bb4821
6 changed files with 44 additions and 17 deletions

View File

@ -6,7 +6,7 @@ use std::ops::{Add, AddAssign};
use std::rc::Rc; use std::rc::Rc;
use crate::diag::StrResult; 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::layout::{Layout, PackedNode};
use crate::library::{ use crate::library::{
Decoration, DocumentNode, FlowChild, FlowNode, PageNode, ParChild, ParNode, Decoration, DocumentNode, FlowChild, FlowNode, PageNode, ParChild, ParNode,
@ -384,6 +384,7 @@ impl Builder {
struct PageBuilder { struct PageBuilder {
size: Size, size: Size,
padding: Sides<Linear>, padding: Sides<Linear>,
fill: Option<Paint>,
hard: bool, hard: bool,
} }
@ -392,15 +393,17 @@ impl PageBuilder {
Self { Self {
size: style.page.size, size: style.page.size,
padding: style.page.margins(), padding: style.page.margins(),
fill: style.page.fill,
hard, hard,
} }
} }
fn build(self, child: FlowNode, keep: bool) -> Option<PageNode> { fn build(self, child: FlowNode, keep: bool) -> Option<PageNode> {
let Self { size, padding, hard } = self; let Self { size, padding, fill, hard } = self;
(!child.children.is_empty() || (keep && hard)).then(|| PageNode { (!child.children.is_empty() || (keep && hard)).then(|| PageNode {
size,
child: child.pack().padded(padding), child: child.pack().padded(padding),
size,
fill,
}) })
} }
} }

View File

@ -18,6 +18,7 @@ pub fn page(ctx: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
let right = args.named("right")?; let right = args.named("right")?;
let bottom = args.named("bottom")?; let bottom = args.named("bottom")?;
let flip = args.named("flip")?; let flip = args.named("flip")?;
let fill = args.named("fill")?;
ctx.template.modify(move |style| { ctx.template.modify(move |style| {
let page = style.page_mut(); let page = style.page_mut();
@ -60,6 +61,10 @@ pub fn page(ctx: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
if flip.unwrap_or(false) { if flip.unwrap_or(false) {
std::mem::swap(&mut page.size.w, &mut page.size.h); 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); ctx.template.pagebreak(false);
@ -77,10 +82,12 @@ pub fn pagebreak(_: &mut EvalContext, _: &mut Args) -> TypResult<Value> {
/// Layouts its children onto one or multiple pages. /// Layouts its children onto one or multiple pages.
#[derive(Debug, Hash)] #[derive(Debug, Hash)]
pub struct PageNode { pub struct PageNode {
/// The size of the page.
pub size: Size,
/// The node that produces the actual pages. /// The node that produces the actual pages.
pub child: PackedNode, pub child: PackedNode,
/// The size of the page.
pub size: Size,
/// The background fill.
pub fill: Option<Paint>,
} }
impl PageNode { impl PageNode {
@ -90,6 +97,19 @@ impl PageNode {
// that axis. // that axis.
let expand = self.size.to_spec().map(Length::is_finite); let expand = self.size.to_spec().map(Length::is_finite);
let regions = Regions::repeat(self.size, self.size, expand); let regions = Regions::repeat(self.size, self.size, expand);
self.child.layout(ctx, &regions).into_iter().map(|c| c.item).collect()
// Layout the child.
let mut frames: Vec<_> =
self.child.layout(ctx, &regions).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
} }
} }

View File

@ -131,6 +131,7 @@ impl Layout for ShapeNode {
frames = node.layout(ctx, &pod); frames = node.layout(ctx, &pod);
} }
// TODO: What if there are multiple or no frames?
// Extract the frame. // Extract the frame.
Rc::take(frames.into_iter().next().unwrap().item) Rc::take(frames.into_iter().next().unwrap().item)
} else { } else {

View File

@ -71,6 +71,8 @@ pub struct PageStyle {
/// The amount of white space on each side of the page. If a side is set to /// 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. /// `None`, the default for the paper class is used.
pub margins: Sides<Option<Linear>>, pub margins: Sides<Option<Linear>>,
/// The background fill of the page.
pub fill: Option<Paint>,
} }
impl PageStyle { impl PageStyle {
@ -93,6 +95,7 @@ impl Default for PageStyle {
class: paper.class(), class: paper.class(),
size: paper.size(), size: paper.size(),
margins: Sides::splat(None), margins: Sides::splat(None),
fill: None,
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -2,15 +2,15 @@
--- ---
// Set width and height. // Set width and height.
#page(width: 120pt, height: 120pt) #page(width: 80pt, height: 80pt)
[#page(width: 40pt) High] [#page(width: 40pt) High]
[#page(height: 40pt) Wide] [#page(height: 40pt) Wide]
// Set all margins at once. // Set all margins at once.
[ [
#page(margins: 30pt) #page(margins: 5pt)
#align(top, left)[TL] #place(top, left)[TL]
#align(bottom, right)[BR] #place(bottom, right)[BR]
] ]
// Set individual margins. // Set individual margins.
@ -26,15 +26,10 @@
// Flipped predefined paper. // Flipped predefined paper.
[#page(paper: "a11", flip: true) Flipped A11] [#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. // Test a combination of pages with bodies and normal content.
#page(height: 50pt) #page(width: 80pt, height: 30pt)
[#page() First] [#page() First]
[#page() Second] [#page() Second]
@ -43,4 +38,9 @@ Wide
Fourth Fourth
[#page(height: 25pt)] [#page(height: 25pt)]
Sixth Sixth
[#page() Seventh and last] [#page() Seventh]
---
#page(width: 80pt, height: 40pt, fill: eastern)
#font(15pt, "Roboto", fill: white, smallcaps: true)
Typst