Start restructuring WrapMap with simpler concurrency
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
co-authored by
Nathan Sobo
parent
80f13dd737
commit
5d22c6c4bd
@@ -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
Reference in New Issue
Block a user