diff --git a/Cargo.lock b/Cargo.lock index 171599d..5b91459 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,6 +31,7 @@ dependencies = [ "compiler_builtins", "log", "num-integer", + "pc-screen-font", "uefi", "x86_64", ] @@ -44,7 +45,7 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "compiler_builtins" version = "0.1.36" -source = "git+https://github.com/rust-lang/compiler-builtins#33ad3669db0ac78a917aee787304d1391b6dc676" +source = "git+https://github.com/rust-lang/compiler-builtins#0f2271e566f78dbe7aa3441c9e497c655592acef" [[package]] name = "log" @@ -74,6 +75,14 @@ dependencies = [ "autocfg", ] +[[package]] +name = "pc-screen-font" +version = "0.1.0" +source = "git+https://github.com/jamestmartin/pc-screen-font?rev=aa3d7a09ee5d0ee632676fbbabea8fcaf570b83d#aa3d7a09ee5d0ee632676fbbabea8fcaf570b83d" +dependencies = [ + "num-integer", +] + [[package]] name = "proc-macro2" version = "1.0.24" diff --git a/Cargo.toml b/Cargo.toml index 0a77b8b..311414a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,10 @@ compiler_builtins = { git = "https://github.com/rust-lang/compiler-builtins" } version = "0.4.11" default-features = false +[dependencies.pc-screen-font] +git = "https://github.com/jamestmartin/pc-screen-font" +rev = "aa3d7a09ee5d0ee632676fbbabea8fcaf570b83d" + [dependencies.num-integer] version = "0.1.43" default-features = false diff --git a/src/graphics/font.rs b/src/graphics/font.rs index 577039d..8253e8f 100644 --- a/src/graphics/font.rs +++ b/src/graphics/font.rs @@ -1,4 +1,4 @@ -pub mod psf; +use pc_screen_font; // Note that currently the Font and Glyph traits are fairly specialized to PSF. // They will certainly have to be modified to support other types of fonts, @@ -29,3 +29,15 @@ pub trait Glyph { /// This function will panic if `x` and `y` are outside the width and height of this glyph. fn get(&self, x: usize, y: usize) -> bool; } + +impl Font for pc_screen_font::Font { + type Glyph = pc_screen_font::Glyph; + fn bounding_box(&self) -> (usize, usize) { self.bounding_box() } + fn lookup<'a>(&'a self, ch: char) -> Option<&'a Self::Glyph> { self.lookup(ch) } +} + +impl Glyph for pc_screen_font::Glyph { + fn width(&self) -> usize { self.width() } + fn height(&self) -> usize { self.height() } + fn get(&self, x: usize, y: usize) -> bool { self.get(x, y).unwrap() } +} diff --git a/src/graphics/font/psf.rs b/src/graphics/font/psf.rs deleted file mode 100644 index 1700e3b..0000000 --- a/src/graphics/font/psf.rs +++ /dev/null @@ -1,136 +0,0 @@ -use alloc::vec::Vec; -use crate::graphics::font::{Font, Glyph}; - -pub struct PSF { - width: usize, - height: usize, - glyphs: Vec, - // TODO: Replace this with a proper associative structure. - unicode: Vec, -} - -/// Associates a unicode character and a glyph. -struct UnicodeMap { - c: char, - // The index of the glyph. - i: usize, -} - -pub struct PSFGlyph { - bitmap: Vec, - line_size: usize, - width: usize, - height: usize, -} - -impl PSF { - pub fn parse(font: &[u8]) -> PSF { - use core::convert::TryInto; - - // The number of glyphs in this font. - let length = u32::from_le_bytes(font[16..20].try_into().unwrap()) as usize; - // The size in bytes of a single glyph. - let charsize = u32::from_le_bytes(font[20..24].try_into().unwrap()) as usize; - // The height in pixels of this font's bounding box. - let height = u32::from_le_bytes(font[24..28].try_into().unwrap()) as usize; - // The width in pixels of this font's bounding box. - let width = u32::from_le_bytes(font[28..32].try_into().unwrap()) as usize; - // The size in bytes of a single row of pixels in a glyph. - let line_size = num_integer::div_ceil(width, 8); - - let glyphs_offset = 32; // the size of the header - let glyphs_size = length * charsize; - let unicode_offset = glyphs_offset + glyphs_size; - - let mut glyphs = Vec::with_capacity(length); - - for i in 0..length { - let mut bitmap = Vec::with_capacity(charsize); - let bitmap_begin = glyphs_offset + charsize * i; - let bitmap_end = bitmap_begin + charsize; - bitmap.extend_from_slice(&font[bitmap_begin..bitmap_end]); - - glyphs.push(PSFGlyph { - bitmap: bitmap, - line_size: line_size, - // Glyphs may overflow the font's nominal resolution in the padding bytes of the line! - // This trick only works for the width because there is no vertical padding. - // TODO: Pre-compute widths and bounding box offsets of individual glyphs. - width: line_size * 8, - height: height, - }); - } - - // HACK: This unicode map parser is still a mess. - let mut unicode_map = Vec::new(); - let unicode_info = &font[unicode_offset..]; - let mut glyph = 0; - let mut i = 0; - while i < unicode_info.len() { - let mut nc = unicode_info[i]; - - while nc != 0xFE && nc != 0xFF { - let ch_bytes = nc.leading_ones().max(1) as usize; - let st = core::str::from_utf8(&unicode_info[i..i + ch_bytes]).expect("Invalid character"); - let ch = st.chars().next().unwrap(); - unicode_map.push(UnicodeMap { c: ch, i: glyph }); - i += ch_bytes; - nc = unicode_info[i]; - } - - // TODO: Support multi-codepoint spellings of characters. - while nc != 0xFF { - i += 1; - nc = unicode_info[i]; - } - - i += 1; - glyph += 1; - } - - PSF { - width: width, - height: height, - glyphs: glyphs, - unicode: unicode_map, - } - } - - /// The index of the glyph associated with a particular unicde character. - fn index_of(&self, c: char) -> Option { - for entry in &self.unicode { - if entry.c == c { - return Some(entry.i); - } - } - None - } -} - -impl Font for PSF { - type Glyph = PSFGlyph; - - fn bounding_box(&self) -> (usize, usize) { - (self.width, self.height) - } - - fn lookup<'a>(&'a self, c: char) -> Option<&'a PSFGlyph> { - self.index_of(c).map(|i| &self.glyphs[i]) - } -} - -impl Glyph for PSFGlyph { - fn width(&self) -> usize { self.width } - fn height(&self) -> usize { self.height } - - fn get(&self, x: usize, y: usize) -> bool { - if x > self.width || y > self.height { - crate::panic!("Glyph pixel index out of bounds."); - } - - let (line_byte_index, bit_index) = num_integer::div_rem(x, 8); - let mask = 0b10000000 >> bit_index; - let byte = self.bitmap[(y * self.line_size + line_byte_index) as usize]; - byte & mask > 0 - } -}