summaryrefslogtreecommitdiff
path: root/src/library/page.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-12-15 11:11:57 +0100
committerLaurenz <laurmaedje@gmail.com>2021-12-15 11:11:57 +0100
commitae38be9097bbb32142ef776e77e627ac12379000 (patch)
treef365a348d4c77d2d607d37fee3bc65a601d00a64 /src/library/page.rs
parentfe21c4d399d291e75165b664762f0aa8bdc4724a (diff)
Set Rules Episode IV: A New Fold
Diffstat (limited to 'src/library/page.rs')
-rw-r--r--src/library/page.rs59
1 files changed, 40 insertions, 19 deletions
diff --git a/src/library/page.rs b/src/library/page.rs
index 490eef66..8905ffb6 100644
--- a/src/library/page.rs
+++ b/src/library/page.rs
@@ -14,32 +14,43 @@ pub fn page(ctx: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
Value::Str(string) => Paper::from_str(&string).map_err(|e| e.to_string())?,
}
+ let body: Option<Node> = args.find();
+
+ let mut map = Styles::new();
+ let styles = match body {
+ Some(_) => &mut map,
+ None => &mut ctx.styles,
+ };
+
if let Some(paper) = args.named::<Paper>("paper")?.or_else(|| args.find()) {
- ctx.styles.set(PageNode::CLASS, paper.class());
- ctx.styles.set(PageNode::WIDTH, Smart::Custom(paper.width()));
- ctx.styles.set(PageNode::HEIGHT, Smart::Custom(paper.height()));
+ styles.set(PageNode::CLASS, paper.class());
+ styles.set(PageNode::WIDTH, Smart::Custom(paper.width()));
+ styles.set(PageNode::HEIGHT, Smart::Custom(paper.height()));
}
if let Some(width) = args.named("width")? {
- ctx.styles.set(PageNode::CLASS, PaperClass::Custom);
- ctx.styles.set(PageNode::WIDTH, width);
+ styles.set(PageNode::CLASS, PaperClass::Custom);
+ styles.set(PageNode::WIDTH, width);
}
if let Some(height) = args.named("height")? {
- ctx.styles.set(PageNode::CLASS, PaperClass::Custom);
- ctx.styles.set(PageNode::HEIGHT, height);
+ styles.set(PageNode::CLASS, PaperClass::Custom);
+ styles.set(PageNode::HEIGHT, height);
}
let margins = args.named("margins")?;
- set!(ctx, PageNode::FLIPPED => args.named("flipped")?);
- set!(ctx, PageNode::LEFT => args.named("left")?.or(margins));
- set!(ctx, PageNode::TOP => args.named("top")?.or(margins));
- set!(ctx, PageNode::RIGHT => args.named("right")?.or(margins));
- set!(ctx, PageNode::BOTTOM => args.named("bottom")?.or(margins));
- set!(ctx, PageNode::FILL => args.named("fill")?);
-
- Ok(Value::None)
+ set!(styles, PageNode::FLIPPED => args.named("flipped")?);
+ set!(styles, PageNode::LEFT => args.named("left")?.or(margins));
+ set!(styles, PageNode::TOP => args.named("top")?.or(margins));
+ set!(styles, PageNode::RIGHT => args.named("right")?.or(margins));
+ set!(styles, PageNode::BOTTOM => args.named("bottom")?.or(margins));
+ set!(styles, PageNode::FILL => args.named("fill")?);
+
+ Ok(match body {
+ Some(body) => Value::block(body.into_block().styled(map)),
+ None => Value::None,
+ })
}
/// `pagebreak`: Start a new page.
@@ -48,7 +59,7 @@ pub fn pagebreak(_: &mut EvalContext, _: &mut Args) -> TypResult<Value> {
}
/// Layouts its child onto one or multiple pages.
-#[derive(Debug, Hash)]
+#[derive(Hash)]
pub struct PageNode {
/// The node producing the content.
pub node: PackedNode,
@@ -82,9 +93,8 @@ properties! {
impl PageNode {
/// Layout the page run into a sequence of frames, one per page.
pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<Rc<Frame>> {
- // TODO(set): Use chaining.
- let prev = std::mem::replace(&mut ctx.styles, self.styles.clone());
- ctx.styles.apply(&prev);
+ let prev = ctx.styles.clone();
+ ctx.styles = self.styles.chain(&ctx.styles);
// When one of the lengths is infinite the page fits its content along
// that axis.
@@ -127,6 +137,17 @@ impl PageNode {
}
}
+impl Debug for PageNode {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ if f.alternate() {
+ self.styles.fmt(f)?;
+ }
+ f.write_str("Page(")?;
+ self.node.fmt(f)?;
+ f.write_str(")")
+ }
+}
+
/// Specification of a paper.
#[derive(Debug, Copy, Clone)]
pub struct Paper {