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
+11 -5
View File
@@ -385,14 +385,14 @@ impl Background {
}
}
pub fn block_on<F, T>(&self, timeout: Duration, future: F) -> Option<T>
pub fn block_with_timeout<F, T>(&self, timeout: Duration, mut future: F) -> Result<T, F>
where
T: 'static,
F: Future<Output = T>,
F: 'static + Unpin + Future<Output = T>,
{
match self {
let output = match self {
Self::Production { .. } => {
smol::block_on(async move { util::timeout(timeout, future).await.ok() })
smol::block_on(util::timeout(timeout, Pin::new(&mut future))).ok()
}
Self::Deterministic(executor) => {
let max_ticks = {
@@ -400,8 +400,14 @@ impl Background {
let range = state.block_on_ticks.clone();
state.rng.gen_range(range)
};
executor.block_on(max_ticks, future)
executor.block_on(max_ticks, Pin::new(&mut future))
}
};
if let Some(output) = output {
Ok(output)
} else {
Err(future)
}
}
+2 -2
View File
@@ -2198,8 +2198,8 @@ impl Editor {
font_cache.em_width(font_id, settings.buffer_font_size)
}
pub fn set_wrap_width(&self, width: f32) {
self.display_map.set_wrap_width(Some(width));
pub fn set_wrap_width(&self, width: f32, cx: &AppContext) {
self.display_map.set_wrap_width(Some(width), cx);
}
// TODO: Can we make this not return a result?
+5 -4
View File
@@ -1,4 +1,5 @@
mod fold_map;
mod line_wrapper;
mod tab_map;
mod wrap_map;
@@ -74,8 +75,8 @@ impl DisplayMap {
self.wrap_map.sync(snapshot, edits, cx);
}
pub fn set_wrap_width(&self, width: Option<f32>) {
self.wrap_map.set_wrap_width(width);
pub fn set_wrap_width(&self, width: Option<f32>, cx: &AppContext) {
self.wrap_map.set_wrap_width(width, cx);
}
pub fn notifications(&self) -> impl Stream<Item = ()> {
@@ -212,11 +213,11 @@ impl DisplayMapSnapshot {
}
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
pub struct DisplayPoint(wrap_map::OutputPoint);
pub struct DisplayPoint(wrap_map::WrapPoint);
impl DisplayPoint {
pub fn new(row: u32, column: u32) -> Self {
Self(wrap_map::OutputPoint::new(row, column))
Self(wrap_map::WrapPoint::new(row, column))
}
pub fn zero() -> Self {
+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
+1 -1
View File
@@ -366,7 +366,7 @@ impl Element for EditorElement {
let wrap_width = text_size.x() - text_offset.x() - overscroll.x();
// TODO: Core text doesn't seem to be keeping our lines below the specified wrap width. Find out why.
let wrap_width = wrap_width - em_width;
view.set_wrap_width(wrap_width);
view.set_wrap_width(wrap_width, app);
let autoscroll_horizontally = view.autoscroll_vertically(size.y(), line_height, app);