diff --git a/Cargo.lock b/Cargo.lock index e3ce78d..2b26e50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -208,6 +208,26 @@ dependencies = [ "byteorder", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "either" version = "1.6.1" @@ -255,7 +275,18 @@ checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] @@ -552,6 +583,7 @@ name = "post_maker" version = "0.1.0" dependencies = [ "clap", + "dirs", "fltk", "fltk-theme", "image", @@ -616,7 +648,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom", + "getrandom 0.1.16", "libc", "rand_chacha", "rand_core", @@ -639,7 +671,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.16", ] [[package]] @@ -691,6 +723,25 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom 0.2.3", + "redox_syscall", +] + [[package]] name = "rulinalg" version = "0.4.2" @@ -827,6 +878,12 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + [[package]] name = "weezl" version = "0.1.5" diff --git a/Cargo.toml b/Cargo.toml index 858d42c..5ef5469 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,5 +15,4 @@ rusttype = "0.9" serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } lazy_static = "1.4" -# rust_decimal = "1.20" -# rust_decimal_macros = "1.20" +dirs = "4.0.0" diff --git a/imgs/75e253532946877dea6aaa5a60ffd51a.conf b/imgs/75e253532946877dea6aaa5a60ffd51a.conf index 3a1739d..5dba742 100644 --- a/imgs/75e253532946877dea6aaa5a60ffd51a.conf +++ b/imgs/75e253532946877dea6aaa5a60ffd51a.conf @@ -1 +1 @@ -{"path":"/home/piyush/Projects/post_maker/75e253532946877dea6aaa5a60ffd51a.jpg","dimension":[400.0,500.0],"original_dimension":[720.0,1280.0],"crop_position":[0.0,190.0],"quote":"wow!","tag":"","quote_position":853.3333333333334,"tag_position":853.3333333333334,"rgba":[25,29,34,190],"is_saved":false} \ No newline at end of file +{"path":"/home/piyush/Projects/post_maker/imgs/75e253532946877dea6aaa5a60ffd51a.jpg","dimension":[400.0,500.0],"original_dimension":[720.0,1280.0],"crop_position":[0.0,190.0],"quote":"wow!","tag":"@juzlilthings","quote_position":853.3333333333334,"tag_position":853.3333333333334,"rgba":[25,29,34,190],"is_saved":false} \ No newline at end of file diff --git a/imgs/export/75e253532946877dea6aaa5a60ffd51a.jpg b/imgs/export/75e253532946877dea6aaa5a60ffd51a.jpg new file mode 100644 index 0000000..1b06daa Binary files /dev/null and b/imgs/export/75e253532946877dea6aaa5a60ffd51a.jpg differ diff --git a/src/config.rs b/src/config.rs index 68565cb..3451846 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,8 @@ +use std::path::Path; + use clap::{ArgEnum, Parser}; use fltk_theme::ThemeType; +use serde::{Deserialize, Serialize}; /// Simple program calculate size of stuff in quote image #[derive(Parser, Debug)] @@ -55,6 +58,54 @@ impl Into for Themes { } } +#[derive(Debug, Serialize, Deserialize)] +pub struct ConfigFile { + pub quote_font_ttf: String, + pub tag_font_ttf: String, + pub quote_font_ratio: f64, + pub tag_font_ratio: f64, + pub color_layer: [u8; 4], +} + +impl Default for ConfigFile { + fn default() -> Self { + Self { + quote_font_ttf: String::new(), + tag_font_ttf: String::new(), + quote_font_ratio: 259.0, + tag_font_ratio: 96.0, + color_layer: [25, 29, 34, 190], + } + } +} + +impl ConfigFile { + pub(crate) fn load() -> Self { + let conf = match dirs::config_dir() { + Some(path) => path.join("post_maker.config"), + None => std::env::current_exe() + .unwrap() + .parent() + .unwrap() + .join("post_maker.config"), + }; + + if conf.exists() { + if let Ok(text) = std::fs::read_to_string(&conf) { + if let Ok(config) = serde_json::from_str::(&text) { + return config; + } + } + } + + let config = Self::default(); + if let Err(_) = std::fs::write(&conf, serde_json::to_string(&config).unwrap()) { + eprintln!("Can't write config!"); + } + config + } +} + pub(crate) fn config() -> Args { let args = Args::parse(); args diff --git a/src/draw_thread.rs b/src/draw_thread.rs index 3b56eee..79c4279 100644 --- a/src/draw_thread.rs +++ b/src/draw_thread.rs @@ -1,6 +1,7 @@ //! Thread to manage drawing in background use crate::{ + globals, main_window::{MainWindow, Page}, AppMessage, }; @@ -187,12 +188,11 @@ fn load_image( tag_position.set_range(0.0, prop.original_dimension.1); tag_position.set_value(prop.tag_position); - prop.rgba = [ - layer_red.value() as u8, - layer_green.value() as u8, - layer_blue.value() as u8, - layer_alpha.value() as u8, - ]; + layer_red.set_value(globals::CONFIG.color_layer[0] as f64); + layer_green.set_value(globals::CONFIG.color_layer[1] as f64); + layer_blue.set_value(globals::CONFIG.color_layer[2] as f64); + layer_alpha.set_value(globals::CONFIG.color_layer[3] as f64); + prop.rgba = globals::CONFIG.color_layer; match crop { Some((x, y)) => { diff --git a/src/globals.rs b/src/globals.rs new file mode 100644 index 0000000..ce20dcc --- /dev/null +++ b/src/globals.rs @@ -0,0 +1,31 @@ +use crate::config; +use lazy_static::lazy_static; +use rusttype::Font; +use std::io::Read; + +lazy_static! { + pub static ref CONFIG: config::ConfigFile = config::ConfigFile::load(); + pub static ref FONT_QUOTE: Font<'static> = { + let mut buffer = Vec::new(); + if let Ok(mut file) = std::fs::File::open(&CONFIG.quote_font_ttf) { + if let Ok(_) = file.read_to_end(&mut buffer) { + if let Some(out) = rusttype::Font::try_from_vec(buffer) { + return out; + } + } + } + rusttype::Font::try_from_vec(include_bytes!("../ReenieBeanie-Regular.ttf").to_vec()) + .unwrap() + }; + pub static ref FONT_TAG: Font<'static> = { + let mut buffer = Vec::new(); + if let Ok(mut file) = std::fs::File::open(&CONFIG.quote_font_ttf) { + if let Ok(_) = file.read_to_end(&mut buffer) { + if let Some(out) = rusttype::Font::try_from_vec(buffer) { + return out; + } + } + } + rusttype::Font::try_from_vec(include_bytes!("../Kalam-Regular.ttf").to_vec()).unwrap() + }; +} diff --git a/src/main.rs b/src/main.rs index 3a58993..44c1846 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,13 @@ mod config; mod crop_window; mod draw_thread; +mod globals; mod main_window; -mod properties; mod utils; // use crop_window::CropWindow; use fltk::{ app::{channel, App}, - enums::Font, prelude::*, }; use fltk_theme::WidgetTheme; @@ -31,10 +30,6 @@ fn main() { .into(), ) .apply(); - let f1 = Font::load_font("ReenieBeanie-Regular.ttf").unwrap(); - let f2 = Font::load_font("Kalam-Regular.ttf").unwrap(); - Font::set_font(Font::Times, &f1); - Font::set_font(Font::TimesItalic, &f2); let draw_buff: Arc>> = Arc::new(RwLock::new(vec![])); let (main_sender, main_receiver) = channel::(); diff --git a/src/properties.rs b/src/properties.rs deleted file mode 100644 index 05cdcf7..0000000 --- a/src/properties.rs +++ /dev/null @@ -1,22 +0,0 @@ -use lazy_static::lazy_static; -use rusttype::Font; -use std::io::Read; - -lazy_static! { - pub static ref FONT_QUOTE: Font<'static> = { - let mut buffer = Vec::new(); - std::fs::File::open("ReenieBeanie-Regular.ttf") - .unwrap() - .read_to_end(&mut buffer) - .unwrap(); - rusttype::Font::try_from_vec(buffer).unwrap() - }; - pub static ref FONT_TAG: Font<'static> = { - let mut buffer = Vec::new(); - std::fs::File::open("Kalam-Regular.ttf") - .unwrap() - .read_to_end(&mut buffer) - .unwrap(); - rusttype::Font::try_from_vec(buffer).unwrap() - }; -} diff --git a/src/utils.rs b/src/utils.rs index e9a5d2e..02f75d9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -7,7 +7,7 @@ use std::{ use image::{DynamicImage, GenericImageView, ImageBuffer}; use serde::{Deserialize, Serialize}; -use crate::properties; +use crate::globals; pub(crate) struct Coord(pub(crate) f64, pub(crate) f64); @@ -128,55 +128,64 @@ impl ImageContainer { pub(crate) fn recalc(&mut self) { let prop = self.properties.read().unwrap(); let mut tmp = self.image.clone(); - let (width, height): (f64, f64) = Coord::from(tmp.dimensions()).into(); - let layer = - DynamicImage::ImageRgba8(ImageBuffer::from_fn(width as u32, height as u32, |_, _| { - image::Rgba(prop.rgba) - })); - image::imageops::overlay(&mut tmp, &layer, 0, 0); + draw_layer_and_text( + &mut tmp, + &prop.rgba, + &prop.quote, + prop.quote_position, + &prop.tag, + prop.tag_position, + prop.original_dimension.1, + ); - let size = quote_from_height(height); - for (index, line) in prop.quote.lines().enumerate() { - let (text_width, text_height) = measure_line( - &properties::FONT_QUOTE, - line, - rusttype::Scale::uniform(size as f32), - ); + // let layer = + // DynamicImage::ImageRgba8(ImageBuffer::from_fn(width as u32, height as u32, |_, _| { + // image::Rgba(prop.rgba) + // })); + // image::imageops::overlay(&mut tmp, &layer, 0, 0); - imageproc::drawing::draw_text_mut( - &mut tmp, - image::Rgba([255, 255, 255, 255]), - ((width - text_width) / 2.0) as u32, - ((prop.quote_position * height) / prop.original_dimension.1 - + (text_height / 2.0) - + index as f64 * (text_height * 1.2)) as u32, - rusttype::Scale::uniform(size as f32), - &properties::FONT_QUOTE, - line, - ); - } + // let size = quote_from_height(height); + // for (index, line) in prop.quote.lines().enumerate() { + // let (text_width, text_height) = measure_line( + // &globals::FONT_QUOTE, + // line, + // rusttype::Scale::uniform(size as f32), + // ); - let size = tag_from_height(height); - for (index, line) in prop.tag.lines().enumerate() { - let (text_width, text_height) = measure_line( - &properties::FONT_TAG, - line, - rusttype::Scale::uniform(size as f32), - ); + // imageproc::drawing::draw_text_mut( + // &mut tmp, + // image::Rgba([255, 255, 255, 255]), + // ((width - text_width) / 2.0) as u32, + // ((prop.quote_position * height) / prop.original_dimension.1 + // + (text_height / 2.0) + // + index as f64 * (text_height * 1.2)) as u32, + // rusttype::Scale::uniform(size as f32), + // &globals::FONT_QUOTE, + // line, + // ); + // } - imageproc::drawing::draw_text_mut( - &mut tmp, - image::Rgba([255, 255, 255, 255]), - (width * 0.99 - text_width) as u32, - ((prop.tag_position * height) / prop.original_dimension.1 - + (text_height / 2.0) - + index as f64 * (text_height * 1.2)) as u32, - rusttype::Scale::uniform(size as f32), - &properties::FONT_TAG, - line, - ); - } + // let size = tag_from_height(height); + // for (index, line) in prop.tag.lines().enumerate() { + // let (text_width, text_height) = measure_line( + // &globals::FONT_TAG, + // line, + // rusttype::Scale::uniform(size as f32), + // ); + + // imageproc::drawing::draw_text_mut( + // &mut tmp, + // image::Rgba([255, 255, 255, 255]), + // (width * 0.99 - text_width) as u32, + // ((prop.tag_position * height) / prop.original_dimension.1 + // + (text_height / 2.0) + // + index as f64 * (text_height * 1.2)) as u32, + // rusttype::Scale::uniform(size as f32), + // &globals::FONT_TAG, + // line, + // ); + // } self.buffer = tmp; } @@ -208,54 +217,64 @@ impl ImageContainer { crop_height as u32, ); - let layer = DynamicImage::ImageRgba8(ImageBuffer::from_fn( - crop_width as u32, - crop_height as u32, - |_, _| image::Rgba(prop.rgba), - )); - image::imageops::overlay(&mut img, &layer, 0, 0); + draw_layer_and_text( + &mut img, + &prop.rgba, + &prop.quote, + prop.quote_position, + &prop.tag, + prop.tag_position, + prop.original_dimension.1, + ); - let size = quote_from_height(crop_height); - for (index, line) in prop.quote.lines().enumerate() { - let (text_width, text_height) = measure_line( - &properties::FONT_QUOTE, - line, - rusttype::Scale::uniform(size as f32), - ); + // let layer = DynamicImage::ImageRgba8(ImageBuffer::from_fn( + // crop_width as u32, + // crop_height as u32, + // |_, _| image::Rgba(prop.rgba), + // )); + // image::imageops::overlay(&mut img, &layer, 0, 0); - imageproc::drawing::draw_text_mut( - &mut img, - image::Rgba([255, 255, 255, 255]), - ((crop_width - text_width) / 2.0) as u32, - ((prop.quote_position * crop_height) / prop.original_dimension.1 - + (text_height / 2.0) - + index as f64 * (text_height * 1.2)) as u32, - rusttype::Scale::uniform(size as f32), - &properties::FONT_QUOTE, - line, - ); - } + // let size = quote_from_height(crop_height); + // for (index, line) in prop.quote.lines().enumerate() { + // let (text_width, text_height) = measure_line( + // &globals::FONT_QUOTE, + // line, + // rusttype::Scale::uniform(size as f32), + // ); - let size = tag_from_height(crop_height); - for (index, line) in prop.tag.lines().enumerate() { - let (text_width, text_height) = measure_line( - &properties::FONT_TAG, - line, - rusttype::Scale::uniform(size as f32), - ); + // imageproc::drawing::draw_text_mut( + // &mut img, + // image::Rgba([255, 255, 255, 255]), + // ((crop_width - text_width) / 2.0) as u32, + // ((prop.quote_position * crop_height) / prop.original_dimension.1 + // + (text_height / 2.0) + // + index as f64 * (text_height * 1.2)) as u32, + // rusttype::Scale::uniform(size as f32), + // &globals::FONT_QUOTE, + // line, + // ); + // } - imageproc::drawing::draw_text_mut( - &mut img, - image::Rgba([255, 255, 255, 255]), - (crop_width * 0.99 - text_width) as u32, - ((prop.tag_position * crop_height) / prop.original_dimension.1 - + (text_height / 2.0) - + index as f64 * (text_height * 1.2)) as u32, - rusttype::Scale::uniform(size as f32), - &properties::FONT_TAG, - line, - ); - } + // let size = tag_from_height(crop_height); + // for (index, line) in prop.tag.lines().enumerate() { + // let (text_width, text_height) = measure_line( + // &globals::FONT_TAG, + // line, + // rusttype::Scale::uniform(size as f32), + // ); + + // imageproc::drawing::draw_text_mut( + // &mut img, + // image::Rgba([255, 255, 255, 255]), + // (crop_width * 0.99 - text_width) as u32, + // ((prop.tag_position * crop_height) / prop.original_dimension.1 + // + (text_height / 2.0) + // + index as f64 * (text_height * 1.2)) as u32, + // rusttype::Scale::uniform(size as f32), + // &globals::FONT_TAG, + // line, + // ); + // } image::save_buffer( export, @@ -299,6 +318,65 @@ impl ImageProperties { } } +fn draw_layer_and_text( + tmp: &mut DynamicImage, + rgba: &[u8; 4], + quote: &str, + quote_position: f64, + tag: &str, + tag_position: f64, + original_height: f64, +) { + let (width, height): (f64, f64) = Coord::from(tmp.dimensions()).into(); + let layer = + DynamicImage::ImageRgba8(ImageBuffer::from_fn(width as u32, height as u32, |_, _| { + image::Rgba(rgba.to_owned()) + })); + image::imageops::overlay(tmp, &layer, 0, 0); + + let size = quote_from_height(height); + for (index, line) in quote.lines().enumerate() { + let (text_width, text_height) = measure_line( + &globals::FONT_QUOTE, + line, + rusttype::Scale::uniform(size as f32), + ); + + imageproc::drawing::draw_text_mut( + tmp, + image::Rgba([255, 255, 255, 255]), + ((width - text_width) / 2.0) as u32, + ((quote_position * height) / original_height + + (text_height / 2.0) + + index as f64 * (text_height * 1.2)) as u32, + rusttype::Scale::uniform(size as f32), + &globals::FONT_QUOTE, + line, + ); + } + + let size = tag_from_height(height); + for (index, line) in tag.lines().enumerate() { + let (text_width, text_height) = measure_line( + &globals::FONT_TAG, + line, + rusttype::Scale::uniform(size as f32), + ); + + imageproc::drawing::draw_text_mut( + tmp, + image::Rgba([255, 255, 255, 255]), + (width * 0.99 - text_width) as u32, + ((tag_position * height) / original_height + + (text_height / 2.0) + + index as f64 * (text_height * 1.2)) as u32, + rusttype::Scale::uniform(size as f32), + &globals::FONT_TAG, + line, + ); + } +} + pub(crate) fn get_4_5(width: f64, height: f64) -> (f64, f64) { if width > width_from_height(height) { (width_from_height(height), height) @@ -316,11 +394,11 @@ pub(crate) fn height_from_width(width: f64) -> f64 { } pub(crate) fn quote_from_height(height: f64) -> f64 { - (height * 60.0) / 1350.0 + (height * globals::CONFIG.quote_font_ratio) / 5000.0 } pub(crate) fn tag_from_height(height: f64) -> f64 { - (height * 50.0) / 1350.0 + (height * globals::CONFIG.tag_font_ratio) / 5000.0 } pub(crate) fn measure_line(