diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 89 |
1 files changed, 87 insertions, 2 deletions
diff --git a/src/main.rs b/src/main.rs index e7a11a9..235023a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,88 @@ -fn main() { - println!("Hello, world!"); +#[macro_use] +extern crate rocket; + +use quick_xml::events::BytesText; +use quick_xml::Writer; +use rocket::http::{ContentType, Status}; +use std::io; +use std::io::{Cursor, Write}; +use std::process::{Command, Stdio}; + +fn to_input_svg(text: &str) -> anyhow::Result<Vec<u8>> { + let mut writer = Writer::new(Cursor::new(vec![])); + writer + .create_element("svg") + .with_attribute(("xmlns", "http://www.w3.org/2000/svg")) + .write_inner_content(|writer| { + writer + .create_element("style") + .write_text_content(BytesText::new("text { font-family: 'linja pona'; }"))?; + writer + .create_element("text") + .write_text_content(BytesText::new(text))?; + Ok(()) + })?; + Ok(writer.into_inner().into_inner()) +} + +fn to_final_svg(text: &str) -> anyhow::Result<String> { + let input_svg = to_input_svg(text)?; + let mut inkscape_command = Command::new("inkscape") + .args([ + "--pipe", + "--export-type=svg", + "--export-area-drawing", + "--export-plain-svg", + "--export-text-to-path", + ]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn()?; + + inkscape_command + .stdin + .take() + .unwrap() + .write_all(&input_svg)?; + + let mut svgo_command = Command::new("svgo") + .args(["--config", "./svgo.config.js", "-"]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn()?; + + io::copy( + &mut inkscape_command.stdout.take().unwrap(), + &mut svgo_command.stdin.take().unwrap(), + )?; + + let inkscape_result = inkscape_command.wait()?; + assert!(inkscape_result.success()); + let svgo_result = svgo_command.wait_with_output()?; + assert!(svgo_result.status.success()); + let result = String::from_utf8(svgo_result.stdout)?; + Ok(result) +} + +#[get("/")] +fn index() -> &'static str { + "Hello, world!" +} + +#[get("/render/<text>")] +fn render(text: &str) -> Result<(ContentType, String), (Status, String)> { + match to_final_svg(text) { + Ok(svg) => Ok((ContentType::SVG, svg)), + Err(e) => Err((Status::InternalServerError, e.to_string())), + } +} + +#[rocket::main] +async fn main() -> Result<(), rocket::Error> { + let _rocket = rocket::build() + .mount("/", routes![index, render]) + .launch() + .await?; + + Ok(()) } |