sctk_adwaita/title/
font_preference.rs

1#[derive(Debug)]
2pub(crate) struct FontPreference {
3    pub name: String,
4    pub style: Option<String>,
5    pub pt_size: f32,
6}
7
8impl Default for FontPreference {
9    fn default() -> Self {
10        Self {
11            name: "sans-serif".into(),
12            style: None,
13            pt_size: 10.0,
14        }
15    }
16}
17
18impl FontPreference {
19    /// Parse config string like `Cantarell 12`, `Cantarell Bold 11`, `Noto Serif CJK HK Bold 12`.
20    pub fn from_name_style_size(conf: &str) -> Option<Self> {
21        // assume last is size, 2nd last is style and the rest is name.
22        match conf.rsplit_once(' ') {
23            Some((head, tail)) if tail.chars().all(|c| c.is_numeric()) => {
24                let pt_size: f32 = tail.parse().unwrap_or(10.0);
25                match head.rsplit_once(' ') {
26                    Some((name, style)) if !name.is_empty() => Some(Self {
27                        name: name.into(),
28                        style: Some(style.into()),
29                        pt_size,
30                    }),
31                    None if !head.is_empty() => Some(Self {
32                        name: head.into(),
33                        style: None,
34                        pt_size,
35                    }),
36                    _ => None,
37                }
38            }
39            Some((head, tail)) if !head.is_empty() => Some(Self {
40                name: head.into(),
41                style: Some(tail.into()),
42                pt_size: 10.0,
43            }),
44            None if !conf.is_empty() => Some(Self {
45                name: conf.into(),
46                style: None,
47                pt_size: 10.0,
48            }),
49            _ => None,
50        }
51    }
52}
53
54#[test]
55fn pref_from_multi_name_variant_size() {
56    let pref = FontPreference::from_name_style_size("Noto Serif CJK HK Bold 12").unwrap();
57    assert_eq!(pref.name, "Noto Serif CJK HK");
58    assert_eq!(pref.style, Some("Bold".into()));
59    assert!((pref.pt_size - 12.0).abs() < f32::EPSILON);
60}
61
62#[test]
63fn pref_from_name_variant_size() {
64    let pref = FontPreference::from_name_style_size("Cantarell Bold 12").unwrap();
65    assert_eq!(pref.name, "Cantarell");
66    assert_eq!(pref.style, Some("Bold".into()));
67    assert!((pref.pt_size - 12.0).abs() < f32::EPSILON);
68}
69
70#[test]
71fn pref_from_name_size() {
72    let pref = FontPreference::from_name_style_size("Cantarell 12").unwrap();
73    assert_eq!(pref.name, "Cantarell");
74    assert_eq!(pref.style, None);
75    assert!((pref.pt_size - 12.0).abs() < f32::EPSILON);
76}
77
78#[test]
79fn pref_from_name() {
80    let pref = FontPreference::from_name_style_size("Cantarell").unwrap();
81    assert_eq!(pref.name, "Cantarell");
82    assert_eq!(pref.style, None);
83    assert!((pref.pt_size - 10.0).abs() < f32::EPSILON);
84}
85#[test]
86fn pref_from_multi_name_style() {
87    let pref = FontPreference::from_name_style_size("Foo Bar Baz Bold").unwrap();
88    assert_eq!(pref.name, "Foo Bar Baz");
89    assert_eq!(pref.style, Some("Bold".into()));
90    assert!((pref.pt_size - 10.0).abs() < f32::EPSILON);
91}