premium_pixel/
awakening.rs

1use crate::Surface;
2
3/// Write on a surface using the Awakening typeface
4pub trait Awakening {
5    /// Write the text with the baseline starting at the given position.
6    /// Returns the width of the text in pixels.
7    fn awakening(&mut self, x: i32, y: i32, text: &str) -> i32;
8}
9
10impl<S: Surface> Awakening for S {
11    fn awakening(&mut self, x: i32, y: i32, text: &str) -> i32 {
12        let mut k = 0;
13        let mut w = 0;
14        for glyph in Glyphs::from(text) {
15            let b = glyph.data().next().unwrap_or(0);
16            if (k | (k << 1)) & (b | (b << 1)) != 0 {
17                w += 1;
18            }
19            for col in glyph.data() {
20                for i in 0..16 {
21                    if col & (1 << i) != 0 {
22                        self.pixel(x + w, y - 10 + i);
23                    }
24                }
25                k = col;
26                w += 1;
27            }
28        }
29        w
30    }
31}
32
33struct Glyphs<'a> {
34    text: &'a [u8],
35}
36
37struct GlyphLookup<'a>(&'a [u8]);
38
39struct Glyph<'a> {
40    text: &'a [u8],
41    data: &'a [u8],
42    tall: bool,
43}
44
45struct GlyphData<'a> {
46    data: &'a [u8],
47    tall: bool,
48}
49
50impl<'a> From<&'a str> for Glyphs<'a> {
51    fn from(value: &'a str) -> Self {
52        Self {
53            text: value.as_bytes(),
54        }
55    }
56}
57
58impl Iterator for Glyphs<'_> {
59    type Item = Glyph<'static>;
60    fn next(&mut self) -> Option<Self::Item> {
61        'not_found: while !self.text.is_empty() {
62            let b = *self.text.first()?;
63            if b == b' ' {
64                self.text = &self.text[1..];
65                return Some(SPACE);
66            }
67            let start = INDEX[b as usize >> 2];
68            if start < 0 {
69                self.text = &self.text[1..];
70                continue 'not_found;
71            }
72            for glyph in GlyphLookup(&DATA[start as usize..]) {
73                if self.text.starts_with(glyph.text) {
74                    self.text = &self.text[glyph.text.len()..];
75                    return Some(glyph);
76                } else if glyph.text[0] > self.text[0] {
77                    self.text = &self.text[1..];
78                    continue 'not_found;
79                }
80            }
81        }
82        None
83    }
84}
85
86impl<'a> Iterator for GlyphLookup<'a> {
87    type Item = Glyph<'a>;
88    fn next(&mut self) -> Option<Self::Item> {
89        let mut s = self.0;
90        let l = *s.first()? as usize;
91        s = &s[1..];
92        let text = s.get(..l)?;
93        s = &s[l..];
94        let l = *s.first()? as usize;
95        let tall = l & 128 != 0;
96        let l = l & 127;
97        s = &s[1..];
98        let data = s.get(..l)?;
99        s = &s[l..];
100        self.0 = s;
101        Some(Glyph { text, data, tall })
102    }
103}
104
105impl<'a> Glyph<'a> {
106    fn data(&self) -> GlyphData<'a> {
107        GlyphData {
108            data: self.data,
109            tall: self.tall,
110        }
111    }
112}
113
114impl Iterator for GlyphData<'_> {
115    type Item = u16;
116    fn next(&mut self) -> Option<Self::Item> {
117        if self.tall {
118            let col = u16::from_le_bytes([*self.data.first()?, *self.data.get(1)?]);
119            self.data = &self.data[2..];
120            Some(col)
121        } else {
122            let col = u16::from(*self.data.first()?) << 4;
123            self.data = &self.data[1..];
124            Some(col)
125        }
126    }
127}
128
129const SPACE: Glyph<'static> = Glyph {
130    text: b" ",
131    data: &[0, 0, 0],
132    tall: false,
133};
134const DATA: &[u8] = &[
135    /* "\b" */ 1, 8, 1, 0, /* "\t" */ 1, 9, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* "!" */ 1,
136    33, 1, 46, /* "\"" */ 1, 34, 3, 3, 0, 3, /* "#" */ 1, 35, 5, 20, 62, 20, 62, 20,
137    /* "$" */ 1, 36, 5, 36, 42, 107, 42, 18, /* "%" */ 1, 37, 5, 34, 16, 8, 4, 34,
138    /* "&" */ 1, 38, 5, 20, 42, 42, 20, 40, /* "'" */ 1, 39, 1, 3, /* "(" */ 1, 40,
139    2, 62, 65, /* ")" */ 1, 41, 2, 65, 62, /* "+" */ 1, 43, 5, 8, 8, 62, 8, 8,
140    /* "," */ 1, 44, 2, 64, 32, /* "-" */ 1, 45, 4, 8, 8, 8, 8, /* "." */ 1, 46, 1,
141    32, /* "/" */ 1, 47, 5, 32, 16, 8, 4, 2, /* "0" */ 1, 48, 5, 30, 33, 37, 33, 30,
142    /* "1" */ 1, 49, 3, 34, 63, 32, /* "2" */ 1, 50, 5, 34, 49, 41, 41, 38,
143    /* "3" */ 1, 51, 5, 18, 33, 33, 37, 26, /* "4" */ 1, 52, 5, 24, 20, 18, 63, 16,
144    /* "5" */ 1, 53, 5, 23, 37, 37, 37, 25, /* "6" */ 1, 54, 5, 28, 38, 37, 37, 24,
145    /* "7" */ 1, 55, 5, 1, 1, 57, 5, 3, /* "8" */ 1, 56, 5, 26, 37, 37, 37, 26,
146    /* "9" */ 1, 57, 5, 6, 73, 41, 25, 14, /* ":" */ 1, 58, 1, 20, /* ";" */ 1, 59,
147    2, 64, 40, /* "<" */ 1, 60, 3, 8, 20, 34, /* "=" */ 1, 61, 3, 20, 20, 20,
148    /* ">" */ 1, 62, 3, 34, 20, 8, /* "?" */ 1, 63, 5, 4, 2, 42, 10, 4, /* "@" */ 1,
149    64, 7, 62, 65, 93, 85, 93, 81, 14, /* "A" */ 1, 65, 5, 62, 9, 9, 9, 62, /* "B" */ 1,
150    66, 5, 63, 37, 37, 37, 26, /* "C" */ 1, 67, 5, 30, 33, 33, 33, 34, /* "D" */ 1, 68,
151    5, 63, 33, 33, 34, 28, /* "E" */ 1, 69, 5, 63, 37, 37, 37, 33, /* "F" */ 1, 70, 5,
152    63, 5, 5, 5, 1, /* "G" */ 1, 71, 5, 28, 34, 33, 41, 58, /* "H" */ 1, 72, 5, 63, 4, 4,
153    4, 63, /* "I" */ 1, 73, 3, 33, 63, 33, /* "J" */ 1, 74, 5, 16, 32, 32, 33, 31,
154    /* "K" */ 1, 75, 5, 63, 0, 12, 18, 33, /* "L" */ 1, 76, 5, 63, 32, 32, 32, 32,
155    /* "M" */ 1, 77, 5, 63, 2, 4, 2, 63, /* "N" */ 1, 78, 5, 63, 6, 12, 24, 63,
156    /* "O" */ 1, 79, 5, 30, 33, 33, 33, 30, /* "P" */ 1, 80, 5, 63, 9, 9, 9, 6,
157    /* "Q" */ 1, 81, 5, 30, 33, 41, 17, 46, /* "R" */ 1, 82, 5, 63, 5, 13, 21, 34,
158    /* "S" */ 1, 83, 5, 18, 37, 37, 37, 24, /* "T" */ 1, 84, 5, 1, 1, 63, 1, 1,
159    /* "U" */ 1, 85, 5, 31, 32, 32, 32, 31, /* "V" */ 1, 86, 5, 15, 16, 32, 16, 15,
160    /* "W" */ 1, 87, 5, 63, 16, 8, 16, 63, /* "X" */ 1, 88, 5, 33, 18, 12, 18, 33,
161    /* "Y" */ 1, 89, 5, 3, 4, 56, 4, 3, /* "Z" */ 1, 90, 5, 33, 49, 45, 35, 33,
162    /* "[" */ 1, 91, 2, 127, 65, /* "\\" */ 1, 92, 5, 2, 4, 8, 16, 32, /* "]" */ 1,
163    93, 2, 65, 127, /* "_" */ 1, 95, 4, 32, 32, 32, 32, /* "a" */ 1, 97, 5, 16, 42, 42,
164    42, 60, /* "b" */ 1, 98, 5, 63, 36, 34, 34, 28, /* "c" */ 1, 99, 5, 28, 34, 34, 34,
165    36, /* "d" */ 1, 100, 5, 28, 34, 34, 36, 63, /* "e" */ 1, 101, 5, 28, 42, 42, 42, 12,
166    /* "ff" */ 2, 102, 102, 7, 8, 126, 9, 9, 126, 9, 1, /* "f" */ 1, 102, 4, 8, 126, 9,
167    1, /* "g" */ 1, 103, 5, 24, 164, 162, 146, 126, /* "h" */ 1, 104, 5, 63, 4, 2, 2, 60,
168    /* "i" */ 1, 105, 2, 4, 61, /* "j" */ 1, 106, 3, 128, 132, 125, /* "k" */ 1,
169    107, 4, 63, 8, 20, 34, /* "l" */ 1, 108, 2, 1, 63, /* "m" */ 1, 109, 5, 62, 4, 8, 4,
170    62, /* "n" */ 1, 110, 5, 62, 2, 2, 4, 56, /* "o" */ 1, 111, 5, 28, 34, 34, 34, 28,
171    /* "p" */ 1, 112, 5, 254, 34, 34, 36, 24, /* "q" */ 1, 113, 5, 24, 36, 34, 34, 254,
172    /* "r" */ 1, 114, 4, 62, 4, 2, 2, /* "s" */ 1, 115, 5, 36, 42, 42, 42, 16,
173    /* "t" */ 1, 116, 4, 2, 31, 34, 32, /* "u" */ 1, 117, 5, 14, 16, 32, 32, 62,
174    /* "v" */ 1, 118, 5, 14, 16, 32, 16, 14, /* "w" */ 1, 119, 5, 62, 16, 8, 16, 62,
175    /* "x" */ 1, 120, 5, 34, 20, 8, 20, 34, /* "y" */ 1, 121, 5, 142, 144, 144, 72, 62,
176    /* "z" */ 1, 122, 5, 34, 50, 42, 38, 34, /* "{" */ 1, 123, 3, 8, 54, 65,
177    /* "|" */ 1, 124, 1, 127, /* "}" */ 1, 125, 3, 65, 54, 8, /* "¡" */ 2, 194,
178    161, 1, 116, /* "©" */ 2, 194, 169, 8, 30, 33, 12, 18, 18, 20, 33, 30, /* "«" */ 2,
179    194, 171, 4, 8, 20, 8, 20, /* "°" */ 2, 194, 176, 3, 7, 5, 7, /* "µ" */ 2, 194,
180    181, 5, 254, 16, 32, 32, 62, /* "»" */ 2, 194, 187, 4, 20, 8, 20, 8, /* "¿" */ 2,
181    194, 191, 5, 32, 80, 84, 64, 32, /* "À" */ 2, 195, 128, 138, 224, 3, 148, 0, 152, 0, 144,
182    0, 224, 3, /* "Á" */ 2, 195, 129, 138, 224, 3, 144, 0, 152, 0, 148, 0, 224, 3,
183    /* "Â" */ 2, 195, 130, 138, 224, 3, 152, 0, 148, 0, 152, 0, 224, 3, /* "Ä" */ 2,
184    195, 132, 138, 224, 3, 148, 0, 144, 0, 148, 0, 224, 3, /* "Æ" */ 2, 195, 134, 9, 62, 9,
185    9, 9, 63, 37, 37, 37, 33, /* "Ç" */ 2, 195, 135, 5, 30, 161, 225, 33, 18,
186    /* "È" */ 2, 195, 136, 138, 240, 3, 84, 2, 88, 2, 80, 2, 16, 2, /* "É" */ 2, 195,
187    137, 138, 240, 3, 80, 2, 88, 2, 84, 2, 16, 2, /* "Ê" */ 2, 195, 138, 138, 240, 3, 88, 2,
188    84, 2, 88, 2, 16, 2, /* "Ë" */ 2, 195, 139, 138, 240, 3, 84, 2, 80, 2, 84, 2, 16, 2,
189    /* "Í" */ 2, 195, 141, 134, 16, 2, 248, 3, 20, 2, /* "Î" */ 2, 195, 142, 134, 24,
190    2, 244, 3, 24, 2, /* "Ï" */ 2, 195, 143, 134, 20, 2, 240, 3, 20, 2, /* "Ð" */ 2,
191    195, 144, 6, 8, 63, 41, 33, 34, 28, /* "Ñ" */ 2, 195, 145, 5, 62, 5, 10, 17, 62,
192    /* "Ó" */ 2, 195, 147, 138, 224, 1, 16, 2, 24, 2, 20, 2, 224, 1, /* "Ô" */ 2, 195,
193    148, 138, 224, 1, 24, 2, 20, 2, 24, 2, 224, 1, /* "Ö" */ 2, 195, 150, 138, 224, 1, 20, 2,
194    16, 2, 20, 2, 224, 1, /* "Ù" */ 2, 195, 153, 138, 240, 1, 4, 2, 8, 2, 0, 2, 240, 1,
195    /* "Ú" */ 2, 195, 154, 138, 240, 1, 0, 2, 8, 2, 4, 2, 240, 1, /* "Û" */ 2, 195,
196    155, 138, 240, 1, 8, 2, 4, 2, 8, 2, 240, 1, /* "Ü" */ 2, 195, 156, 138, 240, 1, 4, 2, 0,
197    2, 4, 2, 240, 1, /* "Ý" */ 2, 195, 157, 138, 48, 0, 64, 0, 136, 3, 68, 0, 48, 0,
198    /* "Þ" */ 2, 195, 158, 4, 63, 18, 18, 12, /* "ß" */ 2, 195, 159, 4, 62, 1, 41, 22,
199    /* "à" */ 2, 195, 160, 138, 0, 1, 168, 2, 176, 2, 160, 2, 192, 3, /* "á" */ 2, 195,
200    161, 138, 0, 1, 160, 2, 176, 2, 168, 2, 192, 3, /* "â" */ 2, 195, 162, 138, 0, 1, 176, 2,
201    168, 2, 176, 2, 192, 3, /* "ä" */ 2, 195, 164, 138, 0, 1, 168, 2, 160, 2, 168, 2, 192, 3,
202    /* "æ" */ 2, 195, 166, 9, 16, 42, 42, 42, 60, 42, 42, 42, 12, /* "ç" */ 2, 195,
203    167, 5, 28, 162, 226, 34, 36, /* "è" */ 2, 195, 168, 138, 192, 1, 168, 2, 176, 2, 160, 2,
204    192, 0, /* "é" */ 2, 195, 169, 138, 192, 1, 160, 2, 176, 2, 168, 2, 192, 0,
205    /* "ê" */ 2, 195, 170, 138, 192, 1, 176, 2, 168, 2, 176, 2, 192, 0, /* "ë" */ 2,
206    195, 171, 138, 192, 1, 168, 2, 160, 2, 168, 2, 192, 0, /* "í" */ 2, 195, 173, 132, 80, 0,
207    200, 3, /* "î" */ 2, 195, 174, 134, 80, 0, 200, 3, 16, 0, /* "ï" */ 2, 195, 175, 3,
208    5, 60, 1, /* "ð" */ 2, 195, 176, 138, 128, 1, 72, 2, 104, 2, 80, 2, 232, 1,
209    /* "ó" */ 2, 195, 179, 138, 192, 1, 32, 2, 48, 2, 40, 2, 192, 1, /* "ô" */ 2, 195,
210    180, 138, 192, 1, 48, 2, 40, 2, 48, 2, 192, 1, /* "ö" */ 2, 195, 182, 138, 192, 1, 40, 2,
211    32, 2, 40, 2, 192, 1, /* "ù" */ 2, 195, 185, 138, 224, 0, 8, 1, 16, 2, 0, 2, 224, 3,
212    /* "ú" */ 2, 195, 186, 138, 224, 0, 0, 1, 16, 2, 8, 2, 224, 3, /* "û" */ 2, 195,
213    187, 138, 224, 0, 16, 1, 8, 2, 16, 2, 224, 3, /* "ü" */ 2, 195, 188, 138, 224, 0, 8, 1,
214    0, 2, 8, 2, 224, 3, /* "ý" */ 2, 195, 189, 138, 224, 8, 0, 9, 16, 9, 136, 4, 224, 3,
215    /* "þ" */ 2, 195, 190, 5, 255, 36, 34, 34, 28, /* "Œ" */ 2, 197, 146, 9, 30, 33,
216    33, 33, 63, 37, 37, 37, 33, /* "œ" */ 2, 197, 147, 9, 28, 34, 34, 34, 28, 42, 42, 42, 12,
217    /* "Ω" */ 2, 206, 169, 5, 46, 49, 1, 49, 46, /* "‘" */ 3, 226, 128, 152, 2, 6, 5,
218    /* "’" */ 3, 226, 128, 153, 2, 5, 3, /* "‚" */ 3, 226, 128, 154, 2, 80, 48,
219    /* "“" */ 3, 226, 128, 156, 5, 6, 5, 0, 6, 5, /* "”" */ 3, 226, 128, 157, 5, 5,
220    3, 0, 5, 3, /* "„" */ 3, 226, 128, 158, 5, 80, 48, 0, 80, 48, /* "…" */ 3, 226,
221    128, 166, 5, 32, 0, 32, 0, 32,
222];
223const INDEX: [i16; 64] = [
224    -1, -1, 0, -1, -1, -1, -1, -1, 15, 33, 61, 79, 103, 133, 165, 190, 216, 250, 282, 312, 344,
225    376, 408, 437, 457, 481, 523, 549, 578, 609, 640, 670, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226    -1, -1, -1, -1, -1, -1, 680, 1343, -1, 1369, -1, -1, -1, -1, 1378, -1, -1, -1, -1, -1, -1, -1,
227];