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
//! Font families, weights, etcetera

use std::sync::Arc;

/// A reference to a font family.
///
/// This may be either a CSS-style "generic family name", such as "serif"
/// or "monospace", or it can be an explicit family name.
///
/// To use a generic family name, use the provided associated constants:
/// `FontFamily::SERIF`, `FontFamily::SANS_SERIF`, `FontFamily::SYSTEM_UI`,
/// and `FontFamily::MONOSPACE`.
///
/// To use a specific font family you should not construct this type directly;
/// instead you should verify that the desired family exists, via the
/// [`Text::font_family`] API.
///
/// [`Text::font_family`]: crate::Text::font_family
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FontFamily(FontFamilyInner);

/// The inner representation of a font family.
///
/// This is not public API for users of piet; it is exposed for backends only.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[doc(hidden)]
#[non_exhaustive]
pub enum FontFamilyInner {
    Serif,
    SansSerif,
    Monospace,
    SystemUi,
    Named(Arc<str>),
}

/// A font weight, represented as a value in the range 1..=1000.
///
/// This is based on the [CSS `font-weight`] property. In general, you should
/// prefer the constants defined on this type, such as `FontWeight::REGULAR` or
/// `FontWeight::BOLD`.
///
/// [CSS `font-weight`]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FontWeight(u16);

/// A font style, which may be italic or regular.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FontStyle {
    /// Prefer the regular style for the current font family, if available.
    Regular,
    /// Prefer the italic style for the current font family, if available.
    ///
    /// If italic is not available and oblique is, we will use that; if neither
    /// is available we will apply synthetic italics to the regular style.
    Italic,
}

impl FontFamily {
    /// A san-serif font, such as Arial or Helvetica.
    pub const SANS_SERIF: FontFamily = FontFamily(FontFamilyInner::SansSerif);
    /// A serif font, such as Times New Roman or Charter.
    pub const SERIF: FontFamily = FontFamily(FontFamilyInner::Serif);
    /// The platform's preferred UI font; San Francisco on macOS, and Segoe UI
    /// on recent Windows.
    pub const SYSTEM_UI: FontFamily = FontFamily(FontFamilyInner::SystemUi);
    /// A monospace font.
    pub const MONOSPACE: FontFamily = FontFamily(FontFamilyInner::Monospace);

    /// Create a new font family with a given name, without verifying that it exists.
    ///
    /// This should generally not be used; instead you should create a `FontFamily`
    /// by calling the [`Text::font_family`] method, which verifies that the
    /// family name exists.
    ///
    /// [`Text::font_family`]: crate::Text::font_family
    pub fn new_unchecked(s: impl Into<Arc<str>>) -> Self {
        FontFamily(FontFamilyInner::Named(s.into()))
    }

    /// The name of the font family.
    pub fn name(&self) -> &str {
        match &self.0 {
            FontFamilyInner::Serif => "serif",
            FontFamilyInner::SansSerif => "sans-serif",
            FontFamilyInner::SystemUi => "system-ui",
            FontFamilyInner::Monospace => "monospace",
            FontFamilyInner::Named(s) => s,
        }
    }

    /// Returns `true` if this is a generic font family.
    pub fn is_generic(&self) -> bool {
        !matches!(self.0, FontFamilyInner::Named(_))
    }

    /// Backend-only API; access the inner `FontFamilyInner` enum.
    #[doc(hidden)]
    pub fn inner(&self) -> &FontFamilyInner {
        &self.0
    }
}

impl FontWeight {
    /// 100
    pub const THIN: FontWeight = FontWeight(100);
    /// 100
    pub const HAIRLINE: FontWeight = FontWeight::THIN;

    /// 200
    pub const EXTRA_LIGHT: FontWeight = FontWeight(200);

    /// 300
    pub const LIGHT: FontWeight = FontWeight(300);

    /// 400
    pub const REGULAR: FontWeight = FontWeight(400);
    /// 400
    pub const NORMAL: FontWeight = FontWeight::REGULAR;

    /// 500
    pub const MEDIUM: FontWeight = FontWeight(500);

    /// 600
    pub const SEMI_BOLD: FontWeight = FontWeight(600);

    /// 700
    pub const BOLD: FontWeight = FontWeight(700);

    /// 800
    pub const EXTRA_BOLD: FontWeight = FontWeight(800);

    /// 900
    pub const BLACK: FontWeight = FontWeight(900);
    /// 900
    pub const HEAVY: FontWeight = FontWeight::BLACK;

    /// 950
    pub const EXTRA_BLACK: FontWeight = FontWeight(950);

    /// Create a new `FontWeight` with a custom value.
    ///
    /// Values will be clamped to the range 1..=1000.
    pub fn new(raw: u16) -> FontWeight {
        let raw = raw.clamp(1, 1000);
        FontWeight(raw)
    }

    /// Return the raw value as a u16.
    pub const fn to_raw(self) -> u16 {
        self.0
    }
}

impl Default for FontFamily {
    fn default() -> Self {
        FontFamily::SYSTEM_UI
    }
}

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

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