Merge PR #2859: Treat CRLF as a single line break in fonts::wrap

This commit is contained in:
aiongg
2026-10-22 01:47:23 +00:00
+12 -2
View File
@@ -69,7 +69,7 @@ fn is_wide(c: char) -> bool {
)
}
/// Greedy line breaking within `width` points (paragraphs split on newlines; words longer
/// Greedy line breaking within `width` points (paragraphs split on line breaks, where CRLF counts as one; words longer
/// than a line are broken by character).
pub fn wrap(text: &str, size: f64, width: f64) -> Vec<String> {
wrap_with(text, size, width, helvetica_width)
@@ -78,7 +78,8 @@ pub fn wrap(text: &str, size: f64, width: f64) -> Vec<String> {
/// [`wrap`], measuring with `measure` (for example [`cjk_width`]).
pub fn wrap_with(text: &str, size: f64, width: f64, measure: impl Fn(&str, f64) -> f64) -> Vec<String> {
let mut lines = Vec::new();
for para in text.split(['\n', '\r']) {
// A CRLF pair is one break, a lone CR or LF is one break each.
for para in text.replace("\r\n", "\n").split(['\n', '\r']) {
let mut line = String::new();
// No word is on the line yet; an empty word (a leading space) still starts it.
let mut fresh = true;
@@ -277,6 +278,15 @@ mod tests {
assert_eq!(broken, wrap(" abcdefghijklmnopqrstuvwxyz", 11.0, 40.0));
}
#[test]
fn crlf_is_one_line_break() {
assert_eq!(wrap("a\r\nb", 12.0, 100.0), ["a", "b"]);
assert_eq!(wrap("a\rb", 12.0, 100.0), ["a", "b"]);
assert_eq!(wrap("a\nb", 12.0, 100.0), ["a", "b"]);
assert_eq!(wrap("a\r\n\r\nb", 12.0, 100.0), ["a", "", "b"]);
assert_eq!(wrap("a\n\rb", 12.0, 100.0), ["a", "", "b"]);
}
#[test]
fn win_ansi_encodability_matches_the_encoder() {
for c in ['a', 'é', 'ÿ', '€', '—', '™', '\t', '?'] {