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