typst_library/math/style.rs
1use codex::styling::MathVariant;
2
3use crate::foundations::{Cast, Content, func};
4use crate::math::EquationElem;
5
6/// Bold font style in math.
7///
8/// ```example
9/// $ bold(A) := B^+ $
10/// ```
11#[func(keywords = ["mathbf"])]
12pub fn bold(
13 /// The content to style.
14 body: Content,
15) -> Content {
16 body.set(EquationElem::bold, true)
17}
18
19/// Upright (non-italic) font style in math.
20///
21/// ```example
22/// $ upright(A) != A $
23/// ```
24#[func(keywords = ["mathup"])]
25pub fn upright(
26 /// The content to style.
27 body: Content,
28) -> Content {
29 body.set(EquationElem::italic, Some(false))
30}
31
32/// Italic font style in math.
33///
34/// For roman letters and greek lowercase letters, this is already the default.
35#[func(keywords = ["mathit"])]
36pub fn italic(
37 /// The content to style.
38 body: Content,
39) -> Content {
40 body.set(EquationElem::italic, Some(true))
41}
42
43/// Serif (roman) font style in math.
44///
45/// This is already the default.
46#[func(keywords = ["mathrm"])]
47pub fn serif(
48 /// The content to style.
49 body: Content,
50) -> Content {
51 body.set(EquationElem::variant, Some(MathVariant::Plain))
52}
53
54/// Sans-serif font style in math.
55///
56/// ```example
57/// $ sans(A B C) $
58/// ```
59#[func(title = "Sans Serif", keywords = ["mathsf"])]
60pub fn sans(
61 /// The content to style.
62 body: Content,
63) -> Content {
64 body.set(EquationElem::variant, Some(MathVariant::SansSerif))
65}
66
67/// Calligraphic (chancery) font style in math.
68///
69/// ```example
70/// Let $cal(P)$ be the set of ...
71/// ```
72///
73/// This is the default calligraphic/script style for most math fonts. See
74/// [`scr`]($math.scr) for more on how to get the other style (roundhand).
75#[func(title = "Calligraphic", keywords = ["mathcal", "chancery"])]
76pub fn cal(
77 /// The content to style.
78 body: Content,
79) -> Content {
80 body.set(EquationElem::variant, Some(MathVariant::Chancery))
81}
82
83/// Script (roundhand) font style in math.
84///
85/// ```example
86/// $scr(L)$ is not the set of linear
87/// maps $cal(L)$.
88/// ```
89///
90/// There are two ways that fonts can support differentiating `cal` and `scr`.
91/// The first is using Unicode variation sequences. This works out of the box
92/// in Typst, however only a few math fonts currently support this.
93///
94/// The other way is using [font features]($text.features). For example, the
95/// roundhand style might be available in a font through the
96/// _[stylistic set]($text.stylistic-set) 1_ (`ss01`) feature. To use it in
97/// Typst, you could then define your own version of `scr` like in the example
98/// below.
99///
100/// ```example:"Recreation using stylistic set 1"
101/// #let scr(it) = text(
102/// stylistic-set: 1,
103/// $cal(it)$,
104/// )
105///
106/// We establish $cal(P) != scr(P)$.
107/// ```
108#[func(title = "Script Style", keywords = ["mathscr", "roundhand"])]
109pub fn scr(
110 /// The content to style.
111 body: Content,
112) -> Content {
113 body.set(EquationElem::variant, Some(MathVariant::Roundhand))
114}
115
116/// Fraktur font style in math.
117///
118/// ```example
119/// $ frak(P) $
120/// ```
121#[func(title = "Fraktur", keywords = ["mathfrak"])]
122pub fn frak(
123 /// The content to style.
124 body: Content,
125) -> Content {
126 body.set(EquationElem::variant, Some(MathVariant::Fraktur))
127}
128
129/// Monospace font style in math.
130///
131/// ```example
132/// $ mono(x + y = z) $
133/// ```
134#[func(title = "Monospace", keywords = ["mathtt"])]
135pub fn mono(
136 /// The content to style.
137 body: Content,
138) -> Content {
139 body.set(EquationElem::variant, Some(MathVariant::Monospace))
140}
141
142/// Blackboard bold (double-struck) font style in math.
143///
144/// For uppercase latin letters, blackboard bold is additionally available
145/// through [symbols]($category/symbols/sym) of the form `NN` and `RR`.
146///
147/// ```example
148/// $ bb(b) $
149/// $ bb(N) = NN $
150/// $ f: NN -> RR $
151/// ```
152#[func(title = "Blackboard Bold", keywords = ["mathbb"])]
153pub fn bb(
154 /// The content to style.
155 body: Content,
156) -> Content {
157 body.set(EquationElem::variant, Some(MathVariant::DoubleStruck))
158}
159
160/// Forced display style in math.
161///
162/// This is the normal size for block equations.
163///
164/// ```example
165/// $sum_i x_i/2 = display(sum_i x_i/2)$
166/// ```
167#[func(title = "Display Size", keywords = ["displaystyle"])]
168pub fn display(
169 /// The content to size.
170 body: Content,
171 /// Whether to impose a height restriction for exponents, like regular sub-
172 /// and superscripts do.
173 #[named]
174 #[default(false)]
175 cramped: bool,
176) -> Content {
177 body.set(EquationElem::size, MathSize::Display)
178 .set(EquationElem::cramped, cramped)
179}
180
181/// Forced inline (text) style in math.
182///
183/// This is the normal size for inline equations.
184///
185/// ```example
186/// $ sum_i x_i/2
187/// = inline(sum_i x_i/2) $
188/// ```
189#[func(title = "Inline Size", keywords = ["textstyle"])]
190pub fn inline(
191 /// The content to size.
192 body: Content,
193 /// Whether to impose a height restriction for exponents, like regular sub-
194 /// and superscripts do.
195 #[named]
196 #[default(false)]
197 cramped: bool,
198) -> Content {
199 body.set(EquationElem::size, MathSize::Text)
200 .set(EquationElem::cramped, cramped)
201}
202
203/// Forced script style in math.
204///
205/// This is the smaller size used in powers or sub- or superscripts.
206///
207/// ```example
208/// $sum_i x_i/2 = script(sum_i x_i/2)$
209/// ```
210#[func(title = "Script Size", keywords = ["scriptstyle"])]
211pub fn script(
212 /// The content to size.
213 body: Content,
214 /// Whether to impose a height restriction for exponents, like regular sub-
215 /// and superscripts do.
216 #[named]
217 #[default(true)]
218 cramped: bool,
219) -> Content {
220 body.set(EquationElem::size, MathSize::Script)
221 .set(EquationElem::cramped, cramped)
222}
223
224/// Forced second script style in math.
225///
226/// This is the smallest size, used in second-level sub- and superscripts
227/// (script of the script).
228///
229/// ```example
230/// $sum_i x_i/2 = sscript(sum_i x_i/2)$
231/// ```
232#[func(title = "Script-Script Size", keywords = ["scriptscriptstyle"])]
233pub fn sscript(
234 /// The content to size.
235 body: Content,
236 /// Whether to impose a height restriction for exponents, like regular sub-
237 /// and superscripts do.
238 #[named]
239 #[default(true)]
240 cramped: bool,
241) -> Content {
242 body.set(EquationElem::size, MathSize::ScriptScript)
243 .set(EquationElem::cramped, cramped)
244}
245
246/// The size of elements in an equation.
247///
248/// See the TeXbook p. 141.
249#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Cast)]
250pub enum MathSize {
251 /// Second-level sub- and superscripts.
252 ScriptScript,
253 /// Sub- and superscripts.
254 Script,
255 /// Math in text.
256 Text,
257 /// Math on its own line.
258 Display,
259}