Factor out alignment deduplication into separate function ♻

This commit is contained in:
Laurenz 2021-03-13 16:57:15 +01:00
parent f190d33d0c
commit ceb00a2e77
4 changed files with 80 additions and 72 deletions

View File

@ -619,8 +619,9 @@ impl From<ValueAny> for Value {
/// - [`Cast<Value>`](Cast) for `T`. /// - [`Cast<Value>`](Cast) for `T`.
/// ///
/// # Example /// # Example
/// Make a type `FontFamily` that can be cast from a [`Value::Any`] variant /// Allow a type `FontFamily` to be cast from:
/// containing a `FontFamily` or from a string. /// - a [`Value::Any`] variant already containing a `FontFamily`
/// - a string, producing a `FontFamiliy::Named(..)`.
/// ``` /// ```
/// # use typst::typify; /// # use typst::typify;
/// # enum FontFamily { Named(String) } /// # enum FontFamily { Named(String) }

View File

@ -41,7 +41,7 @@ fn shrink(areas: &Areas, padding: Sides<Linear>) -> Areas {
} }
} }
/// Enlarge the box and move all elements inwards. /// Enlarge the frame and move all elements inwards.
fn pad(frame: &mut Frame, padding: Sides<Linear>) { fn pad(frame: &mut Frame, padding: Sides<Linear>) {
let padding = padding.resolve(frame.size); let padding = padding.resolve(frame.size);
let origin = Point::new(padding.left, padding.top); let origin = Point::new(padding.left, padding.top);

View File

@ -32,17 +32,35 @@ pub fn align(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value {
Value::template("align", move |ctx| { Value::template("align", move |ctx| {
let snapshot = ctx.state.clone(); let snapshot = ctx.state.clone();
let values = first
.into_iter()
.chain(second.into_iter())
.map(|arg: Spanned<AlignValue>| (arg.v.axis(), arg))
.chain(hor.into_iter().map(|arg| (Some(SpecAxis::Horizontal), arg)))
.chain(ver.into_iter().map(|arg| (Some(SpecAxis::Vertical), arg)));
apply(ctx, values);
if ctx.state.aligns.main != snapshot.aligns.main {
ctx.push_linebreak();
}
if let Some(body) = &body {
body.exec(ctx);
ctx.state = snapshot;
}
})
}
/// Deduplicate and apply the alignments.
fn apply(
ctx: &mut ExecContext,
values: impl Iterator<Item = (Option<SpecAxis>, Spanned<AlignValue>)>,
) {
let mut had = Gen::uniform(false); let mut had = Gen::uniform(false);
let mut had_center = false; let mut had_center = false;
// Infer the axes alignments belong to. for (axis, Spanned { v: arg, span }) in values {
for (axis, Spanned { v: arg, span }) in first
.into_iter()
.chain(second.into_iter())
.map(|arg: Spanned<Alignment>| (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. // Check whether we know which axis this alignment belongs to.
if let Some(axis) = axis { if let Some(axis) = axis {
// We know the axis. // We know the axis.
@ -60,7 +78,7 @@ pub fn align(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value {
} else { } else {
// We don't know the axis: This has to be a `center` alignment for a // We don't know the axis: This has to be a `center` alignment for a
// positional argument. // positional argument.
debug_assert_eq!(arg, Alignment::Center); debug_assert_eq!(arg, AlignValue::Center);
if had.main && had.cross { if had.main && had.cross {
ctx.diag(error!(span, "duplicate alignment")); ctx.diag(error!(span, "duplicate alignment"));
@ -80,11 +98,10 @@ pub fn align(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value {
if had_center && (had.main || had.cross) { if had_center && (had.main || had.cross) {
if had.main { if had.main {
ctx.state.aligns.cross = Align::Center; ctx.state.aligns.cross = Align::Center;
had.cross = true;
} else { } else {
ctx.state.aligns.main = Align::Center; ctx.state.aligns.main = Align::Center;
had.main = true;
} }
had = Gen::uniform(true);
had_center = false; had_center = false;
} }
} }
@ -94,21 +111,11 @@ pub fn align(ctx: &mut EvalContext, args: &mut ValueArgs) -> Value {
if had_center { if had_center {
ctx.state.aligns.cross = Align::Center; ctx.state.aligns.cross = Align::Center;
} }
if ctx.state.aligns.main != snapshot.aligns.main {
ctx.push_linebreak();
}
if let Some(body) = &body {
body.exec(ctx);
ctx.state = snapshot;
}
})
} }
/// An alignment argument. /// An alignment value.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub(super) enum Alignment { pub(super) enum AlignValue {
Left, Left,
Center, Center,
Right, Right,
@ -116,7 +123,7 @@ pub(super) enum Alignment {
Bottom, Bottom,
} }
impl Alignment { impl AlignValue {
/// The specific axis this alignment refers to. /// The specific axis this alignment refers to.
fn axis(self) -> Option<SpecAxis> { fn axis(self) -> Option<SpecAxis> {
match self { match self {
@ -129,7 +136,7 @@ impl Alignment {
} }
} }
impl Switch for Alignment { impl Switch for AlignValue {
type Other = Align; type Other = Align;
fn switch(self, dirs: LayoutDirs) -> Self::Other { 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 { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.pad(match self { f.pad(match self {
Self::Left => "left", Self::Left => "left",
@ -165,5 +172,5 @@ impl Display for Alignment {
} }
typify! { typify! {
Alignment: "alignment", AlignValue: "alignment",
} }

View File

@ -57,11 +57,11 @@ pub fn new() -> Scope {
set!(func: "v", v); set!(func: "v", v);
// Constants. // Constants.
set!(any: "left", Alignment::Left); set!(any: "left", AlignValue::Left);
set!(any: "center", Alignment::Center); set!(any: "center", AlignValue::Center);
set!(any: "right", Alignment::Right); set!(any: "right", AlignValue::Right);
set!(any: "top", Alignment::Top); set!(any: "top", AlignValue::Top);
set!(any: "bottom", Alignment::Bottom); set!(any: "bottom", AlignValue::Bottom);
set!(any: "ltr", Dir::LTR); set!(any: "ltr", Dir::LTR);
set!(any: "rtl", Dir::RTL); set!(any: "rtl", Dir::RTL);
set!(any: "ttb", Dir::TTB); set!(any: "ttb", Dir::TTB);