Print random easter egg

This commit is contained in:
Joscha 2024-03-30 16:28:30 +01:00
parent b293408cbc
commit a9ba160c13
15 changed files with 106 additions and 3 deletions

1
Cargo.lock generated
View file

@ -1388,6 +1388,7 @@ dependencies = [
"rand",
"rust-embed",
"serde",
"showbits-assets",
"showbits-common",
"taffy",
"time",

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -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"),
];

View file

@ -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"

View file

@ -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)]

View file

@ -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<RgbaImage> {
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<i64>>::into(paint.height());
last_idx = Some(idx);
}
// Finally, draw the cover
imageops::overlay(&mut image, &cover, 0, 0);
let mut tree = Tree::<Context>::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(())
}
}

View file

@ -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<Command>, 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<Server>, request: Form<PostChatMessageF
.await;
}
// /egg
async fn post_egg(server: State<Server>) {
let _ = server.tx.send(Command::draw(EggDrawing)).await;
}
// /image
async fn post_image(server: State<Server>, mut multipart: Multipart) -> somehow::Result<Response> {