1impl From<String> for GuiFont {
2 fn from(option: String) -> Self {
3 let mut out = GuiFont::default();
4 let mut state = ParseState::Normal;
5 let mut current = String::new();
6 for c in option.chars() {
7 match state {
8 ParseState::Normal => {
9 if c.is_whitespace() && current.is_empty() {
10 continue;
11 }
12
13 match c {
14 '\\' => state = ParseState::Escape,
15 ',' => {
16 out.fonts.push(current);
17 current = String::default();
18 state = ParseState::Normal;
19 }
20 '_' => current.push(' '),
21 ':' => state = ParseState::OptionStart,
22 _ => current.push(c),
23 }
24 }
25
26 ParseState::Escape => {
27 current.push(c);
28 state = ParseState::Normal;
29 }
30
31 ParseState::OptionStart => {
32 state = match c {
33 'w' | 'W' => ParseState::OptionSize(0, SizeKind::Width),
34 'h' | 'H' => ParseState::OptionSize(0, SizeKind::Height),
35 _ => ParseState::OptionUnknown,
36 };
37 }
38
39 ParseState::OptionSize(size, kind) => match c {
40 '0'..='9' => {
41 let size = size * 10 + c as u32 - '0' as u32;
42 state = ParseState::OptionSize(size, kind);
43 }
44 ',' => {
45 out.fonts.push(current);
46 out.size = FontSize::new(size as f32, kind);
47 current = String::default();
48 state = ParseState::Normal;
49 }
50 ':' => {
51 out.size = FontSize::new(size as f32, kind);
52 state = ParseState::OptionStart;
53 }
54 _ => {
55 log::warn!("Bad font height option");
56 break;
57 }
58 },
59
60 ParseState::OptionUnknown => match c {
61 ',' => {
62 out.fonts.push(current);
63 current = String::default();
64 state = ParseState::Normal;
65 }
66 ':' => state = ParseState::OptionStart,
67 _ => {}
68 },
69 }
70 }
71
72 if let ParseState::OptionSize(size, kind) = state {
73 out.size = FontSize::new(size as f32, kind);
74 }
75
76 if !current.is_empty() {
77 out.fonts.push(current);
78 }
79
80 out
81 }
82}
83
84#[derive(Debug, Default, Clone, PartialEq)]
85pub struct GuiFont {
86 pub fonts: Vec<String>,
87 pub size: FontSize,
88}
89
90#[derive(Debug, Clone, Copy, PartialEq)]
91pub enum FontSize {
92 Width(f32),
93 Height(f32),
94}
95
96impl FontSize {
97 fn new(size: f32, kind: SizeKind) -> Self {
98 match kind {
99 SizeKind::Width => Self::Width(size),
100 SizeKind::Height => Self::Height(size),
101 }
102 }
103}
104
105impl Default for FontSize {
106 fn default() -> Self {
107 Self::Height(18.)
108 }
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq)]
112enum ParseState {
113 Normal,
115 Escape,
117 OptionStart,
119 OptionSize(u32, SizeKind),
121 OptionUnknown,
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126enum SizeKind {
127 Width,
128 Height,
129}