From b818d6acddb033e26c1ad8dcab23be537f04aca8 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Fri, 16 Feb 2018 00:40:00 +0100 Subject: [PATCH] Apply scaling to underline Until now the underline position and thickness has been used without applying any scaling. However they are both specified in font units which do not change with the font size. To make sure the underline looks correct with every size of the font, the thickness and position are now scaled by the `x_scale` stored in the font metrics. This does not fix strikethrough yet, even though it looks significantly better, the implementation is still a hack. To make sure the underline doesn't disappear with small fonts, the minimum underline thickness has been set to `1`. This decision was made because the `Hack` font has an underline thickness under `0.5` with relatively big fonts. This edge-case can lead to some odd behavior when making the font size super tiny (smaller than readable) so just not rendering any underline might be a viable alternative. --- font/src/ft/mod.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs index 6d77a61c..2eb3a034 100644 --- a/font/src/ft/mod.rs +++ b/font/src/ft/mod.rs @@ -93,10 +93,15 @@ impl ::Rasterize for FreeTypeRasterizer { 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()) / 64.).round(); + (f32::from(face.ft_face.underline_position()) * x_scale / 64.).round(); let underline_thickness = - (f32::from(face.ft_face.underline_thickness()) / 64.).round(); + (f32::from(face.ft_face.underline_thickness()) * x_scale / 64.) + .round() + .max(1.); Ok(Metrics { average_advance: full.cell_width,