Horizon alignment

This commit is contained in:
Laurenz 2021-11-23 11:58:16 +01:00
parent 02f114d072
commit d3f6040ced
9 changed files with 42 additions and 48 deletions

View File

@ -3,27 +3,26 @@ use super::*;
/// Where to align something along an axis.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Align {
/// Align at the left side of the axis.
/// Align at the left side.
Left,
/// Align at the top side of the axis.
Top,
/// Align in the middle of the axis.
/// Align in the horizontal middle.
Center,
/// Align at the right side of the axis.
/// Align at the right side.
Right,
/// Align at the bottom side of the axis.
/// Align at the top side.
Top,
/// Align in the vertical middle.
Horizon,
/// Align at the bottom side.
Bottom,
}
impl Align {
/// The axis this alignment belongs to if it is specific.
pub const fn axis(self) -> Option<SpecAxis> {
/// The axis this alignment belongs to.
pub const fn axis(self) -> SpecAxis {
match self {
Self::Left => Some(SpecAxis::Horizontal),
Self::Top => Some(SpecAxis::Vertical),
Self::Center => None,
Self::Right => Some(SpecAxis::Horizontal),
Self::Bottom => Some(SpecAxis::Vertical),
Self::Left | Self::Center | Self::Right => SpecAxis::Horizontal,
Self::Top | Self::Horizon | Self::Bottom => SpecAxis::Vertical,
}
}
@ -31,9 +30,10 @@ impl Align {
pub const fn inv(self) -> Self {
match self {
Self::Left => Self::Right,
Self::Top => Self::Bottom,
Self::Center => Self::Center,
Self::Right => Self::Left,
Self::Top => Self::Bottom,
Self::Horizon => Self::Horizon,
Self::Bottom => Self::Top,
}
}
@ -42,8 +42,8 @@ impl Align {
pub fn resolve(self, range: Range<Length>) -> Length {
match self {
Self::Left | Self::Top => range.start,
Self::Center | Self::Horizon => (range.start + range.end) / 2.0,
Self::Right | Self::Bottom => range.end,
Self::Center => (range.start + range.end) / 2.0,
}
}
}
@ -63,9 +63,10 @@ impl Debug for Align {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.pad(match self {
Self::Left => "left",
Self::Top => "top",
Self::Center => "center",
Self::Right => "right",
Self::Top => "top",
Self::Horizon => "horizon",
Self::Bottom => "bottom",
})
}

View File

@ -14,6 +14,14 @@ pub enum Dir {
}
impl Dir {
/// The specific axis this direction belongs to.
pub const fn axis(self) -> SpecAxis {
match self {
Self::LTR | Self::RTL => SpecAxis::Horizontal,
Self::TTB | Self::BTT => SpecAxis::Vertical,
}
}
/// The side this direction starts at.
pub const fn start(self) -> Side {
match self {
@ -34,11 +42,13 @@ impl Dir {
}
}
/// The specific axis this direction belongs to.
pub const fn axis(self) -> SpecAxis {
/// The inverse direction.
pub const fn inv(self) -> Self {
match self {
Self::LTR | Self::RTL => SpecAxis::Horizontal,
Self::TTB | Self::BTT => SpecAxis::Vertical,
Self::LTR => Self::RTL,
Self::RTL => Self::LTR,
Self::TTB => Self::BTT,
Self::BTT => Self::TTB,
}
}
@ -51,24 +61,6 @@ impl Dir {
Self::RTL | Self::BTT => false,
}
}
/// The factor for this direction.
///
/// - `1.0` if the direction is positive.
/// - `-1.0` if the direction is negative.
pub const fn factor(self) -> f64 {
if self.is_positive() { 1.0 } else { -1.0 }
}
/// The inverse direction.
pub const fn inv(self) -> Self {
match self {
Self::LTR => Self::RTL,
Self::RTL => Self::LTR,
Self::TTB => Self::BTT,
Self::BTT => Self::TTB,
}
}
}
impl Debug for Dir {

View File

@ -20,8 +20,8 @@ pub(super) fn parse_aligns(args: &mut Args) -> TypResult<Spec<Option<Align>>> {
let mut y = args.named("vertical")?;
for Spanned { v, span } in args.all::<Spanned<Align>>() {
match v.axis() {
None | Some(SpecAxis::Horizontal) if x.is_none() => x = Some(v),
None | Some(SpecAxis::Vertical) if y.is_none() => y = Some(v),
SpecAxis::Horizontal if x.is_none() => x = Some(v),
SpecAxis::Vertical if y.is_none() => y = Some(v),
_ => bail!(span, "unexpected argument"),
}
}

View File

@ -121,9 +121,10 @@ pub fn new() -> Scope {
std.def_const("ttb", Dir::TTB);
std.def_const("btt", Dir::BTT);
std.def_const("left", Align::Left);
std.def_const("top", Align::Top);
std.def_const("center", Align::Center);
std.def_const("right", Align::Right);
std.def_const("top", Align::Top);
std.def_const("horizon", Align::Horizon);
std.def_const("bottom", Align::Bottom);
std.def_const("serif", FontFamily::Serif);
std.def_const("sans-serif", FontFamily::SansSerif);

View File

@ -33,7 +33,7 @@ pub fn par(ctx: &mut EvalContext, args: &mut Args) -> TypResult<Value> {
let mut align = None;
if let Some(Spanned { v, span }) = args.named::<Spanned<Align>>("align")? {
if matches!(v.axis(), None | Some(SpecAxis::Horizontal)) {
if v.axis() == SpecAxis::Horizontal {
align = Some(v);
} else {
bail!(span, "must be horizontal");

View File

@ -10,12 +10,12 @@
Auto-sized circle. \
#circle(fill: rgb("eb5278"), thickness: 2pt,
align(center, center)[But, soft!]
align(center, horizon)[But, soft!]
)
Center-aligned rect in auto-sized circle.
#circle(fill: forest, stroke: conifer,
align(center, center,
align(center, horizon,
rect(fill: conifer, pad(5pt)[But, soft!])
)
)
@ -37,7 +37,7 @@ Expanded by height.
---
// Test relative sizing.
#let centered(body) = align(center, center, body)
#let centered(body) = align(center, horizon, body)
#font(fill: white)
#rect(width: 100pt, height: 50pt, fill: rgb("aaa"), centered[
#circle(radius: 10pt, fill: eastern, centered[A]) // D=20pt

View File

@ -9,7 +9,7 @@ Rect in ellipse in fixed rect. \
#rect(width: 3cm, height: 2cm, fill: rgb("2a631a"),
ellipse(fill: forest,
rect(fill: conifer,
align(center, center)[
align(center, horizon)[
Stuff inside an ellipse!
]
)

View File

@ -16,7 +16,7 @@
rect(fill: forest, thickness: 2pt),
rect(fill: forest, stroke: conifer, thickness: 2pt),
) {
(align(vertical: center)[{i + 1}.], rect, [])
(align(horizon)[{i + 1}.], rect, [])
}
#grid(

View File

@ -7,7 +7,7 @@
align(center, square(size: 20pt, fill: eastern)),
align(right, square(size: 15pt, fill: eastern)),
)
#align(center, center, rect(fill: eastern, height: 10pt))
#align(center, horizon, rect(fill: eastern, height: 10pt))
#align(bottom, stack(
align(center, rect(fill: conifer, height: 10pt)),
rect(fill: forest, height: 10pt),