windows: Fix ascent/descent calculations (#40103)
This applies the same fix as #39886 for Windows. Previously we were using `GetLineMetrics` to determine the ascent and descent values for each line. It seems like this has the same behavior as `GetTypographicBounds` on macOS, which is to return the minimum ascent and descent for the current state of the `TextLayout` object. This causes the ascent/descent to be unstable when adding or removing an emoji because a font fallback is triggered when an emoji is present on the line. The issue is fixed by switching to `font.GetMetrics` to get the ascent and descent, which should always return stable values for the main font, instead of changing when there's a fallback. This also should support situations where we have multiple explicit fonts on the same line, although that probably can't be triggered in Zed right now. Release Notes: - windows: Fixed a vertical shift in text layout when inserting or removing an emoji. Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
This commit is contained in:
co-authored by
Bennet Bo Fenner
parent
02bdba80a4
commit
f1db1f3a3c
@@ -606,19 +606,21 @@ impl DirectWriteState {
|
||||
};
|
||||
|
||||
let mut first_run = true;
|
||||
let mut ascent = Pixels::default();
|
||||
let mut descent = Pixels::default();
|
||||
let mut max_ascent = 0.0_f32;
|
||||
let mut max_descent = 0.0_f32;
|
||||
for run in font_runs {
|
||||
let font_info = &self.fonts[run.font_id.0];
|
||||
let mut metrics = std::mem::zeroed();
|
||||
font_info.font_face.GetMetrics(&mut metrics);
|
||||
let font_scale = font_size.0 / metrics.Base.designUnitsPerEm as f32;
|
||||
max_ascent = max_ascent.max(metrics.Base.ascent as f32 * font_scale);
|
||||
max_descent = max_descent.max(-(metrics.Base.descent as f32 * font_scale));
|
||||
|
||||
if first_run {
|
||||
first_run = false;
|
||||
let mut metrics = vec![DWRITE_LINE_METRICS::default(); 4];
|
||||
let mut line_count = 0u32;
|
||||
text_layout.GetLineMetrics(Some(&mut metrics), &mut line_count as _)?;
|
||||
ascent = px(metrics[0].baseline);
|
||||
descent = px(metrics[0].height - metrics[0].baseline);
|
||||
continue;
|
||||
}
|
||||
let font_info = &self.fonts[run.font_id.0];
|
||||
|
||||
let current_text = &text[utf8_offset..(utf8_offset + run.len)];
|
||||
utf8_offset += run.len;
|
||||
let current_text_utf16_length = current_text.encode_utf16().count() as u32;
|
||||
@@ -660,8 +662,8 @@ impl DirectWriteState {
|
||||
Ok(LineLayout {
|
||||
font_size,
|
||||
width,
|
||||
ascent,
|
||||
descent,
|
||||
ascent: max_ascent.into(),
|
||||
descent: max_descent.into(),
|
||||
runs,
|
||||
len: text.len(),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user