| 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::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 ] |
| 63 | fn 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 ] |
| 71 | fn 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 ] |
| 79 | fn 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 ] |
| 86 | fn 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 | } |
| 92 | |