diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-09-27 13:40:56 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-09-27 13:45:18 +0200 |
| commit | e10b3d838a75ea351f8477e07f2e1e647f4539dc (patch) | |
| tree | 286183d4b7492ecf95b7a8b0a9c245bb85191db5 | |
| parent | ff37a2893dc7f0a29faa7cc57ccb4d746f483bed (diff) | |
Fix panic due to bad alignments in stack function
| -rw-r--r-- | src/eval/ops.rs | 6 | ||||
| -rw-r--r-- | src/layout/par.rs | 6 | ||||
| -rw-r--r-- | src/layout/stack.rs | 12 | ||||
| -rw-r--r-- | src/library/layout.rs | 24 | ||||
| -rw-r--r-- | tests/ref/layout/stack.png | bin | 325 -> 318 bytes | |||
| -rw-r--r-- | tests/typ/layout/stack.typ | 34 |
6 files changed, 57 insertions, 25 deletions
diff --git a/src/eval/ops.rs b/src/eval/ops.rs index c7a45614..8756e8c6 100644 --- a/src/eval/ops.rs +++ b/src/eval/ops.rs @@ -181,13 +181,13 @@ pub fn div(lhs: Value, rhs: Value) -> StrResult<Value> { (Relative(a), Float(b)) => Relative(a / b), (Relative(a), Relative(b)) => Float(a / b), + (Linear(a), Int(b)) => Linear(a / b as f64), + (Linear(a), Float(b)) => Linear(a / b), + (Fractional(a), Int(b)) => Fractional(a / b as f64), (Fractional(a), Float(b)) => Fractional(a / b), (Fractional(a), Fractional(b)) => Float(a / b), - (Linear(a), Int(b)) => Linear(a / b as f64), - (Linear(a), Float(b)) => Linear(a / b), - (a, b) => mismatch!("cannot divide {} by {}", a, b), }) } diff --git a/src/layout/par.rs b/src/layout/par.rs index 847612b9..beb7a1d6 100644 --- a/src/layout/par.rs +++ b/src/layout/par.rs @@ -96,9 +96,9 @@ impl From<ParNode> for LayoutNode { impl Debug for ParChild { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - ParChild::Spacing(v) => write!(f, "Spacing({:?})", v), - ParChild::Text(text, ..) => write!(f, "Text({:?})", text), - ParChild::Any(node, ..) => f.debug_tuple("Any").field(node).finish(), + Self::Spacing(v) => write!(f, "Spacing({:?})", v), + Self::Text(text, ..) => write!(f, "Text({:?})", text), + Self::Any(node, ..) => node.fmt(f), } } } diff --git a/src/layout/stack.rs b/src/layout/stack.rs index 4b148ad8..e3416e6b 100644 --- a/src/layout/stack.rs +++ b/src/layout/stack.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Debug, Formatter}; + use super::*; /// A node that stacks its children. @@ -14,7 +16,6 @@ pub struct StackNode { } /// A child of a stack node. -#[derive(Debug)] #[cfg_attr(feature = "layout-cache", derive(Hash))] pub enum StackChild { /// Spacing between other nodes. @@ -39,6 +40,15 @@ impl From<StackNode> for LayoutNode { } } +impl Debug for StackChild { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Self::Spacing(v) => write!(f, "Spacing({:?})", v), + Self::Any(node, _) => node.fmt(f), + } + } +} + /// Performs stack layout. struct StackLayouter<'a> { /// The stack node to layout. diff --git a/src/library/layout.rs b/src/library/layout.rs index 8f645869..e958f3a3 100644 --- a/src/library/layout.rs +++ b/src/library/layout.rs @@ -192,11 +192,6 @@ pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { let children: Vec<Template> = args.all().collect(); Ok(Value::Template(Template::from_block(move |state| { - let children = children - .iter() - .map(|child| StackChild::Any(child.to_stack(state).into(), state.aligns)) - .collect(); - let mut dirs = Gen::new(None, dir).unwrap_or(state.dirs); // If the directions become aligned, fix up the inline direction since @@ -205,6 +200,19 @@ pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { dirs.inline = state.dirs.block; } + // Use the current alignments for all children, but take care to apply + // them to the correct axes (by swapping them if the stack axes are + // different from the state axes). + let mut aligns = state.aligns; + if dirs.block.axis() == state.dirs.inline.axis() { + aligns = Gen::new(aligns.block, aligns.inline); + } + + let children = children + .iter() + .map(|child| StackChild::Any(child.to_stack(state).into(), aligns)) + .collect(); + StackNode { dirs, children } }))) } @@ -233,9 +241,6 @@ pub fn grid(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { ); Ok(Value::Template(Template::from_block(move |state| { - let children = - children.iter().map(|child| child.to_stack(&state).into()).collect(); - // If the directions become aligned, try to fix up the direction which // is not user-defined. let mut dirs = Gen::new(column_dir, row_dir).unwrap_or(state.dirs); @@ -253,6 +258,9 @@ pub fn grid(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { }; } + let children = + children.iter().map(|child| child.to_stack(&state).into()).collect(); + GridNode { dirs, tracks: tracks.clone(), diff --git a/tests/ref/layout/stack.png b/tests/ref/layout/stack.png Binary files differindex 2f190c4d..bc0eb48b 100644 --- a/tests/ref/layout/stack.png +++ b/tests/ref/layout/stack.png diff --git a/tests/typ/layout/stack.typ b/tests/typ/layout/stack.typ index 729d85fc..384f574f 100644 --- a/tests/typ/layout/stack.typ +++ b/tests/typ/layout/stack.typ @@ -1,18 +1,32 @@ // Test stack layouts. --- -#let rect(width, fill) = rect(width: width, height: 1cm, fill: fill) -#stack( - rect(2cm, rgb("2a631a")), - rect(3cm, forest), - rect(1cm, conifer), +// Test stacks with different directions. +#let widths = ( + 30pt, 20pt, 40pt, 15pt, + 30pt, 50%, 20pt, 100%, ) +#let shaded = { + let v = 0 + let next() = { v += 0.1; rgb(v, v, v) } + w => rect(width: w, height: 10pt, fill: next()) +} + +#let items = for w in widths { (shaded(w),) } + +#align(right) +#page(width: 50pt, margins: 0pt) +#stack(dir: btt, ..items) +#pagebreak() + +// Currently stack works like flexbox apparently. +#stack(dir: ltr, ..items) + --- // Test overflowing stack. - -#let rect(width, fill) = rect(width: 1cm, height: 0.4cm, fill: fill) -#box(height: 0.5cm, stack( - rect(3cm, forest), - rect(1cm, conifer), +#page(width: 50pt, height: 30pt, margins: 0pt) +#box(stack( + rect(width: 40pt, height: 20pt, fill: conifer), + rect(width: 30pt, height: 13pt, fill: forest), )) |
