diff --git a/src/eval/value.rs b/src/eval/value.rs index 7f31ea138..206369177 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -619,8 +619,9 @@ impl From for Value { /// - [`Cast`](Cast) for `T`. /// /// # Example -/// Make a type `FontFamily` that can be cast from a [`Value::Any`] variant -/// containing a `FontFamily` or from a string. +/// Allow a type `FontFamily` to be cast from: +/// - a [`Value::Any`] variant already containing a `FontFamily` +/// - a string, producing a `FontFamiliy::Named(..)`. /// ``` /// # use typst::typify; /// # enum FontFamily { Named(String) } diff --git a/src/layout/pad.rs b/src/layout/pad.rs index 02adebeb0..88ef88284 100644 --- a/src/layout/pad.rs +++ b/src/layout/pad.rs @@ -41,7 +41,7 @@ fn shrink(areas: &Areas, padding: Sides) -> Areas { } } -/// Enlarge the box and move all elements inwards. +/// Enlarge the frame and move all elements inwards. fn pad(frame: &mut Frame, padding: Sides) { let padding = padding.resolve(frame.size); let origin = Point::new(padding.left, padding.top); diff --git a/src/library/align.rs b/src/library/align.rs index 98feb3ef7..31367a5a1 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -32,68 +32,14 @@ pub fn align(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value { Value::template("align", move |ctx| { let snapshot = ctx.state.clone(); - let mut had = Gen::uniform(false); - let mut had_center = false; - - // Infer the axes alignments belong to. - for (axis, Spanned { v: arg, span }) in first + let values = first .into_iter() .chain(second.into_iter()) - .map(|arg: Spanned| (arg.v.axis(), arg)) + .map(|arg: Spanned| (arg.v.axis(), arg)) .chain(hor.into_iter().map(|arg| (Some(SpecAxis::Horizontal), arg))) - .chain(ver.into_iter().map(|arg| (Some(SpecAxis::Vertical), arg))) - { - // Check whether we know which axis this alignment belongs to. - if let Some(axis) = axis { - // We know the axis. - let gen_axis = axis.switch(ctx.state.dirs); - let gen_align = arg.switch(ctx.state.dirs); + .chain(ver.into_iter().map(|arg| (Some(SpecAxis::Vertical), arg))); - if arg.axis().map_or(false, |a| a != axis) { - ctx.diag(error!(span, "invalid alignment for {} axis", axis)); - } else if had.get(gen_axis) { - ctx.diag(error!(span, "duplicate alignment for {} axis", axis)); - } else { - *ctx.state.aligns.get_mut(gen_axis) = gen_align; - *had.get_mut(gen_axis) = true; - } - } else { - // We don't know the axis: This has to be a `center` alignment for a - // positional argument. - debug_assert_eq!(arg, Alignment::Center); - - if had.main && had.cross { - ctx.diag(error!(span, "duplicate alignment")); - } else if had_center { - // Both this and the previous one are unspecified `center` - // alignments. Both axes should be centered. - ctx.state.aligns.main = Align::Center; - ctx.state.aligns.cross = Align::Center; - had = Gen::uniform(true); - } else { - had_center = true; - } - } - - // If we we know the other alignment, we can handle the unspecified - // `center` alignment. - if had_center && (had.main || had.cross) { - if had.main { - ctx.state.aligns.cross = Align::Center; - had.cross = true; - } else { - ctx.state.aligns.main = Align::Center; - had.main = true; - } - had_center = false; - } - } - - // If `had_center` wasn't flushed by now, it's the only argument and - // then we default to applying it to the cross axis. - if had_center { - ctx.state.aligns.cross = Align::Center; - } + apply(ctx, values); if ctx.state.aligns.main != snapshot.aligns.main { ctx.push_linebreak(); @@ -106,9 +52,70 @@ pub fn align(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value { }) } -/// An alignment argument. +/// Deduplicate and apply the alignments. +fn apply( + ctx: &mut ExecContext, + values: impl Iterator, Spanned)>, +) { + let mut had = Gen::uniform(false); + let mut had_center = false; + + for (axis, Spanned { v: arg, span }) in values { + // Check whether we know which axis this alignment belongs to. + if let Some(axis) = axis { + // We know the axis. + let gen_axis = axis.switch(ctx.state.dirs); + let gen_align = arg.switch(ctx.state.dirs); + + if arg.axis().map_or(false, |a| a != axis) { + ctx.diag(error!(span, "invalid alignment for {} axis", axis)); + } else if had.get(gen_axis) { + ctx.diag(error!(span, "duplicate alignment for {} axis", axis)); + } else { + *ctx.state.aligns.get_mut(gen_axis) = gen_align; + *had.get_mut(gen_axis) = true; + } + } else { + // We don't know the axis: This has to be a `center` alignment for a + // positional argument. + debug_assert_eq!(arg, AlignValue::Center); + + if had.main && had.cross { + ctx.diag(error!(span, "duplicate alignment")); + } else if had_center { + // Both this and the previous one are unspecified `center` + // alignments. Both axes should be centered. + ctx.state.aligns.main = Align::Center; + ctx.state.aligns.cross = Align::Center; + had = Gen::uniform(true); + } else { + had_center = true; + } + } + + // If we we know the other alignment, we can handle the unspecified + // `center` alignment. + if had_center && (had.main || had.cross) { + if had.main { + ctx.state.aligns.cross = Align::Center; + } else { + ctx.state.aligns.main = Align::Center; + } + had = Gen::uniform(true); + had_center = false; + } + } + + // If `had_center` wasn't flushed by now, it's the only argument and + // then we default to applying it to the cross axis. + if had_center { + ctx.state.aligns.cross = Align::Center; + } +} + +/// An alignment value. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] -pub(super) enum Alignment { +pub(super) enum AlignValue { Left, Center, Right, @@ -116,7 +123,7 @@ pub(super) enum Alignment { Bottom, } -impl Alignment { +impl AlignValue { /// The specific axis this alignment refers to. fn axis(self) -> Option { match self { @@ -129,7 +136,7 @@ impl Alignment { } } -impl Switch for Alignment { +impl Switch for AlignValue { type Other = Align; fn switch(self, dirs: LayoutDirs) -> Self::Other { @@ -152,7 +159,7 @@ impl Switch for Alignment { } } -impl Display for Alignment { +impl Display for AlignValue { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.pad(match self { Self::Left => "left", @@ -165,5 +172,5 @@ impl Display for Alignment { } typify! { - Alignment: "alignment", + AlignValue: "alignment", } diff --git a/src/library/mod.rs b/src/library/mod.rs index 54d6a14cb..b33ec7116 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -57,11 +57,11 @@ pub fn new() -> Scope { set!(func: "v", v); // Constants. - set!(any: "left", Alignment::Left); - set!(any: "center", Alignment::Center); - set!(any: "right", Alignment::Right); - set!(any: "top", Alignment::Top); - set!(any: "bottom", Alignment::Bottom); + set!(any: "left", AlignValue::Left); + set!(any: "center", AlignValue::Center); + set!(any: "right", AlignValue::Right); + set!(any: "top", AlignValue::Top); + set!(any: "bottom", AlignValue::Bottom); set!(any: "ltr", Dir::LTR); set!(any: "rtl", Dir::RTL); set!(any: "ttb", Dir::TTB);