Checkpoint

Nathan Sobo created

Change summary

crates/gpui3/src/elements/text.rs                 | 15 ++++++++-------
crates/gpui3/src/gpui3.rs                         |  3 ++-
crates/gpui3/src/platform.rs                      |  7 ++++++-
crates/gpui3/src/platform/mac/text_system.rs      |  6 +++---
crates/gpui3/src/text_system.rs                   | 11 ++++++-----
crates/gpui3/src/text_system/line.rs              |  8 ++++----
crates/gpui3/src/text_system/line_wrapper.rs      | 12 ++++++------
crates/gpui3/src/text_system/text_layout_cache.rs | 14 +++++++-------
8 files changed, 42 insertions(+), 34 deletions(-)

Detailed changes

crates/gpui3/src/elements/text.rs 🔗

@@ -1,12 +1,13 @@
 use crate::{
-    size, AnyElement, Bounds, Element, IntoAnyElement, LayoutId, Line, Pixels, Size, ViewContext,
+    size, AnyElement, Bounds, Element, IntoAnyElement, LayoutId, Line, Pixels, SharedString, Size,
+    ViewContext,
 };
 use parking_lot::Mutex;
 use smallvec::SmallVec;
 use std::{marker::PhantomData, sync::Arc};
-use util::{arc_cow::ArcCow, ResultExt};
+use util::ResultExt;
 
-impl<S: 'static + Send + Sync> IntoAnyElement<S> for ArcCow<'static, str> {
+impl<S: 'static + Send + Sync> IntoAnyElement<S> for SharedString {
     fn into_any(self) -> AnyElement<S> {
         Text {
             text: self,
@@ -19,7 +20,7 @@ impl<S: 'static + Send + Sync> IntoAnyElement<S> for ArcCow<'static, str> {
 impl<V: 'static + Send + Sync> IntoAnyElement<V> for &'static str {
     fn into_any(self) -> AnyElement<V> {
         Text {
-            text: ArcCow::from(self),
+            text: self.into(),
             state_type: PhantomData,
         }
         .into_any()
@@ -31,7 +32,7 @@ impl<V: 'static + Send + Sync> IntoAnyElement<V> for &'static str {
 impl<S: 'static + Send + Sync> IntoAnyElement<S> for String {
     fn into_any(self) -> AnyElement<S> {
         Text {
-            text: ArcCow::from(self),
+            text: self.into(),
             state_type: PhantomData,
         }
         .into_any()
@@ -39,7 +40,7 @@ impl<S: 'static + Send + Sync> IntoAnyElement<S> for String {
 }
 
 pub struct Text<S> {
-    text: ArcCow<'static, str>,
+    text: SharedString,
     state_type: PhantomData<S>,
 }
 
@@ -78,7 +79,7 @@ impl<S: 'static + Send + Sync> Element for Text<S> {
             move |known_dimensions, _| {
                 let Some(lines) = text_system
                     .layout_text(
-                        text.as_ref(),
+                        &text,
                         font_size,
                         &[text_style.to_run(text.len())],
                         known_dimensions.width, // Wrap if we know the width.

crates/gpui3/src/gpui3.rs 🔗

@@ -51,6 +51,7 @@ pub use util::arc_cow::ArcCow;
 pub use view::*;
 pub use window::*;
 
+use derive_more::{Deref, DerefMut};
 use std::{
     any::{Any, TypeId},
     mem,
@@ -180,7 +181,7 @@ impl<T> Flatten<T> for Result<T> {
     }
 }
 
-#[derive(Clone, Eq, PartialEq, Hash)]
+#[derive(Deref, DerefMut, Eq, PartialEq, Hash, Clone)]
 pub struct SharedString(ArcCow<'static, str>);
 
 impl Default for SharedString {

crates/gpui3/src/platform.rs 🔗

@@ -171,7 +171,12 @@ pub trait PlatformTextSystem: Send + Sync {
     fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option<GlyphId>;
     fn glyph_raster_bounds(&self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>>;
     fn rasterize_glyph(&self, params: &RenderGlyphParams) -> Result<(Size<DevicePixels>, Vec<u8>)>;
-    fn layout_line(&self, text: &str, font_size: Pixels, runs: &[(usize, FontId)]) -> LineLayout;
+    fn layout_line(
+        &self,
+        text: &SharedString,
+        font_size: Pixels,
+        runs: &[(usize, FontId)],
+    ) -> LineLayout;
     fn wrap_line(
         &self,
         text: &str,

crates/gpui3/src/platform/mac/text_system.rs 🔗

@@ -151,7 +151,7 @@ impl PlatformTextSystem for MacTextSystem {
 
     fn layout_line(
         &self,
-        text: &str,
+        text: &SharedString,
         font_size: Pixels,
         font_runs: &[(usize, FontId)],
     ) -> LineLayout {
@@ -339,7 +339,7 @@ impl MacTextSystemState {
 
     fn layout_line(
         &mut self,
-        text: &str,
+        text: &SharedString,
         font_size: Pixels,
         font_runs: &[(usize, FontId)],
     ) -> LineLayout {
@@ -416,12 +416,12 @@ impl MacTextSystemState {
 
         let typographic_bounds = line.get_typographic_bounds();
         LineLayout {
+            text: text.clone(),
             width: typographic_bounds.width.into(),
             ascent: typographic_bounds.ascent.into(),
             descent: typographic_bounds.descent.into(),
             runs,
             font_size,
-            len: text.len(),
         }
     }
 

crates/gpui3/src/text_system.rs 🔗

@@ -147,7 +147,7 @@ impl TextSystem {
 
     pub fn layout_text(
         &self,
-        text: &str,
+        text: &SharedString,
         font_size: Pixels,
         runs: &[TextRun],
         wrap_width: Option<Pixels>,
@@ -158,8 +158,9 @@ impl TextSystem {
 
         let mut lines = SmallVec::new();
         let mut line_start = 0;
-        for line in text.split('\n') {
-            let line_end = line_start + line.len();
+        for line_text in text.split('\n') {
+            let line_text = SharedString::from(line_text.to_string());
+            let line_end = line_start + line_text.len();
 
             let mut last_font: Option<Font> = None;
             let mut decoration_runs = SmallVec::<[DecorationRun; 32]>::new();
@@ -204,7 +205,7 @@ impl TextSystem {
 
             let layout = self
                 .text_layout_cache
-                .layout_line(line, font_size, &font_runs);
+                .layout_line(&line_text, font_size, &font_runs);
             lines.push(Arc::new(Line::new(layout, decoration_runs)));
 
             line_start = line_end + 1; // Skip `\n` character.
@@ -391,12 +392,12 @@ impl From<u32> for GlyphId {
 
 #[derive(Default, Debug)]
 pub struct LineLayout {
+    pub text: SharedString,
     pub font_size: Pixels,
     pub width: Pixels,
     pub ascent: Pixels,
     pub descent: Pixels,
     pub runs: Vec<ShapedRun>,
-    pub len: usize,
 }
 
 #[derive(Debug)]

crates/gpui3/src/text_system/line.rs 🔗

@@ -63,11 +63,11 @@ impl Line {
     }
 
     pub fn len(&self) -> usize {
-        self.layout.len
+        self.layout.text.len()
     }
 
     pub fn is_empty(&self) -> bool {
-        self.layout.len == 0
+        self.layout.text.is_empty()
     }
 
     pub fn index_for_x(&self, x: Pixels) -> Option<usize> {
@@ -139,7 +139,7 @@ impl Line {
                         run_end += style_run.len as usize;
                         color = style_run.color;
                     } else {
-                        run_end = self.layout.len;
+                        run_end = self.layout.text.len();
                         finished_underline = current_underline.take();
                     }
                 }
@@ -247,7 +247,7 @@ impl Line {
                             ));
                         }
                     } else {
-                        style_run_end = self.layout.len;
+                        style_run_end = self.layout.text.len();
                         _color = black();
                         finished_underline = current_underline.take();
                     }

crates/gpui3/src/text_system/line_wrapper.rs 🔗

@@ -1,4 +1,4 @@
-use crate::{px, FontId, Line, Pixels, PlatformTextSystem, ShapedBoundary};
+use crate::{px, FontId, Line, Pixels, PlatformTextSystem, ShapedBoundary, SharedString};
 use collections::HashMap;
 use std::{iter, sync::Arc};
 
@@ -89,7 +89,7 @@ impl LineWrapper {
 
     pub fn wrap_shaped_line<'a>(
         &'a mut self,
-        str: &'a str,
+        str: &'a SharedString,
         line: &'a Line,
         wrap_width: Pixels,
     ) -> impl Iterator<Item = ShapedBoundary> + 'a {
@@ -183,7 +183,7 @@ impl LineWrapper {
 
     fn compute_width_for_char(&self, c: char) -> Pixels {
         self.platform_text_system
-            .layout_line(&c.to_string(), self.font_size, &[(1, self.font_id)])
+            .layout_line(&c.to_string().into(), self.font_size, &[(1, self.font_id)])
             .width
     }
 }
@@ -295,10 +295,10 @@ mod tests {
                 }
             }
 
-            let text = "aa bbb cccc ddddd eeee";
+            let text = "aa bbb cccc ddddd eeee".into();
             let lines = text_system
                 .layout_text(
-                    text,
+                    &text,
                     px(16.),
                     &[
                         normal.with_len(4),
@@ -319,7 +319,7 @@ mod tests {
             );
             assert_eq!(
                 wrapper
-                    .wrap_shaped_line(text, &line, px(72.))
+                    .wrap_shaped_line(&text, &line, px(72.))
                     .collect::<Vec<_>>(),
                 &[
                     ShapedBoundary {

crates/gpui3/src/text_system/text_layout_cache.rs 🔗

@@ -1,4 +1,4 @@
-use crate::{FontId, LineLayout, Pixels, PlatformTextSystem, ShapedGlyph, ShapedRun};
+use crate::{FontId, LineLayout, Pixels, PlatformTextSystem, ShapedGlyph, ShapedRun, SharedString};
 use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard};
 use smallvec::SmallVec;
 use std::{
@@ -30,9 +30,9 @@ impl TextLayoutCache {
         curr_frame.clear();
     }
 
-    pub fn layout_line<'a>(
-        &'a self,
-        text: &'a str,
+    pub fn layout_line(
+        &self,
+        text: &SharedString,
         font_size: Pixels,
         runs: &[(usize, FontId)],
     ) -> Arc<LineLayout> {
@@ -53,7 +53,7 @@ impl TextLayoutCache {
         } else {
             let layout = Arc::new(self.platform_text_system.layout_line(text, font_size, runs));
             let key = CacheKeyValue {
-                text: text.into(),
+                text: text.clone(),
                 font_size,
                 runs: SmallVec::from(runs),
             };
@@ -83,7 +83,7 @@ impl<'a> Hash for (dyn CacheKey + 'a) {
 
 #[derive(Eq)]
 struct CacheKeyValue {
-    text: String,
+    text: SharedString,
     font_size: Pixels,
     runs: SmallVec<[(usize, FontId); 1]>,
 }
@@ -91,7 +91,7 @@ struct CacheKeyValue {
 impl CacheKey for CacheKeyValue {
     fn key(&self) -> CacheKeyRef {
         CacheKeyRef {
-            text: self.text.as_str(),
+            text: &self.text,
             font_size: self.font_size,
             runs: self.runs.as_slice(),
         }