skrifa/outline/
metrics.rs

1//! Helper for loading (possibly variable) horizontal glyph metrics.
2
3use raw::{
4    tables::{hmtx::Hmtx, hvar::Hvar},
5    types::{F2Dot14, GlyphId},
6    FontRef, TableProvider,
7};
8
9/// Access to horizontal glyph metrics.
10#[derive(Clone)]
11pub(crate) struct GlyphHMetrics<'a> {
12    pub hmtx: Hmtx<'a>,
13    pub hvar: Option<Hvar<'a>>,
14}
15
16impl<'a> GlyphHMetrics<'a> {
17    pub fn new(font: &FontRef<'a>) -> Option<Self> {
18        // Note: hmtx is required and HVAR is optional
19        let hmtx = font.hmtx().ok()?;
20        let hvar = font.hvar().ok();
21        Some(Self { hmtx, hvar })
22    }
23
24    /// Returns the advance width (in font units) for the given glyph and
25    /// the location in variation space represented by the set of normalized
26    /// coordinates in 2.14 fixed point.
27    pub fn advance_width(&self, gid: GlyphId, coords: &'a [F2Dot14]) -> i32 {
28        let mut advance = self.hmtx.advance(gid).unwrap_or_default() as i32;
29        if let (false, Some(hvar)) = (coords.is_empty(), &self.hvar) {
30            advance += hvar
31                .advance_width_delta(gid, coords)
32                .map(|delta| delta.to_i32())
33                .unwrap_or(0);
34        }
35        advance
36    }
37
38    /// Returns the left side bearing (in font units) for the given glyph and
39    /// the location in variation space represented by the set of normalized
40    /// coordinates in 2.14 fixed point.    
41    pub fn lsb(&self, gid: GlyphId, coords: &'a [F2Dot14]) -> i32 {
42        let mut lsb = self.hmtx.side_bearing(gid).unwrap_or_default() as i32;
43        if let (false, Some(hvar)) = (coords.is_empty(), &self.hvar) {
44            lsb += hvar
45                .lsb_delta(gid, coords)
46                .map(|delta| delta.to_i32())
47                .unwrap_or(0);
48        }
49        lsb
50    }
51}