mplusfonts/
charmap.rs

1use embedded_graphics::iterator::raw::RawDataSlice;
2use embedded_graphics::pixelcolor::PixelColor;
3use embedded_graphics::pixelcolor::raw::BigEndian;
4
5use crate::glyph::Glyph;
6
7/// Key that is unique to a charmap entry in a bitmap font.
8pub type CharmapEntryKey<'a> = &'a str;
9
10/// Charmap entry.
11#[derive(Debug)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13pub struct CharmapEntry<'a, C, const N: usize>
14where
15    C: PixelColor + From<C::Raw>,
16    RawDataSlice<'a, C::Raw, BigEndian>: IntoIterator<Item = C::Raw>,
17{
18    /// The key for the charmap entry.
19    pub key: CharmapEntryKey<'a>,
20    /// The value for advancing the position in the text run for the charmap entry.
21    pub advance_chars: usize,
22    /// A function that takes the key for the next charmap entry, returning the value for advancing
23    /// the position along the _x_-axis for the charmap entry in order to get to the position of
24    /// the next charmap entry.
25    pub advance_width_to: fn(CharmapEntryKey<'a>) -> f32,
26    /// The glyph.
27    pub glyph: Glyph<'a, C, N>,
28}
29
30/// Charmap, for looking up glyph data, matching as many characters as possible at a time.
31#[derive(Debug)]
32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
33pub enum Charmap<'a, C, const N: usize>
34where
35    C: PixelColor + From<C::Raw>,
36    RawDataSlice<'a, C::Raw, BigEndian>: IntoIterator<Item = C::Raw>,
37{
38    /// A leaf node with a single charmap entry.
39    Leaf(CharmapEntry<'a, C, N>),
40    /// A branch node with a function that takes the next character to match, returning another
41    /// charmap.
42    Branch(fn(char) -> &'a Charmap<'a, C, N>),
43}
44
45impl<'a, C, const N: usize> CharmapEntry<'a, C, N>
46where
47    C: PixelColor + From<C::Raw>,
48    RawDataSlice<'a, C::Raw, BigEndian>: IntoIterator<Item = C::Raw>,
49{
50    /// Charmap entry for the invisible glyph.
51    pub const NULL: Self = Self {
52        key: "",
53        advance_chars: 0,
54        advance_width_to: |_| 0.0,
55        glyph: Glyph::NULL,
56    };
57}
58
59impl<'a, C, const N: usize> Charmap<'a, C, N>
60where
61    C: PixelColor + From<C::Raw>,
62    RawDataSlice<'a, C::Raw, BigEndian>: IntoIterator<Item = C::Raw>,
63{
64    /// Finds the charmap entry for a given input, traversing the branch nodes while also matching
65    /// characters from the specified string slice until a leaf node is found.
66    pub fn get(&self, slice: &str) -> &CharmapEntry<'a, C, N> {
67        let mut chars = slice.chars();
68        let first = chars.next().unwrap_or_default();
69        let slice = chars.as_str();
70
71        match self {
72            Self::Leaf(entry) => entry,
73            Self::Branch(map) => map(first).get(slice),
74        }
75    }
76}