diff --git a/font8x8_basic.bin b/font8x8_basic.bin deleted file mode 100644 index 2116412..0000000 --- a/font8x8_basic.bin +++ /dev/null @@ -1,16 +0,0 @@ -00000000 00 00 00 00 00 00 00 00 18 18 18 18 18 00 18 00 -00000010 6c 6c 6c 00 00 00 00 00 6c 6c fe 6c fe 6c 6c 00 -00000020 18 3e 60 3c 06 7c 18 00 00 c6 cc 18 30 66 c6 00 -00000030 38 6c 38 76 dc cc 76 00 18 18 30 00 00 00 00 00 -00000040 0c 18 30 30 30 18 0c 00 30 18 0c 0c 0c 18 30 00 -00000050 00 66 3c ff 3c 66 00 00 00 18 18 7e 18 18 00 00 -00000060 00 00 00 00 18 18 30 00 00 00 00 7e 00 00 00 00 -00000070 00 00 00 00 00 18 18 00 06 0c 18 30 60 c0 80 00 -00000080 38 6c c6 c6 c6 6c 38 00 18 38 18 18 18 18 7e 00 -00000090 7c c6 06 1c 30 66 fe 00 7c c6 06 3c 06 c6 7c 00 -000000a0 1c 3c 6c cc fe 0c 1e 00 fe c0 fc 06 06 c6 7c 00 -000000b0 38 60 c0 fc c6 c6 7c 00 fe c6 0c 18 30 30 30 00 -000000c0 7c c6 c6 7c c6 c6 7c 00 7c c6 c6 7e 06 0c 78 00 -000000d0 00 18 18 00 00 18 18 00 00 18 18 00 00 18 18 30 -000000e0 0c 18 30 60 30 18 0c 00 00 00 7e 00 7e 00 00 00 -000000f0 30 18 0c 06 0c 18 30 00 7c c6 0c 18 18 00 18 00 diff --git a/src/main.rs b/src/main.rs index bab23b3..e68450d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,9 +6,11 @@ use std::thread; use std::sync::mpsc::{self, Receiver, Sender}; use hound::{WavSpec, WavWriter, SampleFormat}; use image::{Rgba, RgbaImage}; +use rusttype::{Font, Scale, point}; // Simple 8x8 bitmap font implementation mod builtin_font { + use image::{Rgba, RgbaImage}; // Each character is 8 bytes (8x8 pixels) const FONT_DATA: &[u8] = include_bytes!("../font8x8_basic.bin"); @@ -18,9 +20,10 @@ mod builtin_font { y: u32, text: &str, color: Rgba, + scale: u32, // scale factor for font size ) { - let char_width = 8; - let char_height = 8; + let char_width = 8u32; + let char_height = 8u32; for (i, c) in text.chars().enumerate() { let char_index = c as usize; @@ -28,15 +31,21 @@ mod builtin_font { continue; } - let font_data = &FONT_DATA[char_index * char_width..(char_index + 1) * char_width]; + let font_data = &FONT_DATA[char_index * char_width as usize..(char_index + 1) * char_width as usize]; for row in 0..char_height { for col in 0..char_width { if font_data[row as usize] & (1 << (7 - col)) != 0 { - let px = x + (i as u32 * char_width) + col; - let py = y + row; - if px < image.width() && py < image.height() { - image.put_pixel(px, py, color); + let px = x + (i as u32 * char_width * scale) + col * scale; + let py = y + row * scale; + for dx in 0..scale { + for dy in 0..scale { + let fx = px + dx; + let fy = py + dy; + if fx < image.width() && fy < image.height() { + image.put_pixel(fx, fy, color); + } + } } } } @@ -169,6 +178,38 @@ impl Robot36EncoderApp { } } + fn draw_callsign_with_rusttype(image: &mut RgbaImage, text: &str) { + // Path to a common system font found on this system + let font_data = std::fs::read("/usr/share/fonts/TTF/VictorMonoNerdFont-Thin.ttf") + .expect("Failed to load system font"); + let font = Font::try_from_vec(font_data).expect("Error constructing Font"); + let scale = Scale::uniform(32.0); // Adjust size as needed + let start = point(5.0, 32.0); // x, y baseline + let color = Rgba([0u8, 0u8, 0u8, 255u8]); + + // Draw each glyph + let v_metrics = font.v_metrics(scale); + let glyphs: Vec<_> = font.layout(text, scale, start).collect(); + for glyph in glyphs { + if let Some(bb) = glyph.pixel_bounding_box() { + glyph.draw(|gx, gy, gv| { + let x = gx as i32 + bb.min.x; + let y = gy as i32 + bb.min.y; + if x >= 0 && y >= 0 && (x as u32) < image.width() && (y as u32) < image.height() { + let alpha = (gv * 255.0) as u8; + let pixel = image.get_pixel_mut(x as u32, y as u32); + *pixel = Rgba([ + color[0], + color[1], + color[2], + alpha, + ]); + } + }); + } + } + } + fn encode_image_impl( input_path: PathBuf, output_path: PathBuf, @@ -184,22 +225,7 @@ impl Robot36EncoderApp { // Add callsign overlay if provided if !callsign.is_empty() { - // Draw black background for text - for y in 0..16 { - for x in 0..(callsign.len() as u32 * 8).min(image.width()) { - if x < image.width() && y < image.height() { - image.put_pixel(x, y, Rgba([0u8, 0u8, 0u8, 200u8])); - } - } - } - - // Draw text - builtin_font::draw_text( - &mut image, - 5, 5, // x, y position - &callsign, - Rgba([255u8, 255u8, 255u8, 255u8]), // white text - ); + Self::draw_callsign_with_rusttype(&mut image, &callsign); } // Calculate target size while maintaining aspect ratio