nightshade 0.13.3

A cross-platform data-oriented game engine.
Documentation
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
}