From 59b561b440060e7b0d13160fb69519d127e6c687 Mon Sep 17 00:00:00 2001 From: Rachel K <32377646+rkanati@users.noreply.github.com> Date: Sun, 21 Jan 2018 21:29:57 +0000 Subject: [PATCH] Better character cell width with FreeType (#1029) This should fix #1020, #710, and #902 --- font/src/ft/mod.rs | 58 ++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs index 7ed3b42..68d2faf 100644 --- a/font/src/ft/mod.rs +++ b/font/src/ft/mod.rs @@ -86,19 +86,13 @@ impl ::Rasterize for FreeTypeRasterizer { } fn metrics(&self, key: FontKey) -> Result { - let face = self.faces - .get(&key) - .ok_or(Error::FontNotLoaded)?; + let full = self.full_metrics(key)?; - let size_metrics = face.ft_face.size_metrics() - .ok_or(Error::MissingSizeMetrics)?; - - let width = (size_metrics.max_advance / 64) as f64; - let height = (size_metrics.height / 64) as f64; - let descent = (size_metrics.descender / 64) as f32; + let height = (full.size_metrics.height / 64) as f64; + let descent = (full.size_metrics.descender / 64) as f32; Ok(Metrics { - average_advance: width, + average_advance: full.cell_width, line_height: height, descent: descent, }) @@ -141,6 +135,11 @@ impl IntoFontconfigType for Weight { } } +struct FullMetrics { + size_metrics: freetype::ffi::FT_Size_Metrics, + cell_width: f64 +} + impl FreeTypeRasterizer { /// Load a font face according to `FontDesc` fn get_face(&mut self, desc: &FontDesc, size: Size) -> Result { @@ -159,6 +158,25 @@ impl FreeTypeRasterizer { } } + fn full_metrics(&self, key: FontKey) -> Result { + let face = self.faces + .get(&key) + .ok_or(Error::FontNotLoaded)?; + + let size_metrics = face.ft_face.size_metrics() + .ok_or(Error::MissingSizeMetrics)?; + + let width = match face.ft_face.load_char('0' as usize, face.load_flags) { + Ok(_) => face.ft_face.glyph().metrics().horiAdvance / 64, + Err(_) => size_metrics.max_advance / 64 + } as f64; + + Ok(FullMetrics { + size_metrics: size_metrics, + cell_width: width + }) + } + fn get_matching_face( &mut self, desc: &FontDesc, @@ -278,16 +296,13 @@ impl FreeTypeRasterizer { super::UNDERLINE_CURSOR_CHAR => { // Get the primary face metrics // This always loads the default face - let face = self.faces.get(&glyph_key.font_key).unwrap(); - let size_metrics = face.ft_face - .size_metrics() - .ok_or(Error::MissingSizeMetrics)?; + let full = self.full_metrics(glyph_key.font_key)?; // Get the bottom of the bounding box - let descent = (size_metrics.descender / 64) as i32; + let descent = (full.size_metrics.descender / 64) as i32; // Get the width of the cell - let width = (size_metrics.max_advance / 64) as i32; + let width = full.cell_width as i32; // Return the new custom glyph return super::get_underline_cursor_glyph(descent, width); @@ -295,20 +310,17 @@ impl FreeTypeRasterizer { super::BEAM_CURSOR_CHAR | super::BOX_CURSOR_CHAR => { // Get the primary face metrics // This always loads the default face - let face = self.faces.get(&glyph_key.font_key).unwrap(); - let size_metrics = face.ft_face - .size_metrics() - .ok_or(Error::MissingSizeMetrics)?; + let full = self.full_metrics(glyph_key.font_key)?; // Get the height of the cell - let height = (size_metrics.height / 64) as i32; + let height = (full.size_metrics.height / 64) as i32; // Get the top of the bounding box - let descent = (size_metrics.descender / 64) as i32; + let descent = (full.size_metrics.descender / 64) as i32; let ascent = height + descent; // Get the width of the cell - let width = (size_metrics.max_advance / 64) as i32; + let width = full.cell_width as i32; // Return the new custom glyph return if glyph_key.c == super::BEAM_CURSOR_CHAR {