Project init : basic SVG rendering

This commit is contained in:
2023-06-16 19:52:56 -05:00
commit 08344b9af6
7 changed files with 1463 additions and 0 deletions

47
src/main.rs Normal file
View File

@@ -0,0 +1,47 @@
use std::net::SocketAddr;
use axum::{http::StatusCode, Json, response::IntoResponse, Router, routing::{get, post}};
use axum::body::{Bytes, Full};
use axum::extract::ConnectInfo;
use axum::http::header;
use axum::response::Response;
mod svg;
#[tokio::main]
async fn main() {
// initialize tracing
tracing_subscriber::fmt::init();
let app = Router::new()
.route("/", get(root));
// run our app with hyper
// `axum::Server` is a re-export of `hyper::Server`
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!("listening on {}", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service_with_connect_info::<SocketAddr>())
.await
.unwrap();
}
// basic handler that responds with a static string
async fn root(connect_info: ConnectInfo<SocketAddr>) -> impl IntoResponse {
let raw_image = svg::get();
if raw_image.is_err() {
return Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(Full::from(
format!("Internal Server Error :: {}", raw_image.err().unwrap())
))
.unwrap();
}
Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "image/x-png")
.body(Full::from(raw_image.unwrap()))
.unwrap()
}

50
src/svg.rs Normal file
View File

@@ -0,0 +1,50 @@
use png::EncodingError;
use resvg::{tiny_skia, usvg};
use resvg::usvg::{fontdb, TreeParsing, TreeTextToPath};
#[derive(Debug, Clone)]
pub struct RenderError {
pub message: Option<String>,
}
impl std::fmt::Display for RenderError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
if self.message.is_none() {
write!(f, "RenderError")
} else {
write!(f, "RenderError: {}", self.message.as_ref().unwrap())
}
}
}
pub fn get() -> Result<Vec<u8>, RenderError> {
let rtree = {
let mut opt = usvg::Options::default();
// Get file's absolute directory.
opt.resources_dir = std::fs::canonicalize("")
.ok()
.and_then(|p| p.parent().map(|p| p.to_path_buf()));
let mut fontdb = fontdb::Database::new();
fontdb.load_system_fonts();
let svg_data = std::fs::read("test.svg").unwrap();
// print bytes as string
println!("{:?}", String::from_utf8(svg_data.clone()).unwrap());
let mut tree_result = usvg::Tree::from_data(&svg_data, &opt);
if tree_result.is_err() { return Err(RenderError { message: Some("Failed to parse".to_string()) }); }
let tree = tree_result.as_mut().unwrap();
tree.convert_text(&fontdb);
resvg::Tree::from_usvg(&tree)
};
let pixmap_size = rtree.size.to_int_size();
let mut pixmap = tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height()).unwrap();
rtree.render(tiny_skia::Transform::default(), &mut pixmap.as_mut());
pixmap.encode_png().map_err(|_| RenderError { message: Some("Failed to encode".to_string()) })
}