1 | #[derive (Debug)] |
2 | pub(crate) struct FontPreference { |
3 | pub name: String, |
4 | pub style: Option<String>, |
5 | pub pt_size: f32, |
6 | } |
7 | |
8 | impl 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 | |
18 | impl 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 ] |
55 | fn pref_from_multi_name_variant_size() { |
56 | let pref: FontPreference = FontPreference::from_name_style_size(conf:"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 ] |
63 | fn pref_from_name_variant_size() { |
64 | let pref: FontPreference = FontPreference::from_name_style_size(conf:"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 ] |
71 | fn pref_from_name_size() { |
72 | let pref: FontPreference = FontPreference::from_name_style_size(conf:"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 ] |
79 | fn pref_from_name() { |
80 | let pref: FontPreference = FontPreference::from_name_style_size(conf:"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 ] |
86 | fn pref_from_multi_name_style() { |
87 | let pref: FontPreference = FontPreference::from_name_style_size(conf:"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 | } |
92 | |