mirror of
https://github.com/typst/typst
synced 2025-07-29 23:37:55 +08:00
185 lines
4.3 KiB
Rust
185 lines
4.3 KiB
Rust
use ecow::EcoString;
|
|
|
|
use crate::foundations::{func, scope, ty, Repr};
|
|
use crate::layout::{Axis, Side};
|
|
|
|
/// The four directions into which content can be laid out.
|
|
///
|
|
/// Possible values are:
|
|
/// - `{ltr}`: Left to right.
|
|
/// - `{rtl}`: Right to left.
|
|
/// - `{ttb}`: Top to bottom.
|
|
/// - `{btt}`: Bottom to top.
|
|
///
|
|
/// These values are available globally and
|
|
/// also in the direction type's scope, so you can write either of the following
|
|
/// two:
|
|
/// ```example
|
|
/// #stack(dir: rtl)[A][B][C]
|
|
/// #stack(dir: direction.rtl)[A][B][C]
|
|
/// ```
|
|
#[ty(scope, name = "direction")]
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
pub enum Dir {
|
|
/// Left to right.
|
|
LTR,
|
|
/// Right to left.
|
|
RTL,
|
|
/// Top to bottom.
|
|
TTB,
|
|
/// Bottom to top.
|
|
BTT,
|
|
}
|
|
|
|
impl Dir {
|
|
/// Whether this direction points into the positive coordinate direction.
|
|
///
|
|
/// The positive directions are left-to-right and top-to-bottom.
|
|
pub const fn is_positive(self) -> bool {
|
|
match self {
|
|
Self::LTR | Self::TTB => true,
|
|
Self::RTL | Self::BTT => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[scope]
|
|
impl Dir {
|
|
pub const LTR: Self = Self::LTR;
|
|
pub const RTL: Self = Self::RTL;
|
|
pub const TTB: Self = Self::TTB;
|
|
pub const BTT: Self = Self::BTT;
|
|
|
|
/// Returns a direction from a starting point.
|
|
///
|
|
/// ```example
|
|
/// direction.from(left) \
|
|
/// direction.from(right) \
|
|
/// direction.from(top) \
|
|
/// direction.from(bottom)
|
|
/// ```
|
|
#[func]
|
|
pub const fn from(side: Side) -> Dir {
|
|
match side {
|
|
Side::Left => Self::LTR,
|
|
Side::Right => Self::RTL,
|
|
Side::Top => Self::TTB,
|
|
Side::Bottom => Self::BTT,
|
|
}
|
|
}
|
|
|
|
/// Returns a direction from an end point.
|
|
///
|
|
/// ```example
|
|
/// direction.to(left) \
|
|
/// direction.to(right) \
|
|
/// direction.to(top) \
|
|
/// direction.to(bottom)
|
|
/// ```
|
|
#[func]
|
|
pub const fn to(side: Side) -> Dir {
|
|
match side {
|
|
Side::Right => Self::LTR,
|
|
Side::Left => Self::RTL,
|
|
Side::Bottom => Self::TTB,
|
|
Side::Top => Self::BTT,
|
|
}
|
|
}
|
|
|
|
/// The axis this direction belongs to, either `{"horizontal"}` or
|
|
/// `{"vertical"}`.
|
|
///
|
|
/// ```example
|
|
/// #ltr.axis() \
|
|
/// #ttb.axis()
|
|
/// ```
|
|
#[func]
|
|
pub const fn axis(self) -> Axis {
|
|
match self {
|
|
Self::LTR | Self::RTL => Axis::X,
|
|
Self::TTB | Self::BTT => Axis::Y,
|
|
}
|
|
}
|
|
|
|
/// The corresponding sign, for use in calculations.
|
|
///
|
|
/// ```example
|
|
/// #ltr.sign() \
|
|
/// #rtl.sign() \
|
|
/// #ttb.sign() \
|
|
/// #btt.sign()
|
|
/// ```
|
|
#[func]
|
|
pub const fn sign(self) -> i64 {
|
|
match self {
|
|
Self::LTR | Self::TTB => 1,
|
|
Self::RTL | Self::BTT => -1,
|
|
}
|
|
}
|
|
|
|
/// The start point of this direction, as an alignment.
|
|
///
|
|
/// ```example
|
|
/// #ltr.start() \
|
|
/// #rtl.start() \
|
|
/// #ttb.start() \
|
|
/// #btt.start()
|
|
/// ```
|
|
#[func]
|
|
pub const fn start(self) -> Side {
|
|
match self {
|
|
Self::LTR => Side::Left,
|
|
Self::RTL => Side::Right,
|
|
Self::TTB => Side::Top,
|
|
Self::BTT => Side::Bottom,
|
|
}
|
|
}
|
|
|
|
/// The end point of this direction, as an alignment.
|
|
///
|
|
/// ```example
|
|
/// #ltr.end() \
|
|
/// #rtl.end() \
|
|
/// #ttb.end() \
|
|
/// #btt.end()
|
|
/// ```
|
|
#[func]
|
|
pub const fn end(self) -> Side {
|
|
match self {
|
|
Self::LTR => Side::Right,
|
|
Self::RTL => Side::Left,
|
|
Self::TTB => Side::Bottom,
|
|
Self::BTT => Side::Top,
|
|
}
|
|
}
|
|
|
|
/// The inverse direction.
|
|
///
|
|
/// ```example
|
|
/// #ltr.inv() \
|
|
/// #rtl.inv() \
|
|
/// #ttb.inv() \
|
|
/// #btt.inv()
|
|
/// ```
|
|
#[func(title = "Inverse")]
|
|
pub const fn inv(self) -> Dir {
|
|
match self {
|
|
Self::LTR => Self::RTL,
|
|
Self::RTL => Self::LTR,
|
|
Self::TTB => Self::BTT,
|
|
Self::BTT => Self::TTB,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Repr for Dir {
|
|
fn repr(&self) -> EcoString {
|
|
match self {
|
|
Self::LTR => "ltr".into(),
|
|
Self::RTL => "rtl".into(),
|
|
Self::TTB => "ttb".into(),
|
|
Self::BTT => "btt".into(),
|
|
}
|
|
}
|
|
}
|