ailloli_ui_core/style/
text_style.rs

1//! Text font, logical size, color, and paint-only decoration.
2
3use crate::FontId;
4
5use super::Color;
6
7/// Paint-only line decoration applied after text shaping and layout.
8///
9/// Possible values are no decoration and underline.
10///
11/// # Examples
12///
13/// ```
14/// use ailloli_ui_core::TextDecoration;
15/// assert_eq!(TextDecoration::default(), TextDecoration::None);
16/// ```
17#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
18pub enum TextDecoration {
19    /// No additional line; this is the default.
20    #[default]
21    None,
22    /// Paint an underline without changing text shaping or layout metrics.
23    Underline,
24}
25
26/// Font and color for text layout and draw commands.
27///
28/// # Examples
29///
30/// ```
31/// use ailloli_ui_core::{Color, FontId, TextStyle};
32/// let style = TextStyle::new(FontId::Ui, 14, Color::WHITE);
33/// assert_eq!(style.px_size, 14);
34/// ```
35#[derive(Debug, Clone, Copy, PartialEq)]
36pub struct TextStyle {
37    /// Built-in font-family slot.
38    pub font: FontId,
39    /// Font size in logical pixels.
40    pub px_size: u16,
41    /// Linear-RGBA glyph and decoration color.
42    pub color: Color,
43    /// Paint-only line decoration.
44    pub decoration: TextDecoration,
45}
46
47impl TextStyle {
48    /// Creates undecorated text with the supplied font, size, and color.
49    ///
50    /// A zero pixel size is representable and left for the text engine to
51    /// interpret.
52    ///
53    /// # Examples
54    ///
55    /// ```
56    /// use ailloli_ui_core::{Color, FontId, TextDecoration, TextStyle};
57    /// let style = TextStyle::new(FontId::Mono, 13, Color::BLACK);
58    /// assert_eq!(style.decoration, TextDecoration::None);
59    /// ```
60    pub const fn new(font: FontId, px_size: u16, color: Color) -> Self {
61        Self {
62            font,
63            px_size,
64            color,
65            decoration: TextDecoration::None,
66        }
67    }
68
69    /// Returns this style with [`TextDecoration::Underline`].
70    ///
71    /// # Examples
72    ///
73    /// ```
74    /// use ailloli_ui_core::{Color, FontId, TextDecoration, TextStyle};
75    /// assert_eq!(TextStyle::new(FontId::Ui, 14, Color::WHITE).underline().decoration, TextDecoration::Underline);
76    /// ```
77    pub const fn underline(mut self) -> Self {
78        self.decoration = TextDecoration::Underline;
79        self
80    }
81
82    /// Returns this style with [`TextDecoration::None`].
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// use ailloli_ui_core::{Color, FontId, TextDecoration, TextStyle};
88    /// let style = TextStyle::new(FontId::Ui, 14, Color::WHITE).underline().without_decoration();
89    /// assert_eq!(style.decoration, TextDecoration::None);
90    /// ```
91    pub const fn without_decoration(mut self) -> Self {
92        self.decoration = TextDecoration::None;
93        self
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    //! Covers the decoration default and both decoration builders.
100
101    use super::*;
102    use crate::Color;
103
104    #[test]
105    fn decoration_defaults_to_none_and_builders_toggle_it() {
106        let style = TextStyle::new(FontId::Ui, 14, Color::WHITE);
107        assert_eq!(style.decoration, TextDecoration::None);
108        assert_eq!(style.underline().decoration, TextDecoration::Underline);
109        assert_eq!(
110            style.underline().without_decoration().decoration,
111            TextDecoration::None
112        );
113    }
114}