font/formats/opentype/
metrics.rs

1use std::io::Result;
2
3use opentype::truetype::tables::HorizontalMetrics;
4use opentype::truetype::GlyphID;
5
6use crate::formats::opentype::cache::{Cache, Reference};
7use crate::Number;
8
9pub struct Metrics {
10    horizontal_metrics: Reference<HorizontalMetrics>,
11}
12
13impl Metrics {
14    #[inline]
15    pub fn new(horizontal_metrics: Reference<HorizontalMetrics>) -> Self {
16        Metrics { horizontal_metrics }
17    }
18
19    #[inline]
20    pub fn get(&self, glyph_id: GlyphID) -> (Number, Number) {
21        let (advance_width, left_side_bearing) = self.horizontal_metrics.borrow().get(glyph_id);
22        (advance_width.into(), left_side_bearing.into())
23    }
24}
25
26pub fn read<T: crate::Read>(cache: &mut Cache<T>) -> Result<crate::Metrics> {
27    use opentype::truetype::tables::WindowsMetrics;
28
29    let font_header = cache.font_header()?.clone();
30    let font_header = font_header.borrow();
31    let windows_metrics = cache.windows_metrics()?.borrow();
32    macro_rules! get(
33        (@version0 $($version:ident),+) => (
34            match &*windows_metrics {
35                $(WindowsMetrics::$version(ref table) => (
36                    table.windows_ascender.into(),
37                    table.typographic_ascender.into(),
38                    table.typographic_descender.into(),
39                    -Number::from(table.windows_descender),
40                    table.typographic_line_gap.into(),
41                ),)*
42            }
43        );
44        (@version2 $($version:ident),+) => (
45            match &*windows_metrics {
46                $(WindowsMetrics::$version(ref table) => (
47                    table.cap_height.into(),
48                    table.x_height.into(),
49                ),)*
50                _ => (
51                    Number::NAN,
52                    Number::NAN,
53                ),
54            }
55        );
56    );
57    let (clipping_ascender, ascender, descender, clipping_descender, line_gap) =
58        get!(@version0 Version0, Version1, Version2, Version3, Version4, Version5);
59    let (cap_height, x_height) = get!(@version2 Version2, Version3, Version4, Version5);
60    Ok(crate::Metrics {
61        granularity: font_header.units_per_em.into(),
62        clipping_ascender,
63        ascender,
64        cap_height,
65        x_height,
66        baseline: if font_header.flags.is_baseline_at_0() {
67            0.0
68        } else {
69            Number::NAN
70        },
71        descender,
72        clipping_descender,
73        line_gap,
74    })
75}