1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use truetype::tables::offsets::Offsets;

use crate::tape::Read;
use crate::{Result, Table};

/// A font.
pub struct Font {
    /// The offset table.
    pub offsets: Offsets,
}

impl Font {
    /// Read a file.
    #[inline]
    pub fn read<T>(tape: &mut T) -> Result<Self>
    where
        T: crate::tape::Read,
    {
        Read::take(tape)
    }

    /// Read a table.
    #[inline]
    pub fn take<'l, T, U>(&self, tape: &mut T) -> Result<Option<U>>
    where
        T: crate::tape::Read,
        U: Table<'l, Parameter = ()>,
    {
        self.take_given(tape, ())
    }

    /// Read a table given a parameter.
    pub fn take_given<'l, T, U>(&self, tape: &mut T, parameter: U::Parameter) -> Result<Option<U>>
    where
        T: crate::tape::Read,
        U: Table<'l>,
    {
        let tag = U::tag();
        for record in &self.offsets.records {
            if record.tag == tag {
                #[cfg(not(feature = "ignore-invalid-checksums"))]
                if record.checksum != record.checksum(tape)? {
                    raise!("found a malformed font table with {:?}", record.tag);
                }
                Read::jump(tape, record.offset as u64)?;
                return Ok(Some(Table::take(tape, parameter)?));
            }
        }
        Ok(None)
    }
}

impl crate::value::Read for Font {
    #[inline]
    fn read<T: crate::tape::Read>(tape: &mut T) -> Result<Self> {
        Ok(Self {
            offsets: tape.take()?,
        })
    }
}