Word-wrap text into visual lines that fit within `max_width`. Splits on '\n' first (hard breaks), then wraps long lines at word boundaries. If `max_width <= 0`, no wrapping occurs (equivalent to `split_lines`).
(
text: &str,
max_width: f32,
font_asset: Option<&'static crate::renderer::FontAsset>,
font_size: u16,
measure_fn: &dyn Fn(&str, &crate::text::TextConfig) -> crate::math::Dimension
| 1463 | /// Splits on '\n' first (hard breaks), then wraps long lines at word boundaries. |
| 1464 | /// If `max_width <= 0`, no wrapping occurs (equivalent to `split_lines`). |
| 1465 | pub fn wrap_lines( |
| 1466 | text: &str, |
| 1467 | max_width: f32, |
| 1468 | font_asset: Option<&'static crate::renderer::FontAsset>, |
| 1469 | font_size: u16, |
| 1470 | measure_fn: &dyn Fn(&str, &crate::text::TextConfig) -> crate::math::Dimensions, |
| 1471 | ) -> Vec<VisualLine> { |
| 1472 | let config = crate::text::TextConfig { |
| 1473 | font_asset, |
| 1474 | font_size, |
| 1475 | ..Default::default() |
| 1476 | }; |
| 1477 | |
| 1478 | let hard_lines = split_lines(text); |
| 1479 | let mut result = Vec::new(); |
| 1480 | |
| 1481 | for (global_start, line_text) in hard_lines { |
| 1482 | if line_text.is_empty() { |
| 1483 | result.push(VisualLine { |
| 1484 | text: String::new(), |
| 1485 | global_char_start: global_start, |
| 1486 | char_count: 0, |
| 1487 | }); |
| 1488 | continue; |
| 1489 | } |
| 1490 | |
| 1491 | if max_width <= 0.0 { |
| 1492 | // No wrapping |
| 1493 | result.push(VisualLine { |
| 1494 | text: line_text.to_string(), |
| 1495 | global_char_start: global_start, |
| 1496 | char_count: line_text.chars().count(), |
| 1497 | }); |
| 1498 | continue; |
| 1499 | } |
| 1500 | |
| 1501 | // Check if the whole line fits |
| 1502 | let full_width = measure_fn(line_text, &config).width; |
| 1503 | if full_width <= max_width { |
| 1504 | result.push(VisualLine { |
| 1505 | text: line_text.to_string(), |
| 1506 | global_char_start: global_start, |
| 1507 | char_count: line_text.chars().count(), |
| 1508 | }); |
| 1509 | continue; |
| 1510 | } |
| 1511 | |
| 1512 | // Need to wrap this line |
| 1513 | let chars: Vec<char> = line_text.chars().collect(); |
| 1514 | let total_chars = chars.len(); |
| 1515 | let mut line_char_start = 0; // index within chars[] |
| 1516 | |
| 1517 | while line_char_start < total_chars { |
| 1518 | // Find how many characters fit in max_width |
| 1519 | let mut fit_count = 0; |
| 1520 | |
| 1521 | #[cfg(feature = "text-styling")] |
| 1522 | { |