Skip to content

Commit

Permalink
[skrifa] use hdmx table if available (#1165)
Browse files Browse the repository at this point in the history
In `ScaledOutline::adjusted_advance_width()` prefer widths from `hdmx` over phantom points to better match FreeType.
  • Loading branch information
dfrg authored Oct 2, 2024
1 parent d4e29ac commit bbc62a6
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
25 changes: 25 additions & 0 deletions skrifa/src/outline/glyf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use read_fonts::{
Anchor, CompositeGlyph, CompositeGlyphFlags, Glyf, Glyph, PointMarker, SimpleGlyph,
},
gvar::Gvar,
hdmx::Hdmx,
loca::Loca,
},
types::{F26Dot6, F2Dot14, Fixed, GlyphId, Point, Tag},
Expand All @@ -38,6 +39,7 @@ pub struct Outlines<'a> {
loca: Loca<'a>,
glyf: Glyf<'a>,
gvar: Option<Gvar<'a>>,
hdmx: Option<Hdmx<'a>>,
fpgm: &'a [u8],
prep: &'a [u8],
cvt_len: u32,
Expand Down Expand Up @@ -112,6 +114,7 @@ impl<'a> Outlines<'a> {
loca: font.loca(None).ok()?,
glyf: font.glyf().ok()?,
gvar: font.gvar().ok(),
hdmx: font.hdmx().ok(),
fpgm,
prep,
cvt_len,
Expand Down Expand Up @@ -231,6 +234,21 @@ impl<'a> Outlines<'a> {
}
Ok(())
}

fn hdmx_width(&self, ppem: f32, glyph_id: GlyphId) -> Option<u8> {
let hdmx = self.hdmx.as_ref()?;
let ppem_u8 = ppem as u8;
// Make sure our ppem is integral and fits into u8
if ppem_u8 as f32 == ppem {
// <https://gitlab.freedesktop.org/freetype/freetype/-/blob/57617782464411201ce7bbc93b086c1b4d7d84a5/src/truetype/ttgload.c#L1996>
hdmx.record_for_size(ppem_u8)?
.widths
.get(glyph_id.to_u32() as usize)
.copied()
} else {
None
}
}
}

trait Scaler {
Expand Down Expand Up @@ -290,6 +308,7 @@ pub(crate) struct HarfBuzzScaler<'a> {
point_count: usize,
contour_count: usize,
component_delta_count: usize,
ppem: f32,
scale: F26Dot6,
is_scaled: bool,
/// Phantom points. These are 4 extra points appended to the end of an
Expand Down Expand Up @@ -318,6 +337,7 @@ impl<'a> HarfBuzzScaler<'a> {
point_count: 0,
contour_count: 0,
component_delta_count: 0,
ppem: ppem.unwrap_or_default(),
scale,
is_scaled,
phantom: Default::default(),
Expand All @@ -335,6 +355,7 @@ impl<'a> HarfBuzzScaler<'a> {
self.phantom,
&mut self.memory.flags[..self.point_count],
&mut self.memory.contours[..self.contour_count],
self.outlines.hdmx_width(self.ppem, glyph_id),
))
}
}
Expand All @@ -347,6 +368,7 @@ pub(crate) struct FreeTypeScaler<'a> {
point_count: usize,
contour_count: usize,
component_delta_count: usize,
ppem: f32,
scale: F26Dot6,
is_scaled: bool,
is_hinted: bool,
Expand Down Expand Up @@ -378,6 +400,7 @@ impl<'a> FreeTypeScaler<'a> {
point_count: 0,
contour_count: 0,
component_delta_count: 0,
ppem: ppem.unwrap_or_default(),
scale,
is_scaled,
is_hinted: false,
Expand Down Expand Up @@ -406,6 +429,7 @@ impl<'a> FreeTypeScaler<'a> {
point_count: 0,
contour_count: 0,
component_delta_count: 0,
ppem: ppem.unwrap_or_default(),
scale,
is_scaled,
// We don't hint unscaled outlines
Expand All @@ -427,6 +451,7 @@ impl<'a> FreeTypeScaler<'a> {
self.phantom,
&mut self.memory.flags[..self.point_count],
&mut self.memory.contours[..self.contour_count],
self.outlines.hdmx_width(self.ppem, glyph_id),
))
}
}
Expand Down
12 changes: 11 additions & 1 deletion skrifa/src/outline/glyf/outline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ where
pub flags: &'a mut [PointFlags],
pub contours: &'a mut [u16],
pub phantom_points: [Point<C>; 4],
pub hdmx_width: Option<u8>,
}

impl<'a, C> ScaledOutline<'a, C>
Expand All @@ -117,6 +118,7 @@ where
phantom_points: [Point<C>; 4],
flags: &'a mut [PointFlags],
contours: &'a mut [u16],
hdmx_width: Option<u8>,
) -> Self {
let x_shift = phantom_points[0].x;
if x_shift != C::zeroed() {
Expand All @@ -129,6 +131,7 @@ where
flags,
contours,
phantom_points,
hdmx_width,
}
}

Expand All @@ -137,7 +140,14 @@ where
}

pub fn adjusted_advance_width(&self) -> C {
self.phantom_points[1].x - self.phantom_points[0].x
// Prefer widths from hdmx, otherwise take difference between first
// two phantom points
// <https://gitlab.freedesktop.org/freetype/freetype/-/blob/57617782464411201ce7bbc93b086c1b4d7d84a5/src/truetype/ttgload.c#L1996>
if let Some(hdmx_width) = self.hdmx_width {
C::from_i32(hdmx_width as i32)
} else {
self.phantom_points[1].x - self.phantom_points[0].x
}
}

pub fn to_path(
Expand Down

0 comments on commit bbc62a6

Please sign in to comment.