* Added support for blured box around quotes

* Removed useless ttf and added opensans
* Cleaned global and grouped all fonts together in one function
This commit is contained in:
Piyush मिश्रः 2022-08-17 20:00:26 +05:30
parent 55d394380d
commit 90d72f9d4e
12 changed files with 475 additions and 296 deletions

470
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package] [package]
name = "post_maker" name = "post_maker"
version = "0.5.0-alpha.1" version = "0.6.0-alpha.1"
edition = "2021" edition = "2021"
description = "Post Maker helps you to make post for Instagram and other Social Media apps easily." description = "Post Maker helps you to make post for Instagram and other Social Media apps easily."
authors = ["PiyushXCoder <https://piyushxcoder.in>"] authors = ["PiyushXCoder <https://piyushxcoder.in>"]

BIN
assets/OpenSans-Regular.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -132,6 +132,7 @@ pub(crate) struct ConfigFile {
pub(crate) color_layer: [u8; 4], pub(crate) color_layer: [u8; 4],
pub(crate) minimum_width_limit: f64, // for export of image pub(crate) minimum_width_limit: f64, // for export of image
pub(crate) maximum_width_limit: f64, // for export of image pub(crate) maximum_width_limit: f64, // for export of image
pub(crate) draw_box_around_quote: bool,
pub(crate) image_format: ImageType, pub(crate) image_format: ImageType,
} }
@ -155,10 +156,11 @@ impl Default for ConfigFile {
tag_y_position_ratio: 0.5, tag_y_position_ratio: 0.5,
tag2_position_ratio: 0.95, tag2_position_ratio: 0.95,
image_ratio: (4.0, 5.0), image_ratio: (4.0, 5.0),
color_layer: [20, 22, 25, 197], color_layer: [20, 22, 25, 80],
minimum_width_limit: 650.0, minimum_width_limit: 650.0,
maximum_width_limit: 1080.0, maximum_width_limit: 1080.0,
image_format: ImageType::Png, draw_box_around_quote: true,
image_format: ImageType::Jpeg,
} }
} }
} }

View File

@ -23,7 +23,7 @@ use crate::{
use fltk::{ use fltk::{
app, app,
browser::{Browser, BrowserType}, browser::{Browser, BrowserType},
button::{Button, RadioRoundButton}, button::{Button, CheckButton, RadioRoundButton},
dialog::{FileDialogOptions, NativeFileChooser}, dialog::{FileDialogOptions, NativeFileChooser},
enums::{self, Align, Event, Font}, enums::{self, Align, Event, Font},
frame::Frame, frame::Frame,
@ -65,6 +65,7 @@ pub(crate) struct ConfigWindow {
pub(crate) tag2_position_ratio: ValueInput, pub(crate) tag2_position_ratio: ValueInput,
pub(crate) image_ratio_width: ValueInput, pub(crate) image_ratio_width: ValueInput,
pub(crate) image_ratio_height: ValueInput, pub(crate) image_ratio_height: ValueInput,
pub(crate) draw_box_around_quote: CheckButton,
pub(crate) minimum_width_limit: ValueInput, pub(crate) minimum_width_limit: ValueInput,
pub(crate) maximum_width_limit: ValueInput, pub(crate) maximum_width_limit: ValueInput,
/// RGB value of top translucent layer /// RGB value of top translucent layer
@ -389,6 +390,18 @@ impl ConfigWindow {
image_ratio_grp.end(); image_ratio_grp.end();
col.set_size(&image_ratio_grp, 30); col.set_size(&image_ratio_grp, 30);
// Draw box around Quote
let mut label = Frame::default().with_label("Draw Box:");
label.set_label_font(enums::Font::HelveticaBold);
col.set_size(&label, 15);
let mut draw_box_around_quote_flex = Flex::default().row();
draw_box_around_quote_flex.set_size(&Frame::default(), 20);
let mut draw_box_around_quote = CheckButton::default().with_label("Draw box around text");
draw_box_around_quote.set_value(true);
draw_box_around_quote_flex.end();
col.set_size(&draw_box_around_quote_flex, 30);
let mut label = Frame::default().with_label("Image with limits:"); let mut label = Frame::default().with_label("Image with limits:");
label.set_label_font(enums::Font::HelveticaBold); label.set_label_font(enums::Font::HelveticaBold);
col.set_size(&label, 15); col.set_size(&label, 15);
@ -505,6 +518,7 @@ impl ConfigWindow {
tag2_position_ratio, tag2_position_ratio,
image_ratio_width, image_ratio_width,
image_ratio_height, image_ratio_height,
draw_box_around_quote,
minimum_width_limit, minimum_width_limit,
maximum_width_limit, maximum_width_limit,
translucent_layer_rgb, translucent_layer_rgb,
@ -561,6 +575,8 @@ impl ConfigWindow {
.set_value(config.tag2_position_ratio); .set_value(config.tag2_position_ratio);
self.image_ratio_width.set_value(config.image_ratio.0); self.image_ratio_width.set_value(config.image_ratio.0);
self.image_ratio_height.set_value(config.image_ratio.1); self.image_ratio_height.set_value(config.image_ratio.1);
self.draw_box_around_quote
.set_checked(config.draw_box_around_quote);
self.minimum_width_limit self.minimum_width_limit
.set_value(config.minimum_width_limit); .set_value(config.minimum_width_limit);
self.maximum_width_limit self.maximum_width_limit
@ -611,6 +627,7 @@ impl ConfigWindow {
let mut tag2_position_ratio = self.tag2_position_ratio.clone(); let mut tag2_position_ratio = self.tag2_position_ratio.clone();
let mut image_ratio_width = self.image_ratio_width.clone(); let mut image_ratio_width = self.image_ratio_width.clone();
let mut image_ratio_height = self.image_ratio_height.clone(); let mut image_ratio_height = self.image_ratio_height.clone();
let draw_box_around_quote = self.draw_box_around_quote.clone();
let mut minimum_width_limit = self.minimum_width_limit.clone(); let mut minimum_width_limit = self.minimum_width_limit.clone();
let mut maximum_width_limit = self.maximum_width_limit.clone(); let mut maximum_width_limit = self.maximum_width_limit.clone();
let mut layer_rgb = self.translucent_layer_rgb.clone(); let mut layer_rgb = self.translucent_layer_rgb.clone();
@ -657,6 +674,7 @@ impl ConfigWindow {
tag2_position_ratio.set_value(conf.tag2_position_ratio); tag2_position_ratio.set_value(conf.tag2_position_ratio);
image_ratio_width.set_value(conf.image_ratio.0); image_ratio_width.set_value(conf.image_ratio.0);
image_ratio_height.set_value(conf.image_ratio.1); image_ratio_height.set_value(conf.image_ratio.1);
draw_box_around_quote.set_checked(conf.draw_box_around_quote);
minimum_width_limit.set_value(conf.minimum_width_limit); minimum_width_limit.set_value(conf.minimum_width_limit);
maximum_width_limit.set_value(conf.maximum_width_limit); maximum_width_limit.set_value(conf.maximum_width_limit);
utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb); utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb);
@ -687,6 +705,7 @@ impl ConfigWindow {
let mut tag2_position_ratio = self.tag2_position_ratio.clone(); let mut tag2_position_ratio = self.tag2_position_ratio.clone();
let mut image_ratio_width = self.image_ratio_width.clone(); let mut image_ratio_width = self.image_ratio_width.clone();
let mut image_ratio_height = self.image_ratio_height.clone(); let mut image_ratio_height = self.image_ratio_height.clone();
let draw_box_around_quote = self.draw_box_around_quote.clone();
let mut minimum_width_limit = self.minimum_width_limit.clone(); let mut minimum_width_limit = self.minimum_width_limit.clone();
let mut maximum_width_limit = self.maximum_width_limit.clone(); let mut maximum_width_limit = self.maximum_width_limit.clone();
let mut layer_rgb = self.translucent_layer_rgb.clone(); let mut layer_rgb = self.translucent_layer_rgb.clone();
@ -732,6 +751,7 @@ impl ConfigWindow {
tag2_position_ratio.set_value(conf.tag2_position_ratio); tag2_position_ratio.set_value(conf.tag2_position_ratio);
image_ratio_width.set_value(conf.image_ratio.0); image_ratio_width.set_value(conf.image_ratio.0);
image_ratio_height.set_value(conf.image_ratio.1); image_ratio_height.set_value(conf.image_ratio.1);
draw_box_around_quote.set_checked(conf.draw_box_around_quote);
minimum_width_limit.set_value(conf.minimum_width_limit); minimum_width_limit.set_value(conf.minimum_width_limit);
maximum_width_limit.set_value(conf.maximum_width_limit); maximum_width_limit.set_value(conf.maximum_width_limit);
utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb); utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb);
@ -759,6 +779,7 @@ impl ConfigWindow {
let mut tag2_position_ratio = self.tag2_position_ratio.clone(); let mut tag2_position_ratio = self.tag2_position_ratio.clone();
let mut image_ratio_width = self.image_ratio_width.clone(); let mut image_ratio_width = self.image_ratio_width.clone();
let mut image_ratio_height = self.image_ratio_height.clone(); let mut image_ratio_height = self.image_ratio_height.clone();
let draw_box_around_quote = self.draw_box_around_quote.clone();
let mut minimum_width_limit = self.minimum_width_limit.clone(); let mut minimum_width_limit = self.minimum_width_limit.clone();
let mut maximum_width_limit = self.maximum_width_limit.clone(); let mut maximum_width_limit = self.maximum_width_limit.clone();
let mut layer_rgb = self.translucent_layer_rgb.clone(); let mut layer_rgb = self.translucent_layer_rgb.clone();
@ -794,6 +815,7 @@ impl ConfigWindow {
tag2_position_ratio.set_value(conf.tag2_position_ratio); tag2_position_ratio.set_value(conf.tag2_position_ratio);
image_ratio_width.set_value(conf.image_ratio.0); image_ratio_width.set_value(conf.image_ratio.0);
image_ratio_height.set_value(conf.image_ratio.1); image_ratio_height.set_value(conf.image_ratio.1);
draw_box_around_quote.set_checked(conf.draw_box_around_quote);
minimum_width_limit.set_value(conf.minimum_width_limit); minimum_width_limit.set_value(conf.minimum_width_limit);
maximum_width_limit.set_value(conf.maximum_width_limit); maximum_width_limit.set_value(conf.maximum_width_limit);
utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb); utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb);
@ -1108,6 +1130,18 @@ impl ConfigWindow {
true true
}); });
let browse = self.browse.clone();
let configs = Rc::clone(&self.configs);
self.draw_box_around_quote.handle(move |f, _| {
if let Some(conf) = configs
.borrow_mut()
.get_mut(&browse.selected_text().unwrap())
{
conf.draw_box_around_quote = f.value();
}
true
});
// Minimum Width Limit // Minimum Width Limit
let browse = self.browse.clone(); let browse = self.browse.clone();
let configs = Rc::clone(&self.configs); let configs = Rc::clone(&self.configs);
@ -1225,6 +1259,7 @@ impl ConfigWindow {
let mut tag2_position_ratio = self.tag2_position_ratio.clone(); let mut tag2_position_ratio = self.tag2_position_ratio.clone();
let mut image_ratio_width = self.image_ratio_width.clone(); let mut image_ratio_width = self.image_ratio_width.clone();
let mut image_ratio_height = self.image_ratio_height.clone(); let mut image_ratio_height = self.image_ratio_height.clone();
let draw_box_around_quote = self.draw_box_around_quote.clone();
let mut minimum_width_limit = self.minimum_width_limit.clone(); let mut minimum_width_limit = self.minimum_width_limit.clone();
let mut maximum_width_limit = self.maximum_width_limit.clone(); let mut maximum_width_limit = self.maximum_width_limit.clone();
let mut layer_rgb = self.translucent_layer_rgb.clone(); let mut layer_rgb = self.translucent_layer_rgb.clone();
@ -1253,13 +1288,23 @@ impl ConfigWindow {
tag2_position_ratio.set_value(conf.tag2_position_ratio); tag2_position_ratio.set_value(conf.tag2_position_ratio);
image_ratio_width.set_value(conf.image_ratio.0); image_ratio_width.set_value(conf.image_ratio.0);
image_ratio_height.set_value(conf.image_ratio.1); image_ratio_height.set_value(conf.image_ratio.1);
draw_box_around_quote.set_checked(conf.draw_box_around_quote);
minimum_width_limit.set_value(conf.minimum_width_limit); minimum_width_limit.set_value(conf.minimum_width_limit);
maximum_width_limit.set_value(conf.maximum_width_limit); maximum_width_limit.set_value(conf.maximum_width_limit);
utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb); utils::set_color_btn_rgba(conf.color_layer, &mut layer_rgb);
layer_rgb.redraw(); layer_rgb.redraw();
layer_alpha.set_value(conf.color_layer[3] as f64); layer_alpha.set_value(conf.color_layer[3] as f64);
match conf.image_format {
ImageType::Png => {
png_format.set_value(true); png_format.set_value(true);
jpeg_format.set_value(false); jpeg_format.set_value(false);
}
ImageType::Jpeg => {
png_format.set_value(false);
jpeg_format.set_value(true);
}
_ => {}
}
configs configs
.borrow_mut() .borrow_mut()
.insert(browse.selected_text().unwrap(), conf); .insert(browse.selected_text().unwrap(), conf);

View File

@ -18,5 +18,5 @@ pub(crate) fn message_default(txt: &str) {
pub(crate) fn choice_default(txt: &str, b0: &str, b1: &str) -> i32 { pub(crate) fn choice_default(txt: &str, b0: &str, b1: &str) -> i32 {
let (x, y) = get_mouse(); let (x, y) = get_mouse();
dialog::choice(x, y, txt, b0, b1, "") dialog::choice2(x, y, txt, b0, b1, "").unwrap_or(-1)
} }

View File

@ -33,85 +33,19 @@ lazy_static! {
pub(crate) static ref MAIN_SENDER: RwLock<Option<fltk::app::Sender<crate::AppMessage>>> = RwLock::new(None); pub(crate) static ref MAIN_SENDER: RwLock<Option<fltk::app::Sender<crate::AppMessage>>> = RwLock::new(None);
/// TTF Font for Quote /// TTF Font for Quote
pub(crate) static ref FONT_QUOTE: Font<'static> = { pub(crate) static ref FONT_QUOTE: Font<'static> = load_font(rw_read!(CONFIG).quote_font.as_str());
let mut buffer = Vec::new();
if let Ok(mut file) = std::fs::File::open(rw_read!(CONFIG).quote_font.as_str()) {
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!("../assets/fonts/ReenieBeanie-Regular.ttf").to_vec(),
)
.unwrap()
};
/// TTF Font for Subquote /// TTF Font for Subquote
pub(crate) static ref FONT_SUBQUOTE: Font<'static> = { pub(crate) static ref FONT_SUBQUOTE: Font<'static> = load_font(rw_read!(CONFIG).subquote_font.as_str());
let mut buffer = Vec::new();
if let Ok(mut file) = std::fs::File::open(rw_read!(CONFIG).subquote_font.as_str())
{
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!("../assets/fonts/ReenieBeanie-Regular.ttf").to_vec(),
)
.unwrap()
};
/// TTF Font for Subquote 2 /// TTF Font for Subquote 2
pub(crate) static ref FONT_SUBQUOTE2: Font<'static> = { pub(crate) static ref FONT_SUBQUOTE2: Font<'static> = load_font(rw_read!(CONFIG).subquote2_font.as_str());
let mut buffer = Vec::new();
if let Ok(mut file) =
std::fs::File::open(rw_read!(CONFIG).subquote2_font.as_str())
{
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!("../assets/fonts/Rajdhani-Regular.ttf").to_vec(),
)
.unwrap()
};
/// TTF Font for Tag /// TTF Font for Tag
pub(crate) static ref FONT_TAG: Font<'static> = { pub(crate) static ref FONT_TAG: Font<'static> = load_font(rw_read!(CONFIG).tag_font.as_str());
let mut buffer = Vec::new();
if let Ok(mut file) = std::fs::File::open(&rw_read!(CONFIG).tag_font.as_str()) {
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!("../assets/fonts/Kalam-Regular.ttf").to_vec())
.unwrap()
};
/// TTF Font for Tag 2 /// TTF Font for Tag 2
pub(crate) static ref FONT_TAG2: Font<'static> = { pub(crate) static ref FONT_TAG2: Font<'static> = load_font(rw_read!(CONFIG).tag2_font.as_str());
let mut buffer = Vec::new();
if let Ok(mut file) = std::fs::File::open(&rw_read!(CONFIG).tag2_font.as_str()) {
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!("../assets/fonts/Rajdhani-Regular.ttf").to_vec(),
)
.unwrap()
};
/// Image to use for Window /// Image to use for Window
pub(crate) static ref ICON: OsString = include_str!("../assets/icon.svg").into(); pub(crate) static ref ICON: OsString = include_str!("../assets/icon.svg").into();
@ -128,3 +62,15 @@ lazy_static! {
img.into() img.into()
}; };
} }
fn load_font(path: &str) -> Font<'static> {
let mut buffer = Vec::new();
if let Ok(mut file) = std::fs::File::open(path) {
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!("../assets/OpenSans-Regular.ttf").to_vec()).unwrap()
}

View File

@ -777,8 +777,8 @@ impl MainWindow {
self.next_btn.set_callback(move |_| { self.next_btn.set_callback(move |_| {
let prop = rw_read!(properties); let prop = rw_read!(properties);
if !prop.is_saved { if !prop.is_saved {
let save = fltk::dialog::choice_default("Save?", "yes", "no", "cancel"); let save = fltk::dialog::choice2_default("Save?", "yes", "no", "cancel");
match save { match save.unwrap_or(-1) {
0 => sender.send_it(DrawMessage::Save), 0 => sender.send_it(DrawMessage::Save),
1 => {} 1 => {}
_ => return, _ => return,
@ -801,8 +801,8 @@ impl MainWindow {
self.back_btn.set_callback(move |_| { self.back_btn.set_callback(move |_| {
let prop = rw_read!(properties); let prop = rw_read!(properties);
if !prop.is_saved { if !prop.is_saved {
let save = fltk::dialog::choice_default("Save?", "yes", "no", "cancel"); let save = fltk::dialog::choice2_default("Save?", "yes", "no", "cancel");
match save { match save.unwrap_or(-1) {
0 => sender.send_it(DrawMessage::Save), 0 => sender.send_it(DrawMessage::Save),
1 => {} 1 => {}
_ => return, _ => return,
@ -824,8 +824,8 @@ impl MainWindow {
self.file_choice.set_callback(move |_| { self.file_choice.set_callback(move |_| {
let prop = rw_read!(properties); let prop = rw_read!(properties);
if !prop.is_saved { if !prop.is_saved {
let save = fltk::dialog::choice_default("Save?", "yes", "no", "cancel"); let save = fltk::dialog::choice2_default("Save?", "yes", "no", "cancel");
match save { match save.unwrap_or(-1) {
0 => sender.send_it(DrawMessage::Save), 0 => sender.send_it(DrawMessage::Save),
1 => {} 1 => {}
_ => return, _ => return,

View File

@ -20,7 +20,8 @@ use std::{
}; };
use fltk::{button::Button, enums, prelude::*}; use fltk::{button::Button, enums, prelude::*};
use image::{DynamicImage, GenericImageView, ImageBuffer, ImageEncoder}; use image::{DynamicImage, GenericImageView, ImageBuffer, ImageEncoder, Pixel};
use imageproc::rect::Rect;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::globals; use crate::globals;
@ -211,6 +212,7 @@ impl ImageContainer {
&prop.tag2, &prop.tag2,
prop.tag_position, prop.tag_position,
prop.tag2_position, prop.tag2_position,
prop.original_dimension.0,
prop.original_dimension.1, prop.original_dimension.1,
); );
@ -275,6 +277,7 @@ impl ImageContainer {
&prop.tag2, &prop.tag2,
prop.tag_position, prop.tag_position,
prop.tag2_position, prop.tag2_position,
prop.original_dimension.0,
prop.original_dimension.1, prop.original_dimension.1,
); );
@ -571,6 +574,7 @@ fn draw_layer_and_text(
tag2: &str, tag2: &str,
tag_y_position: f64, tag_y_position: f64,
tag2_position: f64, tag2_position: f64,
original_width: f64,
original_height: f64, original_height: f64,
) { ) {
let (width, height): (f64, f64) = Coord::from(tmp.dimensions()).into(); let (width, height): (f64, f64) = Coord::from(tmp.dimensions()).into();
@ -586,16 +590,21 @@ fn draw_layer_and_text(
&globals::FONT_QUOTE, &globals::FONT_QUOTE,
size, size,
quote_position, quote_position,
original_width,
original_height, original_height,
true,
quote, quote,
); );
let size = subquote_from_height(height); let size = subquote_from_height(height);
draw_multiline_mid_string( draw_multiline_mid_string(
tmp, tmp,
&globals::FONT_SUBQUOTE, &globals::FONT_SUBQUOTE,
size, size,
subquote_position, subquote_position,
original_width,
original_height, original_height,
true,
subquote, subquote,
); );
let size = subquote2_from_height(height); let size = subquote2_from_height(height);
@ -604,7 +613,9 @@ fn draw_layer_and_text(
&globals::FONT_SUBQUOTE2, &globals::FONT_SUBQUOTE2,
size, size,
subquote2_position, subquote2_position,
original_width,
original_height, original_height,
true,
subquote2, subquote2,
); );
@ -614,7 +625,9 @@ fn draw_layer_and_text(
&globals::FONT_TAG2, &globals::FONT_TAG2,
size, size,
tag2_position, tag2_position,
original_width,
original_height, original_height,
false,
tag2, tag2,
); );
@ -645,24 +658,137 @@ pub(crate) fn draw_multiline_mid_string(
font: &rusttype::Font, font: &rusttype::Font,
size: f64, size: f64,
position: f64, position: f64,
original_width: f64,
original_height: f64, original_height: f64,
boxed: bool,
text: &str, text: &str,
) { ) {
let (mut box_width, mut box_height) = (0.0, 0.0);
let (width, height): (f64, f64) = Coord::from(tmp.dimensions()).into(); let (width, height): (f64, f64) = Coord::from(tmp.dimensions()).into();
for (index, line) in text.lines().enumerate() { for (index, line) in text.lines().enumerate() {
let (text_width, text_height) = let (text_width, text_height) =
measure_line(font, line, rusttype::Scale::uniform(size as f32)); measure_line(font, line, rusttype::Scale::uniform(size as f32));
if text_width > box_width {
box_width = text_width;
}
box_height += text_height * 1.15;
let (x, y) = (
(width - text_width) / 2.0,
(position * height) / original_height + index as f64 * (text_height * 1.15),
);
if !boxed || !rw_read!(globals::CONFIG).draw_box_around_quote {
imageproc::drawing::draw_text_mut( imageproc::drawing::draw_text_mut(
tmp, tmp,
image::Rgba([255, 255, 255, 255]), image::Rgba([255, 255, 255, 100]),
((width - text_width) / 2.0) as i32, x as i32,
((position * height) / original_height + index as f64 * (text_height * 1.15)) as i32, y as i32,
rusttype::Scale::uniform(size as f32), rusttype::Scale::uniform(size as f32),
font, font,
line, line,
); );
} }
}
if boxed && rw_read!(globals::CONFIG).draw_box_around_quote {
draw_box(
tmp,
box_width,
box_height,
position,
original_width,
original_height,
);
let size = quote_from_height(height);
draw_multiline_mid_string(
tmp,
font,
size,
position,
original_width,
original_height,
false,
text,
);
}
}
/// Draws box around text.
fn draw_box(
tmp: &mut DynamicImage,
box_width: f64,
box_height: f64,
position: f64,
original_width: f64,
original_height: f64,
) {
if box_width <= 0.0 {
return;
}
let (width, height): (f64, f64) = Coord::from(tmp.dimensions()).into();
let (delta_x, delta_y) = (width / original_width, height / original_height);
let (x_gap, y_gap) = (8.0 * delta_x, 5.0 * delta_y);
let (x, y) = (
((width - box_width) / 2.0 - x_gap) as u32,
((position * height) / original_height - y_gap) as u32,
);
let (w, h) = (
(box_width + x_gap * 2.0) as u32,
(box_height + y_gap * 2.0) as u32,
);
if x >= width as u32 || y >= height as u32 {
return;
}
let mut buff = tmp.crop(x, y, w, h);
let layer = DynamicImage::ImageRgba8(ImageBuffer::from_fn(w, h, |_, _| {
image::Rgba([20, 22, 25, 80])
}));
image::imageops::overlay(&mut buff, &layer, 0, 0);
buff = buff.blur(15.0);
let (dx, dy) = (20.0 * delta_x, 20.0 * delta_y);
let mut shadow = DynamicImage::new_rgba8(w + (dx * 2.0) as u32, h + (dy * 2.0) as u32);
imageproc::drawing::draw_hollow_rect_mut(
&mut shadow,
Rect::at(dx as i32, dy as i32).of_size(w, h),
image::Rgba([30, 30, 30, 255]),
);
shadow = shadow.blur(5.0 * delta_x as f32);
image::imageops::overlay(tmp, &shadow, x as i64 - dx as i64, y as i64 - dy as i64);
image::imageops::overlay(tmp, &buff, x as i64, y as i64);
let mut color = buff.get_pixel(0, 0).to_rgba();
color.blend(&buff.get_pixel(0, buff.height() - 1).to_rgba());
color.blend(
&buff
.get_pixel(buff.width() - 1, buff.height() - 1)
.to_rgba(),
);
color.blend(&buff.get_pixel(buff.width() - 1, 0).to_rgba());
imageproc::drawing::draw_hollow_rect_mut(
tmp,
Rect::at(
x as i32 - (delta_x * 1.0) as i32,
y as i32 - (delta_x * 1.0) as i32,
)
.of_size(w + (delta_x * 2.0) as u32, h + (delta_x * 2.0) as u32),
color.clone(),
);
color.blend(&image::Rgba([0, 0, 0, 2]));
imageproc::drawing::draw_hollow_rect_mut(
tmp,
Rect::at(x as i32, y as i32).of_size(w, h),
color.clone(),
);
} }
/// Get size of text to draw on image /// Get size of text to draw on image