diff options
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, }) } |