diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 2cff835ba..5a8b857a0 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -22,7 +22,7 @@ use fontdock::FontStyle; use crate::diag::Diag; use crate::diag::{Deco, Feedback, Pass}; -use crate::geom::{BoxAlign, Flow, Gen, Length, Linear, Relative, Sides, Size}; +use crate::geom::{BoxAlign, Dir, Flow, Gen, Length, Linear, Relative, Sides, Size}; use crate::layout::{ Document, Expansion, LayoutNode, Pad, Pages, Par, Softness, Spacing, Stack, Text, }; @@ -223,6 +223,23 @@ impl EvalContext { (group, std::mem::replace(&mut self.inner, outer)) } + /// Updates the flow directions if the resulting main and cross directions + /// apply to different axes. Generates an appropriate error, otherwise. + pub fn set_flow(&mut self, new: Gen>>) { + let flow = Gen::new( + new.main.map(|s| s.v).unwrap_or(self.state.flow.main), + new.cross.map(|s| s.v).unwrap_or(self.state.flow.cross), + ); + + if flow.main.axis() != flow.cross.axis() { + self.state.flow = flow; + } else { + for dir in new.main.iter().chain(new.cross.iter()) { + self.diag(error!(dir.span, "aligned axis")); + } + } + } + /// Construct a text node from the given string based on the active text /// state. pub fn make_text_node(&self, text: String) -> Text { diff --git a/src/library/align.rs b/src/library/align.rs index a54925f07..4f4a17500 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -17,7 +17,6 @@ use std::fmt::{self, Display, Formatter}; /// There may not be two alignment specifications for the same axis. pub fn align(mut args: Args, ctx: &mut EvalContext) -> Value { let snapshot = ctx.state.clone(); - let body = args.find::(); let first = args.get::<_, Spanned>(ctx, 0); let second = args.get::<_, Spanned>(ctx, 1); @@ -33,13 +32,14 @@ pub fn align(mut args: Args, ctx: &mut EvalContext) -> Value { .chain(ver.into_iter().map(|align| (Some(SpecAxis::Vertical), align))); let align = dedup_aligns(ctx, iter); - if align.main != ctx.state.align.main { + let ends_par = align.main != ctx.state.align.main; + ctx.state.align = align; + + if ends_par { ctx.end_par_group(); ctx.start_par_group(); } - ctx.state.align = align; - if let Some(body) = body { body.eval(ctx); ctx.state = snapshot; diff --git a/src/library/boxed.rs b/src/library/boxed.rs index 3d7214ae0..1ec17d880 100644 --- a/src/library/boxed.rs +++ b/src/library/boxed.rs @@ -9,10 +9,12 @@ use crate::prelude::*; /// - `height`: The height of the box (length or relative to parent's height). pub fn boxed(mut args: Args, ctx: &mut EvalContext) -> Value { let snapshot = ctx.state.clone(); - let body = args.find::().unwrap_or_default(); let width = args.get::<_, Linear>(ctx, "width"); let height = args.get::<_, Linear>(ctx, "height"); + let main = args.get::<_, Spanned>(ctx, "main"); + let cross = args.get::<_, Spanned>(ctx, "cross"); + ctx.set_flow(Gen::new(main, cross)); args.done(ctx); let flow = ctx.state.flow; diff --git a/src/library/font.rs b/src/library/font.rs index bb84f06be..5de0a953c 100644 --- a/src/library/font.rs +++ b/src/library/font.rs @@ -53,7 +53,6 @@ use crate::prelude::*; /// ``` pub fn font(mut args: Args, ctx: &mut EvalContext) -> Value { let snapshot = ctx.state.clone(); - let body = args.find::(); if let Some(linear) = args.find::() { @@ -67,7 +66,6 @@ pub fn font(mut args: Args, ctx: &mut EvalContext) -> Value { let mut needs_flattening = false; let list: Vec<_> = args.find_all::().map(|s| s.to_lowercase()).collect(); - if !list.is_empty() { Rc::make_mut(&mut ctx.state.font.families).list = list; needs_flattening = true; diff --git a/src/library/page.rs b/src/library/page.rs index efb40f100..057098650 100644 --- a/src/library/page.rs +++ b/src/library/page.rs @@ -17,6 +17,9 @@ use crate::prelude::*; /// - `bottom`: The bottom margin (length or relative to height). /// - `flip`: Flips custom or paper-defined width and height (boolean). pub fn page(mut args: Args, ctx: &mut EvalContext) -> Value { + let snapshot = ctx.state.clone(); + let body = args.find::(); + if let Some(paper) = args.find::() { ctx.state.page.class = paper.class; ctx.state.page.size = paper.size(); @@ -57,8 +60,19 @@ pub fn page(mut args: Args, ctx: &mut EvalContext) -> Value { std::mem::swap(&mut size.width, &mut size.height); } + let main = args.get::<_, Spanned>(ctx, "main"); + let cross = args.get::<_, Spanned>(ctx, "cross"); + ctx.set_flow(Gen::new(main, cross)); + args.done(ctx); + if let Some(body) = body { + ctx.end_page_group(); + ctx.start_page_group(true); + body.eval(ctx); + ctx.state = snapshot; + } + ctx.end_page_group(); ctx.start_page_group(false);