diff options
author | Christian Duerr <chrisduerr@users.noreply.github.com> | 2018-12-22 17:16:54 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-22 17:16:54 +0000 |
commit | 2f9b815ebdcee4558284e5e9cef6ef282dc87b08 (patch) | |
tree | 09bf03e5c69d9e7e99e04ff55983ea5774435b86 /font | |
parent | dad44134e2546dffec918a00169d32c6f9edc709 (diff) |
Add proper underline and strikeout support
This makes use of the new rectangle rendering methods used to display
the colored visual bell to add proper underline and strikeout support to
Alacritty.
Diffstat (limited to 'font')
-rw-r--r-- | font/src/darwin/mod.rs | 15 | ||||
-rw-r--r-- | font/src/ft/mod.rs | 36 | ||||
-rw-r--r-- | font/src/lib.rs | 4 | ||||
-rw-r--r-- | font/src/rusttype/mod.rs | 21 |
4 files changed, 73 insertions, 3 deletions
diff --git a/font/src/darwin/mod.rs b/font/src/darwin/mod.rs index 7f01f57b..ca784ae6 100644 --- a/font/src/darwin/mod.rs +++ b/font/src/darwin/mod.rs @@ -430,10 +430,25 @@ impl Font { let leading = self.ct_font.leading() as f64; let line_height = (ascent + descent + leading + 0.5).floor(); + // Strikeout and underline metrics + // CoreText doesn't provide strikeout so we provide our own + let underline_position = + (self.ct_font.underline_position() - descent) + .round() as f32; + let underline_thickness = self.ct_font.underline_thickness() + .round() + .max(1.) as f32; + let strikeout_position = (line_height as f32 / 2. - descent as f32).round(); + let strikeout_thickness = underline_thickness; + Metrics { average_advance, line_height, descent: -(self.ct_font.descent() as f32), + underline_position, + underline_thickness, + strikeout_position, + strikeout_thickness, } } diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs index 1d3f64bd..03e8bb31 100644 --- a/font/src/ft/mod.rs +++ b/font/src/ft/mod.rs @@ -18,6 +18,7 @@ use std::cmp::min; use std::path::PathBuf; use std::fmt; +use freetype::tt_os2::TrueTypeOS2Table; use freetype::{self, Library}; use libc::c_uint; @@ -86,15 +87,50 @@ impl ::Rasterize for FreeTypeRasterizer { } fn metrics(&self, key: FontKey, _size: Size) -> Result<Metrics, Error> { + let face = self.faces + .get(&key) + .ok_or(Error::FontNotLoaded)?; let full = self.full_metrics(key)?; let height = (full.size_metrics.height / 64) as f64; let descent = (full.size_metrics.descender / 64) as f32; + // Get underline position and thickness in device pixels + let x_scale = full.size_metrics.x_scale as f32 / 65536.0; + let underline_position = + (f32::from(face.ft_face.underline_position()) * x_scale / 64.).round(); + let underline_thickness = + (f32::from(face.ft_face.underline_thickness()) * x_scale / 64.) + .round() + .max(1.); + + // Get strikeout position and thickness in device pixels + let (strikeout_position, strikeout_thickness) = + match TrueTypeOS2Table::from_face(&mut face.ft_face.clone()) + { + Some(os2) => { + let strikeout_position = + (f32::from(os2.y_strikeout_position()) * x_scale / 64.).round(); + let strikeout_thickness = + (f32::from(os2.y_strikeout_size()) * x_scale / 64.).round(); + (strikeout_position, strikeout_thickness) + }, + _ => { + // Fallback if font doesn't provide info about strikeout + trace!("No strikeout data available for font, using fallback."); + let strikeout_position = height as f32 / 2. + descent; + (strikeout_position, underline_thickness) + }, + }; + Ok(Metrics { average_advance: full.cell_width, line_height: height, descent, + underline_position, + underline_thickness, + strikeout_position, + strikeout_thickness, }) } diff --git a/font/src/lib.rs b/font/src/lib.rs index 1db08217..fdba4b87 100644 --- a/font/src/lib.rs +++ b/font/src/lib.rs @@ -336,6 +336,10 @@ pub struct Metrics { pub average_advance: f64, pub line_height: f64, pub descent: f32, + pub underline_position: f32, + pub underline_thickness: f32, + pub strikeout_position: f32, + pub strikeout_thickness: f32, } pub trait Rasterize { diff --git a/font/src/rusttype/mod.rs b/font/src/rusttype/mod.rs index dea58150..2d28a8bd 100644 --- a/font/src/rusttype/mod.rs +++ b/font/src/rusttype/mod.rs @@ -33,10 +33,25 @@ impl crate::Rasterize for RustTypeRasterizer { .ok_or(Error::MissingGlyph)? .scaled(scale) .h_metrics(); + + let line_height = f64::from(vmetrics.ascent - vmetrics.descent + vmetrics.line_gap); + let average_advance = f64::from(hmetrics.advance_width); + let descent = vmetrics.descent; + + // Strikeout and underline metrics + // RustType doesn't support these, so we make up our own + let thickness = (descent / 5.).round(); + let underline_position = descent / 2. + thickness / 2.; + let strikeout_position = (line_height as f32 / 2. - descent).round(); + Ok(Metrics { - descent: vmetrics.descent, - average_advance: f64::from(hmetrics.advance_width), - line_height: f64::from(vmetrics.ascent - vmetrics.descent + vmetrics.line_gap), + descent, + average_advance, + line_height, + underline_position, + underline_thickness: thickness, + strikeout_position, + strikeout_thickness: thickness, }) } |