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}