pub(super) fn wrap_text(
font_data: &crate::ecs::text::resources::FontAtlasData,
text: &str,
font_size: f32,
available_width: f32,
) -> String {
if available_width <= 0.0 {
return text.to_string();
}
let scale = font_size / font_data.font_size;
let mut result = String::with_capacity(text.len() + 16);
let mut line_width = 0.0f32;
let mut word_start = 0;
let mut word_width = 0.0f32;
let mut prev_char: Option<char> = None;
let chars: Vec<char> = text.chars().collect();
for index in 0..chars.len() {
let character = chars[index];
if character == '\n' {
result.push_str(&chars[word_start..=index].iter().collect::<String>());
line_width = 0.0;
word_start = index + 1;
word_width = 0.0;
prev_char = None;
continue;
}
let char_width = if let Some(glyph) = font_data.glyphs.get(&character) {
let mut width = glyph.advance * scale;
if let Some(previous) = prev_char
&& let Some(&kern) = font_data.kerning.get(&(previous, character))
{
width += kern * scale;
}
width
} else {
0.0
};
word_width += char_width;
prev_char = Some(character);
if character.is_whitespace() || index == chars.len() - 1 {
if line_width + word_width > available_width && line_width > 0.0 {
if result.ends_with(' ') {
result.pop();
}
result.push('\n');
line_width = 0.0;
}
let end = index + 1;
result.push_str(&chars[word_start..end].iter().collect::<String>());
line_width += word_width;
word_start = end;
word_width = 0.0;
}
}
result
}