Fix block cursor does not render italic for vim (#10249)

Hans created

Release Notes:

- Fixed #8799

Change summary

crates/editor/src/element.rs               | 10 +++++++++-
crates/gpui/src/text_system.rs             | 11 +++++++++++
crates/gpui/src/text_system/line_layout.rs | 12 ++++++++++++
3 files changed, 32 insertions(+), 1 deletion(-)

Detailed changes

crates/editor/src/element.rs 🔗

@@ -884,13 +884,21 @@ impl EditorElement {
                                     SharedString::from(character.to_string())
                                 };
                                 let len = text.len();
+
+                                let font = cursor_row_layout
+                                    .font_id_for_index(cursor_column)
+                                    .and_then(|cursor_font_id| {
+                                        cx.text_system().get_font_for_id(cursor_font_id)
+                                    })
+                                    .unwrap_or(self.style.text.font());
+
                                 cx.text_system()
                                     .shape_line(
                                         text,
                                         cursor_row_layout.font_size,
                                         &[TextRun {
                                             len,
-                                            font: self.style.text.font(),
+                                            font: font,
                                             color: self.style.background,
                                             background_color: None,
                                             strikethrough: None,

crates/gpui/src/text_system.rs 🔗

@@ -117,6 +117,17 @@ impl TextSystem {
         }
     }
 
+    /// Get the Font for the Font Id.
+    pub fn get_font_for_id(&self, id: FontId) -> Option<Font> {
+        let lock = self.font_ids_by_font.read();
+        lock.iter()
+            .filter_map(|(font, result)| match result {
+                Ok(font_id) if *font_id == id => Some(font.clone()),
+                _ => None,
+            })
+            .next()
+    }
+
     /// Resolves the specified font, falling back to the default font stack if
     /// the font fails to load.
     ///

crates/gpui/src/text_system/line_layout.rs 🔗

@@ -103,6 +103,18 @@ impl LineLayout {
         self.width
     }
 
+    /// The corresponding Font at the given index
+    pub fn font_id_for_index(&self, index: usize) -> Option<FontId> {
+        for run in &self.runs {
+            for glyph in &run.glyphs {
+                if glyph.index >= index {
+                    return Some(run.font_id);
+                }
+            }
+        }
+        None
+    }
+
     fn compute_wrap_boundaries(
         &self,
         text: &str,