ttf_parser/ggg/
context.rs

1use super::{ClassDefinition, Coverage, LookupIndex};
2use crate::parser::{FromData, FromSlice, LazyArray16, LazyOffsetArray16, Stream};
3
4/// A [Contextual Lookup Subtable](
5/// https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#seqctxt1).
6#[allow(missing_docs)]
7#[derive(Clone, Copy, Debug)]
8pub enum ContextLookup<'a> {
9    /// Simple glyph contexts.
10    Format1 {
11        coverage: Coverage<'a>,
12        sets: SequenceRuleSets<'a>,
13    },
14    /// Class-based glyph contexts.
15    Format2 {
16        coverage: Coverage<'a>,
17        classes: ClassDefinition<'a>,
18        sets: SequenceRuleSets<'a>,
19    },
20    /// Coverage-based glyph contexts.
21    Format3 {
22        coverage: Coverage<'a>,
23        coverages: LazyOffsetArray16<'a, Coverage<'a>>,
24        lookups: LazyArray16<'a, SequenceLookupRecord>,
25    },
26}
27
28impl<'a> ContextLookup<'a> {
29    pub(crate) fn parse(data: &'a [u8]) -> Option<Self> {
30        let mut s = Stream::new(data);
31        match s.read::<u16>()? {
32            1 => {
33                let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
34                let count = s.read::<u16>()?;
35                let offsets = s.read_array16(count)?;
36                Some(Self::Format1 {
37                    coverage,
38                    sets: SequenceRuleSets::new(data, offsets),
39                })
40            }
41            2 => {
42                let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
43                let classes = ClassDefinition::parse(s.read_at_offset16(data)?)?;
44                let count = s.read::<u16>()?;
45                let offsets = s.read_array16(count)?;
46                Some(Self::Format2 {
47                    coverage,
48                    classes,
49                    sets: SequenceRuleSets::new(data, offsets),
50                })
51            }
52            3 => {
53                let input_count = s.read::<u16>()?;
54                let lookup_count = s.read::<u16>()?;
55                let coverage = Coverage::parse(s.read_at_offset16(data)?)?;
56                let coverages = s.read_array16(input_count.checked_sub(1)?)?;
57                let lookups = s.read_array16(lookup_count)?;
58                Some(Self::Format3 {
59                    coverage,
60                    coverages: LazyOffsetArray16::new(data, coverages),
61                    lookups,
62                })
63            }
64            _ => None,
65        }
66    }
67
68    /// Returns the subtable coverage.
69    #[inline]
70    pub fn coverage(&self) -> Coverage<'a> {
71        match self {
72            Self::Format1 { coverage, .. } => *coverage,
73            Self::Format2 { coverage, .. } => *coverage,
74            Self::Format3 { coverage, .. } => *coverage,
75        }
76    }
77}
78
79/// A list of [`SequenceRuleSet`]s.
80pub type SequenceRuleSets<'a> = LazyOffsetArray16<'a, SequenceRuleSet<'a>>;
81
82impl<'a> FromSlice<'a> for SequenceRuleSet<'a> {
83    fn parse(data: &'a [u8]) -> Option<Self> {
84        Self::parse(data)
85    }
86}
87
88impl<'a> FromSlice<'a> for SequenceRule<'a> {
89    fn parse(data: &'a [u8]) -> Option<Self> {
90        let mut s = Stream::new(data);
91        let input_count = s.read::<u16>()?;
92        let lookup_count = s.read::<u16>()?;
93        let input = s.read_array16(input_count.checked_sub(1)?)?;
94        let lookups = s.read_array16(lookup_count)?;
95        Some(Self { input, lookups })
96    }
97}
98
99/// A set of [`SequenceRule`]s.
100pub type SequenceRuleSet<'a> = LazyOffsetArray16<'a, SequenceRule<'a>>;
101
102/// A sequence rule.
103#[allow(missing_docs)]
104#[derive(Clone, Copy, Debug)]
105pub struct SequenceRule<'a> {
106    pub input: LazyArray16<'a, u16>,
107    pub lookups: LazyArray16<'a, SequenceLookupRecord>,
108}
109
110/// A sequence rule record.
111#[allow(missing_docs)]
112#[derive(Clone, Copy, Debug)]
113pub struct SequenceLookupRecord {
114    pub sequence_index: u16,
115    pub lookup_list_index: LookupIndex,
116}
117
118impl FromData for SequenceLookupRecord {
119    const SIZE: usize = 4;
120
121    #[inline]
122    fn parse(data: &[u8]) -> Option<Self> {
123        let mut s = Stream::new(data);
124        Some(Self {
125            sequence_index: s.read::<u16>()?,
126            lookup_list_index: s.read::<LookupIndex>()?,
127        })
128    }
129}