diff options
feat: code generation :3
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | Cargo.lock | 269 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | build.rs | 213 | ||||
| -rw-r--r-- | src/font.rs | 3 | ||||
| -rw-r--r-- | src/generated/mod.rs | 1 | ||||
| -rw-r--r-- | src/main.rs | 1 | 
7 files changed, 134 insertions, 356 deletions
| @@ -1,2 +1,4 @@  /target  /assets/computed-fonts +/src/generated/* +!/src/generated/mod.rs @@ -9,227 +9,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"  [[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "bit_field" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" - -[[package]]  name = "bitflags"  version = "1.3.2"  source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"  [[package]] -name = "bytemuck" -version = "1.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]]  name = "cfg-if"  version = "1.0.0"  source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"  [[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]]  name = "cosin-2025-invite-deck"  version = "0.1.0"  dependencies = [ - "image",   "rusttype",   "sdl2",  ]  [[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "exr" -version = "1.73.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" -dependencies = [ - "bit_field", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "flate2" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "gif" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - -[[package]] -name = "image" -version = "0.24.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "exr", - "gif", - "jpeg-decoder", - "num-traits", - "png", - "qoi", - "tiff", -] - -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" -dependencies = [ - "rayon", -] - -[[package]]  name = "lazy_static"  version = "1.5.0"  source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"  [[package]] -name = "lebe" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" - -[[package]]  name = "libc"  version = "0.2.169"  source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"  [[package]] -name = "miniz_oxide" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]]  name = "owned_ttf_parser"  version = "0.15.2"  source = "registry+https://github.com/rust-lang/crates.io-index" @@ -239,48 +50,6 @@ dependencies = [  ]  [[package]] -name = "png" -version = "0.17.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" -dependencies = [ - "bitflags", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]]  name = "rusttype"  version = "0.9.3"  source = "registry+https://github.com/rust-lang/crates.io-index" @@ -314,29 +83,6 @@ dependencies = [  ]  [[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - -[[package]]  name = "ttf-parser"  version = "0.15.2"  source = "registry+https://github.com/rust-lang/crates.io-index" @@ -347,18 +93,3 @@ name = "version-compare"  version = "0.1.1"  source = "registry+https://github.com/rust-lang/crates.io-index"  checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" - -[[package]] -name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - -[[package]] -name = "zune-inflate" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" -dependencies = [ - "simd-adler32", -] @@ -14,5 +14,4 @@ codegen-units = 1  panic = "abort"  [build-dependencies] -image = "0.24.9"  rusttype = "0.9.3" @@ -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(())  } diff --git a/src/font.rs b/src/font.rs index 738ae30..546fabe 100644 --- a/src/font.rs +++ b/src/font.rs @@ -15,6 +15,9 @@ fn insert_value(arr: &mut Vec<*const Glyph>, idx: usize, glyph: *const Glyph) {    arr[idx] = glyph;  } +pub trait BakedFont { +  fn get_char(character: char) -> &'static [u8]; +}  pub struct Font<'a> {    pub texture: &'a [u8],    pub glyphs: Vec<*const Glyph>, diff --git a/src/generated/mod.rs b/src/generated/mod.rs new file mode 100644 index 0000000..bfbdc1d --- /dev/null +++ b/src/generated/mod.rs @@ -0,0 +1 @@ +pub mod fonts; diff --git a/src/main.rs b/src/main.rs index bfcc5f6..39f39d2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@  extern crate sdl2;  mod font; +pub mod generated;  use font::{UwUFont, UWU_WIDTH};  use sdl2::event::Event; |