diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-04-30 14:12:28 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-04-30 14:12:28 +0200 |
| commit | f9e115daf54c29358f890b137f50a33a781af680 (patch) | |
| tree | 496de52246629ea8039db6beea94eb779ed2851d /src/library/layout | |
| parent | f7c67cde72e6a67f45180856b332bae9863243bd (diff) | |
New block spacing model
Diffstat (limited to 'src/library/layout')
| -rw-r--r-- | src/library/layout/align.rs | 12 | ||||
| -rw-r--r-- | src/library/layout/columns.rs | 5 | ||||
| -rw-r--r-- | src/library/layout/flow.rs | 41 | ||||
| -rw-r--r-- | src/library/layout/pad.rs | 12 | ||||
| -rw-r--r-- | src/library/layout/page.rs | 4 | ||||
| -rw-r--r-- | src/library/layout/spacing.rs | 45 | ||||
| -rw-r--r-- | src/library/layout/stack.rs | 12 |
7 files changed, 91 insertions, 40 deletions
diff --git a/src/library/layout/align.rs b/src/library/layout/align.rs index 2a4d039e..c050d2a4 100644 --- a/src/library/layout/align.rs +++ b/src/library/layout/align.rs @@ -13,9 +13,15 @@ pub struct AlignNode { #[node] impl AlignNode { fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> { - let aligns: Spec<_> = args.find()?.unwrap_or_default(); - let body: LayoutNode = args.expect("body")?; - Ok(Content::block(body.aligned(aligns))) + let aligns: Spec<Option<RawAlign>> = args.find()?.unwrap_or_default(); + let body: Content = args.expect("body")?; + Ok(match (body, aligns) { + (Content::Block(node), _) => Content::Block(node.aligned(aligns)), + (other, Spec { x: Some(x), y: None }) => { + other.styled(ParNode::ALIGN, HorizontalAlign(x)) + } + (other, _) => Content::Block(other.pack().aligned(aligns)), + }) } } diff --git a/src/library/layout/columns.rs b/src/library/layout/columns.rs index 4963043e..8e523694 100644 --- a/src/library/layout/columns.rs +++ b/src/library/layout/columns.rs @@ -106,7 +106,8 @@ pub struct ColbreakNode; #[node] impl ColbreakNode { - fn construct(_: &mut Context, _: &mut Args) -> TypResult<Content> { - Ok(Content::Colbreak) + fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> { + let weak = args.named("weak")?.unwrap_or(false); + Ok(Content::Colbreak { weak }) } } diff --git a/src/library/layout/flow.rs b/src/library/layout/flow.rs index 6b43c8b7..6193a68f 100644 --- a/src/library/layout/flow.rs +++ b/src/library/layout/flow.rs @@ -1,3 +1,5 @@ +use std::cmp::Ordering; + use super::{AlignNode, PlaceNode, Spacing}; use crate::library::prelude::*; use crate::library::text::ParNode; @@ -10,18 +12,14 @@ use crate::library::text::ParNode; pub struct FlowNode(pub StyleVec<FlowChild>); /// A child of a flow node. -#[derive(Hash)] +#[derive(Hash, PartialEq)] pub enum FlowChild { - /// Leading between other children. - Leading, - /// A paragraph / block break. - Parbreak, - /// A column / region break. - Colbreak, /// Vertical spacing between other children. Spacing(Spacing), /// An arbitrary block-level node. Node(LayoutNode), + /// A column / region break. + Colbreak, } impl Layout for FlowNode { @@ -36,25 +34,15 @@ impl Layout for FlowNode { for (child, map) in self.0.iter() { let styles = map.chain(&styles); match child { - FlowChild::Leading => { - let amount = styles.get(ParNode::LEADING); - layouter.layout_spacing(amount.into(), styles); - } - FlowChild::Parbreak => { - let leading = styles.get(ParNode::LEADING); - let spacing = styles.get(ParNode::SPACING); - let amount = leading + spacing; - layouter.layout_spacing(amount.into(), styles); - } - FlowChild::Colbreak => { - layouter.finish_region(); - } FlowChild::Spacing(kind) => { layouter.layout_spacing(*kind, styles); } FlowChild::Node(ref node) => { layouter.layout_node(ctx, node, styles)?; } + FlowChild::Colbreak => { + layouter.finish_region(); + } } } @@ -72,11 +60,18 @@ impl Debug for FlowNode { impl Debug for FlowChild { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Self::Leading => f.pad("Leading"), - Self::Parbreak => f.pad("Parbreak"), - Self::Colbreak => f.pad("Colbreak"), Self::Spacing(kind) => write!(f, "{:?}", kind), Self::Node(node) => node.fmt(f), + Self::Colbreak => f.pad("Colbreak"), + } + } +} + +impl PartialOrd for FlowChild { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + match (self, other) { + (Self::Spacing(a), Self::Spacing(b)) => a.partial_cmp(b), + _ => None, } } } diff --git a/src/library/layout/pad.rs b/src/library/layout/pad.rs index e688e423..2be21bcb 100644 --- a/src/library/layout/pad.rs +++ b/src/library/layout/pad.rs @@ -13,12 +13,12 @@ pub struct PadNode { impl PadNode { fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> { let all = args.find()?; - let hor = args.named("horizontal")?; - let ver = args.named("vertical")?; - let left = args.named("left")?.or(hor).or(all).unwrap_or_default(); - let top = args.named("top")?.or(ver).or(all).unwrap_or_default(); - let right = args.named("right")?.or(hor).or(all).unwrap_or_default(); - let bottom = args.named("bottom")?.or(ver).or(all).unwrap_or_default(); + let x = args.named("x")?; + let y = args.named("y")?; + let left = args.named("left")?.or(x).or(all).unwrap_or_default(); + let top = args.named("top")?.or(y).or(all).unwrap_or_default(); + let right = args.named("right")?.or(x).or(all).unwrap_or_default(); + let bottom = args.named("bottom")?.or(y).or(all).unwrap_or_default(); let body: LayoutNode = args.expect("body")?; let padding = Sides::new(left, top, right, bottom); Ok(Content::block(body.padded(padding))) diff --git a/src/library/layout/page.rs b/src/library/layout/page.rs index 8e5801ea..4307d2f9 100644 --- a/src/library/layout/page.rs +++ b/src/library/layout/page.rs @@ -165,8 +165,8 @@ pub struct PagebreakNode; #[node] impl PagebreakNode { fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> { - let soft = args.named("soft")?.unwrap_or(false); - Ok(Content::Pagebreak(soft)) + let weak = args.named("weak")?.unwrap_or(false); + Ok(Content::Pagebreak { weak }) } } diff --git a/src/library/layout/spacing.rs b/src/library/layout/spacing.rs index 3468af5e..8a96e378 100644 --- a/src/library/layout/spacing.rs +++ b/src/library/layout/spacing.rs @@ -1,4 +1,7 @@ +use std::cmp::Ordering; + use crate::library::prelude::*; +use crate::library::text::ParNode; /// Horizontal spacing. pub struct HNode; @@ -6,7 +9,9 @@ pub struct HNode; #[node] impl HNode { fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> { - Ok(Content::Horizontal(args.expect("spacing")?)) + let amount = args.expect("spacing")?; + let weak = args.named("weak")?.unwrap_or(false); + Ok(Content::Horizontal { amount, weak }) } } @@ -16,7 +21,9 @@ pub struct VNode; #[node] impl VNode { fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> { - Ok(Content::Vertical(args.expect("spacing")?)) + let amount = args.expect("spacing")?; + let weak = args.named("weak")?.unwrap_or(false); + Ok(Content::Vertical { amount, weak, generated: false }) } } @@ -25,7 +32,8 @@ impl VNode { pub enum Spacing { /// Spacing specified in absolute terms and relative to the parent's size. Relative(Relative<RawLength>), - /// Spacing specified as a fraction of the remaining free space in the parent. + /// Spacing specified as a fraction of the remaining free space in the + /// parent. Fractional(Fraction), } @@ -42,6 +50,16 @@ impl From<Length> for Spacing { } } +impl PartialOrd for Spacing { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + match (self, other) { + (Self::Relative(a), Self::Relative(b)) => a.partial_cmp(b), + (Self::Fractional(a), Self::Fractional(b)) => a.partial_cmp(b), + _ => None, + } + } +} + castable! { Spacing, Expected: "relative length or fraction", @@ -50,3 +68,24 @@ castable! { Value::Relative(v) => Self::Relative(v), Value::Fraction(v) => Self::Fractional(v), } + +/// Spacing around and between block-level nodes, relative to paragraph spacing. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub struct BlockSpacing(Relative<RawLength>); + +castable!(BlockSpacing: Relative<RawLength>); + +impl Resolve for BlockSpacing { + type Output = Length; + + fn resolve(self, styles: StyleChain) -> Self::Output { + let whole = styles.get(ParNode::SPACING); + self.0.resolve(styles).relative_to(whole) + } +} + +impl From<Ratio> for BlockSpacing { + fn from(ratio: Ratio) -> Self { + Self(ratio.into()) + } +} diff --git a/src/library/layout/stack.rs b/src/library/layout/stack.rs index f915c215..bbfeeab0 100644 --- a/src/library/layout/stack.rs +++ b/src/library/layout/stack.rs @@ -1,5 +1,6 @@ use super::{AlignNode, Spacing}; use crate::library::prelude::*; +use crate::library::text::ParNode; /// Arrange nodes and spacing along an axis. #[derive(Debug, Hash)] @@ -180,7 +181,16 @@ impl<'a> StackLayouter<'a> { .downcast::<AlignNode>() .and_then(|node| node.aligns.get(self.axis)) .map(|align| align.resolve(styles)) - .unwrap_or(self.dir.start().into()); + .unwrap_or_else(|| { + if let Some(Content::Styled(styled)) = node.downcast::<Content>() { + let map = &styled.1; + if map.contains(ParNode::ALIGN) { + return StyleChain::with_root(&styled.1).get(ParNode::ALIGN); + } + } + + self.dir.start().into() + }); let frames = node.layout(ctx, &self.regions, styles)?; let len = frames.len(); |
