use image::{RgbaImage, imageops}; use rand::{Rng, seq::SliceRandom}; use showbits_assets::{EGG_BAD_COVERS, EGG_BAD_PATTERNS, EGG_COVERS, EGG_PATTERNS}; use showbits_common::{ Node, Tree, WidgetExt, color::{self, WHITE}, widgets::{Image, Text}, }; use taffy::{AlignItems, Display, FlexDirection, style_helpers::percent}; use crate::printer::Printer; use super::{Context, Drawing}; pub struct EggDrawing; fn load_image(bytes: &[u8]) -> RgbaImage { image::load_from_memory(bytes) .expect("malformed image data") .into_rgba8() } impl Drawing for EggDrawing { fn draw(&self, printer: &mut Printer, ctx: &mut Context) -> anyhow::Result<()> { let mut rng = rand::thread_rng(); // Choose which set of egg images to use let bad_egg = rng.gen_range(0..8) == 0; let (covers, patterns) = if bad_egg { (EGG_BAD_COVERS, EGG_BAD_PATTERNS) } else { (EGG_COVERS, EGG_PATTERNS) }; // Load images from memory let covers = covers.iter().map(|img| load_image(img)).collect::>(); let patterns = patterns .iter() .map(|img| load_image(img)) .collect::>(); // Choose a random cover let cover = covers.choose(&mut rng).expect("too few covers"); // Prepare image of appropriate size let mut image = RgbaImage::from_pixel(cover.width(), cover.height(), color::to_image_color(WHITE)); // Draw patterns onto egg let mut last_idx = None; let mut y = rng.gen_range(-100_i64..0); while y < image.height().into() { let idx = loop { let idx = rng.gen_range(0..patterns.len()); if Some(idx) != last_idx { break idx; } }; let paint = &patterns[idx]; imageops::overlay(&mut image, paint, 0, y); y += <_ as Into>::into(paint.height()); last_idx = Some(idx); } // Finally, draw the cover imageops::overlay(&mut image, cover, 0, 0); let mut tree = Tree::::new(WHITE); let image = Image::new(image) .with_grow(false) .with_shrink(false) .node() .register(&mut tree)?; let text = Text::new() .with_metrics(Text::default_metrics().scale(2.0)) .and_plain("Frohe Ostern!") .widget(&mut ctx.font_stuff) .node() .register(&mut tree)?; let root = Node::empty() .with_size_width(percent(1.0)) .with_display(Display::Flex) .with_flex_direction(FlexDirection::Column) .with_align_items(Some(AlignItems::Center)) .and_child(image) .and_child(text) .register(&mut tree)?; printer.print_tree(&mut tree, ctx, root)?; printer.feed()?; Ok(()) } }