Compare commits

...

3 commits

5 changed files with 449 additions and 323 deletions

715
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,8 @@ use text::EmbeddedFonts;
use tower_http::{catch_panic::CatchPanicLayer, trace::TraceLayer}; use tower_http::{catch_panic::CatchPanicLayer, trace::TraceLayer};
use tracing::Span; use tracing::Span;
use crate::routes::static_files;
mod color; mod color;
mod polygon; mod polygon;
mod routes; mod routes;
@ -20,9 +22,9 @@ async fn main() {
fonts: EmbeddedFonts::load(), fonts: EmbeddedFonts::load(),
}; };
let app = Router::new() let app = Router::new()
.nest("/", routes::static_files::routes()) .fallback(static_files::router)
.route("/logo", get(routes::logo::png))
.route("/logo.png", get(routes::logo::png)) .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

@ -1,11 +1,5 @@
use std::time::Instant; use axum::extract::{Query, State};
use cairo::{freetype::Face, Context, FontFace, Format, ImageSurface};
use axum::{
extract::{Query, State},
routing::get,
Router,
};
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};
@ -47,12 +41,6 @@ fn create_image_surface(properties: &ImageProperties) -> ImageSurface {
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) {
@ -153,25 +141,3 @@ pub async fn png(
data, data,
) )
} }
#[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,
)
}

View file

@ -2,17 +2,14 @@ use axum::{
body::{boxed, Full}, body::{boxed, Full},
http::{header, StatusCode, Uri}, http::{header, StatusCode, Uri},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
Router,
}; };
use rust_embed::{EmbeddedFile, RustEmbed}; use rust_embed::{EmbeddedFile, RustEmbed};
use crate::SharedState;
#[derive(RustEmbed)] #[derive(RustEmbed)]
#[folder = "web"] #[folder = "web"]
struct StaticFiles; struct StaticFiles;
async fn static_files(uri: Uri) -> impl IntoResponse { pub async fn router(uri: Uri) -> impl IntoResponse {
let path = uri.path().trim_start_matches('/'); let path = uri.path().trim_start_matches('/');
match StaticFiles::get(path) { match StaticFiles::get(path) {
@ -50,7 +47,3 @@ fn not_found() -> Response {
.body(boxed(Full::from("404"))) .body(boxed(Full::from("404")))
.unwrap() .unwrap()
} }
pub fn routes() -> Router<SharedState> {
Router::new().fallback(static_files)
}

View file

@ -48,7 +48,7 @@
<label for="logo_variant"> <label for="logo_variant">
Variant Variant
</label> </label>
<select id="logo_variant" value="DarkText"> <select id="logo_variant" name="variant" value="DarkText">
<option value="DarkText" selected>dark text</option> <option value="DarkText" selected>dark text</option>
<option value="LightText">light text</option> <option value="LightText">light text</option>
<option value="NoText">no text</option> <option value="NoText">no text</option>
@ -59,7 +59,7 @@
Orientation Orientation
</label> </label>
<select id="logo_orientation" value="Landscape"> <select id="logo_orientation" name="orientation" value="Landscape">
<option value="Landscape" selected>landscape</option> <option value="Landscape" selected>landscape</option>
<option value="Portrait" selected>portrait</option> <option value="Portrait" selected>portrait</option>
</select> </select>