Fix line metrics

Since bitmap fonts do not provide their own underline metrics, the
self-calculated metrics which have been used for rusttype are now also
used for bitmap fonts with freetype.

The rusttype and bitmap fallback metrics have incorrectly offset the
underline by the underline height. Since the position is already defined
as the center point, that is not necessary.

All rounding and clamping has also been removed from the font library,
so that the raw values are reported now. The clamping and rounding is
now done in the line renderer.
This commit is contained in:
Christian Duerr 2018-12-31 17:01:06 +00:00 committed by GitHub
parent 9ffaac8ee7
commit 7275ecc282
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 26 additions and 27 deletions

View File

@ -430,21 +430,17 @@ impl Font {
let leading = self.ct_font.leading() as f64; let leading = self.ct_font.leading() as f64;
let line_height = (ascent + descent + leading + 0.5).floor(); let line_height = (ascent + descent + leading + 0.5).floor();
// Strikeout and underline metrics // Strikeout and underline metrics.
// CoreText doesn't provide strikeout so we provide our own // CoreText doesn't provide strikeout so we provide our own.
let underline_position = let underline_position = (self.ct_font.underline_position() - descent) as f32;
(self.ct_font.underline_position() - descent) let underline_thickness = self.ct_font.underline_thickness() as f32;
.round() as f32; let strikeout_position = (line_height / 2. - descent) 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; let strikeout_thickness = underline_thickness;
Metrics { Metrics {
average_advance, average_advance,
line_height, line_height,
descent: -(self.ct_font.descent() as f32), descent: -(descent as f32),
underline_position, underline_position,
underline_thickness, underline_thickness,
strikeout_position, strikeout_position,

View File

@ -97,22 +97,22 @@ impl ::Rasterize for FreeTypeRasterizer {
// Get underline position and thickness in device pixels // Get underline position and thickness in device pixels
let x_scale = full.size_metrics.x_scale as f32 / 65536.0; let x_scale = full.size_metrics.x_scale as f32 / 65536.0;
let underline_position = let mut underline_position = f32::from(face.ft_face.underline_position()) * x_scale / 64.;
(f32::from(face.ft_face.underline_position()) * x_scale / 64.).round(); let mut underline_thickness = f32::from(face.ft_face.underline_thickness()) * x_scale / 64.;
let underline_thickness =
(f32::from(face.ft_face.underline_thickness()) * x_scale / 64.) // Fallback for bitmap fonts which do not provide underline metrics
.round() if underline_position == 0. {
.max(1.); underline_thickness = (descent / 5.).round();
underline_position = descent / 2.;
}
// Get strikeout position and thickness in device pixels // Get strikeout position and thickness in device pixels
let (strikeout_position, strikeout_thickness) = let (strikeout_position, strikeout_thickness) =
match TrueTypeOS2Table::from_face(&mut face.ft_face.clone()) match TrueTypeOS2Table::from_face(&mut face.ft_face.clone())
{ {
Some(os2) => { Some(os2) => {
let strikeout_position = let strikeout_position = f32::from(os2.y_strikeout_position()) * x_scale / 64.;
(f32::from(os2.y_strikeout_position()) * x_scale / 64.).round(); let strikeout_thickness = f32::from(os2.y_strikeout_size()) * x_scale / 64.;
let strikeout_thickness =
(f32::from(os2.y_strikeout_size()) * x_scale / 64.).round();
(strikeout_position, strikeout_thickness) (strikeout_position, strikeout_thickness)
}, },
_ => { _ => {

View File

@ -38,11 +38,11 @@ impl crate::Rasterize for RustTypeRasterizer {
let average_advance = f64::from(hmetrics.advance_width); let average_advance = f64::from(hmetrics.advance_width);
let descent = vmetrics.descent; let descent = vmetrics.descent;
// Strikeout and underline metrics // Strikeout and underline metrics.
// RustType doesn't support these, so we make up our own // RustType doesn't support these, so we make up our own.
let thickness = (descent / 5.).round(); let thickness = (descent / 5.).round();
let underline_position = descent / 2. + thickness / 2.; let underline_position = descent / 2.;
let strikeout_position = (line_height as f32 / 2. - descent).round(); let strikeout_position = line_height as f32 / 2. - descent;
Ok(Metrics { Ok(Metrics {
descent, descent,

View File

@ -122,12 +122,15 @@ fn create_rect(
let end_x = (end.column.0 + 1) as f32 * size.cell_width; let end_x = (end.column.0 + 1) as f32 * size.cell_width;
let width = end_x - start_x; let width = end_x - start_x;
let (position, height) = match flag { let (position, mut height) = match flag {
Flags::UNDERLINE => (metrics.underline_position, metrics.underline_thickness), Flags::UNDERLINE => (metrics.underline_position, metrics.underline_thickness),
Flags::STRIKEOUT => (metrics.strikeout_position, metrics.strikeout_thickness), Flags::STRIKEOUT => (metrics.strikeout_position, metrics.strikeout_thickness),
_ => unimplemented!("Invalid flag for cell line drawing specified"), _ => unimplemented!("Invalid flag for cell line drawing specified"),
}; };
// Make sure lines are always visible
height = height.max(1.);
let cell_bottom = (start.line.0 as f32 + 1.) * size.cell_height; let cell_bottom = (start.line.0 as f32 + 1.) * size.cell_height;
let baseline = cell_bottom + metrics.descent; let baseline = cell_bottom + metrics.descent;
@ -139,9 +142,9 @@ fn create_rect(
let rect = Rect::new( let rect = Rect::new(
start_x + size.padding_x, start_x + size.padding_x,
y + size.padding_y, y.round() + size.padding_y,
width, width,
height, height.round(),
); );
(rect, start.fg) (rect, start.fg)