Chore: commit unstaged changed

test/generate-svg-logo
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]
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"
tokio = { version = "1.0", features = ["full"] }
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 text::EmbeddedFonts;
use tower_http::{catch_panic::CatchPanicLayer, trace::TraceLayer};
@ -21,7 +21,8 @@ async fn main() {
};
let app = Router::new()
.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())
.layer(
TraceLayer::new_for_http()

View File

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