read_fonts/tables/
cff2.rs

1//! The [CFF2](https://learn.microsoft.com/en-us/typography/opentype/spec/cff2) table
2
3include!("../../generated/generated_cff2.rs");
4
5use super::postscript::Index2;
6
7/// The [Compact Font Format (CFF) version 2](https://learn.microsoft.com/en-us/typography/opentype/spec/cff2) table
8#[derive(Clone)]
9pub struct Cff2<'a> {
10    header: Cff2Header<'a>,
11    global_subrs: Index2<'a>,
12}
13
14impl<'a> Cff2<'a> {
15    pub fn offset_data(&self) -> FontData<'a> {
16        self.header.offset_data()
17    }
18
19    pub fn header(&self) -> &Cff2Header<'a> {
20        &self.header
21    }
22
23    /// Returns the raw data containing the top dict.
24    ///
25    /// See <https://learn.microsoft.com/en-us/typography/opentype/spec/cff2#7-top-dict-data>
26    pub fn top_dict_data(&self) -> &'a [u8] {
27        self.header.top_dict_data()
28    }
29
30    /// Returns the global subroutine index.
31    ///
32    /// This contains sub-programs that are referenced by one or more
33    /// charstrings in the font set.
34    ///
35    /// See "Local/Global Subrs INDEXes" at <https://adobe-type-tools.github.io/font-tech-notes/pdfs/5176.CFF.pdf#page=25>
36    pub fn global_subrs(&self) -> Index2<'a> {
37        self.global_subrs.clone()
38    }
39}
40
41impl TopLevelTable for Cff2<'_> {
42    const TAG: Tag = Tag::new(b"CFF2");
43}
44
45impl<'a> FontRead<'a> for Cff2<'a> {
46    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
47        let header = Cff2Header::read(data)?;
48        let global_subrs = Index2::read(FontData::new(header.trailing_data()))?;
49        Ok(Self {
50            header,
51            global_subrs,
52        })
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use crate::{FontData, FontRead, FontRef, TableProvider};
60
61    #[test]
62    fn read_example_cff2_table() {
63        let cff2 = Cff2::read(FontData::new(font_test_data::cff2::EXAMPLE)).unwrap();
64        assert_eq!(cff2.header().major_version(), 2);
65        assert_eq!(cff2.header().minor_version(), 0);
66        assert_eq!(cff2.header().header_size(), 5);
67        assert_eq!(cff2.top_dict_data().len(), 7);
68        assert_eq!(cff2.global_subrs().count(), 0);
69    }
70
71    #[test]
72    fn read_cantarell() {
73        let font = FontRef::new(font_test_data::CANTARELL_VF_TRIMMED).unwrap();
74        let cff2 = font.cff2().unwrap();
75        assert_eq!(cff2.header().major_version(), 2);
76        assert_eq!(cff2.header().minor_version(), 0);
77        assert_eq!(cff2.header().header_size(), 5);
78        assert_eq!(cff2.top_dict_data().len(), 7);
79        assert_eq!(cff2.global_subrs().count(), 0);
80    }
81}