small software-rendered rust tty
Diffstat (limited to 'src/render.rs')
| -rw-r--r-- | src/render.rs | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/render.rs b/src/render.rs new file mode 100644 index 0000000..2e9780c --- /dev/null +++ b/src/render.rs @@ -0,0 +1,125 @@ +use std::sync::LazyLock; + +use swash::FontRef; +use swash::scale::{Render, ScaleContext, Source}; +use swash::zeno::Format; + +#[implicit_fn::implicit_fn] +pub fn render( + x: &super::Terminal, + (w, h): (usize, usize), + ppem: f32, +) -> Image<Vec<u8>, 3> { + let m = FONT.metrics(&[]); + let sz = ppem * (m.max_width / m.units_per_em as f32); + let mut i = Image::alloc(w as _, h as _); + for (col, k) in x.cells.chunks_exact(x.size.0 as _).zip(0..) { + for (cell, j) in + col.iter().skip(2).zip(0..).filter(_.0.letter.is_some()) + { + let id = FONT.charmap().map(cell.letter.unwrap()); + + let x = Render::new(&[Source::Outline]) + .format(Format::Alpha) + .render( + &mut ScaleContext::new() + .builder(*FONT) + .size(ppem) + .build(), + id, + ) + .unwrap(); + unsafe { + if x.placement.width == 0 { + continue; + } + i.as_mut().overlay_at( + &Image::<Box<[u8]>, 4>::from( + Image::<_, 1>::build( + x.placement.width, + x.placement.height, + ) + .buf(&*x.data), + ) + .as_ref(), + 4 + ((j * sz as i32) + x.placement.left) as u32, + (k as f32 * (ppem * 1.25)) as u32 + - x.placement.top as u32, + // x.placement.height - x.placement.top as u32, + ); + } + } + } + i +} + +pub fn dims(font: &FontRef, ppem: f32) -> (f32, f32) { + let m = font.metrics(&[]); + (ppem * (m.max_width / m.units_per_em as f32), ppem) +} + +pub static FONT: LazyLock<FontRef<'static>> = LazyLock::new(|| { + FontRef::from_index(&include_bytes!("../CascadiaCodeNF.ttf")[..], 0) + .unwrap() +}); + +use fimg::{Image, OverlayAt}; +// let x = b"echo -e \"\x1b(0lqqqk\nx \x1b(Bx\nmqqqj"; +// let x = String::from_utf8_lossy(&x); +// println!("{}", x); +#[test] +fn t() { + let f = + FontRef::from_index(&include_bytes!("../CascadiaCode.ttf")[..], 0) + .unwrap(); + + dbg!(f.attributes()); + let m = f.metrics(&[]); + dbg!(m); + let ppem = 30.0; + let sz = ppem * (m.max_width / m.units_per_em as f32); + dbg!( + &mut ScaleContext::new() + .builder(f) + .size(15.0) + .build() + .scale_outline(f.charmap().map('a')) + .unwrap() + .len() + ); + let mut grid = Image::<_, 4>::alloc(2000, 150); + unsafe { grid.chunked_mut().for_each(|x| *x = [0, 0, 0, 255]) }; + for (letter, i) in "the quick brown fox jumped over the lazy dog" + .chars() + .zip(0..) + { + let id = f.charmap().map(letter); + + let x = Render::new(&[Source::Outline]) + .format(Format::Alpha) + .render( + &mut ScaleContext::new().builder(f).size(ppem).build(), + id, + ) + .unwrap(); + unsafe { + if x.placement.width == 0 { + continue; + } + grid.as_mut().overlay_at( + &Image::<Box<[u8]>, 4>::from( + Image::<_, 1>::build( + x.placement.width, + x.placement.height, + ) + .buf(&*x.data), + ) + .as_ref(), + ((i * sz as i32) + x.placement.left) as _, + ppem as u32 - x.placement.top as u32, + // x.placement.height - x.placement.top as u32, + ); + } + } + grid.show(); +} |