aboutsummaryrefslogtreecommitdiff
path: root/font
diff options
context:
space:
mode:
Diffstat (limited to 'font')
-rw-r--r--font/src/darwin/mod.rs15
-rw-r--r--font/src/ft/mod.rs36
-rw-r--r--font/src/lib.rs4
-rw-r--r--font/src/rusttype/mod.rs21
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,
})
}