diff --git a/editor.png b/editor.png index 93123d2..0609464 100644 Binary files a/editor.png and b/editor.png differ diff --git a/src/app.rs b/src/app.rs index df7f884..2cc1ff8 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,10 +1,9 @@ -use rusttype::Font; use image::{ImageBuffer, Rgba}; -use syntect::parsing::SyntaxSet; -use syntect::highlighting::{Theme, ThemeSet}; +use rusttype::Font; use std::path::Path; -use syntect::dumps::{from_binary}; - +use syntect::dumps::from_binary; +use syntect::highlighting::{Theme, ThemeSet}; +use syntect::parsing::SyntaxSet; pub struct AppState { pub pastes: String, @@ -15,14 +14,19 @@ pub struct AppState { } impl AppState { - pub fn new(pastes: String, base_img: ImageBuffer, Vec>, font: Font<'static>) -> Self { + pub fn new( + pastes: String, + base_img: ImageBuffer, Vec>, + font: Font<'static>, + ) -> Self { let theme_path = format!("{}/{}", &pastes, "TwoDark.tmTheme"); Self { pastes, base_img, font, syntaxes: from_binary::(include_bytes!("../assets/syntaxes.bin")), - highlight_theme: ThemeSet::get_theme(Path::new(&theme_path)).unwrap_or_else(|_| panic!("Couldn't load the TwoDark theme!")) + highlight_theme: ThemeSet::get_theme(Path::new(&theme_path)) + .unwrap_or_else(|_| panic!("Couldn't load the TwoDark theme!")), } } } diff --git a/src/consts.rs b/src/consts.rs index 7251704..aa11f5b 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,10 +1,8 @@ use rusttype::Scale; -pub const MARGINS: [i32; 18] = [ -/* 1 2 3 4 5 6 7 8 9 */ - 56, 87, 118, 150, 182, 214, 248, 281, 314, -/* 10 11 12 13 14 15 16 17 18 */ - 346, 379, 412, 445, 478, 511, 544, 576, 607 +pub const MARGINS: [i32; 33] = [ + 75, 91, 107, 123, 139, 155, 171, 187, 203, 219, 235, 251, 267, 283, 299, 315, 331, 347, 363, + 379, 395, 411, 427, 443, 459, 475, 491, 507, 523, 539, 555, 571, 587, ]; -pub const FONT_SCALE: Scale = Scale { x: 22., y: 22. }; +pub const FONT_SCALE: Scale = Scale { x: 16., y: 16. }; diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 1d584ad..43dfd1e 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1,9 +1,12 @@ use crate::{app::AppState, syntax}; -use tokio::task; use tokio::fs; +use tokio::task; - -async fn get_preview(state: &'static AppState, uuid: String, ext: Option) -> Result { +async fn get_preview( + state: &'static AppState, + uuid: String, + ext: Option, +) -> Result { let f = format!("{}/{}", &state.pastes, uuid); let code = fs::read_to_string(f).await.map_err(|_| warp::reject())?; @@ -14,16 +17,25 @@ async fn get_preview(state: &'static AppState, uuid: String, ext: Option Err(warp::reject()) } else { Ok(res.unwrap()) - } - }).await.map_err(|_| warp::reject())?; + }; + }) + .await + .map_err(|_| warp::reject())?; return rendered; } -pub async fn root_handler_known(state: &'static AppState, uuid: String, ext: String) -> Result { +pub async fn root_handler_known( + state: &'static AppState, + uuid: String, + ext: String, +) -> Result { get_preview(state, uuid, Some(ext)).await } -pub async fn root_handler(state: &'static AppState, uuid: String) -> Result { +pub async fn root_handler( + state: &'static AppState, + uuid: String, +) -> Result { get_preview(state, uuid, None).await } diff --git a/src/ipri.rs b/src/ipri.rs index 6263ac4..da937c6 100644 --- a/src/ipri.rs +++ b/src/ipri.rs @@ -1,10 +1,10 @@ -use rusttype::{point, Font, Scale}; -use std::cmp::max; use conv::ValueInto; use image::Pixel; use imageproc::definitions::Clamp; use imageproc::drawing::Canvas; use imageproc::pixelops::weighted_sum; +use rusttype::{point, Font, Scale}; +use std::cmp::max; // custom draw_text forked from improc pub fn draw_text_mut_w<'a, C>( @@ -15,7 +15,8 @@ pub fn draw_text_mut_w<'a, C>( scale: Scale, font: &'a Font<'a>, text: &'a str, -) -> i32 where +) -> i32 +where C: Canvas, ::Subpixel: ValueInto + Clamp, { diff --git a/src/main.rs b/src/main.rs index c5396a0..21b175c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,8 +8,8 @@ mod utils; use rusttype::Font; use warp::Filter; -use warp::http::header::{HeaderMap, HeaderValue}; use std::env; +use warp::http::header::{HeaderMap, HeaderValue}; #[tokio::main] async fn main() { @@ -23,10 +23,11 @@ async fn main() { png_header.insert("Content-type", HeaderValue::from_static("image/png")); let image = image::open(format!("{}/{}", arg, "editor.png")) - .expect("ERR No template image found at provided path") - .to_rgba8(); + .expect("ERR No template image found at provided path") + .to_rgba8(); - let font: Font<'static> = Font::try_from_bytes(include_bytes!("FiraCode-Retina.ttf") as &[u8]).unwrap(); + let font: Font<'static> = + Font::try_from_bytes(include_bytes!("FiraCode-Retina.ttf") as &[u8]).unwrap(); utils::init_state(arg, image, font); @@ -34,16 +35,20 @@ async fn main() { let p = warp::path("p"); let ap = utils::with_state() - .and(warp::path::param()) - .and_then(handlers::root_handler); + .and(warp::path::param()) + .and_then(handlers::root_handler); let pk = warp::path("pk"); let apk = utils::with_state() - .and(warp::path::param()) - .and(warp::path::param()) - .and_then(handlers::root_handler_known); - - warp::serve(p.and(ap).or(pk.and(apk)).with(warp::reply::with::headers(png_header))) - .run(([127, 0, 0, 1], 3030)) - .await; + .and(warp::path::param()) + .and(warp::path::param()) + .and_then(handlers::root_handler_known); + + warp::serve( + p.and(ap) + .or(pk.and(apk)) + .with(warp::reply::with::headers(png_header)), + ) + .run(([127, 0, 0, 1], 3030)) + .await; } diff --git a/src/syntax.rs b/src/syntax.rs index ec9002a..ad017de 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -1,26 +1,34 @@ -use crate::{ipri, utils, app::AppState, consts::{MARGINS, FONT_SCALE}}; +use crate::{ + app::AppState, + consts::{FONT_SCALE, MARGINS}, + ipri, utils, +}; +use image::Rgba; use syntect::easy::HighlightLines; use syntect::highlighting::Color; -use image::Rgba; fn to_rgba8(color: &Color) -> Rgba { Rgba::([color.r, color.g, color.b, color.a]) } -pub fn render_preview(state: &AppState, src: &str, ext: Option) -> Result, Box> { +pub fn render_preview( + state: &AppState, + src: &str, + ext: Option, +) -> Result, Box> { let syntax = ext .map(|e| state.syntaxes.find_syntax_by_extension(&e)) .flatten() .unwrap_or_else(|| &state.syntaxes.find_syntax_plain_text()); let mut h = HighlightLines::new(syntax, &state.highlight_theme); - let lines = src.split_inclusive("\n").take(18); + let lines = src.split_inclusive("\n").take(33); let mut img2 = state.base_img.clone(); for (i, line) in lines.enumerate() { let highlighted = h.highlight(&line, &state.syntaxes); - let mut w = 64; + let mut w = 40; for (style, chunk) in highlighted.iter() { let mut isspace = true; // whether the chunk is purely whitespace let mut sc = 0; // number of spaces in chunk @@ -43,11 +51,19 @@ pub fn render_preview(state: &AppState, src: &str, ext: Option) -> Resul }).collect(); if isspace { - w += utils::space_width()*sc; + w += utils::space_width() * sc; } else { - w += ipri::draw_text_mut_w(&mut img2, to_rgba8(&style.foreground), w, MARGINS[i], FONT_SCALE, &state.font, &c_string); + w += ipri::draw_text_mut_w( + &mut img2, + to_rgba8(&style.foreground), + w, + MARGINS[i], + FONT_SCALE, + &state.font, + &c_string, + ); let trailing_spaces = c_s - cindx - 1; - w += utils::space_width()*trailing_spaces as i32; // rusttype doesn't handle trailing spaces :| + w += utils::space_width() * trailing_spaces as i32; // rusttype doesn't handle trailing spaces :| } } } diff --git a/src/utils.rs b/src/utils.rs index b46d104..133069d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,33 +1,43 @@ use crate::{app::AppState, consts}; -use std::ops::Deref; -use image::{png::PngEncoder, ImageBuffer, Rgba, ImageError, Pixel}; +use image::{png::PngEncoder, ImageBuffer, ImageError, Pixel, Rgba}; use once_cell::sync::OnceCell; -use warp::Filter; use rusttype::{point, Font}; +use std::ops::Deref; +use warp::Filter; static STATE: OnceCell = OnceCell::new(); static SPACE_WIDTH: OnceCell = OnceCell::new(); - // rusttype can't rasterize spaces :| fn init_space_width(font: &Font<'static>) { let offset = point(0.0, font.v_metrics(consts::FONT_SCALE).ascent); let layout = font.layout(" r", consts::FONT_SCALE, offset); - let r = font.glyph('r').scaled(consts::FONT_SCALE).positioned(offset).pixel_bounding_box().unwrap().max.x; + let r = font + .glyph('r') + .scaled(consts::FONT_SCALE) + .positioned(offset) + .pixel_bounding_box() + .unwrap() + .max + .x; let width = layout.last().unwrap().pixel_bounding_box().unwrap().max.x - r; SPACE_WIDTH.set(width).ok().expect("INVALID INIT STATE!!"); } pub fn init_state(pastes: String, base_img: ImageBuffer, Vec>, font: Font<'static>) { init_space_width(&font); - STATE.set(AppState::new(pastes, base_img, font)).ok().expect("INVALID INIT STATE!!"); + STATE + .set(AppState::new(pastes, base_img, font)) + .ok() + .expect("INVALID INIT STATE!!"); } pub fn space_width() -> i32 { *SPACE_WIDTH.get().unwrap() } -pub fn with_state() -> impl Filter + Clone { +pub fn with_state( +) -> impl Filter + Clone { warp::any().map(|| STATE.get().expect("AppState not initialized!!!")) }