renderer.rs
3.1 kB · rust · 103 lines
1use super::Cell2d;2use crate::core::cell::mapping;3use crate::core::enums::Mode;4use crate::core::errors::Result;5use crate::math::dim::push_glyph;6use std::collections::HashMap;78fn painted(cell: &Cell2d) -> Vec<[u8; 4]> {9 match &cell.cell.colors {10 Some(colors) => colors.clone(),11 None => {12 let fresh = cell.clone().paint(&mapping(), Mode::Type);13 fresh.cell.colors.unwrap()14 }15 }16}1718/// Renders the cell as rows of glyphs, or of digits where no glyph is mapped.19///20/// ```21/// let cell = mrlyrs::math::two::carpet(3, 1).unwrap();22/// assert_eq!(mrlyrs::math::two::text(&cell, None), vec!["111", "101", "111"]);23/// ```24pub fn text(cell: &Cell2d, glyphs: Option<&HashMap<u8, char>>) -> Vec<String> {25 let (h, w) = (cell.height(), cell.width());26 let mut rows = Vec::with_capacity(h);27 for y in 0..h {28 let mut row = String::with_capacity(w);29 for x in 0..w {30 let v = cell.types().get(&[y, x]);31 push_glyph(&mut row, v, glyphs);32 }33 rows.push(row);34 }35 rows36}3738/// Renders the cell to PNG bytes at the given pixel scale, painting it by type when unpainted.39pub fn png(cell: &Cell2d, scale: usize) -> Result<Vec<u8>> {40 let colors = painted(cell);41 crate::core::png(&colors, cell.width(), cell.height(), scale)42}4344#[cfg(test)]45mod tests {46 use super::*;47 use crate::math::two::designs;48 #[test]49 fn text_digits_and_glyphs() {50 let c = designs::carpet(3, 1).unwrap();51 let t = text(&c, None);52 assert_eq!(t, vec!["111", "101", "111"]);53 let glyphs = HashMap::from([(0, ' '), (1, '#')]);54 assert_eq!(text(&c, Some(&glyphs)), vec!["###", "# #", "###"]);55 }56 #[test]57 fn png_signature_and_size() {58 let c = designs::carpet(3, 2).unwrap();59 let bytes = png(&c, 4).unwrap();60 assert_eq!(&bytes[0..8], &[137, 80, 78, 71, 13, 10, 26, 10]);61 assert!(bytes.len() > 100);62 }63}6465#[cfg(test)]66mod golden {67 use super::*;68 use crate::math::two::designs;69 #[test]70 fn png_pixels_stay_pinned() {71 let black = [0, 0, 0, 255];72 let white = [255, 255, 255, 255];73 let cases = [74 (75 png(&designs::carpet(3, 2).unwrap(), 4).unwrap(),76 36,77 1024,78 white,79 ),80 (81 png(&designs::htree(5, 1).unwrap(), 1).unwrap(),82 5,83 15,84 black,85 ),86 (87 png(&designs::vtree(7, 1).unwrap(), 3).unwrap(),88 21,89 252,90 white,91 ),92 ];93 for (bytes, side, inked, centre) in &cases {94 let (w, h, pixels) = crate::core::unpng(bytes).unwrap();95 assert_eq!((w, h), (*side, *side));96 assert!(pixels.iter().all(|p| *p == black || *p == white));97 assert_eq!(pixels.iter().filter(|p| **p == black).count(), *inked);98 assert_eq!(pixels[0], black);99 assert_eq!(pixels[(side / 2) * side + side / 2], *centre);100 assert_eq!(pixels[side * side - 1], black);101 }102 }103}