WIP

Antonio Scandurra created

Change summary

gpui/src/platform.rs                   |  3 +
gpui/src/platform/mac/fonts.rs         | 30 +++++++++++++++++++++++----
gpui/src/text_layout.rs                |  2 
zed/src/editor/display_map/wrap_map.rs | 29 +++++++++++++++++++-------
4 files changed, 49 insertions(+), 15 deletions(-)

Detailed changes

gpui/src/platform.rs πŸ”—

@@ -130,10 +130,11 @@ pub trait FontSystem: Send + Sync {
         subpixel_shift: Vector2F,
         scale_factor: f32,
     ) -> Option<(RectI, Vec<u8>)>;
-    fn layout_str(
+    fn layout_line(
         &self,
         text: &str,
         font_size: f32,
         runs: &[(usize, FontId, ColorU)],
     ) -> LineLayout;
+    fn wrap_line(&self, text: &str, font_size: f32, font_id: FontId) -> Vec<usize>;
 }

gpui/src/platform/mac/fonts.rs πŸ”—

@@ -77,13 +77,17 @@ impl platform::FontSystem for FontSystem {
             .rasterize_glyph(font_id, font_size, glyph_id, subpixel_shift, scale_factor)
     }
 
-    fn layout_str(
+    fn layout_line(
         &self,
         text: &str,
         font_size: f32,
         runs: &[(usize, FontId, ColorU)],
     ) -> LineLayout {
-        self.0.read().layout_str(text, font_size, runs)
+        self.0.read().layout_line(text, font_size, runs)
+    }
+
+    fn wrap_line(&self, text: &str, font_size: f32, font_id: FontId) -> Vec<usize> {
+        self.0.read().wrap_line(text, font_size, font_id)
     }
 }
 
@@ -182,7 +186,7 @@ impl FontSystemState {
         }
     }
 
-    fn layout_str(
+    fn layout_line(
         &self,
         text: &str,
         font_size: f32,
@@ -307,6 +311,22 @@ impl FontSystemState {
             len,
         }
     }
+
+    fn wrap_line(&self, text: &str, font_size: f32, font_id: FontId) -> Vec<usize> {
+        let mut string = CFMutableAttributedString::new();
+        string.replace_str(&CFString::new(text), CFRange::init(0, 0));
+        let cf_range = CFRange::init(0 as isize, text.encode_utf16().count() as isize);
+        let font = &self.fonts[font_id.0];
+        unsafe {
+            string.set_attribute(
+                cf_range,
+                kCTFontAttributeName,
+                &font.native_font().clone_with_font_size(font_size as f64),
+            );
+        }
+
+        Vec::new()
+    }
 }
 
 #[cfg(test)]
@@ -333,7 +353,7 @@ mod tests {
         assert_ne!(menlo_regular, menlo_bold);
         assert_ne!(menlo_italic, menlo_bold);
 
-        let line = fonts.layout_str(
+        let line = fonts.layout_line(
             "hello world",
             16.0,
             &[
@@ -360,7 +380,7 @@ mod tests {
         let menlo_regular = fonts.select_font(&menlo, &Properties::new())?;
 
         let text = "This is, m𐍈re 𐍈r less, Zapfino!𐍈";
-        let line = fonts.layout_str(
+        let line = fonts.layout_line(
             text,
             16.0,
             &[

gpui/src/text_layout.rs πŸ”—

@@ -60,7 +60,7 @@ impl TextLayoutCache {
             curr_frame.insert(key, layout.clone());
             Line::new(layout.clone(), runs)
         } else {
-            let layout = Arc::new(self.fonts.layout_str(text, font_size, runs));
+            let layout = Arc::new(self.fonts.layout_line(text, font_size, runs));
             let key = CacheKeyValue {
                 text: text.into(),
                 font_size: OrderedFloat(font_size),

zed/src/editor/display_map/wrap_map.rs πŸ”—

@@ -73,7 +73,7 @@ impl WrapMap {
         }
     }
 
-    pub fn read(&self, folds_snapshot: fold_map::Snapshot, edits: Vec<fold_map::Edit>) -> Snapshot {
+    pub fn sync(&self, folds_snapshot: fold_map::Snapshot, edits: Vec<fold_map::Edit>) -> Snapshot {
         // TODO: interpolate
         self.edits_tx.try_send((folds_snapshot, edits)).unwrap();
         self.state.lock().snapshot.clone()
@@ -186,7 +186,7 @@ mod tests {
     use Bias::{Left, Right};
 
     #[gpui::test]
-    fn test_random_folds(cx: &mut gpui::MutableAppContext) {
+    fn test_random_wraps(cx: &mut gpui::MutableAppContext) {
         let iterations = env::var("ITERATIONS")
             .map(|i| i.parse().expect("invalid `ITERATIONS` variable"))
             .unwrap_or(100);
@@ -218,16 +218,29 @@ mod tests {
                 font_family: font_cache.load_family(&["Helvetica"]).unwrap(),
                 font_size: 14.0,
             };
-            let mut wrapper = BackgroundWrapper::new(config, font_cache.clone(), font_system);
+            let font_id = font_cache
+                .select_font(config.font_family, &Default::default())
+                .unwrap();
+            let mut wrapper =
+                BackgroundWrapper::new(config, font_cache.clone(), font_system.clone());
             let edit = fold_map::Edit {
                 old_bytes: 0..0,
                 new_bytes: 0..snapshot.len(),
             };
-            wrapper.sync(snapshot, vec![edit]);
-            // for line in wrapper.snapshot.text().lines() {
-            //     font_cache.
-            // }
-            // assert_eq!(wrap_map.snapshot().text())
+            wrapper.sync(snapshot.clone(), vec![edit]);
+
+            let mut expected_text = String::new();
+            for line in snapshot.text().lines() {
+                let mut prev_ix = 0;
+                for ix in font_system.wrap_line(line, 14.0, font_id) {
+                    expected_text.push_str(&line[prev_ix..ix]);
+                    expected_text.push('\n');
+                    prev_ix = ix;
+                }
+                expected_text.push_str(&line[prev_ix..]);
+                expected_text.push('\n');
+            }
+            dbg!(expected_text);
         }
     }
 }