use crate::text::{measure_text, split_into_words, Font};
#[derive(Debug, Clone, PartialEq)]
pub struct TextBlockMetrics {
pub width: f64,
pub height: f64,
pub line_count: usize,
}
pub fn compute_line_widths(text: &str, font: &Font, font_size: f64, max_width: f64) -> Vec<f64> {
if text.is_empty() {
return Vec::new();
}
let words = split_into_words(text);
if words.is_empty() {
return Vec::new();
}
let mut line_widths: Vec<f64> = Vec::new();
let mut current_width = 0.0;
for word in &words {
let word_width = measure_text(word, font, font_size);
if current_width > 0.0 && current_width + word_width > max_width {
line_widths.push(current_width);
current_width = word_width;
} else {
current_width += word_width;
}
}
if current_width > 0.0 {
line_widths.push(current_width);
}
line_widths
}
pub fn measure_text_block(
text: &str,
font: &Font,
font_size: f64,
line_height: f64,
max_width: f64,
) -> TextBlockMetrics {
let line_widths = compute_line_widths(text, font, font_size, max_width);
let line_count = line_widths.len();
let width = line_widths.iter().copied().fold(0.0_f64, f64::max);
let height = line_count as f64 * font_size * line_height;
TextBlockMetrics {
width,
height,
line_count,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_compute_line_widths_empty() {
let widths = compute_line_widths("", &Font::Helvetica, 12.0, 200.0);
assert!(widths.is_empty());
}
#[test]
fn test_compute_line_widths_single_word() {
let widths = compute_line_widths("Hello", &Font::Helvetica, 12.0, 500.0);
assert_eq!(widths.len(), 1);
assert!(widths[0] > 0.0);
}
#[test]
fn test_measure_text_block_empty() {
let m = measure_text_block("", &Font::Helvetica, 12.0, 1.2, 300.0);
assert_eq!(m.line_count, 0);
assert_eq!(m.width, 0.0);
assert_eq!(m.height, 0.0);
}
}