kernel/drivers/gpu/basic_fb/
font.rs1use super::framebuffer::BasicFramebuffer;
7
8pub struct Psf2Font {
10 font: &'static [u8],
11 header: Psf2Header,
12}
13impl Psf2Font {
14 const DEFAULT_BACKGROUND_COLOR: u32 = 0x00000000;
15 const DEFAULT_FOREGROUND_COLOR: u32 = 0x00FFFFFF;
16
17 pub fn init() -> Self {
22 let font: &[u8] = include_bytes!("../../../../resources/ter-powerline-v16n.psf");
23 Self {
24 font,
25 header: Psf2Header::parse(font),
26 }
27 }
28
29 fn parse_char(&self, c: char) -> Option<&'static [u8]> {
31 let char_index = c as usize;
32
33 if char_index >= self.header.glyph_count as usize {
34 return None;
35 }
36
37 let start = self.header.header_size as usize + char_index * self.header.bytes_per_glyph as usize;
38
39 Some(&self.font[start..(start + self.header.bytes_per_glyph as usize)])
40 }
41
42 pub fn glyph_height(&self) -> usize {
44 self.header.height as usize
45 }
46
47 pub fn draw_char(&self, fb: &BasicFramebuffer, c: char, x: usize, y: usize, font_color: Option<u32>) -> usize {
52 let Some(glyph) = self.parse_char(c) else { return x; };
53
54 if x + self.header.width as usize > fb.width
55 || y + self.header.height as usize > fb.height
56 {
57 return x;
58 }
59
60 let row_stride = (self.header.width + 7) / 8;
61
62 for row in 0..self.header.height as usize {
63 for col in 0..self.header.width as usize {
64 let byte = glyph[row * row_stride as usize + col / 8];
65 let bit = (byte >> (7 - (col % 8))) & 1;
66
67 let color = if bit == 1 {
68 font_color.unwrap_or(Self::DEFAULT_FOREGROUND_COLOR)
69 } else {
70 Self::DEFAULT_BACKGROUND_COLOR
71 };
72 let pixel_pos = (y + row) * fb.pixels_per_row + (x + col);
73
74 unsafe {
77 fb.fb_pointer.add(pixel_pos).write_volatile(color);
78 }
79 }
80 }
81
82 x + self.header.width as usize
83 }
84
85 pub fn draw_string(&self, fb: &BasicFramebuffer, string: &str, x: &mut usize, y: &mut usize, font_color: Option<u32>) {
88 for c in string.chars() {
89 if c == '\n' {
90 *x = 0;
91 *y += self.header.height as usize;
92 } else {
93 *x = self.draw_char(fb, c, *x, *y, font_color);
94 }
95 }
96 }
97}
98
99struct Psf2Header {
101 pub header_size: u32,
102 pub glyph_count: u32,
103 pub bytes_per_glyph: u32,
104 pub width: u32,
105 pub height: u32
106}
107impl Psf2Header {
108 const MAGIC_NUMBER: u32 = 0x864ab572;
109
110 fn parse(psf2_font: &[u8]) -> Self {
115 use crate::lib::panic::kernel_panic;
116 use crate::lib::panic_codes::PanicCode;
117
118 let read_u32 = |offset: usize| -> u32 {
119 u32::from_le_bytes(psf2_font[offset..(offset + 4)].try_into().unwrap())
120 };
121
122 if psf2_font.len() < 32 {
123 kernel_panic(
124 PanicCode::MalformedPsf2Font,
125 "PSF2 font is too short"
126 );
127 }
128
129 if read_u32(0) != Self::MAGIC_NUMBER {
130 kernel_panic(
131 PanicCode::MalformedPsf2Font,
132 "Invalid PSF2 Magic Number",
133 );
134 }
135
136 let header_size = read_u32(8);
137 let glyph_count = read_u32(16);
138 let bytes_per_glyph = read_u32(20);
139 let width = read_u32(28);
140 let height = read_u32(24);
141
142 let end_of_glyphs = (glyph_count as usize)
143 .checked_mul(bytes_per_glyph as usize)
144 .and_then(|glyph_bytes| glyph_bytes.checked_add(header_size as usize));
145
146 match end_of_glyphs {
147 Some(end) if end <= psf2_font.len() => {}
148 _ => {
149 kernel_panic(
150 PanicCode::MalformedPsf2Font,
151 "PSF2 header declares more glyph data than the font blob contains",
152 );
153 }
154 }
155
156 Self {
157 header_size,
158 glyph_count,
159 bytes_per_glyph,
160 width,
161 height
162 }
163 }
164}