Chore: commit unstaged changed

This commit is contained in:
Dorian Zedler 2023-09-10 12:16:33 +02:00
parent 9d89154b23
commit cec5d50aa6
Signed by: dozedler
GPG key ID: 989DE36109AFA354
3 changed files with 40 additions and 29 deletions

View file

@ -7,7 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
png = "0.11.0" png = "0.11.0"
cairo-rs = { version = "0.17.0", default-features = false, features = ["png", "freetype"] } cairo-rs = { version = "0.17.0", default-features = false, features = ["png", "svg", "freetype"] }
axum = "0.6.10" axum = "0.6.10"
tokio = { version = "1.0", features = ["full"] } tokio = { version = "1.0", features = ["full"] }
rand = "0.8.5" rand = "0.8.5"

View file

@ -1,4 +1,4 @@
use axum::{http::Request, response::Response, Router}; use axum::{http::Request, response::Response, routing::get, Router};
use std::{net::SocketAddr, time::Duration}; use std::{net::SocketAddr, time::Duration};
use text::EmbeddedFonts; use text::EmbeddedFonts;
use tower_http::{catch_panic::CatchPanicLayer, trace::TraceLayer}; use tower_http::{catch_panic::CatchPanicLayer, trace::TraceLayer};
@ -21,7 +21,8 @@ async fn main() {
}; };
let app = Router::new() let app = Router::new()
.nest("/", routes::static_files::routes()) .nest("/", routes::static_files::routes())
.nest("/logo", routes::logo::routes()) .route("/logo.png", get(routes::logo::png))
.route("/logo.svg", get(routes::logo::svg))
.nest("/favicon.ico", routes::favicon::routes()) .nest("/favicon.ico", routes::favicon::routes())
.layer( .layer(
TraceLayer::new_for_http() TraceLayer::new_for_http()

View file

@ -5,7 +5,7 @@ use axum::{
routing::get, routing::get,
Router, Router,
}; };
use cairo::{freetype::Face, Context, FontFace, Format, ImageSurface}; use cairo::{freetype::Face, Context, FontFace, Format, ImageSurface, SvgSurface};
use serde::Deserialize; use serde::Deserialize;
use crate::{color::Color, polygon, text::DrawableText, SharedState}; use crate::{color::Color, polygon, text::DrawableText, SharedState};
@ -27,23 +27,32 @@ enum LogoOrientation {
} }
#[derive(Deserialize, Default)] #[derive(Deserialize, Default)]
struct ImageProperties { pub struct ImageProperties {
#[serde(default)] #[serde(default)]
variant: LogoVariant, variant: LogoVariant,
#[serde(default)] #[serde(default)]
orientation: LogoOrientation, orientation: LogoOrientation,
} }
fn create_surface(properties: &ImageProperties) -> ImageSurface { fn get_surface_size(properties: &ImageProperties) -> (i32, i32) {
let (width, height) = match (&properties.variant, &properties.orientation) { match (&properties.variant, &properties.orientation) {
(LogoVariant::NoText, _) => (400, 400), (LogoVariant::NoText, _) => (400, 400),
(_, LogoOrientation::Landscape) => (2127, 591), (_, LogoOrientation::Landscape) => (2127, 591),
(_, LogoOrientation::Portrait) => (1654, 1654), (_, LogoOrientation::Portrait) => (1654, 1654),
}; }
}
fn create_image_surface(properties: &ImageProperties) -> ImageSurface {
let (width, height) = get_surface_size(properties);
ImageSurface::create(Format::ARgb32, width, height).unwrap() ImageSurface::create(Format::ARgb32, width, height).unwrap()
} }
fn create_svg_surface(properties: &ImageProperties) -> SvgSurface {
let (width, height) = get_surface_size(properties);
SvgSurface::new::<String>(width as f64, height as f64, None).unwrap()
}
fn draw_logo(context: &Context, properties: &ImageProperties) { fn draw_logo(context: &Context, properties: &ImageProperties) {
let (logo_coordinates, logo_outer_radius, logo_inner_radius) = let (logo_coordinates, logo_outer_radius, logo_inner_radius) =
match (&properties.variant, &properties.orientation) { match (&properties.variant, &properties.orientation) {
@ -123,38 +132,21 @@ fn draw_text(
} }
#[axum_macros::debug_handler] #[axum_macros::debug_handler]
async fn handler( pub async fn png(
Query(properties): Query<ImageProperties>, Query(properties): Query<ImageProperties>,
State(state): State<SharedState>, State(state): State<SharedState>,
) -> impl axum::response::IntoResponse { ) -> impl axum::response::IntoResponse {
let start = Instant::now();
let (font_regular, font_light) = state.fonts.get().await; let (font_regular, font_light) = state.fonts.get().await;
println!("{:?}", start.elapsed());
let start = Instant::now();
// cannot use await after this, because surface does not implement Send // cannot use await after this, because surface does not implement Send
let surface = create_image_surface(&properties);
let surface = create_surface(&properties);
let context = Context::new(&surface).unwrap(); let context = Context::new(&surface).unwrap();
println!("{:?}", (surface.width(), surface.height()));
println!("{:?}", start.elapsed());
let start = Instant::now();
draw_logo(&context, &properties); draw_logo(&context, &properties);
println!("{:?}", start.elapsed());
let start = Instant::now();
draw_text(&context, &font_regular, &font_light, &properties); draw_text(&context, &font_regular, &font_light, &properties);
println!("{:?}", start.elapsed());
let start = Instant::now();
let mut data: Vec<u8> = Vec::new(); let mut data: Vec<u8> = Vec::new();
surface.write_to_png(&mut data).unwrap(); surface.write_to_png(&mut data).unwrap();
println!("{:?}", start.elapsed());
( (
axum::response::AppendHeaders([(axum::http::header::CONTENT_TYPE, "image/png")]), axum::response::AppendHeaders([(axum::http::header::CONTENT_TYPE, "image/png")]),
@ -162,6 +154,24 @@ async fn handler(
) )
} }
pub fn routes() -> Router<SharedState> { #[axum_macros::debug_handler]
Router::<SharedState>::new().route("/", get(handler)) pub async fn svg(
Query(properties): Query<ImageProperties>,
State(state): State<SharedState>,
) -> impl axum::response::IntoResponse {
let (font_regular, font_light) = state.fonts.get().await;
// cannot use await after this, because surface does not implement Send
let surface = create_svg_surface(&properties);
let context = Context::new(&surface).unwrap();
draw_logo(&context, &properties);
draw_text(&context, &font_regular, &font_light, &properties);
let mut data: Vec<u8> = Vec::new();
surface.write_to_png(&mut data).unwrap();
(
axum::response::AppendHeaders([(axum::http::header::CONTENT_TYPE, "image/png")]),
data,
)
} }