1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//! Technical implementation of a subset of CSS Fonts Module Level 4 (WD).

use std::str::FromStr;
use strum_macros::EnumString;

use crate::geometry::Dimension;

/// Controls the thickness of outlines rendered to a text element.
#[derive(Copy, Clone, Debug, PartialEq, EnumString)]
pub enum FontWeight {
    /// Accepts a custom normalized font weight scaled between 0 and 1.0
    #[strum(disabled)]
    Number(f32),

    /// This corresponds to the CSS font weight with the same name and has a
    /// numerical value of 100.
    #[strum(serialize = "thin")]
    Thin,

    /// This corresponds to the CSS font weight with the same name and has a
    /// numerical value of 200. This weight is also known as ultra light.
    #[strum(serialize = "extra-light")]
    ExtraLight,

    /// This corresponds to the CSS font weight with the same name and has a
    /// numerical value of 300.
    #[strum(serialize = "light")]
    Light,

    /// This corresponds to the CSS font weight with the same name and has a
    /// numerical value of 400. This is the default font weight.
    #[strum(serialize = "normal")]
    Normal,

    /// This corresponds to the CSS font weight with the same name and has a
    /// numerical value of 500.
    #[strum(serialize = "medium")]
    Medium,

    /// This corresponds to the CSS font weight with the same name and has a
    /// numerical value of 600. This weight is also known as demi bold.
    #[strum(serialize = "semi-bold")]
    SemiBold,

    /// This corresponds to the CSS font weight with the same name and has a
    /// numerical value of 700.
    #[strum(serialize = "bold")]
    Bold,

    /// This corresponds to the CSS font weight with the same name and has a
    /// numerical value of 800. This weight is also known as ultra bold.
    #[strum(serialize = "extra-bold")]
    ExtraBold,

    /// This corresponds to the CSS font weight with the same name and has a
    /// numerical value of 900. This weight is also known as heavy.
    #[strum(serialize = "black")]
    Black,
}

impl Default for FontWeight {
    fn default() -> Self {
        FontWeight::Normal
    }
}

/// Polyhorn provides a few generic font families that can be used to get a
/// system-provided typeface in a particular category that looks best on a
/// user's display. The default generic font family is SansSerif.
#[derive(Copy, Clone, Debug, Eq, PartialEq, EnumString)]
pub enum GenericFontFamily {
    /// This generic font style has serifs attached to the glyphs. Serifs are
    /// those pointy spikes at the extremes of (mostly) uppercase letters. This
    /// style is commonly used for newspaper headings.
    #[strum(serialize = "serif")]
    Serif,

    /// This generic font style has no serifs. This type of font is commonly
    /// used for the main text.
    #[strum(serialize = "sans-serif")]
    SansSerif,

    /// This generic font style has glyphs of equal width. This type of font is
    /// commonly used in code editors where each letter and symbol should have
    /// equal width.
    #[strum(serialize = "monospace")]
    Monospace,
}

impl Default for GenericFontFamily {
    fn default() -> Self {
        GenericFontFamily::SansSerif
    }
}

/// Controls the font family that produces the glyphs that are drawn for a text.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum FontFamily<S = &'static str> {
    /// This is a system-dependent font family in the given generic category.
    Generic(GenericFontFamily),

    /// This is a specific font family referred to by its PostScript name.
    Named(S),
}

impl<S> FromStr for FontFamily<S> {
    type Err = <GenericFontFamily as FromStr>::Err;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(FontFamily::Generic(GenericFontFamily::from_str(s)?))
    }
}

/// Most fonts come in one to three styles: a normal style and one or two
/// slanted styles. The normal font style is the default font style used for
/// text. The oblique font style (if present) is a slanted version of the same
/// source glyphs. An italic font style is made from a separate set of source
/// glyphs.
///
/// Most fonts do not offer both oblique and italic font styles. Oblique fonts
/// are an inexpensive way to get a slanted version of a normal font, whereas
/// italic fonts might cost as much time to make as the original version.
#[derive(Copy, Clone, Debug, Eq, PartialEq, EnumString)]
pub enum FontStyle {
    /// The normal font style is the default font style for text.
    #[strum(serialize = "normal")]
    Normal,

    /// The oblique font style is a slanted version from the same source glyphs.
    #[strum(serialize = "oblique")]
    Oblique,

    /// An italic font style is made from a separate set of source glyphs.
    #[strum(serialize = "italic")]
    Italic,
}

impl Default for FontStyle {
    fn default() -> Self {
        FontStyle::Normal
    }
}

/// Controls the size of text that is rendered to the screen.
#[derive(Copy, Clone, Debug, PartialEq, EnumString)]
pub enum FontSize {
    /// This font size is 3/5th of the medium font size.
    #[strum(serialize = "extra-extra-small")]
    ExtraExtraSmall,

    /// This font size is 3/4th of the medium font size.
    #[strum(serialize = "extra-small")]
    ExtraSmall,

    /// This font size is 8/9th of the medium font size.
    #[strum(serialize = "small")]
    Small,

    /// This is the default font size.
    #[strum(serialize = "medium")]
    Medium,

    /// This font size is 1.2x the medium font size.
    #[strum(serialize = "large")]
    Large,

    /// This font size is 1.5x the medium font size.
    #[strum(serialize = "extra-large")]
    ExtraLarge,

    /// This font size is 2x the medium font size.
    #[strum(serialize = "extra-extra-large")]
    ExtraExtraLarge,

    /// This font size is 3x the medium font size.
    #[strum(serialize = "extra-extra-extra-large")]
    ExtraExtraExtraLarge,

    /// This is a dimension (e.g. pixels or percentage). If the dimension
    /// resolves to either `undefined` or `auto`, the font size will be 0. If
    /// the dimension is a percentage, it will be relative to the parent text
    /// element's font size (not its width).
    #[strum(disabled)]
    Dimension(Dimension<f32>),
}

/// Controls the rendering of text to screen.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Font {
    /// Controls the font family that is used to render text to screen.
    pub family: FontFamily,

    /// Controls the font weight that is used to render text to screen.
    pub weight: FontWeight,

    /// Controls the font style that is used to render text to screen.
    pub style: FontStyle,

    /// Controls the font size that is used to render text to screen.
    pub size: FontSize,
}