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<'_> = Stream::new(data);
91 let input_count: u16 = s.read::<u16>()?;
92 let lookup_count: u16 = s.read::<u16>()?;
93 let input: LazyArray16<'_, u16> = s.read_array16(count:input_count.checked_sub(1)?)?;
94 let lookups: LazyArray16<'_, SequenceLookupRecord> = 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<'_> = Stream::new(data);
124 Some(Self {
125 sequence_index: s.read::<u16>()?,
126 lookup_list_index: s.read::<LookupIndex>()?,
127 })
128 }
129}
130