Skip to main content

oxide_gui_core/
font.rs

1//! Embedded 8×16 bitmap font covering printable ASCII (0x20–0x7E).
2//!
3//! Each glyph is 16 bytes (one per row), 8 pixels wide.  MSB of each byte
4//! is the leftmost pixel.  The font is stored as a `const` so it lands in
5//! read-only data and costs zero heap.
6//!
7//! `render_char` paints one glyph into any `Backend` using `fill_rect(1×1)`
8//! for each lit pixel — simple and correct on every platform.  Backends that
9//! have direct pixel access can bypass this and write the glyph data directly
10//! for better performance.
11
12use crate::backend::Backend;
13use crate::color::Color;
14
15pub const CHAR_W:  u32 = 8;
16pub const CHAR_H:  u32 = 16;
17pub const FIRST:   u8  = 0x20; // ' '
18pub const LAST:    u8  = 0x7E; // '~'
19pub const N_CHARS: usize = (LAST - FIRST + 1) as usize; // 95
20
21/// Render glyph `ch` at pixel `(x, y)` into `backend`.
22pub fn render_char<B: Backend + ?Sized>(backend: &mut B, x: u32, y: u32, ch: char, color: Color) {
23    let byte = ch as u32;
24    if byte < FIRST as u32 || byte > LAST as u32 { return; }
25    let idx = (byte - FIRST as u32) as usize;
26    let glyph = &FONT_DATA[idx * CHAR_H as usize .. (idx + 1) * CHAR_H as usize];
27    for (row, &bits) in glyph.iter().enumerate() {
28        let py = y + row as u32;
29        if py >= backend.height() { break; }
30        for col in 0..CHAR_W {
31            if bits & (0x80 >> col) != 0 {
32                let px = x + col;
33                if px < backend.width() {
34                    backend.fill_rect(px, py, 1, 1, color);
35                }
36            }
37        }
38    }
39}
40
41/// Measure the pixel width of `text` using the embedded font.
42pub fn text_width(text: &str) -> u32 {
43    text.chars().count() as u32 * CHAR_W
44}
45
46// ── Bitmap data ───────────────────────────────────────────────────────────────
47// 95 glyphs × 16 rows = 1 520 bytes.
48// Each byte encodes one row of 8 pixels; MSB = leftmost pixel.
49
50#[rustfmt::skip]
51const FONT_DATA: &[u8] = &[
52// 0x20 ' '
530x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
54// 0x21 '!'
550x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
56// 0x22 '"'
570x00,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
58// 0x23 '#'
590x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
60// 0x24 '$'
610x00,0x0C,0x3E,0x6B,0x68,0x3E,0x0B,0x6B,0x3E,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,
62// 0x25 '%'
630x00,0x60,0x66,0x0C,0x18,0x18,0x30,0x66,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
64// 0x26 '&'
650x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
66// 0x27 "'"
670x00,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
68// 0x28 '('
690x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,
70// 0x29 ')'
710x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
72// 0x2A '*'
730x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
74// 0x2B '+'
750x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
76// 0x2C ','
770x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
78// 0x2D '-'
790x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80// 0x2E '.'
810x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
82// 0x2F '/'
830x00,0x06,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,
84// 0x30 '0'
850x00,0x3C,0x66,0x6E,0x76,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
86// 0x31 '1'
870x00,0x18,0x38,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
88// 0x32 '2'
890x00,0x3C,0x66,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
90// 0x33 '3'
910x00,0x3C,0x66,0x06,0x1C,0x06,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
92// 0x34 '4'
930x00,0x0C,0x1C,0x3C,0x6C,0x7E,0x0C,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
94// 0x35 '5'
950x00,0x7E,0x60,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
96// 0x36 '6'
970x00,0x1C,0x30,0x60,0x7C,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
98// 0x37 '7'
990x00,0x7E,0x06,0x0C,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
100// 0x38 '8'
1010x00,0x3C,0x66,0x66,0x3C,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
102// 0x39 '9'
1030x00,0x3C,0x66,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
104// 0x3A ':'
1050x00,0x00,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
106// 0x3B ';'
1070x00,0x00,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
108// 0x3C '<'
1090x00,0x00,0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
110// 0x3D '='
1110x00,0x00,0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
112// 0x3E '>'
1130x00,0x00,0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
114// 0x3F '?'
1150x00,0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
116// 0x40 '@'
1170x00,0x3C,0x66,0x6E,0x6A,0x6E,0x60,0x62,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
118// 0x41 'A'
1190x00,0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120// 0x42 'B'
1210x00,0x7C,0x66,0x66,0x7C,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122// 0x43 'C'
1230x00,0x3C,0x66,0x60,0x60,0x60,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
124// 0x44 'D'
1250x00,0x78,0x6C,0x66,0x66,0x66,0x66,0x6C,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
126// 0x45 'E'
1270x00,0x7E,0x60,0x60,0x7C,0x60,0x60,0x60,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
128// 0x46 'F'
1290x00,0x7E,0x60,0x60,0x7C,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130// 0x47 'G'
1310x00,0x3C,0x66,0x60,0x60,0x6E,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
132// 0x48 'H'
1330x00,0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
134// 0x49 'I'
1350x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
136// 0x4A 'J'
1370x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
138// 0x4B 'K'
1390x00,0x66,0x6C,0x78,0x70,0x78,0x6C,0x66,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140// 0x4C 'L'
1410x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
142// 0x4D 'M'
1430x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144// 0x4E 'N'
1450x00,0x66,0x76,0x7E,0x7E,0x6E,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
146// 0x4F 'O'
1470x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
148// 0x50 'P'
1490x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150// 0x51 'Q'
1510x00,0x3C,0x66,0x66,0x66,0x66,0x6E,0x3C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
152// 0x52 'R'
1530x00,0x7C,0x66,0x66,0x7C,0x6C,0x66,0x66,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
154// 0x53 'S'
1550x00,0x3C,0x66,0x60,0x3C,0x06,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
156// 0x54 'T'
1570x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
158// 0x55 'U'
1590x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
160// 0x56 'V'
1610x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
162// 0x57 'W'
1630x00,0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
164// 0x58 'X'
1650x00,0x66,0x66,0x3C,0x18,0x3C,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
166// 0x59 'Y'
1670x00,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
168// 0x5A 'Z'
1690x00,0x7E,0x06,0x0C,0x18,0x30,0x60,0x60,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
170// 0x5B '['
1710x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
172// 0x5C '\'
1730x00,0x60,0x60,0x30,0x30,0x18,0x18,0x0C,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
174// 0x5D ']'
1750x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
176// 0x5E '^'
1770x00,0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
178// 0x5F '_'
1790x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,
180// 0x60 '`'
1810x00,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
182// 0x61 'a'
1830x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
184// 0x62 'b'
1850x00,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
186// 0x63 'c'
1870x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
188// 0x64 'd'
1890x00,0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
190// 0x65 'e'
1910x00,0x00,0x00,0x3C,0x66,0x7E,0x60,0x60,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
192// 0x66 'f'
1930x00,0x0E,0x18,0x18,0x3E,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
194// 0x67 'g'
1950x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,
196// 0x68 'h'
1970x00,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
198// 0x69 'i'
1990x00,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
200// 0x6A 'j'
2010x00,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,
202// 0x6B 'k'
2030x00,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
204// 0x6C 'l'
2050x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
206// 0x6D 'm'
2070x00,0x00,0x00,0x76,0x7F,0x6B,0x6B,0x6B,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
208// 0x6E 'n'
2090x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
210// 0x6F 'o'
2110x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
212// 0x70 'p'
2130x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,
214// 0x71 'q'
2150x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x3E,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
216// 0x72 'r'
2170x00,0x00,0x00,0x6C,0x76,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
218// 0x73 's'
2190x00,0x00,0x00,0x3C,0x66,0x38,0x0C,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
220// 0x74 't'
2210x00,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
222// 0x75 'u'
2230x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
224// 0x76 'v'
2250x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
226// 0x77 'w'
2270x00,0x00,0x00,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
228// 0x78 'x'
2290x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
230// 0x79 'y'
2310x00,0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
232// 0x7A 'z'
2330x00,0x00,0x00,0x7E,0x0C,0x18,0x30,0x60,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
234// 0x7B '{'
2350x00,0x0E,0x18,0x18,0x70,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
236// 0x7C '|'
2370x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
238// 0x7D '}'
2390x00,0x70,0x18,0x18,0x0E,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
240// 0x7E '~'
2410x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
242];