commit df94c45f5160a6031d4874690b608029f5cd04ed Author: Jason Date: Thu Jan 22 14:28:32 2026 -0600 Inital commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..be1c5c7 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bitreader" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "886559b1e163d56c765bc3a985febb4eee8009f625244511d8ee3c432e08c066" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "u8g2-font-reader" +version = "0.1.0" +dependencies = [ + "bitreader", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a3c7a78 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "u8g2-font-reader" +version = "0.1.0" +edition = "2024" + +[dependencies] +bitreader = "0.3.11" diff --git a/src/bit_reader.rs b/src/bit_reader.rs new file mode 100644 index 0000000..bb48b83 --- /dev/null +++ b/src/bit_reader.rs @@ -0,0 +1,64 @@ + + +#[derive(Debug)] +pub struct ReverseBitVec<'a> { + data: &'a[u8], + bit_pointer: usize, +} + +impl<'a> ReverseBitVec<'a> { + pub const fn new(data: &'a[u8]) -> Self { + let bit_pointer = data.len() * 8; + ReverseBitVec { data, bit_pointer} + } + + pub fn read_u8(&mut self, bits: u8) -> Option { + let byte = (self.bit_pointer-1)/8; + let bit_in_byte = (8 - (self.bit_pointer % 8)) % 8; + let mask:u16 = ((1<> bit_in_byte; + + let out_u8 = out_u16.to_be_bytes()[1]; + + self.bit_pointer -= bits as usize; + + Some(out_u8) + } +} + +#[cfg(test)] +mod test { + use super::*; + + const DATA: [u8;3] = [0b0101_0101, 0b1100_1100, 0b0000_1111]; + + #[test] + fn full_aligned_byte() { + let mut info = ReverseBitVec::new(&DATA); + + let test = info.read_u8(8); + println!("{:08b}", test.unwrap()); + assert_eq!(Some(0b0000_1111), test); + } + + #[test] + fn partial_aligned_byte() { + let mut info = ReverseBitVec::new(&DATA); + let _ = info.read_u8(8); + let test = info.read_u8(4); + println!("{:08b}", test.unwrap()); + assert_eq!(Some(0b0000_1100), test); + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..4d4892c --- /dev/null +++ b/src/main.rs @@ -0,0 +1,257 @@ +use std::fmt::Display; + +mod bit_reader; + +fn main() { + let font_file = include_bytes!("u8g2_font_logisoso24_tr.u8g2font"); + + let header_bytes = &font_file[0..23]; + let mut data_bytes = &font_file[23..]; + + let header = FontHeader { + glyphs: header_bytes[0], + box_mode: header_bytes[1], + zero_bit_width: header_bytes[2], + one_bit_width: header_bytes[3], + bits_glyph_bitmap_width: header_bytes[4], + bits_glyph_bitmap_height: header_bytes[5], + bits_glyph_bitmap_x_offset: header_bytes[6], + bits_glyph_bitmap_y_offset: header_bytes[7], + bits_glyph_delta: header_bytes[8], + bound_box_width: header_bytes[9], + bound_box_height: header_bytes[10], + bound_box_x: header_bytes[11], + bound_box_y: header_bytes[12], + ascent_capital_a: header_bytes[13], + descent_lowercase_g: header_bytes[14], + paren_ascent: header_bytes[15], + paren_descent: header_bytes[16], + offset_of_capital_a: u16::from_be_bytes([header_bytes[17], header_bytes[18]]), + offset_of_lowercase_a: u16::from_be_bytes([header_bytes[19], header_bytes[20]]), + offset_of_0x0100: u16::from_be_bytes([header_bytes[21], header_bytes[22]]), + }; + + println!("{:?}", header); + + let mut bitvec: Vec = Vec::new(); + let mut glyphs: Vec = Vec::new(); + + for i in 0..header.glyphs { + let glyph = &data_bytes[0..2]; + + let unicode = glyph[0]; + let bytes = glyph[1]; + + let bitmap = &data_bytes[2..bytes as usize]; + for j in bitmap.iter().rev() { + bitvec.push(*j); + } + + /*print!("[ "); + for j in bitvec.iter() { + print!("{:08b} ", j) + } + println!("]");*/ + + let mut bitmap_bits = bit_reader::ReverseBitVec::new(&bitvec); + let glyph_width = bitmap_bits.read_u8(header.bits_glyph_bitmap_width).unwrap(); + let glyph_height = bitmap_bits.read_u8(header.bits_glyph_bitmap_height).unwrap(); + let glyph_x = bitmap_bits.read_u8(header.bits_glyph_bitmap_x_offset).unwrap(); + let glyph_y = bitmap_bits.read_u8(header.bits_glyph_bitmap_y_offset).unwrap(); + let glyph_d = bitmap_bits.read_u8(header.bits_glyph_delta).unwrap(); + + //println!("w: {:08b}, h: {:08b}, x: {:08b}, y: {:08b}, d: {:08b}", glyph_width, glyph_height, glyph_x, glyph_y, glyph_d); + + let glyph_x = glyph_x as i8 - (1<<(header.bits_glyph_bitmap_x_offset-1)); + let glyph_y = glyph_y as i8 - (1<<(header.bits_glyph_bitmap_y_offset-1)); + let glyph_d = glyph_d as i8 - (1<<(header.bits_glyph_delta-1)); + + let target_bitmap_size = glyph_width as u16 * glyph_height as u16; + let mut current_bitmap_size = 0_u16; + + let mut bitmap_entries = Vec::new(); + + loop { + //println!("Bitmap current size: {} target: {}", current_bitmap_size, target_bitmap_size); + if current_bitmap_size >= target_bitmap_size {break;} + let zeros = bitmap_bits.read_u8(header.zero_bit_width).unwrap(); + let ones = bitmap_bits.read_u8(header.one_bit_width).unwrap(); + let mut repeat = 0_u8; + + while bitmap_bits.read_u8(1).unwrap() != 0 { + repeat += 1; + } + let out_bitmap = BitmapEntry { + zeros, + ones, + repeat, + }; + + //println!("{:?}", out_bitmap); + current_bitmap_size += out_bitmap.length(); + bitmap_entries.push(out_bitmap); + } + + let finished_glyph = Glyph { + unicode, + delta: bytes, + glyph_width, + glyph_height, + glyph_x, + glyph_y, + glyph_d, + glyph_data: bitmap_entries, + }; + + //println!("{:?}", finished_glyph); + glyphs.push(finished_glyph); + + bitvec.clear(); + data_bytes = &data_bytes[bytes as usize..]; + } + + let mut bdf_file = String::new(); + + bdf_file.push_str("STARTFONT 2.1\n"); + bdf_file.push_str("u8g2_font_converted\n"); + bdf_file.push_str("SIZE 24 72 72\n"); + bdf_file.push_str(&format!("CHARS {}\n", header.glyphs)); + + for i in glyphs.iter() { + bdf_file.push_str(&format!("STARTCHAR {}\n", i.unicode as char)); + bdf_file.push_str(&format!("ENCODING {}\n", i.unicode)); + + let mut decoded_bits = Vec::new(); + + for j in i.glyph_data.iter() { + let mut tempvec = Vec::new(); + let mut count = j.zeros; + + while count > 0 { + tempvec.push(false); + count -= 1; + } + count = j.ones; + while count > 0 { + tempvec.push(true); + count -= 1; + } + count = j.repeat + 1; + while count > 0 { + decoded_bits.append(&mut tempvec.clone()); + count -= 1; + } + } + + let mut bdf_bitmap: Vec> = Vec::new(); + + while !decoded_bits.is_empty() { + for j in decoded_bits.iter().by_ref().take(i.glyph_width as usize) { + + } + } + } + + bdf_file.push_str("ENDFONT"); + +} + +#[derive(Debug)] +struct FontHeader { + glyphs: u8, + box_mode: u8, + zero_bit_width: u8, + one_bit_width: u8, + bits_glyph_bitmap_width: u8, + bits_glyph_bitmap_height: u8, + bits_glyph_bitmap_x_offset: u8, + bits_glyph_bitmap_y_offset: u8, + bits_glyph_delta: u8, + bound_box_width: u8, + bound_box_height: u8, + bound_box_x: u8, + bound_box_y: u8, + ascent_capital_a: u8, + descent_lowercase_g: u8, + paren_ascent: u8, + paren_descent: u8, + offset_of_capital_a: u16, + offset_of_lowercase_a: u16, + offset_of_0x0100: u16, +} + +#[derive(Debug)] +struct Glyph { + unicode: u8, + delta: u8, + glyph_width: u8, + glyph_height: u8, + glyph_x: i8, + glyph_y: i8, + glyph_d: i8, + glyph_data: Vec, +} + +impl Display for Glyph { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let c = self.unicode as char; + let bytes = self.delta; + let w = self.glyph_width; + let h = self.glyph_height; + let x = self.glyph_x; + let y = self.glyph_y; + let d = self.glyph_d; + + let mut glyph_bits: Vec = Vec::new(); + + let bitmap = for i in self.glyph_data.iter() { + let mut tempvec = Vec::new(); + let mut count = i.zeros; + + while count > 0 { + tempvec.push(false); + count -= 1; + } + count = i.ones; + while count > 0 { + tempvec.push(true); + count -= 1; + } + count = i.repeat + 1; + while count > 0 { + glyph_bits.append(&mut tempvec.clone()); + count -= 1; + } + }; + + let mut out = String::new(); + + for (pos, i) in glyph_bits.iter().enumerate() { + if *i { + out.push('I'); + } else { + out.push('.'); + } + + if (pos+1) % w as usize == 0 { + out.push('\n'); + } + } + + write!(f, "Character: {c}, Data size: {bytes}, size: {w}x{h} offsets X:{x}, Y:{y}, D: {d}\n{out}") + } +} + +#[derive(Debug)] +struct BitmapEntry { + zeros: u8, + ones: u8, + repeat: u8, +} + +impl BitmapEntry { + fn length(&self) -> u16 { + let base = self.zeros + self.ones; + base as u16 * (self.repeat as u16 + 1) + } +} \ No newline at end of file diff --git a/src/u8g2_font_04b_03_tr.u8g2font b/src/u8g2_font_04b_03_tr.u8g2font new file mode 100644 index 0000000..0862590 Binary files /dev/null and b/src/u8g2_font_04b_03_tr.u8g2font differ diff --git a/src/u8g2_font_8x13_tr.u8g2font b/src/u8g2_font_8x13_tr.u8g2font new file mode 100644 index 0000000..a42a481 Binary files /dev/null and b/src/u8g2_font_8x13_tr.u8g2font differ diff --git a/src/u8g2_font_logisoso24_tr.u8g2font b/src/u8g2_font_logisoso24_tr.u8g2font new file mode 100644 index 0000000..eef2e27 Binary files /dev/null and b/src/u8g2_font_logisoso24_tr.u8g2font differ