From 095fa52be5d7ed135f39553359e0253cfea6b71b Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 17 Nov 2021 23:09:23 +0100 Subject: Placed node --- src/eval/template.rs | 16 +++++++++++----- src/layout/mod.rs | 24 +++++++++++++++--------- src/library/align.rs | 26 +++++++++++++++----------- src/library/flow.rs | 35 +++++++++++++++++++++++++++++------ src/library/mod.rs | 7 +++++-- src/library/placed.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/library/stack.rs | 11 +++++++---- src/library/transform.rs | 19 +++++++++---------- 8 files changed, 130 insertions(+), 47 deletions(-) create mode 100644 src/library/placed.rs (limited to 'src') diff --git a/src/eval/template.rs b/src/eval/template.rs index 2df347aa..6c1223cb 100644 --- a/src/eval/template.rs +++ b/src/eval/template.rs @@ -10,7 +10,7 @@ use crate::geom::{Align, Dir, GenAxis, Length, Linear, Sides, Size}; use crate::layout::{Layout, PackedNode}; use crate::library::{ Decoration, DocumentNode, FlowChild, FlowNode, PadNode, PageNode, ParChild, ParNode, - Spacing, + PlacedNode, Spacing, }; use crate::style::Style; use crate::util::EcoString; @@ -331,15 +331,21 @@ impl Builder { } /// Push an inline node into the active paragraph. - fn inline(&mut self, node: impl Into) { + fn inline(&mut self, node: PackedNode) { self.flow.par.push(ParChild::Node(node.into())); } /// Push a block node into the active flow, finishing the active paragraph. - fn block(&mut self, node: impl Into) { - self.parbreak(); - self.flow.push(FlowChild::Node(node.into())); + fn block(&mut self, node: PackedNode) { self.parbreak(); + let in_flow = node.downcast::().is_none(); + self.flow.push(FlowChild::Node(node)); + if in_flow { + self.parbreak(); + } else { + // This prevents duplicate paragraph spacing around placed nodes. + self.flow.last = Last::None; + } } /// Push spacing into the active paragraph or flow depending on the `axis`. diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 33502fff..3ac32722 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -19,7 +19,7 @@ use crate::font::FontStore; use crate::frame::Frame; use crate::geom::{Align, Linear, Spec}; use crate::image::ImageStore; -use crate::library::{AlignNode, DocumentNode, SizedNode}; +use crate::library::{AlignNode, DocumentNode, MoveNode, SizedNode}; use crate::Context; /// Layout a document node into a collection of frames. @@ -104,21 +104,27 @@ impl PackedNode { } /// Force a size for this node. - pub fn sized(self, width: Option, height: Option) -> PackedNode { - if width.is_some() || height.is_some() { - Layout::pack(SizedNode { - child: self, - sizing: Spec::new(width, height), - }) + pub fn sized(self, w: Option, h: Option) -> Self { + if w.is_some() || h.is_some() { + SizedNode { child: self, sizing: Spec::new(w, h) }.pack() } else { self } } /// Set alignments for this node. - pub fn aligned(self, x: Option, y: Option) -> PackedNode { + pub fn aligned(self, x: Option, y: Option) -> Self { if x.is_some() || y.is_some() { - Layout::pack(AlignNode { child: self, aligns: Spec::new(x, y) }) + AlignNode { child: self, aligns: Spec::new(x, y) }.pack() + } else { + self + } + } + + /// Move this node's contents without affecting layout. + pub fn moved(self, dx: Option, dy: Option) -> Self { + if dx.is_some() || dy.is_some() { + MoveNode { child: self, offset: Spec::new(dx, dy) }.pack() } else { self } diff --git a/src/library/align.rs b/src/library/align.rs index 591a4085..19c52f98 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -2,18 +2,8 @@ use super::prelude::*; /// `align`: Configure the alignment along the layouting axes. pub fn align(_: &mut EvalContext, args: &mut Args) -> TypResult { - let mut x = args.named("horizontal")?; - let mut y = args.named("vertical")?; - for Spanned { v, span } in args.all::>() { - match v.axis() { - None | Some(SpecAxis::Horizontal) if x.is_none() => x = Some(v), - None | Some(SpecAxis::Vertical) if y.is_none() => y = Some(v), - _ => bail!(span, "unexpected argument"), - } - } - + let Spec { x, y } = parse_aligns(args)?; let body = args.expect::