Skip to main content

iced_core/
font.rs

1//! Load and use fonts.
2use std::hash::Hash;
3
4/// A font.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
6pub struct Font {
7    /// The [`Family`] of the [`Font`].
8    pub family: Family,
9    /// The [`Weight`] of the [`Font`].
10    pub weight: Weight,
11    /// The [`Stretch`] of the [`Font`].
12    pub stretch: Stretch,
13    /// The [`Style`] of the [`Font`].
14    pub style: Style,
15}
16
17impl Font {
18    /// A non-monospaced sans-serif font with normal [`Weight`].
19    pub const DEFAULT: Font = Font {
20        family: Family::SansSerif,
21        weight: Weight::Normal,
22        stretch: Stretch::Normal,
23        style: Style::Normal,
24    };
25
26    /// A monospaced font with normal [`Weight`].
27    pub const MONOSPACE: Font = Font {
28        family: Family::Monospace,
29        ..Self::DEFAULT
30    };
31
32    /// Creates a [`Font`] with the given [`Family::Name`] and default attributes.
33    pub const fn new(name: &'static str) -> Self {
34        Self {
35            family: Family::Name(name),
36            ..Self::DEFAULT
37        }
38    }
39
40    /// Creates a [`Font`] with the given [`Family`] and default attributes.
41    pub fn with_family(family: impl Into<Family>) -> Self {
42        Font {
43            family: family.into(),
44            ..Self::DEFAULT
45        }
46    }
47
48    /// Sets the [`Weight`] of the [`Font`].
49    pub const fn weight(self, weight: Weight) -> Self {
50        Self { weight, ..self }
51    }
52
53    /// Sets the [`Stretch`] of the [`Font`].
54    pub const fn stretch(self, stretch: Stretch) -> Self {
55        Self { stretch, ..self }
56    }
57
58    /// Sets the [`Style`] of the [`Font`].
59    pub const fn style(self, style: Style) -> Self {
60        Self { style, ..self }
61    }
62}
63
64impl From<&'static str> for Font {
65    fn from(name: &'static str) -> Self {
66        Font::new(name)
67    }
68}
69
70impl From<Family> for Font {
71    fn from(family: Family) -> Self {
72        Font::with_family(family)
73    }
74}
75
76/// A font family.
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
78pub enum Family {
79    /// The name of a font family of choice.
80    Name(&'static str),
81
82    /// Serif fonts represent the formal text style for a script.
83    Serif,
84
85    /// Glyphs in sans-serif fonts, as the term is used in CSS, are generally low
86    /// contrast and have stroke endings that are plain — without any flaring,
87    /// cross stroke, or other ornamentation.
88    #[default]
89    SansSerif,
90
91    /// Glyphs in cursive fonts generally use a more informal script style, and
92    /// the result looks more like handwritten pen or brush writing than printed
93    /// letterwork.
94    Cursive,
95
96    /// Fantasy fonts are primarily decorative or expressive fonts that contain
97    /// decorative or expressive representations of characters.
98    Fantasy,
99
100    /// The sole criterion of a monospace font is that all glyphs have the same
101    /// fixed width.
102    Monospace,
103}
104
105impl Family {
106    /// A list of all the different standalone family variants.
107    pub const VARIANTS: &[Self] = &[
108        Self::Serif,
109        Self::SansSerif,
110        Self::Cursive,
111        Self::Fantasy,
112        Self::Monospace,
113    ];
114
115    /// Creates a [`Family::Name`] from the given string.
116    ///
117    /// The name is interned in a global cache and never freed.
118    pub fn name(name: &str) -> Self {
119        use rustc_hash::FxHashSet;
120        use std::sync::{LazyLock, Mutex};
121
122        static NAMES: LazyLock<Mutex<FxHashSet<&'static str>>> = LazyLock::new(Mutex::default);
123
124        let mut names = NAMES.lock().expect("lock font name cache");
125
126        let Some(name) = names.get(name) else {
127            let name: &'static str = name.to_owned().leak();
128            let _ = names.insert(name);
129
130            return Self::Name(name);
131        };
132
133        Self::Name(name)
134    }
135}
136
137impl From<&str> for Family {
138    fn from(name: &str) -> Self {
139        Family::name(name)
140    }
141}
142
143impl std::fmt::Display for Family {
144    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145        f.write_str(match self {
146            Family::Name(name) => name,
147            Family::Serif => "Serif",
148            Family::SansSerif => "Sans-serif",
149            Family::Cursive => "Cursive",
150            Family::Fantasy => "Fantasy",
151            Family::Monospace => "Monospace",
152        })
153    }
154}
155
156/// The weight of some text.
157#[allow(missing_docs)]
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
159pub enum Weight {
160    Thin,
161    ExtraLight,
162    Light,
163    #[default]
164    Normal,
165    Medium,
166    Semibold,
167    Bold,
168    ExtraBold,
169    Black,
170}
171
172/// The width of some text.
173#[allow(missing_docs)]
174#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
175pub enum Stretch {
176    UltraCondensed,
177    ExtraCondensed,
178    Condensed,
179    SemiCondensed,
180    #[default]
181    Normal,
182    SemiExpanded,
183    Expanded,
184    ExtraExpanded,
185    UltraExpanded,
186}
187
188/// The style of some text.
189#[allow(missing_docs)]
190#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
191pub enum Style {
192    #[default]
193    Normal,
194    Italic,
195    Oblique,
196}
197
198/// A font error.
199#[derive(Debug, Clone, Copy, PartialEq, Eq)]
200pub enum Error {}