1 | use super::{ClassDefinition, Coverage, LookupIndex}; |
2 | use 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)] |
8 | pub 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 | |
28 | impl<'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. |
80 | pub type SequenceRuleSets<'a> = LazyOffsetArray16<'a, SequenceRuleSet<'a>>; |
81 | |
82 | impl<'a> FromSlice<'a> for SequenceRuleSet<'a> { |
83 | fn parse(data: &'a [u8]) -> Option<Self> { |
84 | Self::parse(data) |
85 | } |
86 | } |
87 | |
88 | impl<'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. |
100 | pub type SequenceRuleSet<'a> = LazyOffsetArray16<'a, SequenceRule<'a>>; |
101 | |
102 | /// A sequence rule. |
103 | #[allow (missing_docs)] |
104 | #[derive (Clone, Copy, Debug)] |
105 | pub 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)] |
113 | pub struct SequenceLookupRecord { |
114 | pub sequence_index: u16, |
115 | pub lookup_list_index: LookupIndex, |
116 | } |
117 | |
118 | impl 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 | |