Avoid allocation in LineWrapper::wrap_line
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
co-authored by
Nathan Sobo
parent
59bb6624e2
commit
2dcf04cfb9
@@ -36,37 +36,42 @@ impl LineWrapper {
|
||||
.wrap_line(line, self.font_id, self.font_size, wrap_width)
|
||||
}
|
||||
|
||||
pub fn wrap_line(&self, line: &str, wrap_width: f32) -> Vec<usize> {
|
||||
pub fn wrap_line<'a>(
|
||||
&'a self,
|
||||
line: &'a str,
|
||||
wrap_width: f32,
|
||||
) -> impl Iterator<Item = usize> + 'a {
|
||||
let mut width = 0.0;
|
||||
let mut boundaries = Vec::new();
|
||||
let mut last_boundary_ix = 0;
|
||||
let mut last_boundary_width = 0.0;
|
||||
let mut last_candidate_ix = 0;
|
||||
let mut last_candidate_width = 0.0;
|
||||
let mut last_wrap_ix = 0;
|
||||
let mut prev_c = '\0';
|
||||
for (ix, c) in line.char_indices() {
|
||||
if c == '\n' {
|
||||
break;
|
||||
}
|
||||
|
||||
if self.is_boundary(prev_c, c) {
|
||||
last_boundary_ix = ix;
|
||||
last_boundary_width = width;
|
||||
}
|
||||
|
||||
let char_width = self.width_for_char(c);
|
||||
width += char_width;
|
||||
if width > wrap_width && ix > *boundaries.last().unwrap_or(&0) {
|
||||
if last_boundary_ix > 0 {
|
||||
boundaries.push(last_boundary_ix);
|
||||
width -= last_boundary_width;
|
||||
last_boundary_ix = 0;
|
||||
} else {
|
||||
boundaries.push(ix);
|
||||
width = char_width;
|
||||
let char_indices = line.char_indices();
|
||||
char_indices.filter_map(move |(ix, c)| {
|
||||
if c != '\n' {
|
||||
if self.is_boundary(prev_c, c) {
|
||||
last_candidate_ix = ix;
|
||||
last_candidate_width = width;
|
||||
}
|
||||
|
||||
let char_width = self.width_for_char(c);
|
||||
width += char_width;
|
||||
if width > wrap_width && ix > last_wrap_ix {
|
||||
if last_candidate_ix > 0 {
|
||||
last_wrap_ix = last_candidate_ix;
|
||||
width -= last_candidate_width;
|
||||
last_candidate_ix = 0;
|
||||
} else {
|
||||
last_wrap_ix = ix;
|
||||
width = char_width;
|
||||
}
|
||||
return Some(last_wrap_ix);
|
||||
}
|
||||
prev_c = c;
|
||||
}
|
||||
prev_c = c;
|
||||
}
|
||||
boundaries
|
||||
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
fn is_boundary(&self, prev: char, next: char) -> bool {
|
||||
@@ -132,7 +137,9 @@ mod tests {
|
||||
&[7, 12, 18],
|
||||
);
|
||||
assert_eq!(
|
||||
wrapper.wrap_line("aa bbb cccc ddddd eeee", 72.0),
|
||||
wrapper
|
||||
.wrap_line("aa bbb cccc ddddd eeee", 72.0)
|
||||
.collect::<Vec<_>>(),
|
||||
&[7, 12, 18],
|
||||
);
|
||||
|
||||
@@ -141,7 +148,9 @@ mod tests {
|
||||
&[4, 11, 18],
|
||||
);
|
||||
assert_eq!(
|
||||
wrapper.wrap_line("aaa aaaaaaaaaaaaaaaaaa", 72.0),
|
||||
wrapper
|
||||
.wrap_line("aaa aaaaaaaaaaaaaaaaaa", 72.0)
|
||||
.collect::<Vec<_>>(),
|
||||
&[4, 11, 18],
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user