Start restructuring WrapMap with simpler concurrency

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld
2021-07-22 16:21:42 -07:00
co-authored by Nathan Sobo
parent 80f13dd737
commit 5d22c6c4bd
6 changed files with 530 additions and 581 deletions
+108
View File
@@ -0,0 +1,108 @@
use crate::Settings;
use gpui::{fonts::FontId, FontCache, FontSystem};
use parking_lot::Mutex;
use std::{collections::HashMap, sync::Arc};
pub struct LineWrapper {
font_system: Arc<dyn FontSystem>,
font_cache: Arc<FontCache>,
font_id: FontId,
font_size: f32,
cached_ascii_char_widths: Mutex<[f32; 128]>,
cached_other_char_widths: Mutex<HashMap<char, f32>>,
}
impl LineWrapper {
pub fn new(
font_system: Arc<dyn FontSystem>,
font_cache: Arc<FontCache>,
settings: Settings,
) -> Self {
let font_id = font_cache
.select_font(settings.buffer_font_family, &Default::default())
.unwrap();
let font_size = settings.buffer_font_size;
Self {
font_cache,
font_system,
font_id,
font_size,
cached_ascii_char_widths: Mutex::new([f32::NAN; 128]),
cached_other_char_widths: Mutex::new(HashMap::new()),
}
}
pub fn wrap_line_with_shaping(&self, line: &str, wrap_width: f32) -> Vec<usize> {
self.font_system
.wrap_line(line, self.font_id, self.font_size, wrap_width)
}
pub fn wrap_line_without_shaping(&self, line: &str, wrap_width: f32) -> Vec<usize> {
let mut width = 0.0;
let mut result = Vec::new();
let mut last_boundary_ix = 0;
let mut last_boundary_width = 0.0;
let mut prev_c = '\0';
for (ix, c) in line.char_indices() {
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 {
if last_boundary_ix > 0 {
result.push(last_boundary_ix);
width -= last_boundary_width;
last_boundary_ix = 0;
} else {
result.push(ix);
width = char_width;
}
}
prev_c = c;
}
result
}
fn is_boundary(&self, prev: char, next: char) -> bool {
if prev == ' ' || next == ' ' {
return true;
}
false
}
fn width_for_char(&self, c: char) -> f32 {
if (c as u32) < 128 {
let mut cached_ascii_char_widths = self.cached_ascii_char_widths.lock();
let mut width = cached_ascii_char_widths[c as usize];
if width.is_nan() {
width = self.compute_width_for_char(c);
cached_ascii_char_widths[c as usize] = width;
}
width
} else {
let mut cached_other_char_widths = self.cached_other_char_widths.lock();
let mut width = cached_other_char_widths
.get(&c)
.copied()
.unwrap_or(f32::NAN);
if width.is_nan() {
width = self.compute_width_for_char(c);
cached_other_char_widths.insert(c, width);
}
width
}
}
fn compute_width_for_char(&self, c: char) -> f32 {
self.font_system
.layout_line(
&c.to_string(),
self.font_size,
&[(1, self.font_id, Default::default())],
)
.width
}
}
File diff suppressed because it is too large Load Diff