diff --git a/Cargo.lock b/Cargo.lock index 0a3029b..118bf97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1388,6 +1388,7 @@ dependencies = [ "rand", "rust-embed", "serde", + "showbits-assets", "showbits-common", "taffy", "time", diff --git a/showbits-assets/data/egg.xcf b/showbits-assets/data/egg.xcf new file mode 100644 index 0000000..5b61745 Binary files /dev/null and b/showbits-assets/data/egg.xcf differ diff --git a/showbits-assets/data/egg_cover.png b/showbits-assets/data/egg_cover.png new file mode 100644 index 0000000..5169947 Binary files /dev/null and b/showbits-assets/data/egg_cover.png differ diff --git a/showbits-assets/data/egg_pattern_0.png b/showbits-assets/data/egg_pattern_0.png new file mode 100644 index 0000000..d73318e Binary files /dev/null and b/showbits-assets/data/egg_pattern_0.png differ diff --git a/showbits-assets/data/egg_pattern_1.png b/showbits-assets/data/egg_pattern_1.png new file mode 100644 index 0000000..510a3e3 Binary files /dev/null and b/showbits-assets/data/egg_pattern_1.png differ diff --git a/showbits-assets/data/egg_pattern_2.png b/showbits-assets/data/egg_pattern_2.png new file mode 100644 index 0000000..941ac33 Binary files /dev/null and b/showbits-assets/data/egg_pattern_2.png differ diff --git a/showbits-assets/data/egg_pattern_3.png b/showbits-assets/data/egg_pattern_3.png new file mode 100644 index 0000000..cc75e53 Binary files /dev/null and b/showbits-assets/data/egg_pattern_3.png differ diff --git a/showbits-assets/data/egg_pattern_4.png b/showbits-assets/data/egg_pattern_4.png new file mode 100644 index 0000000..d4d9c65 Binary files /dev/null and b/showbits-assets/data/egg_pattern_4.png differ diff --git a/showbits-assets/data/egg_pattern_5.png b/showbits-assets/data/egg_pattern_5.png new file mode 100644 index 0000000..ee0d4b4 Binary files /dev/null and b/showbits-assets/data/egg_pattern_5.png differ diff --git a/showbits-assets/data/egg_pattern_6.png b/showbits-assets/data/egg_pattern_6.png new file mode 100644 index 0000000..794d082 Binary files /dev/null and b/showbits-assets/data/egg_pattern_6.png differ diff --git a/showbits-assets/src/lib.rs b/showbits-assets/src/lib.rs index 345dfe0..0ca41c0 100644 --- a/showbits-assets/src/lib.rs +++ b/showbits-assets/src/lib.rs @@ -3,3 +3,14 @@ pub const UNIFONT_JP: &[u8] = include_bytes!("../data/unifont_jp-15.1.05.otf"); pub const UNIFONT_UPPER: &[u8] = include_bytes!("../data/unifont_upper-15.1.05.otf"); pub const UNIFONT_NAME: &str = "Unifont"; pub const UNIFONT_SIZE: f32 = 16.0; + +pub const EGG_COVER: &[u8] = include_bytes!("../data/egg_cover.png"); +pub const EGG_PATTERNS: &[&[u8]] = &[ + include_bytes!("../data/egg_pattern_0.png"), + include_bytes!("../data/egg_pattern_1.png"), + include_bytes!("../data/egg_pattern_2.png"), + include_bytes!("../data/egg_pattern_3.png"), + include_bytes!("../data/egg_pattern_4.png"), + include_bytes!("../data/egg_pattern_5.png"), + include_bytes!("../data/egg_pattern_6.png"), +]; diff --git a/showbits-thermal-printer/Cargo.toml b/showbits-thermal-printer/Cargo.toml index 9f1147e..34d73c8 100644 --- a/showbits-thermal-printer/Cargo.toml +++ b/showbits-thermal-printer/Cargo.toml @@ -15,6 +15,7 @@ palette.workspace = true rand = "0.8.5" rust-embed = "8.3.0" serde = { version = "1.0.197", features = ["derive"] } +showbits-assets.workspace = true showbits-common.workspace = true taffy.workspace = true time = "0.3.34" diff --git a/showbits-thermal-printer/src/drawer.rs b/showbits-thermal-printer/src/drawer.rs index b385b7b..378c0ba 100644 --- a/showbits-thermal-printer/src/drawer.rs +++ b/showbits-thermal-printer/src/drawer.rs @@ -1,6 +1,7 @@ mod calendar; mod cells; mod chat_message; +mod egg; mod image; mod photo; mod text; @@ -12,7 +13,7 @@ use crate::printer::Printer; pub use self::{ calendar::CalendarDrawing, cells::CellsDrawing, chat_message::ChatMessageDrawing, - image::ImageDrawing, photo::PhotoDrawing, text::TextDrawing, + egg::EggDrawing, image::ImageDrawing, photo::PhotoDrawing, text::TextDrawing, }; #[derive(Default)] diff --git a/showbits-thermal-printer/src/drawer/egg.rs b/showbits-thermal-printer/src/drawer/egg.rs new file mode 100644 index 0000000..ec59e3f --- /dev/null +++ b/showbits-thermal-printer/src/drawer/egg.rs @@ -0,0 +1,82 @@ +use image::{imageops, RgbaImage}; +use rand::Rng; +use showbits_assets::{EGG_COVER, EGG_PATTERNS}; +use showbits_common::{ + color::{self, WHITE}, + widgets::{Image, Text}, + Node, Tree, WidgetExt, +}; +use taffy::{style_helpers::percent, AlignItems, Display, FlexDirection}; + +use crate::printer::Printer; + +use super::{Context, Drawing}; + +pub struct EggDrawing; + +fn load_image(bytes: &[u8]) -> anyhow::Result { + Ok(image::load_from_memory(bytes)?.into_rgba8()) +} + +impl Drawing for EggDrawing { + fn draw(&self, printer: &mut Printer, ctx: &mut Context) -> anyhow::Result<()> { + // Load image data from memory + let cover = load_image(EGG_COVER)?; + let mut patterns = vec![]; + for pattern in EGG_PATTERNS { + patterns.push(load_image(pattern)?); + } + + // Prepare egg image + 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 = rand::thread_rng().gen_range(-100_i64..0); + while y < image.height().into() { + let idx = loop { + let idx = rand::thread_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(()) + } +} diff --git a/showbits-thermal-printer/src/server.rs b/showbits-thermal-printer/src/server.rs index 79318d9..dfe1777 100644 --- a/showbits-thermal-printer/src/server.rs +++ b/showbits-thermal-printer/src/server.rs @@ -13,8 +13,8 @@ use serde::Deserialize; use tokio::{net::TcpListener, sync::mpsc}; use crate::drawer::{ - CalendarDrawing, CellsDrawing, ChatMessageDrawing, Command, ImageDrawing, PhotoDrawing, - TextDrawing, + CalendarDrawing, CellsDrawing, ChatMessageDrawing, Command, EggDrawing, ImageDrawing, + PhotoDrawing, TextDrawing, }; use self::{r#static::get_static_file, statuscode::status_code}; @@ -29,6 +29,7 @@ pub async fn run(tx: mpsc::Sender, addr: String) -> anyhow::Result<()> .route("/calendar", post(post_calendar)) .route("/cells", post(post_cells)) .route("/chat_message", post(post_chat_message)) + .route("/egg", post(post_egg)) .route("/image", post(post_image).fallback(get_static_file)) .route("/photo", post(post_photo).fallback(get_static_file)) .route("/text", post(post_text)) @@ -97,6 +98,12 @@ async fn post_chat_message(server: State, request: Form) { + let _ = server.tx.send(Command::draw(EggDrawing)).await; +} + // /image async fn post_image(server: State, mut multipart: Multipart) -> somehow::Result {