feat: render to png + edits
This commit is contained in:
parent
947687345f
commit
dd53cce7f6
1 changed files with 120 additions and 20 deletions
110
src/main.rs
110
src/main.rs
|
@ -1,8 +1,13 @@
|
||||||
use std::{ffi::OsString, fs, net::TcpListener, process};
|
use std::{net::TcpListener, process, rc::Rc};
|
||||||
|
|
||||||
use ctrlc;
|
use ctrlc;
|
||||||
use http::responses::{Body, Response};
|
use http::responses::{Body, Response};
|
||||||
|
|
||||||
|
use resvg::{
|
||||||
|
tiny_skia::{Color, Pixmap, Transform},
|
||||||
|
usvg,
|
||||||
|
};
|
||||||
|
|
||||||
mod handlers;
|
mod handlers;
|
||||||
mod http;
|
mod http;
|
||||||
mod icons;
|
mod icons;
|
||||||
|
@ -19,10 +24,10 @@ fn main() {
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|_| fatal("Failed to set termination signal handler"));
|
.unwrap_or_else(|_| fatal("Failed to set termination signal handler"));
|
||||||
|
|
||||||
let icons = match icons::Icons::build() {
|
let icons_rc = Rc::new(match icons::Icons::build() {
|
||||||
Ok(icons) => icons,
|
Ok(icons) => icons,
|
||||||
Err(e) => fatal(e),
|
Err(e) => fatal(e),
|
||||||
};
|
});
|
||||||
|
|
||||||
let mut handlers = handlers::Handlers::new();
|
let mut handlers = handlers::Handlers::new();
|
||||||
|
|
||||||
|
@ -34,14 +39,16 @@ fn main() {
|
||||||
Response::new(req, 200, Body::Static("OK - luciders is running"))
|
Response::new(req, 200, Body::Static("OK - luciders is running"))
|
||||||
});
|
});
|
||||||
|
|
||||||
handlers.add_handler("/icons/[icon].svg", move |req| {
|
handlers.add_handler("/icons/[icon].svg", {
|
||||||
|
let icons = Rc::clone(&icons_rc);
|
||||||
|
move |req| {
|
||||||
if req.method != "GET" {
|
if req.method != "GET" {
|
||||||
return Response::new(req, 405, Body::Static("Method Not Allowed"));
|
return Response::new(req, 405, Body::Static("Method Not Allowed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let icon_filename = match req.url.get_path_segment(1) {
|
let icon_filename = match req.url.get_path_segment(1) {
|
||||||
Some(icon) => icon,
|
Some(icon) => icon,
|
||||||
None => return Response::new(req, 404, Body::Static("Icon Not Found")),
|
None => return Response::new(req, 404, Body::Static("Icon Segment Not Found")),
|
||||||
};
|
};
|
||||||
|
|
||||||
let icon_name = &icon_filename[..icon_filename.len() - icons::ICON_FILE_EXTENSION_LEN];
|
let icon_name = &icon_filename[..icon_filename.len() - icons::ICON_FILE_EXTENSION_LEN];
|
||||||
|
@ -56,6 +63,99 @@ fn main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return Response::new(req, 200, Body::Bytes(icon, "image/svg+xml"));
|
return Response::new(req, 200, Body::Bytes(icon, "image/svg+xml"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
handlers.add_handler("/icons/[icon].png", {
|
||||||
|
let icons = Rc::clone(&icons_rc);
|
||||||
|
move |req| {
|
||||||
|
if req.method != "GET" {
|
||||||
|
return Response::new(req, 405, Body::Static("Method Not Allowed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let icon_filename = match req.url.get_path_segment(1) {
|
||||||
|
Some(icon) => icon,
|
||||||
|
None => return Response::new(req, 404, Body::Static("Icon Segment Not Found")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let icon_name = &icon_filename[..icon_filename.len() - icons::ICON_FILE_EXTENSION_LEN];
|
||||||
|
|
||||||
|
if !icons.has_iconname(icon_name) {
|
||||||
|
return Response::new(req, 404, Body::Static("Icon Not Found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let icon = match icons.get_icon(icon_name) {
|
||||||
|
Some(icon) => icon,
|
||||||
|
None => return Response::new(req, 500, Body::Static("Failed to read icon")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let tree = match usvg::Tree::from_data(&icon, &usvg::Options::default()) {
|
||||||
|
Ok(tree) => tree,
|
||||||
|
Err(_) => {
|
||||||
|
return Response::new(req, 500, Body::Static("Failed to load icon into tree"))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Options handling
|
||||||
|
let mut scale = 1;
|
||||||
|
match req.url.query.get("scale") {
|
||||||
|
Some(scale_str) => {
|
||||||
|
match scale_str.parse::<u32>() {
|
||||||
|
Ok(scale_val) => {
|
||||||
|
if scale_val <= 0 || scale_val > 100 {
|
||||||
|
return Response::new(req, 400, Body::Static("Invalid scale value. Scale value must be an integer > 0 and <= 100"));
|
||||||
|
}
|
||||||
|
scale = scale_val;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return Response::new(req, 400, Body::Static("Invalid scale value. Scale value must be an integer > 0 and <= 100"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut padding = 0;
|
||||||
|
match req.url.query.get("padding") {
|
||||||
|
Some(padding_str) => {
|
||||||
|
match padding_str.parse::<u32>() {
|
||||||
|
Ok(padding_val) => {
|
||||||
|
if padding_val > 100 {
|
||||||
|
return Response::new(req, 400, Body::Static("Invalid padding value. Padding value must be an integer >= 0 and <= 100"));
|
||||||
|
}
|
||||||
|
|
||||||
|
padding = padding_val;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return Response::new(req, 400, Body::Static("Invalid padding value. Padding value must be an integer >= 0 and <= 100"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let length = 24 * scale + padding;
|
||||||
|
|
||||||
|
let mut pixmap = match Pixmap::new(length, length) {
|
||||||
|
Some(pixmap) => pixmap,
|
||||||
|
None => return Response::new(req, 500, Body::Static("Failed to create pixmap")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut pixmap_mut = pixmap.as_mut();
|
||||||
|
|
||||||
|
resvg::render(
|
||||||
|
&tree,
|
||||||
|
Transform::from_scale(scale as f32, scale as f32)
|
||||||
|
.post_concat(Transform::from_translate(length as f32 / 2.0 - 12.0 * scale as f32, length as f32 / 2.0 - 12.0 * scale as f32)),
|
||||||
|
&mut pixmap_mut,
|
||||||
|
);
|
||||||
|
let png = match pixmap.encode_png() {
|
||||||
|
Ok(png) => png,
|
||||||
|
Err(_) => return Response::new(req, 500, Body::Static("Failed to encode PNG")),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Response::new(req, 200, Body::Bytes(png, "image/png"));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
handlers.bind(listener);
|
handlers.bind(listener);
|
||||||
|
|
Loading…
Reference in a new issue