embedded_graphics/mono_font/
mapping.rs1use core::ops::RangeInclusive;
47
48pub trait GlyphMapping: Sync {
50 fn index(&self, c: char) -> usize;
54}
55
56impl<F> GlyphMapping for F
57where
58 F: Sync + Fn(char) -> usize,
59{
60 fn index(&self, c: char) -> usize {
61 self(c)
62 }
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
71pub struct StrGlyphMapping<'a> {
72 data: &'a str,
73 replacement_index: usize,
74}
75
76impl<'a> StrGlyphMapping<'a> {
77 pub const fn new(data: &'a str, replacement_index: usize) -> Self {
79 Self {
80 data,
81 replacement_index,
82 }
83 }
84
85 pub fn ranges(&self) -> impl Iterator<Item = (usize, RangeInclusive<char>)> + '_ {
87 let mut chars = self.data.chars();
88 let mut index = 0;
89
90 core::iter::from_fn(move || {
91 let start_index = index;
92
93 let range = match chars.next()? {
94 '\0' => {
95 let start = chars.next()?;
96 let end = chars.next()?;
97
98 index += end as usize - start as usize + 1;
99
100 start..=end
101 }
102 c => {
103 index += 1;
104
105 c..=c
106 }
107 };
108
109 Some((start_index, range))
110 })
111 }
112
113 pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
115 let mut chars = self.data.chars();
116
117 core::iter::from_fn(move || {
118 let range = match chars.next()? {
119 '\0' => {
120 let start = chars.next()?;
121 let end = chars.next()?;
122
123 start..=end
124 }
125 c => c..=c,
126 };
127
128 Some(range)
129 })
130 .flatten()
131 }
132
133 pub fn contains(&self, c: char) -> bool {
135 self.chars().any(|v| v == c)
136 }
137}
138
139impl GlyphMapping for StrGlyphMapping<'_> {
140 fn index(&self, c: char) -> usize {
141 self.chars()
143 .enumerate()
144 .find(|(_, v)| c == *v)
145 .map(|(index, _)| index)
146 .unwrap_or(self.replacement_index)
147 }
148}
149
150macro_rules! impl_mapping {
151 ($( $(#[$meta:meta])* ($enum_variant:ident, $constant:ident, $mapping:expr), )*) => {
152 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
158 pub enum Mapping {
159 $(
160 $(#[$meta])*
161 $enum_variant,
162 )*
163 }
164
165 impl Mapping {
166 pub fn iter() -> impl Iterator<Item = Self> {
168 const ALL: &[Mapping] = &[$(Mapping::$enum_variant),*];
169
170 ALL.iter().copied()
171 }
172
173 pub const fn mime(self) -> &'static str {
175 match self {
176 $(Mapping::$enum_variant => stringify!($constant)),*
177 }
178 }
179
180 pub const fn glyph_mapping(self) -> &'static StrGlyphMapping<'static> {
182 match self {
183 $(Self::$enum_variant => &$constant),*
184 }
185 }
186 }
187
188 $(
189 $(#[$meta])*
190 pub const $constant: StrGlyphMapping = StrGlyphMapping::new($mapping, '?' as usize - ' ' as usize);
191 )*
192 };
193}
194
195impl_mapping!(
197 (Ascii, ASCII, "\0\u{20}\u{7f}"),
199
200 (Iso8859_1, ISO_8859_1, "\0\u{20}\u{7f}\0\u{a0}\u{ff}"),
202
203 (Iso8859_2, ISO_8859_2, "\0\u{20}\u{7f}\u{a0}\u{104}\u{2d8}\u{141}\u{a4}\u{13d}\u{15a}\u{a7}\u{a8}\u{160}\u{15e}\u{164}\u{179}\u{ad}\u{17d}\u{17b}\u{b0}\u{105}\u{2db}\u{142}\u{b4}\u{13e}\u{15b}\u{2c7}\u{b8}\u{161}\u{15f}\u{165}\u{17a}\u{2dd}\u{17e}\u{17c}\u{154}\u{c1}\u{c2}\u{102}\u{c4}\u{139}\u{106}\u{c7}\u{10c}\u{c9}\u{118}\u{cb}\u{11a}\u{cd}\u{ce}\u{10e}\u{110}\u{143}\u{147}\u{d3}\u{d4}\u{150}\u{d6}\u{d7}\u{158}\u{16e}\u{da}\u{170}\u{dc}\u{dd}\u{162}\u{df}\u{155}\u{e1}\u{e2}\u{103}\u{e4}\u{13a}\u{107}\u{e7}\u{10d}\u{e9}\u{119}\u{eb}\u{11b}\u{ed}\u{ee}\u{10f}\u{111}\u{144}\u{148}\u{f3}\u{f4}\u{151}\u{f6}\u{f7}\u{159}\u{16f}\u{fa}\u{171}\u{fc}\u{fd}\u{163}\u{2d9}"),
205
206 (Iso8859_3, ISO_8859_3, "\0\u{20}\u{7f}\u{a0}\u{126}\u{2d8}\0\u{a3}\u{a5}\u{124}\u{a7}\u{a8}\u{130}\u{15e}\u{11e}\u{134}\u{ad}\u{ae}\u{17b}\u{b0}\u{127}\0\u{b2}\u{b5}\u{125}\u{b7}\u{b8}\u{131}\u{15f}\u{11f}\u{135}\u{bd}\u{be}\u{17c}\0\u{c0}\u{c4}\u{10a}\u{108}\0\u{c7}\u{d4}\u{120}\u{d6}\u{d7}\u{11c}\0\u{d9}\u{dc}\u{16c}\u{15c}\0\u{df}\u{e4}\u{10b}\u{109}\0\u{e7}\u{f4}\u{121}\u{f6}\u{f7}\u{11d}\0\u{f9}\u{fc}\u{16d}\u{15d}\u{2d9}"),
208
209 (Iso8859_4, ISO_8859_4, "\0\u{20}\u{7f}\u{a0}\u{104}\u{138}\u{156}\u{a4}\u{128}\u{13b}\u{a7}\u{a8}\u{160}\u{112}\u{122}\u{166}\u{ad}\u{17d}\u{af}\u{b0}\u{105}\u{2db}\u{157}\u{b4}\u{129}\u{13c}\u{2c7}\u{b8}\u{161}\u{113}\u{123}\u{167}\u{14a}\u{17e}\u{14b}\u{100}\0\u{c1}\u{c6}\u{12e}\u{10c}\u{c9}\u{118}\u{cb}\u{116}\u{cd}\u{ce}\u{12a}\u{110}\u{145}\u{14c}\u{136}\0\u{d4}\u{d8}\u{172}\0\u{da}\u{dc}\u{168}\u{16a}\u{df}\u{101}\0\u{e1}\u{e6}\u{12f}\u{10d}\u{e9}\u{119}\u{eb}\u{117}\u{ed}\u{ee}\u{12b}\u{111}\u{146}\u{14d}\u{137}\0\u{f4}\u{f8}\u{173}\0\u{fa}\u{fc}\u{169}\u{16b}\u{2d9}"),
211
212 (Iso8859_5, ISO_8859_5, "\0\u{20}\u{7f}\u{a0}\0\u{401}\u{40c}\u{ad}\0\u{40e}\u{44f}\u{2116}\0\u{451}\u{45c}\u{a7}\u{45e}\u{45f}"),
214
215 (Iso8859_7, ISO_8859_7, "\0\u{20}\u{7f}\u{a0}\u{2018}\u{2019}\u{a3}\u{20ac}\u{20af}\0\u{a6}\u{a9}\u{37a}\0\u{ab}\u{ae}\u{2015}\0\u{b0}\u{b3}\0\u{384}\u{386}\u{b7}\0\u{388}\u{38a}\u{bb}\u{38c}\u{bd}\0\u{38e}\u{3cf}"),
217
218 (Iso8859_9, ISO_8859_9, "\0\u{20}\u{7f}\0\u{a0}\u{cf}\u{11e}\0\u{d1}\u{dc}\u{130}\u{15e}\0\u{df}\u{ef}\u{11f}\0\u{f1}\u{fc}\u{131}\u{15f}\u{ff}"),
220
221 (Iso8859_10, ISO_8859_10, "\0\u{20}\u{7f}\u{a0}\u{104}\u{112}\u{122}\u{12a}\u{128}\u{136}\u{a7}\u{13b}\u{110}\u{160}\u{166}\u{17d}\u{ad}\u{16a}\u{14a}\u{b0}\u{105}\u{113}\u{123}\u{12b}\u{129}\u{137}\u{b7}\u{13c}\u{111}\u{161}\u{167}\u{17e}\u{2015}\u{16b}\u{14b}\u{100}\0\u{c1}\u{c6}\u{12e}\u{10c}\u{c9}\u{118}\u{cb}\u{116}\0\u{cd}\u{d0}\u{145}\u{14c}\0\u{d3}\u{d6}\u{168}\u{d8}\u{172}\0\u{da}\u{df}\u{101}\0\u{e1}\u{e6}\u{12f}\u{10d}\u{e9}\u{119}\u{eb}\u{117}\0\u{ed}\u{f0}\u{146}\u{14d}\0\u{f3}\u{f6}\u{169}\u{f8}\u{173}\0\u{fa}\u{fe}\u{138}"),
223
224 (Iso8859_13, ISO_8859_13, "\0\u{20}\u{7f}\u{a0}\u{201d}\0\u{a2}\u{a4}\u{201e}\u{a6}\u{a7}\u{d8}\u{a9}\u{156}\0\u{ab}\u{ae}\u{c6}\0\u{b0}\u{b3}\u{201c}\0\u{b5}\u{b7}\u{f8}\u{b9}\u{157}\0\u{bb}\u{be}\u{e6}\u{104}\u{12e}\u{100}\u{106}\u{c4}\u{c5}\u{118}\u{112}\u{10c}\u{c9}\u{179}\u{116}\u{122}\u{136}\u{12a}\u{13b}\u{160}\u{143}\u{145}\u{d3}\u{14c}\0\u{d5}\u{d7}\u{172}\u{141}\u{15a}\u{16a}\u{dc}\u{17b}\u{17d}\u{df}\u{105}\u{12f}\u{101}\u{107}\u{e4}\u{e5}\u{119}\u{113}\u{10d}\u{e9}\u{17a}\u{117}\u{123}\u{137}\u{12b}\u{13c}\u{161}\u{144}\u{146}\u{f3}\u{14d}\0\u{f5}\u{f7}\u{173}\u{142}\u{15b}\u{16b}\u{fc}\u{17c}\u{17e}\u{2019}"),
226
227 (Iso8859_14, ISO_8859_14, "\0\u{20}\u{7f}\u{a0}\u{1e02}\u{1e03}\u{a3}\u{10a}\u{10b}\u{1e0a}\u{a7}\u{1e80}\u{a9}\u{1e82}\u{1e0b}\u{1ef2}\u{ad}\u{ae}\u{178}\u{1e1e}\u{1e1f}\u{120}\u{121}\u{1e40}\u{1e41}\u{b6}\u{1e56}\u{1e81}\u{1e57}\u{1e83}\u{1e60}\u{1ef3}\u{1e84}\u{1e85}\u{1e61}\0\u{c0}\u{cf}\u{174}\0\u{d1}\u{d6}\u{1e6a}\0\u{d8}\u{dd}\u{176}\0\u{df}\u{ef}\u{175}\0\u{f1}\u{f6}\u{1e6b}\0\u{f8}\u{fd}\u{177}\u{ff}"),
229
230 (Iso8859_15, ISO_8859_15, "\0\u{20}\u{7f}\0\u{a0}\u{a3}\u{20ac}\u{a5}\u{160}\u{a7}\u{161}\0\u{a9}\u{b3}\u{17d}\0\u{b5}\u{b7}\u{17e}\0\u{b9}\u{bb}\u{152}\u{153}\u{178}\0\u{bf}\u{ff}"),
232
233 (Iso8859_16, ISO_8859_16, "\0\u{20}\u{7f}\u{a0}\u{104}\u{105}\u{141}\u{20ac}\u{201e}\u{160}\u{a7}\u{161}\u{a9}\u{218}\u{ab}\u{179}\u{ad}\u{17a}\u{17b}\u{b0}\u{b1}\u{10c}\u{142}\u{17d}\u{201d}\u{b6}\u{b7}\u{17e}\u{10d}\u{219}\u{bb}\u{152}\u{153}\u{178}\u{17c}\0\u{c0}\u{c2}\u{102}\u{c4}\u{106}\0\u{c6}\u{cf}\u{110}\u{143}\0\u{d2}\u{d4}\u{150}\u{d6}\u{15a}\u{170}\0\u{d9}\u{dc}\u{118}\u{21a}\0\u{df}\u{e2}\u{103}\u{e4}\u{107}\0\u{e6}\u{ef}\u{111}\u{144}\0\u{f2}\u{f4}\u{151}\u{f6}\u{15b}\u{171}\0\u{f9}\u{fc}\u{119}\u{21b}\u{ff}"),
235
236 (JisX0201, JIS_X0201, "\0\u{20}\u{7f}\0\u{ff60}\u{ff9f}"),
238);
239
240#[cfg(test)]
241mod tests {
242 use super::*;
243
244 #[test]
245 fn empty() {
246 let mapping = StrGlyphMapping::new("", 0);
247
248 let mut iter = mapping.ranges();
249 assert_eq!(iter.next(), None);
250
251 let mut iter = mapping.chars();
252 assert_eq!(iter.next(), None);
253 }
254
255 #[test]
256 fn one_char() {
257 let mapping = StrGlyphMapping::new("a", 0);
258
259 let mut iter = mapping.ranges();
260 assert_eq!(iter.next(), Some((0, 'a'..='a')));
261 assert_eq!(iter.next(), None);
262
263 let mut iter = mapping.chars();
264 assert_eq!(iter.next(), Some('a'));
265 assert_eq!(iter.next(), None);
266
267 assert_eq!(mapping.index('a'), 0);
268 }
269
270 #[test]
271 fn three_chars() {
272 let mapping = StrGlyphMapping::new("abc", 1);
273
274 let mut iter = mapping.ranges();
275 assert_eq!(iter.next(), Some((0, 'a'..='a')));
276 assert_eq!(iter.next(), Some((1, 'b'..='b')));
277 assert_eq!(iter.next(), Some((2, 'c'..='c')));
278 assert_eq!(iter.next(), None);
279
280 let mut iter = mapping.chars();
281 assert_eq!(iter.next(), Some('a'));
282 assert_eq!(iter.next(), Some('b'));
283 assert_eq!(iter.next(), Some('c'));
284 assert_eq!(iter.next(), None);
285
286 assert_eq!(mapping.index('a'), 0);
287 assert_eq!(mapping.index('b'), 1);
288 assert_eq!(mapping.index('c'), 2);
289 assert_eq!(mapping.index('$'), 1);
290 }
291
292 #[test]
293 fn one_range() {
294 let mapping = StrGlyphMapping::new("\x00ac", 2);
295
296 let mut iter = mapping.ranges();
297 assert_eq!(iter.next(), Some((0, 'a'..='c')));
298 assert_eq!(iter.next(), None);
299
300 let mut iter = mapping.chars();
301 assert_eq!(iter.next(), Some('a'));
302 assert_eq!(iter.next(), Some('b'));
303 assert_eq!(iter.next(), Some('c'));
304 assert_eq!(iter.next(), None);
305
306 assert_eq!(mapping.index('a'), 0);
307 assert_eq!(mapping.index('b'), 1);
308 assert_eq!(mapping.index('c'), 2);
309 assert_eq!(mapping.index('$'), 2);
310 }
311
312 #[test]
313 fn incomplete_range() {
314 let mapping = StrGlyphMapping::new("\x00a", 0);
315
316 let mut iter = mapping.ranges();
317 assert_eq!(iter.next(), None);
318
319 let mut iter = mapping.chars();
320 assert_eq!(iter.next(), None);
321 }
322
323 #[test]
324 fn mixed_ranges_and_chars() {
325 let mapping = StrGlyphMapping::new("a\x00bde", 3);
326
327 let mut iter = mapping.ranges();
328 assert_eq!(iter.next(), Some((0, 'a'..='a')));
329 assert_eq!(iter.next(), Some((1, 'b'..='d')));
330 assert_eq!(iter.next(), Some((4, 'e'..='e')));
331 assert_eq!(iter.next(), None);
332
333 let mut iter = mapping.chars();
334 assert_eq!(iter.next(), Some('a'));
335 assert_eq!(iter.next(), Some('b'));
336 assert_eq!(iter.next(), Some('c'));
337 assert_eq!(iter.next(), Some('d'));
338 assert_eq!(iter.next(), Some('e'));
339 assert_eq!(iter.next(), None);
340
341 assert_eq!(mapping.index('a'), 0);
342 assert_eq!(mapping.index('b'), 1);
343 assert_eq!(mapping.index('c'), 2);
344 assert_eq!(mapping.index('d'), 3);
345 assert_eq!(mapping.index('e'), 4);
346 assert_eq!(mapping.index('$'), 3);
347 }
348
349 #[test]
350 fn dyn_str_glyph_mapping() {
351 let mapping = StrGlyphMapping::new("ab", 0);
352 let dyn_mapping: &dyn GlyphMapping = &mapping;
353
354 assert_eq!(dyn_mapping.index('b'), 1);
355 }
356
357 #[test]
358 fn dyn_fn_glyph_mapping() {
359 fn map(c: char) -> usize {
360 match c {
361 'a' => 0,
362 'b' => 1,
363 _ => 2,
364 }
365 }
366
367 let dyn_mapping: &dyn GlyphMapping = ↦
368
369 assert_eq!(dyn_mapping.index('a'), 0);
370 assert_eq!(dyn_mapping.index('b'), 1);
371 assert_eq!(dyn_mapping.index('?'), 2);
372 }
373}