Inital commit

This commit is contained in:
2026-01-22 14:28:32 -06:00
commit df94c45f51
8 changed files with 354 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

25
Cargo.lock generated Normal file
View File

@@ -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",
]

7
Cargo.toml Normal file
View File

@@ -0,0 +1,7 @@
[package]
name = "u8g2-font-reader"
version = "0.1.0"
edition = "2024"
[dependencies]
bitreader = "0.3.11"

64
src/bit_reader.rs Normal file
View File

@@ -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<u8> {
let byte = (self.bit_pointer-1)/8;
let bit_in_byte = (8 - (self.bit_pointer % 8)) % 8;
let mask:u16 = ((1<<bits)-1)<<bit_in_byte;
//println!("Bit ponter: {}, Byte: {}, Bit in byte: {}, mask: {:016b}", self.bit_pointer, byte, bit_in_byte, mask);
let first_byte = self.data[byte];
let second_byte = if byte == 0 {
0
} else {
self.data[byte-1]
};
let combined = u16::from_le_bytes([first_byte, second_byte]);
let out_u16 = mask & combined;
let out_u16 = out_u16 >> 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);
}
}

257
src/main.rs Normal file
View File

@@ -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<u8> = Vec::new();
let mut glyphs: Vec<Glyph> = 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<u8>> = 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<BitmapEntry>,
}
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<bool> = 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)
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.