mod.rs
3.4 kB · rust · 88 lines
1//! The generator: the pipeline from a recipe to a file, for datasets, the automator, backgrounds.2//!3//! - `recipe`: the tile recipe, its families, groups, parities, catalog and size lists.4//! - `draw`: one recipe drawn at random from a seeded stream under size constraints.5//! - `build`: the recipe to cell builders, one per dimension.6//! - `variation`: the seeded artwork, from recipe through paint to rendered files.7//! - `name`: the canonical name of a recipe, and the recipe back out of it.8//!9//! The doors: [`Tile::new`](crate::gen::recipe::Tile::new),10//! [`Tile::size`](crate::gen::recipe::Tile::size),11//! [`Tile::check`](crate::gen::recipe::Tile::check),12//! [`draw::create`](crate::gen::draw::create), [`build_2d`](crate::gen::build::build_2d),13//! [`variation::create`](crate::gen::variation::create),14//! [`Tile::of`](crate::gen::name::Tile::of) and [`background`](crate::gen::background).1516/// The recipe to cell builders, one per dimension, and the random draws that feed them.17pub mod build;18/// The random tile drawing the dimensions share, on the seeded stream.19pub mod draw;20/// The tile name: a full tile recipe folded to its one canonical object.21pub mod name;22/// The tile recipe: its families, groups, parities, catalog and size lists.23pub mod recipe;24/// The seeded artwork run from tile recipe to rendered files.25pub mod variation;2627pub use recipe::{Group, Parity, Tile};2829use crate::core::error::{value_error, Result};30use crate::core::rng::Rng;3132/// Draws one seeded artwork and returns its PNG bytes: a random flat tile under the default recipe33/// constraints and paint, repeated `width` across and `height` down at one pixel per cell.34///35/// The seed opens one stream, `variation::create` draws its own seed from it, and the paint and36/// render follow on the same stream, so one seed always paints the same background.37///38/// ```39/// let png = mrlyrs::gen::background(1, 2, 2)?;40/// assert_eq!(png[..8], [137, 80, 78, 71, 13, 10, 26, 10]);41/// # Ok::<(), mrlyrs::Error>(())42/// ```43///44/// # Errors45///46/// Errs when the width or the height is zero, or when the artwork will not draw or render.47pub fn background(seed: u64, width: usize, height: usize) -> Result<Vec<u8>> {48 if width == 0 || height == 0 {49 return value_error("a background wants a width and a height above zero.");50 }51 let mut rng = Rng::new(seed);52 let config = variation::Config {53 files: vec![(width, height)],54 ..variation::Config::default()55 };56 let drawn = variation::create(&config, &mut rng)?;57 let built = variation::generate(drawn, &config, &mut rng)?;58 let rendered = variation::render(built, 1, &mut rng)?;59 match rendered.files.into_iter().next() {60 Some(file) => Ok(file.png),61 None => value_error("the background rendered no file."),62 }63}6465#[cfg(test)]66mod tests {67 use super::*;68 #[test]69 fn background_is_a_png_of_the_seed() {70 let a = background(7, 2, 3).unwrap();71 let b = background(7, 2, 3).unwrap();72 assert_eq!(&a[1..4], b"PNG");73 assert_eq!(a, b);74 assert_ne!(a, background(8, 2, 3).unwrap());75 }76 #[test]77 fn refuses_a_background_with_no_pixels() {78 assert!(background(7, 0, 3).is_err());79 assert!(background(7, 2, 0).is_err());80 }81 #[test]82 fn serde_round_trips() {83 for parity in Parity::all() {84 let text = serde_json::to_string(&parity).unwrap();85 assert_eq!(parity, serde_json::from_str(&text).unwrap());86 }87 }88}