From f9b846d6744f4d1babf1f37d15c1f66df06bbe28 Mon Sep 17 00:00:00 2001 From: Fabian Ruhland Date: Tue, 4 Jun 2024 12:03:31 +0200 Subject: [PATCH] library/graphic: Implement scalable character drawing in LFB --- os/kernel/src/device/lfb_terminal.rs | 36 ++++++++++++++-------------- os/library/graphic/src/lfb.rs | 26 ++++++++++++++------ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/os/kernel/src/device/lfb_terminal.rs b/os/kernel/src/device/lfb_terminal.rs index 4e6e872..f3d095d 100644 --- a/os/kernel/src/device/lfb_terminal.rs +++ b/os/kernel/src/device/lfb_terminal.rs @@ -81,7 +81,7 @@ impl DisplayState { pub fn new(buffer: *mut u8, pitch: u32, width: u32, height: u32, bpp: u8) -> Self { let raw_lfb = LFB::new(buffer, pitch, width, height, bpp); let mut lfb = BufferedLFB::new(raw_lfb); - let size = ((width / lfb::CHAR_WIDTH) as u16, (height / lfb::CHAR_HEIGHT) as u16); + let size = ((width / lfb::DEFAULT_CHAR_WIDTH) as u16, (height / lfb::DEFAULT_CHAR_HEIGHT) as u16); let mut char_buffer = Vec::with_capacity(size.0 as usize * size.1 as usize * size_of::()); for _ in 0..char_buffer.capacity() { @@ -114,7 +114,7 @@ impl CursorThread { let cursor = self.terminal.cursor.lock(); let character = display.char_buffer[(cursor.pos.1 * display.size.0 + cursor.pos.0) as usize]; - display.lfb.direct_lfb().draw_char(cursor.pos.0 as u32 * lfb::CHAR_WIDTH, cursor.pos.1 as u32 * lfb::CHAR_HEIGHT, character.fg_color, character.bg_color, if self.visible { character.value } else { CURSOR }); + display.lfb.direct_lfb().draw_char(cursor.pos.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, cursor.pos.1 as u32 * lfb::DEFAULT_CHAR_HEIGHT, character.fg_color, character.bg_color, if self.visible { character.value } else { CURSOR }); self.visible = !self.visible; if sleep_counter >= 1000 { @@ -238,14 +238,14 @@ impl LFBTerminal { } fn print_char_at(display: &mut DisplayState, color: &mut ColorState, c: char, pos: (u16, u16)) -> bool { - display.lfb.lfb().draw_char(pos.0 as u32 * lfb::CHAR_WIDTH, pos.1 as u32 * lfb::CHAR_HEIGHT, color.fg_color, color.bg_color, c) - && display.lfb.direct_lfb().draw_char(pos.0 as u32 * lfb::CHAR_WIDTH, pos.1 as u32 * lfb::CHAR_HEIGHT, color.fg_color, color.bg_color, c) + display.lfb.lfb().draw_char(pos.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, pos.1 as u32 * lfb::DEFAULT_CHAR_HEIGHT, color.fg_color, color.bg_color, c) + && display.lfb.direct_lfb().draw_char(pos.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, pos.1 as u32 * lfb::DEFAULT_CHAR_HEIGHT, color.fg_color, color.bg_color, c) } fn draw_status_bar(display: &mut DisplayState) { // Draw background - for i in 0..display.size.0 as u32 * lfb::CHAR_WIDTH { - for j in 0..lfb::CHAR_HEIGHT { + for i in 0..display.size.0 as u32 * lfb::DEFAULT_CHAR_WIDTH { + for j in 0..lfb::DEFAULT_CHAR_HEIGHT { display.lfb.lfb().draw_pixel(i, j, color::HHU_GREEN); } } @@ -271,11 +271,11 @@ impl LFBTerminal { if let Ok(date) = runtime_services.get_time() { let date_str = format!("{}-{:0>2}-{:0>2} {:0>2}:{:0>2}:{:0>2}", date.year(), date.month(), date.day(), date.hour(), date.minute(), date.second()); - display.lfb.lfb().draw_string((display.size.0 as u32 - date_str.len() as u32) * lfb::CHAR_WIDTH, 0, color::HHU_BLUE, color::INVISIBLE, &date_str); + display.lfb.lfb().draw_string((display.size.0 as u32 - date_str.len() as u32) * lfb::DEFAULT_CHAR_WIDTH, 0, color::HHU_BLUE, color::INVISIBLE, &date_str); } } - display.lfb.flush_lines(0, lfb::CHAR_HEIGHT); + display.lfb.flush_lines(0, lfb::DEFAULT_CHAR_HEIGHT); } fn scroll_up(display: &mut DisplayState, color: &mut ColorState) { @@ -293,8 +293,8 @@ impl LFBTerminal { }); let size = display.size; - display.lfb.lfb().scroll_up(lfb::CHAR_HEIGHT); - display.lfb.lfb().fill_rect(0, (size.1 - 1) as u32 * lfb::CHAR_HEIGHT, size.0 as u32 * lfb::CHAR_WIDTH, lfb::CHAR_HEIGHT, color.bg_color); + display.lfb.lfb().scroll_up(lfb::DEFAULT_CHAR_HEIGHT); + display.lfb.lfb().fill_rect(0, (size.1 - 1) as u32 * lfb::DEFAULT_CHAR_HEIGHT, size.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, lfb::DEFAULT_CHAR_HEIGHT, color.bg_color); LFBTerminal::draw_status_bar(display); display.lfb.flush(); @@ -330,7 +330,7 @@ impl LFBTerminal { fn clear_screen(display: &mut DisplayState, color: &mut ColorState) { // Clear screen let size = display.size; - display.lfb.lfb().fill_rect(0, 0, size.0 as u32 * lfb::CHAR_WIDTH, size.1 as u32 * lfb::CHAR_HEIGHT, color.bg_color); + display.lfb.lfb().fill_rect(0, 0, size.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, size.1 as u32 * lfb::DEFAULT_CHAR_HEIGHT, color.bg_color); // Clear character buffer display.char_buffer.iter_mut().for_each(|item| { @@ -348,10 +348,10 @@ impl LFBTerminal { let size = display.size; // Clear from start of line to cursor - display.lfb.lfb().fill_rect(0, pos.1 as u32 * lfb::CHAR_HEIGHT, pos.0 as u32 * lfb::CHAR_WIDTH, lfb::CHAR_HEIGHT, color.bg_color); + display.lfb.lfb().fill_rect(0, pos.1 as u32 * lfb::DEFAULT_CHAR_HEIGHT, pos.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, lfb::DEFAULT_CHAR_HEIGHT, color.bg_color); // Clear from start of screen to line before cursor - display.lfb.lfb().fill_rect(0, 0, size.0 as u32 * lfb::CHAR_WIDTH, pos.1 as u32 * lfb::CHAR_HEIGHT, color.bg_color); + display.lfb.lfb().fill_rect(0, 0, size.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, pos.1 as u32 * lfb::DEFAULT_CHAR_HEIGHT, color.bg_color); // Clear character buffer from beginning of screen to cursor display.char_buffer.iter_mut().enumerate() @@ -371,10 +371,10 @@ impl LFBTerminal { let size = display.size; // Clear from cursor to end of line - display.lfb.lfb().fill_rect(pos.0 as u32 * lfb::CHAR_WIDTH, pos.1 as u32 * lfb::CHAR_HEIGHT, (size.0 - pos.0) as u32 * lfb::CHAR_WIDTH, lfb::CHAR_HEIGHT, color.bg_color); + display.lfb.lfb().fill_rect(pos.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, pos.1 as u32 * lfb::DEFAULT_CHAR_HEIGHT, (size.0 - pos.0) as u32 * lfb::DEFAULT_CHAR_WIDTH, lfb::DEFAULT_CHAR_HEIGHT, color.bg_color); // Clear from next line to end of screen - display.lfb.lfb().fill_rect(0, (pos.1 + 1) as u32 * lfb::CHAR_HEIGHT, size.0 as u32 * lfb::CHAR_WIDTH, (size.1 - pos.1 - 1) as u32 * lfb::CHAR_HEIGHT, color.bg_color); + display.lfb.lfb().fill_rect(0, (pos.1 + 1) as u32 * lfb::DEFAULT_CHAR_HEIGHT, size.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, (size.1 - pos.1 - 1) as u32 * lfb::DEFAULT_CHAR_HEIGHT, color.bg_color); // Clear character buffer from cursor to end of screen display.char_buffer.iter_mut().skip((pos.1 * size.0 + pos.0) as usize) @@ -393,7 +393,7 @@ impl LFBTerminal { let size = display.size; // Clear line in lfb - display.lfb.lfb().fill_rect(0, pos.1 as u32 * lfb::CHAR_HEIGHT, size.0 as u32 * lfb::CHAR_WIDTH, lfb::CHAR_HEIGHT, color.bg_color); + display.lfb.lfb().fill_rect(0, pos.1 as u32 * lfb::DEFAULT_CHAR_HEIGHT, size.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, lfb::DEFAULT_CHAR_HEIGHT, color.bg_color); // Clear line in character buffer display.char_buffer.iter_mut().skip((pos.1 * size.0) as usize).enumerate() .filter(|item| item.0 < size.0 as usize) @@ -414,7 +414,7 @@ impl LFBTerminal { let size = display.size; // Clear line in lfb - display.lfb.lfb().fill_rect(0, pos.1 as u32 * lfb::CHAR_HEIGHT, pos.0 as u32 * lfb::CHAR_WIDTH, lfb::CHAR_HEIGHT, color.bg_color); + display.lfb.lfb().fill_rect(0, pos.1 as u32 * lfb::DEFAULT_CHAR_HEIGHT, pos.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, lfb::DEFAULT_CHAR_HEIGHT, color.bg_color); // Clear line in character buffer display.char_buffer.iter_mut().skip((pos.1 * size.0) as usize).enumerate() @@ -436,7 +436,7 @@ impl LFBTerminal { let size = display.size; // Clear line in lfb - display.lfb.lfb().fill_rect(pos.0 as u32 * lfb::CHAR_WIDTH, pos.1 as u32 * lfb::CHAR_HEIGHT, (size.0 - pos.0) as u32 * lfb::CHAR_WIDTH, lfb::CHAR_HEIGHT, color.bg_color); + display.lfb.lfb().fill_rect(pos.0 as u32 * lfb::DEFAULT_CHAR_WIDTH, pos.1 as u32 * lfb::DEFAULT_CHAR_HEIGHT, (size.0 - pos.0) as u32 * lfb::DEFAULT_CHAR_WIDTH, lfb::DEFAULT_CHAR_HEIGHT, color.bg_color); // Clear line in character buffer display.char_buffer.iter_mut().skip((pos.1 * size.0 + pos.0) as usize).enumerate() diff --git a/os/library/graphic/src/lfb.rs b/os/library/graphic/src/lfb.rs index 5ded3e9..7056183 100644 --- a/os/library/graphic/src/lfb.rs +++ b/os/library/graphic/src/lfb.rs @@ -17,8 +17,8 @@ pub struct LFB { unsafe impl Send for LFB {} unsafe impl Sync for LFB {} -pub const CHAR_HEIGHT: u32 = 16; -pub const CHAR_WIDTH: u32 = 8; +pub const DEFAULT_CHAR_WIDTH: u32 = 8; +pub const DEFAULT_CHAR_HEIGHT: u32 = 16; impl LFB { pub const fn new(buffer: *mut u8, pitch: u32, width: u32, height: u32, bpp: u8) -> Self { @@ -97,6 +97,10 @@ impl LFB { } pub fn draw_char(&self, x: u32, y: u32, fg_color: Color, bg_color: Color, c: char) -> bool { + self.draw_char_scaled(x, y, 1, 2, fg_color, bg_color, c) + } + + pub fn draw_char_scaled(&self, x: u32, y: u32, x_scale: u32, y_scale: u32, fg_color: Color, bg_color: Color, c: char) -> bool { let mut glyph = BASIC_FONTS.get(c); if glyph.is_none() { glyph = LATIN_FONTS.get(c); @@ -131,13 +135,17 @@ impl LFB { _ => fg_color, }; - self.draw_pixel(x + x_offset, y + y_offset, color); - self.draw_pixel(x + x_offset, y + y_offset + 1, color); - x_offset += 1; + for i in 0..x_scale { + for j in 0..y_scale { + self.draw_pixel(x + x_offset + i, y + y_offset + j, color); + } + } + + x_offset += x_scale; } x_offset = 0; - y_offset += 2; + y_offset += y_scale; } return true; @@ -147,8 +155,12 @@ impl LFB { } pub fn draw_string(&self, x: u32, y: u32, fg_color: Color, bg_color: Color, string: &str) { + self.draw_string_scaled(x, y, 1, 2, fg_color, bg_color, string); + } + + pub fn draw_string_scaled(&self, x: u32, y: u32, x_scale: u32, y_scale: u32, fg_color: Color, bg_color: Color, string: &str) { for c in string.chars().enumerate() { - self.draw_char(x + (c.0 as u32 * CHAR_WIDTH), y, fg_color, bg_color, c.1); + self.draw_char_scaled(x + (c.0 as u32 * (8 * x_scale)), y, x_scale, y_scale, fg_color, bg_color, c.1); } }