typst_library/layout/dir.rs
1use ecow::EcoString;
2
3use crate::foundations::{func, scope, ty, Repr};
4use crate::layout::{Axis, Side};
5
6/// The four directions into which content can be laid out.
7///
8/// Possible values are:
9/// - `{ltr}`: Left to right.
10/// - `{rtl}`: Right to left.
11/// - `{ttb}`: Top to bottom.
12/// - `{btt}`: Bottom to top.
13///
14/// These values are available globally and
15/// also in the direction type's scope, so you can write either of the following
16/// two:
17/// ```example
18/// #stack(dir: rtl)[A][B][C]
19/// #stack(dir: direction.rtl)[A][B][C]
20/// ```
21#[ty(scope, name = "direction")]
22#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
23pub enum Dir {
24 /// Left to right.
25 LTR,
26 /// Right to left.
27 RTL,
28 /// Top to bottom.
29 TTB,
30 /// Bottom to top.
31 BTT,
32}
33
34impl Dir {
35 /// Whether this direction points into the positive coordinate direction.
36 ///
37 /// The positive directions are left-to-right and top-to-bottom.
38 pub const fn is_positive(self) -> bool {
39 match self {
40 Self::LTR | Self::TTB => true,
41 Self::RTL | Self::BTT => false,
42 }
43 }
44}
45
46#[scope]
47impl Dir {
48 pub const LTR: Self = Self::LTR;
49 pub const RTL: Self = Self::RTL;
50 pub const TTB: Self = Self::TTB;
51 pub const BTT: Self = Self::BTT;
52
53 /// The axis this direction belongs to, either `{"horizontal"}` or
54 /// `{"vertical"}`.
55 ///
56 /// ```example
57 /// #ltr.axis() \
58 /// #ttb.axis()
59 /// ```
60 #[func]
61 pub const fn axis(self) -> Axis {
62 match self {
63 Self::LTR | Self::RTL => Axis::X,
64 Self::TTB | Self::BTT => Axis::Y,
65 }
66 }
67
68 /// The start point of this direction, as an alignment.
69 ///
70 /// ```example
71 /// #ltr.start() \
72 /// #rtl.start() \
73 /// #ttb.start() \
74 /// #btt.start()
75 /// ```
76 #[func]
77 pub const fn start(self) -> Side {
78 match self {
79 Self::LTR => Side::Left,
80 Self::RTL => Side::Right,
81 Self::TTB => Side::Top,
82 Self::BTT => Side::Bottom,
83 }
84 }
85
86 /// The end point of this direction, as an alignment.
87 ///
88 /// ```example
89 /// #ltr.end() \
90 /// #rtl.end() \
91 /// #ttb.end() \
92 /// #btt.end()
93 /// ```
94 #[func]
95 pub const fn end(self) -> Side {
96 match self {
97 Self::LTR => Side::Right,
98 Self::RTL => Side::Left,
99 Self::TTB => Side::Bottom,
100 Self::BTT => Side::Top,
101 }
102 }
103
104 /// The inverse direction.
105 ///
106 /// ```example
107 /// #ltr.inv() \
108 /// #rtl.inv() \
109 /// #ttb.inv() \
110 /// #btt.inv()
111 /// ```
112 #[func(title = "Inverse")]
113 pub const fn inv(self) -> Dir {
114 match self {
115 Self::LTR => Self::RTL,
116 Self::RTL => Self::LTR,
117 Self::TTB => Self::BTT,
118 Self::BTT => Self::TTB,
119 }
120 }
121}
122
123impl Repr for Dir {
124 fn repr(&self) -> EcoString {
125 match self {
126 Self::LTR => "ltr".into(),
127 Self::RTL => "rtl".into(),
128 Self::TTB => "ttb".into(),
129 Self::BTT => "btt".into(),
130 }
131 }
132}