From 095fa52be5d7ed135f39553359e0253cfea6b71b Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 17 Nov 2021 23:09:23 +0100 Subject: [PATCH] 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 +++++++++--------- tests/ref/layout/placed.png | Bin 0 -> 31901 bytes tests/typ/layout/move.typ | 2 +- tests/typ/layout/placed.typ | 22 ++++++++++++++++++++ 11 files changed, 153 insertions(+), 48 deletions(-) create mode 100644 src/library/placed.rs create mode 100644 tests/ref/layout/placed.png create mode 100644 tests/typ/layout/placed.typ diff --git a/src/eval/template.rs b/src/eval/template.rs index 2df347aad..6c1223cb1 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 33502fffa..3ac327228 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 591a40857..19c52f987 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -2,6 +2,20 @@ use super::prelude::*; /// `align`: Configure the alignment along the layouting axes. pub fn align(_: &mut EvalContext, args: &mut Args) -> TypResult { + let Spec { x, y } = parse_aligns(args)?; + let body = args.expect::