allsorts_subset_browser/
font_data.rs

1//! Top-level font file representation.
2
3use std::borrow::Cow;
4
5use crate::binary::read::{ReadBinary, ReadCtxt};
6use crate::error::{ParseError, ReadWriteError};
7use crate::tables::{
8    FontTableProvider, OpenTypeFont, SfntVersion, CFF_MAGIC, TRUE_MAGIC, TTCF_MAGIC, TTF_MAGIC,
9};
10use crate::woff::{self, WoffFont};
11use crate::woff2::{self, Woff2Font};
12
13/// Type that can represent any of the supported font formats.
14#[derive(Clone)]
15pub enum FontData<'a> {
16    OpenType(OpenTypeFont<'a>),
17    Woff(WoffFont<'a>),
18    Woff2(Woff2Font<'a>),
19}
20
21/// Generic implementation of the `FontTableProvider` trait
22pub struct DynamicFontTableProvider<'a> {
23    sfnt_version: u32,
24    provider: Box<dyn FontTableProvider + 'a>,
25}
26
27impl<'b> ReadBinary for FontData<'b> {
28    type HostType<'a> = FontData<'a>;
29
30    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
31        let mut peek = ctxt.clone();
32        let magic = peek.read_u32be()?;
33        match magic {
34            TTF_MAGIC | TRUE_MAGIC | CFF_MAGIC => Ok(FontData::OpenType(OpenTypeFont::read(ctxt)?)),
35            TTCF_MAGIC => Ok(FontData::OpenType(OpenTypeFont::read(ctxt)?)),
36            woff::MAGIC => Ok(FontData::Woff(WoffFont::read(ctxt)?)),
37            woff2::MAGIC => Ok(FontData::Woff2(Woff2Font::read(ctxt)?)),
38            _ => Err(ParseError::BadVersion),
39        }
40    }
41}
42
43impl<'a> FontTableProvider for DynamicFontTableProvider<'a> {
44    fn table_data(&self, tag: u32) -> Result<Option<Cow<'_, [u8]>>, ParseError> {
45        self.provider.table_data(tag)
46    }
47
48    fn has_table(&self, tag: u32) -> bool {
49        self.provider.has_table(tag)
50    }
51
52    fn table_tags(&self) -> Option<Vec<u32>> {
53        self.provider.table_tags()
54    }
55}
56
57impl<'a> SfntVersion for DynamicFontTableProvider<'a> {
58    fn sfnt_version(&self) -> u32 {
59        self.sfnt_version
60    }
61}
62
63impl<'a> FontData<'a> {
64    /// Obtain an implementation of `FontTableProvider` for this font.
65    pub fn table_provider(
66        &self,
67        index: usize,
68    ) -> Result<DynamicFontTableProvider<'a>, ReadWriteError> {
69        match self {
70            FontData::OpenType(font) => {
71                let provider = font.table_provider(index)?;
72                Ok(DynamicFontTableProvider {
73                    sfnt_version: provider.sfnt_version(),
74                    provider: Box::new(provider),
75                })
76            }
77            FontData::Woff(font) => {
78                // This clone is relatively cheap as WoffFile is mostly holding borrowed data
79                Ok(DynamicFontTableProvider {
80                    sfnt_version: font.sfnt_version(),
81                    provider: Box::new(font.clone()),
82                })
83            }
84            FontData::Woff2(font) => {
85                let provider = font.table_provider(index)?;
86                Ok(DynamicFontTableProvider {
87                    sfnt_version: provider.sfnt_version(),
88                    provider: Box::new(provider),
89                })
90            }
91        }
92    }
93}