strat9_kernel/arch/x86_64/vga/
font.rs1use alloc::vec::Vec;
6
7pub(crate) const FONT_PSF: &[u8] = include_bytes!("../fonts/zap-ext-light20.psf");
8
9pub(crate) struct FontInfo {
10 pub(crate) glyph_count: usize,
11 pub(crate) bytes_per_glyph: usize,
12 pub(crate) glyph_w: usize,
13 pub(crate) glyph_h: usize,
14 pub(crate) data_offset: usize,
15 pub(crate) unicode_table_offset: Option<usize>,
16}
17
18pub(crate) fn parse_psf(font: &[u8]) -> Option<FontInfo> {
19 if font.len() >= 4 && font[0] == 0x36 && font[1] == 0x04 {
21 let mode = font[2];
22 let glyph_count = if (mode & 0x01) != 0 { 512 } else { 256 };
23 let glyph_h = font[3] as usize;
24 let bytes_per_glyph = glyph_h;
25 return Some(FontInfo {
26 glyph_count,
27 bytes_per_glyph,
28 glyph_w: 8,
29 glyph_h,
30 data_offset: 4,
31 unicode_table_offset: None,
32 });
33 }
34
35 if font.len() >= 32 && font[0] == 0x72 && font[1] == 0xB5 && font[2] == 0x4A && font[3] == 0x86
37 {
38 let rd_u32 = |off: usize| -> u32 {
39 u32::from_le_bytes([font[off], font[off + 1], font[off + 2], font[off + 3]])
40 };
41 let headersize = rd_u32(8) as usize;
42 let flags = rd_u32(12);
43 let glyph_count = rd_u32(16) as usize;
44 let bytes_per_glyph = rd_u32(20) as usize;
45 let glyph_h = rd_u32(24) as usize;
46 let glyph_w = rd_u32(28) as usize;
47 let glyph_bytes = glyph_count.saturating_mul(bytes_per_glyph);
48 let unicode_table_offset = if (flags & 1) != 0 {
49 Some(headersize.saturating_add(glyph_bytes))
50 } else {
51 None
52 };
53 return Some(FontInfo {
54 glyph_count,
55 bytes_per_glyph,
56 glyph_w,
57 glyph_h,
58 data_offset: headersize,
59 unicode_table_offset,
60 });
61 }
62
63 None
64}
65
66fn decode_utf8_at(bytes: &[u8], pos: usize) -> Option<(u32, usize)> {
68 let b0 = *bytes.get(pos)?;
69 if b0 < 0x80 {
70 return Some((b0 as u32, 1));
71 }
72 if (b0 & 0xE0) == 0xC0 {
73 let b1 = *bytes.get(pos + 1)?;
74 if (b1 & 0xC0) != 0x80 {
75 return None;
76 }
77 let cp = (((b0 & 0x1F) as u32) << 6) | ((b1 & 0x3F) as u32);
78 return Some((cp, 2));
79 }
80 if (b0 & 0xF0) == 0xE0 {
81 let b1 = *bytes.get(pos + 1)?;
82 let b2 = *bytes.get(pos + 2)?;
83 if (b1 & 0xC0) != 0x80 || (b2 & 0xC0) != 0x80 {
84 return None;
85 }
86 let cp = (((b0 & 0x0F) as u32) << 12) | (((b1 & 0x3F) as u32) << 6) | ((b2 & 0x3F) as u32);
87 return Some((cp, 3));
88 }
89 if (b0 & 0xF8) == 0xF0 {
90 let b1 = *bytes.get(pos + 1)?;
91 let b2 = *bytes.get(pos + 2)?;
92 let b3 = *bytes.get(pos + 3)?;
93 if (b1 & 0xC0) != 0x80 || (b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80 {
94 return None;
95 }
96 let cp = (((b0 & 0x07) as u32) << 18)
97 | (((b1 & 0x3F) as u32) << 12)
98 | (((b2 & 0x3F) as u32) << 6)
99 | ((b3 & 0x3F) as u32);
100 return Some((cp, 4));
101 }
102 None
103}
104
105pub(crate) fn parse_psf2_unicode_map(font: &[u8], info: &FontInfo) -> Vec<(u32, usize)> {
107 let Some(mut i) = info.unicode_table_offset else {
108 return Vec::new();
109 };
110 if i >= font.len() {
111 return Vec::new();
112 }
113
114 let mut map = Vec::new();
115 for glyph in 0..info.glyph_count {
116 while i < font.len() {
117 let b = font[i];
118 if b == 0xFF {
119 i += 1;
120 break;
121 }
122 if b == 0xFE {
123 i += 1;
125 continue;
126 }
127 if let Some((cp, adv)) = decode_utf8_at(font, i) {
128 if !map.iter().any(|(u, _)| *u == cp) {
129 map.push((cp, glyph));
130 }
131 i += adv;
132 } else {
133 i += 1;
134 }
135 }
136 }
137
138 map
139}