diff --git a/l0dable/build.rs b/l0dable/build.rs index cd855226c38a6d6bc88904842ca82542d0370619..e1c320d6da3d0091fff77c8ca756a9facc245fa3 100644 --- a/l0dable/build.rs +++ b/l0dable/build.rs @@ -36,6 +36,11 @@ fn main() { .file("../c/l0dables/lib/hardware.c") .file("../c/epicardium/api/caller.c") .file("src/client.c") + .file("../c/lib/gfx/Fonts/font12.c") + .file("../c/lib/gfx/Fonts/font16.c") + .file("../c/lib/gfx/Fonts/font20.c") + .file("../c/lib/gfx/Fonts/font24.c") + .file("../c/lib/gfx/Fonts/font8.c") .compile("card10"); println!("cargo:rerun-if-changed=src/client.rs"); diff --git a/l0dable/src/framebuffer/font.rs b/l0dable/src/framebuffer/font.rs new file mode 100644 index 0000000000000000000000000000000000000000..6875046f4bc62ce7dc6851a04470fb83b7e3afbf --- /dev/null +++ b/l0dable/src/framebuffer/font.rs @@ -0,0 +1,68 @@ +use core::slice::from_raw_parts; + +extern "C" { + static Font8: Font; + static Font12: Font; + static Font16: Font; + static Font20: Font; + static Font24: Font; +} + +#[repr(C)] +pub struct Font { + table: *const u8, + pub w: u16, + pub h: u16, +} + +impl Font { + pub fn font8() -> &'static Self { + unsafe { &Font8 } + } + pub fn font12() -> &'static Self { + unsafe { &Font12 } + } + pub fn font16() -> &'static Self { + unsafe { &Font16 } + } + pub fn font20() -> &'static Self { + unsafe { &Font20 } + } + pub fn font24() -> &'static Self { + unsafe { &Font24 } + } + + fn bytes_per_row(&self) -> usize { + self.w as usize / 8 + 1 + } + + pub fn get_glyph(&self, c: char) -> Option<Glyph> { + let h = self.h as usize; + let bytes_per_row = self.bytes_per_row(); + let table = unsafe { + from_raw_parts(self.table, ('~' as usize - (' ' as usize) - 1) * bytes_per_row * h) + }; + let offset = (c as usize - (' ' as usize)) * bytes_per_row * h; + if offset < table.len() { + let table = &table[offset..(offset + bytes_per_row * h)]; + Some(Glyph { + table, + bytes_per_row, + }) + } else { + None + } + } +} + +pub struct Glyph<'a> { + table: &'a [u8], + bytes_per_row: usize, +} + +impl<'a> Glyph<'a> { + pub fn get_pixel(&self, x: usize, y: usize) -> bool { + let offset = x / 8 + y * self.bytes_per_row; + self.table[offset] & (1 << (7 - (x & 7))) != 0 + } +} diff --git a/l0dable/src/framebuffer/mod.rs b/l0dable/src/framebuffer/mod.rs index d57d0f6dd7717f16aefabe5270bfc9606fa828d2..0f8bb9159e7b02e56f2e86c23baeb4d8f87cf7d0 100644 --- a/l0dable/src/framebuffer/mod.rs +++ b/l0dable/src/framebuffer/mod.rs @@ -3,6 +3,11 @@ use core::ops::{Deref, DerefMut}; use crate::bindings::*; use crate::{Color, Display}; +mod font; +pub use font::*; +mod text; +pub use text::TextRenderer; + pub struct FrameBuffer<'d> { _display: &'d Display, buffer: disp_framebuffer, @@ -24,6 +29,13 @@ impl<'d> FrameBuffer<'d> { epic_disp_framebuffer(&mut self.buffer); } } + + pub fn text<'a, 'f>(&'a mut self, x: isize, y: isize, font: &'f Font, color: Color) -> TextRenderer<'a, 'd, 'f> { + TextRenderer { + framebuffer: self, + x, y, font, color, + } + } } impl<'d> Deref for FrameBuffer<'d> { diff --git a/l0dable/src/framebuffer/text.rs b/l0dable/src/framebuffer/text.rs new file mode 100644 index 0000000000000000000000000000000000000000..3814c8d6269474978a3634924e050a8bb8858cab --- /dev/null +++ b/l0dable/src/framebuffer/text.rs @@ -0,0 +1,43 @@ +use core::fmt::Write; +use super::{FrameBuffer, Font}; +use crate::{Color, Display}; + +pub struct TextRenderer<'a, 'd, 'f> { + pub framebuffer: &'a mut FrameBuffer<'d>, + pub x: isize, + pub y: isize, + pub font: &'f Font, + pub color: Color, +} + +impl<'a, 'd, 'f> Write for TextRenderer<'a, 'd, 'f> { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + for c in s.chars() { + self.write_char(c)?; + } + Ok(()) + } + + fn write_char(&mut self, c: char) -> core::fmt::Result { + match self.font.get_glyph(c) { + None => Ok(()), + Some(glyph) => { + for y in 0..self.font.h { + let y1 = self.y + y as isize; + if y1 >= 0 && y1 < Display::H as isize { + for x in 0..self.font.w { + let x1 = self.x + x as isize; + if x1 >= 0 && x1 < Display::W as isize { + if glyph.get_pixel(x as usize, y as usize) { + self.framebuffer[y1 as usize][x1 as usize] = self.color; + } + } + } + } + } + self.x += self.font.w as isize; + Ok(()) + } + } + } +}