From 7c928f3249ec94b6923ac15c4624144eb2e82b5e Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Wed, 15 Mar 2023 10:57:37 +0100 Subject: [PATCH] Feat: correct colors and add text --- images/Makerlab.png | Bin 0 -> 26558 bytes src/color.rs | 14 +++++- src/main.rs | 3 ++ src/polygon.rs | 82 ++++++++++++------------------- src/routes/favicon.rs | 2 +- src/routes/logo.rs | 35 +++++++++---- src/routes/static_files.rs | 2 +- {static => web}/index.html | 11 ++++- {static => web}/pico.min.css | 0 {static => web}/pico.min.css.map | 0 10 files changed, 84 insertions(+), 65 deletions(-) create mode 100644 images/Makerlab.png rename {static => web}/index.html (79%) rename {static => web}/pico.min.css (100%) rename {static => web}/pico.min.css.map (100%) diff --git a/images/Makerlab.png b/images/Makerlab.png new file mode 100644 index 0000000000000000000000000000000000000000..241997be8072239eeec58fff27857f9c290df7fb GIT binary patch literal 26558 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 literal 0 HcmV?d00001 diff --git a/src/color.rs b/src/color.rs index 61dfd9c..f29d680 100644 --- a/src/color.rs +++ b/src/color.rs @@ -60,6 +60,18 @@ where Ok(res.unwrap()) } +impl Color { + pub fn from_hex(hex: &str) -> Self { + serde_json::from_str(&format!("\"{hex}\"")).unwrap() + } +} + +impl From<&str> for Color { + fn from(value: &str) -> Self { + Color::from_hex(value) + } +} + #[cfg(test)] #[test] fn test_serialize_color() { @@ -80,7 +92,7 @@ fn test_deserialize_color() { let deserialized_color: Color = serde_json::from_str(color).unwrap(); assert_eq!(deserialized_color.r, 10); - assert_eq!(deserialized_color.g, 20); + assert_eq!(deserialized_color.g, 20); assert_eq!(deserialized_color.b, 30); assert!(serde_json::from_str::("\"000000\"").is_err()); diff --git a/src/main.rs b/src/main.rs index 7a385d3..1a1e4bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +#![feature(const_trait_impl)] +#![feature(const_convert)] + use axum::Router; use std::net::SocketAddr; diff --git a/src/polygon.rs b/src/polygon.rs index b140448..da740f3 100644 --- a/src/polygon.rs +++ b/src/polygon.rs @@ -1,17 +1,24 @@ use cairo::Context; use rand::{rngs::ThreadRng, Rng}; +use crate::color::Color; + +static COLORS: [(&str, &str); 3] = [ + ("#F4A263", "#E87052"), + ("#E0DA48", "#969A1D"), + ("#309E8F", "#2F3F52"), +]; + fn calculate_polygon_corners( center: (f64, f64), num_sides: i32, - side_length: f64, + radius: f64, rotation_angle_degrees: f64, ) -> Vec<(f64, f64)> { // no idea how this code works, it was written by ChatGPT let mut corners = Vec::new(); let rotation_angle = rotation_angle_degrees.to_radians(); let angle = std::f64::consts::PI / (num_sides as f64); - let radius = side_length / (2.0 * angle.cos()); for i in 0..num_sides { let vertex_angle = angle * (2.0 * i as f64 + 1.0 - num_sides as f64) + rotation_angle; @@ -23,41 +30,18 @@ fn calculate_polygon_corners( corners } -fn set_color_i8((r, g, b): (u8, u8, u8), context: &Context) { - context.set_source_rgb(r as f64 / 255.0, g as f64 / 255.0, b as f64 / 255.0); +fn set_color(color: Color, context: &Context) { + context.set_source_rgb( + color.r as f64 / 255.0, + color.g as f64 / 255.0, + color.b as f64 / 255.0, + ); } -fn generate_color( - rng: &mut ThreadRng, - dark_mode: bool, - unlike: Option<(u8, u8, u8)>, -) -> (u8, u8, u8) { - let criteria = |(r, g, b): (u8, u8, u8)| { - let r = r as u16; - let g = g as u16; - let b = b as u16; - if dark_mode && (r + g + b) < 300 { - return false; - } else if !dark_mode && (r + g + b) > 500 { - return false; - } - - if let Some((r1, g1, b1)) = unlike { - if (r.abs_diff(r1 as u16) + g.abs_diff(g1 as u16) + b.abs_diff(b1 as u16)) < 200 { - return false; - } - } - - return true; - }; - - let mut color = rng.gen(); - - while !criteria(color) { - color = rng.gen(); - } - - color +fn generate_colors(rng: &mut ThreadRng) -> (Color, Color) { + let color_num = rng.gen_range(0..COLORS.len()); + let (c1, c2) = COLORS[color_num]; + (Color::from_hex(c1), Color::from_hex(c2)) } pub fn draw_polygon( @@ -65,11 +49,10 @@ pub fn draw_polygon( side_length: f64, num_sides: i32, context: &Context, - dark_mode: bool, ) -> Result<(), cairo::Error> { let mut rng = rand::thread_rng(); - let c1 = generate_color(&mut rng, dark_mode, None); - set_color_i8(c1, context); + let (c1, _) = generate_colors(&mut rng); + set_color(c1, context); context.new_path(); let corners = calculate_polygon_corners(center, num_sides, side_length, 30.0); @@ -89,11 +72,10 @@ pub fn draw_segmented_polygon( side_length: f64, num_sides: i32, context: &Context, - dark_mode: bool, ) -> Result<(), cairo::Error> { let mut rng = rand::thread_rng(); - let c1 = generate_color(&mut rng, dark_mode, None); - set_color_i8(c1, context); + let (c1, c2) = generate_colors(&mut rng); + set_color(c1, context); context.new_path(); let corners = calculate_polygon_corners(center, num_sides, side_length, 30.0); @@ -112,8 +94,7 @@ pub fn draw_segmented_polygon( context.close_path(); context.fill()?; - let c2 = generate_color(&mut rng, dark_mode, Some(c1)); - set_color_i8(c2, context); + set_color(c2, context); context.new_path(); // draw other side for i in to_corner..(from_corner + 1 + 6) { @@ -129,28 +110,27 @@ pub fn draw_segmented_polygon( pub fn draw_polygon_of_segmented_polygons( center: (f64, f64), - side_length: f64, + radius: f64, + inner_radius: f64, num_sides: i32, context: &Context, - dark_mode: bool, ) -> Result<(), cairo::Error> { - let corners = calculate_polygon_corners(center, num_sides, side_length, 0.0); + let corners = calculate_polygon_corners(center, num_sides, radius, 0.0); for corner in corners { - draw_segmented_polygon(corner, side_length * 0.4, num_sides, &context, dark_mode)?; + draw_segmented_polygon(corner, inner_radius, num_sides, &context)?; } Ok(()) } pub fn draw_polygon_of_polygons( center: (f64, f64), - side_length: f64, + radius: f64, num_sides: i32, context: &Context, - dark_mode: bool, ) -> Result<(), cairo::Error> { - let corners = calculate_polygon_corners(center, num_sides, side_length, 0.0); + let corners = calculate_polygon_corners(center, num_sides, radius, 0.0); for corner in corners { - draw_polygon(corner, side_length * 0.4, num_sides, &context, dark_mode)?; + draw_polygon(corner, radius * 0.4, num_sides, &context)?; } Ok(()) } diff --git a/src/routes/favicon.rs b/src/routes/favicon.rs index a80479f..620544c 100644 --- a/src/routes/favicon.rs +++ b/src/routes/favicon.rs @@ -10,7 +10,7 @@ async fn handler() -> impl axum::response::IntoResponse { context.set_source_rgba(0.0, 0.0, 0.0, 0.0); context.fill().unwrap(); - polygon::draw_polygon_of_polygons((50.0, 50.0), 65.0, 6, &context, false).unwrap(); + polygon::draw_polygon_of_polygons((50.0, 50.0), 65.0, 6, &context).unwrap(); let mut data: Vec = Vec::new(); surface.write_to_png(&mut data).unwrap(); diff --git a/src/routes/logo.rs b/src/routes/logo.rs index 10ea96b..5ed0ab3 100644 --- a/src/routes/logo.rs +++ b/src/routes/logo.rs @@ -1,5 +1,6 @@ use axum::{extract::Query, routing::get, Router}; use cairo::{Context, Format, ImageSurface}; +use rust_embed::RustEmbed; use serde::{de, Deserialize}; use crate::{color::Color, polygon, SharedState}; @@ -29,11 +30,33 @@ struct ImageProperties { #[serde(default = "default_as_false")] #[serde(deserialize_with = "deserialize_bool")] dark_mode: bool, + #[serde(default = "default_as_false")] + #[serde(deserialize_with = "deserialize_bool")] + text: bool, background_color: Option, } +#[derive(RustEmbed)] +#[folder = "images"] +struct ImageFiles; + +fn get_surface_and_logo_coordiates(properties: &ImageProperties) -> (ImageSurface, (f64, f64)) { + if properties.text { + let image = ImageFiles::get("Makerlab.png").unwrap(); + ( + ImageSurface::create_from_png(&mut image.data.as_ref()).unwrap(), + (604.0, 432.0), + ) + } else { + ( + ImageSurface::create(Format::ARgb32, 400, 400).unwrap(), + (200.0, 200.0), + ) + } +} + async fn handler(Query(properties): Query) -> impl axum::response::IntoResponse { - let surface = ImageSurface::create(Format::ARgb32, 400, 400).unwrap(); + let (surface, logo_coordinates) = get_surface_and_logo_coordiates(&properties); let context = Context::new(&surface).unwrap(); if let Some(c) = properties.background_color { @@ -44,14 +67,8 @@ async fn handler(Query(properties): Query) -> impl axum::respon context.paint().unwrap(); - polygon::draw_polygon_of_segmented_polygons( - (200.0, 200.0), - 200.0, - 6, - &context, - properties.dark_mode, - ) - .unwrap(); + polygon::draw_polygon_of_segmented_polygons(logo_coordinates, 148.0, 67.0, 6, &context) + .unwrap(); let mut data: Vec = Vec::new(); surface.write_to_png(&mut data).unwrap(); diff --git a/src/routes/static_files.rs b/src/routes/static_files.rs index e0ef3b9..262e82e 100644 --- a/src/routes/static_files.rs +++ b/src/routes/static_files.rs @@ -9,7 +9,7 @@ use rust_embed::{EmbeddedFile, RustEmbed}; use crate::SharedState; #[derive(RustEmbed)] -#[folder = "static"] +#[folder = "web"] struct StaticFiles; async fn static_files(uri: Uri) -> impl IntoResponse { diff --git a/static/index.html b/web/index.html similarity index 79% rename from static/index.html rename to web/index.html index 753c2f4..f915332 100644 --- a/static/index.html +++ b/web/index.html @@ -26,8 +26,11 @@