use image::{DynamicImage, Rgba};
use imageproc::drawing;
use rusttype::{Font, Scale};
pub const fn div_ceil(lhs: u32, rhs: u32) -> u32 {
let d = lhs / rhs;
let r = lhs % rhs;
if r > 0 && rhs > 0 {
d + 1
} else {
d
}
}
pub fn text_size(
font: &Font,
desired_width: u32,
max_height: u32,
text: &str,
) -> (Scale, u32, u32) {
if text.trim().is_empty() {
return (Scale::uniform(0.), 0, 0);
}
let iter_limit = 1000;
let desired_width = i32::try_from(desired_width).unwrap_or(i32::MAX);
let max_height = i32::try_from(max_height).unwrap_or(i32::MAX);
let mut scale = Scale::uniform(0.);
let mut text_w = 0;
let mut text_h = 0;
let mut i = 0;
while text_w < desired_width && text_h < max_height && i < iter_limit {
scale.x += 1.;
scale.y += 1.;
(text_w, text_h) = drawing::text_size(scale, font, text);
i += 1;
}
(
scale,
text_w.try_into().unwrap_or_default(),
text_h.try_into().unwrap_or_default(),
)
}
pub fn draw_wrapped_text(
img: &mut DynamicImage,
color: Rgba<u8>,
scale: Scale,
font: &Font,
y: u32,
text: &str,
) {
if text.trim().is_empty() {
return;
}
let side_length = i32::try_from(img.height()).unwrap_or_default();
let y = i32::try_from(y).unwrap_or_default();
let lines = {
let mut lines = Vec::new();
let mut line = String::new();
let max_w = 5 * side_length / 6;
for word in text.split_whitespace() {
let new_line = if line.is_empty() {
word.into()
} else {
line.clone() + " " + word
};
let (line_w, _) = drawing::text_size(scale, font, &new_line);
if line_w <= max_w {
line = new_line;
} else {
lines.push(line);
line = word.into();
}
}
lines.push(line);
lines
};
for (n, line) in lines.iter().enumerate() {
let (line_w, line_h) = drawing::text_size(scale, font, line);
let line_x = (side_length - line_w) / 2;
let line_y = y + line_h * i32::try_from(n).unwrap_or_default();
drawing::draw_text_mut(img, color, line_x, line_y, scale, font, line);
}
}