Use ch-width (0) instead of em-width (m) for gutter width calculation (#32548)

Closes #21860

Release Notes:

- Added `ch_width` and `ch_advance` function alongside their `em_*`
counterparts
- Use `ch_*` version to calculate gutter layouts
- Update a stale comment from changes in #31959

The ch units refer to the width of the number `0` whereas em is the
width of `m` and the actual font size (e.g. 16px means 16 px width of
`m`).

This change has no effect for monospaced fonts but can be drastic for
proportional ones as seen below for "Zed Plex Sans" with a
`"min_line_number_width" = 4`.

<img width="726" alt="Screenshot 2025-06-11 at 15 47 35"
src="https://github.com/user-attachments/assets/aa73f4d4-32bc-42cf-a9f6-7e25fee68c9a"
/>
This commit is contained in:
Max Mynter 2025-06-12 07:28:04 +02:00 committed by GitHub
parent f428d54b74
commit 242af863f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 27 additions and 12 deletions

View file

@ -21565,8 +21565,8 @@ impl EditorSnapshot {
return None;
}
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 ch_width = cx.text_system().ch_width(font_id, font_size).log_err()?;
let ch_advance = cx.text_system().ch_advance(font_id, font_size).log_err()?;
let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
matches!(
@ -21579,9 +21579,10 @@ impl EditorSnapshot {
.show_line_numbers
.unwrap_or(gutter_settings.line_numbers);
let line_gutter_width = if show_line_numbers {
// Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
// Avoid flicker-like gutter resizes when the line number gains another digit by
// only resizing the gutter on files with > 10**min_line_number_digits lines.
let min_width_for_number_on_gutter =
em_advance * gutter_settings.min_line_number_digits as f32;
ch_advance * gutter_settings.min_line_number_digits as f32;
max_line_number_width.max(min_width_for_number_on_gutter)
} else {
0.0.into()
@ -21604,20 +21605,20 @@ impl EditorSnapshot {
+ MAX_RELATIVE_TIMESTAMP.len()
+ SPACING_WIDTH;
em_advance * max_char_count
ch_advance * max_char_count
});
let is_singleton = self.buffer_snapshot.is_singleton();
let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
left_padding += if !is_singleton {
em_width * 4.0
ch_width * 4.0
} else if show_runnables || show_breakpoints {
em_width * 3.0
ch_width * 3.0
} else if show_git_gutter && show_line_numbers {
em_width * 2.0
ch_width * 2.0
} else if show_git_gutter || show_line_numbers {
em_width
ch_width
} else {
px(0.)
};
@ -21625,11 +21626,11 @@ impl EditorSnapshot {
let shows_folds = is_singleton && gutter_settings.folds;
let right_padding = if shows_folds && show_line_numbers {
em_width * 4.0
ch_width * 4.0
} else if shows_folds || (!is_singleton && show_line_numbers) {
em_width * 3.0
ch_width * 3.0
} else if show_line_numbers {
em_width
ch_width
} else {
px(0.)
};