| -rw-r--r-- | Cargo.lock | 2 | ||||
| -rw-r--r-- | Cargo.toml | 7 | ||||
| -rw-r--r-- | src/lib.rs | 88 | ||||
| -rw-r--r-- | tests/test.rs | 44 |
4 files changed, 104 insertions, 37 deletions
@@ -89,8 +89,6 @@ checksum = "6a02dba6a60cd31533cf16561ced53239686d18f1464bff49579dd320fcea081" [[package]] name = "fimg" version = "0.4.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6739c38489a0264e04537f68b822f4cb7abb732b41eca5229a91685fcc998939" dependencies = [ "atools", "clipline", @@ -5,6 +5,11 @@ edition = "2024" [dependencies] atools = "0.1.6" -fimg = "0.4.45" +fimg = { path = "../fimg" } +# fimg = { git = "https://github.com/bend-n/fimg" } implicit-fn = "0.1.0" swash = "0.2.5" + +[[test]] +name = "test" +harness = false @@ -1,3 +1,5 @@ +// |jlfJKlBM +// ||||||||||||||||||||||||||||||||||||| #![allow(incomplete_features)] #![feature( super_let, @@ -12,7 +14,7 @@ import_trait_associated_functions )] use std::iter::zip; -mod cell; +pub mod cell; use atools::Join; use swash::FontRef; use swash::scale::{Render, ScaleContext, Source}; @@ -46,36 +48,42 @@ impl<'a, 'b, 'c, 'd> Fonts<'a, 'b, 'c, 'd> { #[implicit_fn::implicit_fn] pub unsafe fn render( cells: &[Cell], - (w, h): (usize, usize), + (c, r): (usize, usize), ppem: f32, bgcolor: [u8; 3], fonts: Fonts, + line_spacing: f32, ) -> Image<Box<[u8]>, 3> { - let m = fonts.regular.metrics(&[]); - let sz = ppem * (m.max_width / m.units_per_em as f32); + assert_eq!(c * r, cells.len(), "cells too short."); + + let (fw, h) = dims(&fonts.regular, ppem, line_spacing); + let fh = h - line_spacing; + let (w, h) = ((fw * c as f32).ceil() as u32, (h * r as f32).ceil() as u32); let mut i = Image::build(w as _, h as _).fill(bgcolor); if w < 60 || h < 60 { return i; } - for (col, k) in cells.chunks_exact(w as _).zip(0..) { + for (col, k) in cells.chunks_exact(c as _).zip(0..) { for (&cell, j) in zip(col, 0..) { if cell.style.bg != bgcolor { - let cell = Image::<_, 4>::build(sz.ceil() as u32, (ppem * 1.25).ceil() as u32) - .fill(cell.style.bg.join(255)); + let cell = + Image::<_, 4>::build(fw.ceil() as u32, (fh + line_spacing).round() as u32) + .fill(cell.style.bg.join(255)); + unsafe { i.as_mut().overlay_at( &cell, - 4 + (j as f32 * sz) as u32, - (k as f32 * (ppem * 1.25)) as u32 - 20, + (j as f32 * fw).round() as u32, + (((k) as f32 * fh) + ((k as f32) * line_spacing as f32)).round() as u32, ) }; } } } - let mut characters: Vec<Glyph> = vec![Glyph::default(); w]; + let mut characters: Vec<Glyph> = vec![Glyph::default(); c]; - for (col, k) in cells.chunks_exact(w as _).zip(0..) { + for (col, k) in cells.chunks_exact(c as _).zip(0..) { let tokenized = col.iter().enumerate().map(|(i, cell)| { let ch = cell.letter.unwrap_or(' '); ( @@ -130,24 +138,24 @@ pub unsafe fn render( if (cell.style.flags & Style::DIM) != 0 { color = color.map(|x| x / 2); } - if (cell.style.flags & Style::UNDERLINE) != 0 { - unsafe { - i.as_mut().overlay_at( - &Image::<_, 4>::build(sz.ceil() as u32, 2).fill(color.join(255)), - 4 + (j as f32 * sz) as u32, - (k as f32 * (ppem * 1.25)) as u32 + 5, - ) - }; - } - if (cell.style.flags & Style::STRIKETHROUGH) != 0 { - unsafe { - i.as_mut().overlay_at( - &Image::<_, 4>::build(sz.ceil() as u32, 2).fill(color.join(255)), - 4 + (j as f32 * sz) as u32, - (k as f32 * (ppem * 1.25)) as u32 - 5, - ) - }; - } + // if (cell.style.flags & Style::UNDERLINE) != 0 { + // unsafe { + // i.as_mut().overlay_at( + // &Image::<_, 4>::build(fw.ceil() as u32, 2).fill(color.join(255)), + // 4 + (j as f32 * fw as u32, + // (k as f32 * (ppem * 1.25)) as u32 + 5, + // ) + // }; + // } + // if (cell.style.flags & Style::STRIKETHROUGH) != 0 { + // unsafe { + // i.as_mut().overlay_at( + // &Image::<_, 4>::build(fw.ceil() as u32, 2).fill(color.join(255)), + // 4 + (j as f32 * fw) as u32, + // (k as f32 * (ppem * 1.25)) as u32 - 5, + // ) + // }; + // } if let Some(_) = cell.letter { let f = match cell.style.flags { f if f & (Style::BOLD | Style::ITALIC) != 0 => fonts.bold_italic, @@ -173,8 +181,12 @@ pub unsafe fn render( i.as_mut().blend_alpha_and_color_at( &item.as_ref(), color, - 4 + ((j as f32 * sz + glyph.x) + x.placement.left as f32).round() as u32, - ((k as f32 * (ppem * 1.25)) as u32).saturating_sub(x.placement.top as u32), + ((j as f32 * fw + glyph.x) + x.placement.left as f32).round() as u32, + ( + dbg!(((k + 1) as f32 * fh) - (x.placement.top as f32)) + // + ((k as f32) * line_spacing as f32) + ) + .round() as u32, ); } } @@ -195,9 +207,17 @@ pub unsafe fn render( i } -pub fn dims(font: &FontRef, ppem: f32) -> (f32, f32) { +pub fn dims(font: &FontRef, ppem: f32, line_spacing: f32) -> (f32, f32) { + // ppem * (m.max_width / m.units_per_em as f32), + // m.max_width * (ppem / m.units_per_em as f32); let m = font.metrics(&[]); - (ppem * (m.max_width / m.units_per_em as f32), ppem * 1.25) + let f = ppem / m.units_per_em as f32; + ( + m.max_width * f, + m.ascent * f + line_spacing, + // ((ppem + line_spacing) * (m.ascent / m.units_per_em as f32)), + ) } -use crate::cell::{Cell, Style}; +pub use crate::cell::Cell; +use crate::cell::Style; use fimg::{Image, OverlayAt}; diff --git a/tests/test.rs b/tests/test.rs new file mode 100644 index 0000000..f8d6aa2 --- /dev/null +++ b/tests/test.rs @@ -0,0 +1,44 @@ +use std::sync::LazyLock; + +use dsb::{Fonts, cell::Style}; +use swash::FontRef; + +fn main() { + let ppem = 300.0; + let lh = 0.0; + let (fw, fh) = dsb::dims(&FONT, ppem, lh); + let (w, h) = (2000, 2000); + + let cols = (w as f32 / fw).floor() as usize; + let rows = (h as f32 / fh).floor() as usize; + + dbg!(cols, rows); + + let cells = include_str!("../src/lib.rs") + .chars() + .filter(|x| !x.is_whitespace()) + .take(cols * rows) + .map(|x: char| dsb::Cell { + style: Style { + bg: [0; 3], + color: [255; 3], + flags: 0, + }, + letter: Some(x), + }) + .collect::<Vec<_>>(); + unsafe { + dsb::render( + &cells, + (cols, rows), + ppem, + [1; 3], + Fonts::new(*FONT, *FONT, *FONT, *FONT), + lh, + ) + } + .show(); +} +pub static FONT: LazyLock<FontRef<'static>> = LazyLock::new(|| { + FontRef::from_index(&include_bytes!("/home/os/CascadiaCodeNF.ttf")[..], 0).unwrap() +}); |