Inital commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
25
Cargo.lock
generated
Normal file
25
Cargo.lock
generated
Normal 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
7
Cargo.toml
Normal 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
64
src/bit_reader.rs
Normal 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
257
src/main.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/u8g2_font_04b_03_tr.u8g2font
Normal file
BIN
src/u8g2_font_04b_03_tr.u8g2font
Normal file
Binary file not shown.
BIN
src/u8g2_font_8x13_tr.u8g2font
Normal file
BIN
src/u8g2_font_8x13_tr.u8g2font
Normal file
Binary file not shown.
BIN
src/u8g2_font_logisoso24_tr.u8g2font
Normal file
BIN
src/u8g2_font_logisoso24_tr.u8g2font
Normal file
Binary file not shown.
Reference in New Issue
Block a user