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
+11
-5
@@ -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
@@ -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?
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user