polyhorn_ui/font/mod.rs
1//! Technical implementation of a subset of CSS Fonts Module Level 4 (WD).
2
3use std::str::FromStr;
4use strum_macros::EnumString;
5
6use crate::geometry::Dimension;
7
8/// Controls the thickness of outlines rendered to a text element.
9#[derive(Copy, Clone, Debug, PartialEq, EnumString)]
10pub enum FontWeight {
11 /// Accepts a custom normalized font weight scaled between 0 and 1.0
12 #[strum(disabled)]
13 Number(f32),
14
15 /// This corresponds to the CSS font weight with the same name and has a
16 /// numerical value of 100.
17 #[strum(serialize = "thin")]
18 Thin,
19
20 /// This corresponds to the CSS font weight with the same name and has a
21 /// numerical value of 200. This weight is also known as ultra light.
22 #[strum(serialize = "extra-light")]
23 ExtraLight,
24
25 /// This corresponds to the CSS font weight with the same name and has a
26 /// numerical value of 300.
27 #[strum(serialize = "light")]
28 Light,
29
30 /// This corresponds to the CSS font weight with the same name and has a
31 /// numerical value of 400. This is the default font weight.
32 #[strum(serialize = "normal")]
33 Normal,
34
35 /// This corresponds to the CSS font weight with the same name and has a
36 /// numerical value of 500.
37 #[strum(serialize = "medium")]
38 Medium,
39
40 /// This corresponds to the CSS font weight with the same name and has a
41 /// numerical value of 600. This weight is also known as demi bold.
42 #[strum(serialize = "semi-bold")]
43 SemiBold,
44
45 /// This corresponds to the CSS font weight with the same name and has a
46 /// numerical value of 700.
47 #[strum(serialize = "bold")]
48 Bold,
49
50 /// This corresponds to the CSS font weight with the same name and has a
51 /// numerical value of 800. This weight is also known as ultra bold.
52 #[strum(serialize = "extra-bold")]
53 ExtraBold,
54
55 /// This corresponds to the CSS font weight with the same name and has a
56 /// numerical value of 900. This weight is also known as heavy.
57 #[strum(serialize = "black")]
58 Black,
59}
60
61impl Default for FontWeight {
62 fn default() -> Self {
63 FontWeight::Normal
64 }
65}
66
67/// Polyhorn provides a few generic font families that can be used to get a
68/// system-provided typeface in a particular category that looks best on a
69/// user's display. The default generic font family is SansSerif.
70#[derive(Copy, Clone, Debug, Eq, PartialEq, EnumString)]
71pub enum GenericFontFamily {
72 /// This generic font style has serifs attached to the glyphs. Serifs are
73 /// those pointy spikes at the extremes of (mostly) uppercase letters. This
74 /// style is commonly used for newspaper headings.
75 #[strum(serialize = "serif")]
76 Serif,
77
78 /// This generic font style has no serifs. This type of font is commonly
79 /// used for the main text.
80 #[strum(serialize = "sans-serif")]
81 SansSerif,
82
83 /// This generic font style has glyphs of equal width. This type of font is
84 /// commonly used in code editors where each letter and symbol should have
85 /// equal width.
86 #[strum(serialize = "monospace")]
87 Monospace,
88}
89
90impl Default for GenericFontFamily {
91 fn default() -> Self {
92 GenericFontFamily::SansSerif
93 }
94}
95
96/// Controls the font family that produces the glyphs that are drawn for a text.
97#[derive(Copy, Clone, Debug, Eq, PartialEq)]
98pub enum FontFamily<S = &'static str> {
99 /// This is a system-dependent font family in the given generic category.
100 Generic(GenericFontFamily),
101
102 /// This is a specific font family referred to by its PostScript name.
103 Named(S),
104}
105
106impl<S> FromStr for FontFamily<S> {
107 type Err = <GenericFontFamily as FromStr>::Err;
108
109 fn from_str(s: &str) -> Result<Self, Self::Err> {
110 Ok(FontFamily::Generic(GenericFontFamily::from_str(s)?))
111 }
112}
113
114/// Most fonts come in one to three styles: a normal style and one or two
115/// slanted styles. The normal font style is the default font style used for
116/// text. The oblique font style (if present) is a slanted version of the same
117/// source glyphs. An italic font style is made from a separate set of source
118/// glyphs.
119///
120/// Most fonts do not offer both oblique and italic font styles. Oblique fonts
121/// are an inexpensive way to get a slanted version of a normal font, whereas
122/// italic fonts might cost as much time to make as the original version.
123#[derive(Copy, Clone, Debug, Eq, PartialEq, EnumString)]
124pub enum FontStyle {
125 /// The normal font style is the default font style for text.
126 #[strum(serialize = "normal")]
127 Normal,
128
129 /// The oblique font style is a slanted version from the same source glyphs.
130 #[strum(serialize = "oblique")]
131 Oblique,
132
133 /// An italic font style is made from a separate set of source glyphs.
134 #[strum(serialize = "italic")]
135 Italic,
136}
137
138impl Default for FontStyle {
139 fn default() -> Self {
140 FontStyle::Normal
141 }
142}
143
144/// Controls the size of text that is rendered to the screen.
145#[derive(Copy, Clone, Debug, PartialEq, EnumString)]
146pub enum FontSize {
147 /// This font size is 3/5th of the medium font size.
148 #[strum(serialize = "extra-extra-small")]
149 ExtraExtraSmall,
150
151 /// This font size is 3/4th of the medium font size.
152 #[strum(serialize = "extra-small")]
153 ExtraSmall,
154
155 /// This font size is 8/9th of the medium font size.
156 #[strum(serialize = "small")]
157 Small,
158
159 /// This is the default font size.
160 #[strum(serialize = "medium")]
161 Medium,
162
163 /// This font size is 1.2x the medium font size.
164 #[strum(serialize = "large")]
165 Large,
166
167 /// This font size is 1.5x the medium font size.
168 #[strum(serialize = "extra-large")]
169 ExtraLarge,
170
171 /// This font size is 2x the medium font size.
172 #[strum(serialize = "extra-extra-large")]
173 ExtraExtraLarge,
174
175 /// This font size is 3x the medium font size.
176 #[strum(serialize = "extra-extra-extra-large")]
177 ExtraExtraExtraLarge,
178
179 /// This is a dimension (e.g. pixels or percentage). If the dimension
180 /// resolves to either `undefined` or `auto`, the font size will be 0. If
181 /// the dimension is a percentage, it will be relative to the parent text
182 /// element's font size (not its width).
183 #[strum(disabled)]
184 Dimension(Dimension<f32>),
185}
186
187/// Controls the rendering of text to screen.
188#[derive(Copy, Clone, Debug, PartialEq)]
189pub struct Font {
190 /// Controls the font family that is used to render text to screen.
191 pub family: FontFamily,
192
193 /// Controls the font weight that is used to render text to screen.
194 pub weight: FontWeight,
195
196 /// Controls the font style that is used to render text to screen.
197 pub style: FontStyle,
198
199 /// Controls the font size that is used to render text to screen.
200 pub size: FontSize,
201}