Skip to main content

read_fonts/ps/cff/
v2.rs

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