editor: Push `em` width calculations down into `EditorSnapshot::gutter_dimensions` (#24062)

Marshall Bowers created

This PR removes the `em_width` and `em_advance` parameters to
`EditorSnapshot::gutter_dimensions` in favor of computing the values
inside of it.

In practice all of the callers were passing in the same values, and
there isn't a circumstance where we would want to pass in different
values.

`gutter_dimensions` has also been modified to return
`Option<GutterDimensions>` instead of `GutterDimensions` so that we can
remove some `.unwrap`s when interacting with the text system.

Release Notes:

- N/A

Change summary

crates/editor/src/editor.rs  | 26 +++++++++++++++-----------
crates/editor/src/element.rs | 28 +++++++++++-----------------
crates/git/src/git.rs        |  5 ++++-
3 files changed, 30 insertions(+), 29 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -15089,15 +15089,16 @@ impl EditorSnapshot {
         &self,
         font_id: FontId,
         font_size: Pixels,
-        em_width: Pixels,
-        em_advance: Pixels,
         max_line_number_width: Pixels,
         cx: &App,
-    ) -> GutterDimensions {
+    ) -> Option<GutterDimensions> {
         if !self.show_gutter {
-            return GutterDimensions::default();
+            return None;
         }
+
         let descent = cx.text_system().descent(font_id, font_size);
+        let em_width = cx.text_system().em_width(font_id, font_size).log_err()?;
+        let em_advance = cx.text_system().em_advance(font_id, font_size).log_err()?;
 
         let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
             matches!(
@@ -15126,13 +15127,16 @@ impl EditorSnapshot {
         let git_blame_entries_width =
             self.git_blame_gutter_max_author_length
                 .map(|max_author_length| {
-                    // Length of the author name, but also space for the commit hash,
-                    // the spacing and the timestamp.
+                    const MAX_RELATIVE_TIMESTAMP: &str = "60 minutes ago";
+
+                    /// The number of characters to dedicate to gaps and margins.
+                    const SPACING_WIDTH: usize = 4;
+
                     let max_char_count = max_author_length
                         .min(GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED)
-                        + 7 // length of commit sha
-                        + 14 // length of max relative timestamp ("60 minutes ago")
-                        + 4; // gaps and margins
+                        + ::git::SHORT_SHA_LENGTH
+                        + MAX_RELATIVE_TIMESTAMP.len()
+                        + SPACING_WIDTH;
 
                     em_advance * max_char_count
                 });
@@ -15158,13 +15162,13 @@ impl EditorSnapshot {
             px(0.)
         };
 
-        GutterDimensions {
+        Some(GutterDimensions {
             left_padding,
             right_padding,
             width: line_gutter_width + left_padding + right_padding,
             margin: -descent,
             git_blame_entries_width,
-        }
+        })
     }
 
     pub fn render_crease_toggle(

crates/editor/src/element.rs 🔗

@@ -6476,14 +6476,14 @@ impl Element for EditorElement {
 
                     let letter_size = size(em_width, line_height);
 
-                    let gutter_dimensions = snapshot.gutter_dimensions(
-                        font_id,
-                        font_size,
-                        em_width,
-                        em_advance,
-                        self.max_line_number_width(&snapshot, window, cx),
-                        cx,
-                    );
+                    let gutter_dimensions = snapshot
+                        .gutter_dimensions(
+                            font_id,
+                            font_size,
+                            self.max_line_number_width(&snapshot, window, cx),
+                            cx,
+                        )
+                        .unwrap_or_default();
                     let text_width = bounds.size.width - gutter_dimensions.width;
 
                     let editor_width = text_width - gutter_dimensions.margin - em_width;
@@ -8043,17 +8043,11 @@ fn compute_auto_height_layout(
     let font_size = style.text.font_size.to_pixels(window.rem_size());
     let line_height = style.text.line_height_in_pixels(window.rem_size());
     let em_width = window.text_system().em_width(font_id, font_size).unwrap();
-    let em_advance = window.text_system().em_advance(font_id, font_size).unwrap();
 
     let mut snapshot = editor.snapshot(window, cx);
-    let gutter_dimensions = snapshot.gutter_dimensions(
-        font_id,
-        font_size,
-        em_width,
-        em_advance,
-        max_line_number_width,
-        cx,
-    );
+    let gutter_dimensions = snapshot
+        .gutter_dimensions(font_id, font_size, max_line_number_width, cx)
+        .unwrap_or_default();
 
     editor.gutter_dimensions = gutter_dimensions;
     let text_width = width - gutter_dimensions.width;

crates/git/src/git.rs 🔗

@@ -45,6 +45,9 @@ actions!(
     ]
 );
 
+/// The length of a Git short SHA.
+pub const SHORT_SHA_LENGTH: usize = 7;
+
 #[derive(Clone, Copy, Eq, Hash, PartialEq)]
 pub struct Oid(libgit::Oid);
 
@@ -64,7 +67,7 @@ impl Oid {
 
     /// Returns this [`Oid`] as a short SHA.
     pub fn display_short(&self) -> String {
-        self.to_string().chars().take(7).collect()
+        self.to_string().chars().take(SHORT_SHA_LENGTH).collect()
     }
 }