diff options
Diffstat (limited to 'build.rs')
-rw-r--r-- | build.rs | 213 |
1 files changed, 127 insertions, 86 deletions
@@ -1,112 +1,153 @@ -use image::{GrayImage, Luma}; -use rusttype::{point, Font, Point, Scale}; -use std::env; +use rusttype::{Font, Point, Scale}; use std::fs::{self, File}; use std::io::{self, Write}; -use std::path::Path; -fn exec(font_path: &str, characters: Vec<char>, font_name: &str) -> io::Result<()> { - let font_data = fs::read(font_path)?; - let font = Font::try_from_vec(font_data).expect("Failed to load font"); - - let scale = Scale::uniform(32.0); // Set the font size - - for &c in &characters { - let image = render_character(&font, scale, c); - save_bits_to_file(font_name, c, &image)?; - } - - Ok(()) +#[derive(Clone)] +struct FontMetadata { + pub charset: &'static str, + pub name: &'static str, + pub font: Font<'static>, } +impl FontMetadata { + pub fn render_character(&self, scale: Scale, character: char) -> Vec<u8> { + let glyph = self.font.glyph(character).scaled(scale); + let bounding_box = glyph.exact_bounding_box().unwrap(); + let width = bounding_box.width() as u32; + let height = bounding_box.height() as u32; -fn render_character(font: &Font, scale: Scale, character: char) -> Vec<u8> { - let glyph = font.glyph(character).scaled(scale); - let bounding_box = glyph.exact_bounding_box().unwrap(); - let width = bounding_box.width() as u32; - let height = bounding_box.height() as u32; + let mut image: Vec<u8> = Vec::new(); - let mut image: Vec<u8> = Vec::new(); - - fn define_item(a: &mut Vec<u8>, i: usize, v: u8) { - if a.len() <= i { - while a.len() < i { - a.push(0x00); + fn define_item(a: &mut Vec<u8>, i: usize, v: u8) { + if a.len() <= i { + while a.len() < i { + a.push(0x00); + } + a.push(v) + } else { + a[i] = v; } - a.push(v) - } else { - a[i] = v; } - } - define_item(&mut image, 2 + ((width as usize) * (height as usize)), 0x00); + define_item(&mut image, 2 + ((width as usize) * (height as usize)), 0x00); - image[0] = (width & 0b0000_0000_1111_1111) as u8; - image[1] = (width & 0b1111_1111_0000_0000 << 8) as u8; - if (image[0] as u16) | (image[1] as u16 >> 8) != width as u16 { - panic!("Width missmatch!"); - } + image[0] = (width & 0b0000_0000_1111_1111) as u8; + image[1] = (width & 0b1111_1111_0000_0000 << 8) as u8; + if (image[0] as u16) | (image[1] as u16 >> 8) != width as u16 { + panic!("Width missmatch!"); + } - glyph - .positioned(Point { x: 0.0, y: 0.0 }) - .draw(|gx: u32, gy: u32, v| { - let bit = (v * 255.0) as u8; - if gx < width { - define_item(&mut image, (2 + (gy * width) + gx) as usize, bit); - } - }); - image -} -fn img_to_hex(image: Vec<u8>) -> Vec<u8> { - let mut image2: Vec<u8> = Vec::new(); - let width = (image[0] as u16) | (image[1] as u16 >> 8); + glyph + .positioned(Point { x: 0.0, y: 0.0 }) + .draw(|gx: u32, gy: u32, v| { + let bit = (v * 255.0) as u8; + if gx < width { + define_item(&mut image, (2 + (gy * width) + gx) as usize, bit); + } + }); + image + } + pub fn img_to_hex(image: Vec<u8>) -> Vec<u8> { + let mut image2: Vec<u8> = Vec::new(); + let width = (image[0] as u16) | (image[1] as u16 >> 8); - let mut i: i32 = -3; - for bit in image { - i += 1; - if i >= 0 { - if i as u16 == width { - i = 0; - image2.push('\n' as u8); + let mut i: i32 = -3; + for bit in image { + i += 1; + if i >= 0 { + if i as u16 == width { + i = 0; + image2.push('\n' as u8); + } + let v = format!("{:x?}", bit); + let v = if v.len() == 1 { format!("0{}", v) } else { v }; + for char in v.chars() { + image2.push(char as u8); + } + // image2.push(if bit < 80 {' ' as u8} else if bit < 150 {'-' as u8} else {'#' as u8}) } - let v = format!("{:x?}", bit); - let v = if v.len() == 1 { format!("0{}", v) } else { v }; - for char in v.chars() { - image2.push(char as u8); + } + image2 + } + fn unique_chars(&self) -> Vec<char> { + let mut v: Vec<char> = Vec::new(); + for char in self.charset.chars() { + if !v.contains(&char) { + v.push(char); } - // image2.push(if bit < 80 {' ' as u8} else if bit < 150 {'-' as u8} else {'#' as u8}) } + v } - image2 } -fn save_bits_to_file(font_name: &str, character: char, bits: &[u8]) -> io::Result<()> { - fs::create_dir_all(format!("assets/computed-fonts/{}/", font_name))?; - let filename = format!( - "assets/computed-fonts/{}/{}.bin", - font_name, character as u8 - ); +fn exec(font: FontMetadata) -> io::Result<()> { + let scale = Scale::uniform(32.0); // Set the font size + + for c in font.unique_chars() { + let image = font.render_character(scale, c); + save_bits_to_file(&font, c as u8, &image)?; + } + + Ok(()) +} + +fn save_bits_to_file(font: &FontMetadata, char: u8, bits: &[u8]) -> io::Result<()> { + fs::create_dir_all(format!("assets/computed-fonts/{}/", font.name))?; + let filename = format!("assets/computed-fonts/{}/{}.bin", font.name, char); let mut file = File::create(&filename)?; file.write_all(bits)?; - let filename = format!( - "assets/computed-fonts/{}/{}.txt", - font_name, character as u8 - ); + let filename = format!("assets/computed-fonts/{}/{}.txt", font.name, char); let mut file = File::create(&filename)?; - file.write_all(&img_to_hex(bits.to_vec()))?; + file.write_all(&FontMetadata::img_to_hex(bits.to_vec()))?; Ok(()) } +fn generate_struct(font: &FontMetadata) -> io::Result<String> { + let name = font.name; + let mut contents = format!( + "pub struct {name} {{}} +impl {name} {{}} +impl BakedFont for {name} {{ + fn get_char(c: char) -> &'static [u8] {{ + match c as u8 {{ +" + ); + for char in font.unique_chars() { + contents = format!( + "{contents} {} => include_bytes!(\"../../assets/computed-fonts/{}/{}.bin\"), +", + char as u8, font.name, char as u8 + ); + } + contents = format!( + "{contents} _ => panic!(\"Glyph {{}} not included in precomputed fonts\", c) + }} + }} +}} +" + ); + Ok(contents) +} fn main() -> Result<(), Box<dyn std::error::Error>> { - exec( - "assets/fonts/Galmuri11.ttf", - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz2053:" - .chars() - .collect(), - "Galmuri", - )?; - exec( - "assets/fonts/CherryBombOne.ttf", - "UwUSpace".chars().collect(), - "CherryBombOne", - )?; + fs::create_dir_all("src/generated")?; + let mut modrs = format!("// Copyright is a sham this is a @generated file. +use crate::font::BakedFont; +"); + let fonts = [ + FontMetadata { + name: "Galmuri", + font: { Font::try_from_vec(fs::read("assets/fonts/Galmuri11.ttf")?).unwrap() }, + charset: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz2053:", + }, + FontMetadata { + name: "CherryBombOne", + font: { Font::try_from_vec(fs::read("assets/fonts/CherryBombOne.ttf")?).unwrap() }, + charset: "UwUSpace", + }, + ]; + for font in fonts { + modrs=format!("{modrs}{} +",generate_struct(&font)?); + exec(font)?; + } + File::create(&"src/generated/fonts.rs")?.write_all(modrs.as_bytes())?; Ok(()) } |