1use crate::parser::{FromData, LazyArray16, NumFrom, Offset, Offset32, Stream};
4use crate::GlyphId;
5
6#[derive(Clone, Copy, Debug)]
9pub struct SvgDocument<'a> {
10 pub data: &'a [u8],
14 pub start_glyph_id: GlyphId,
16 pub end_glyph_id: GlyphId,
18}
19
20impl SvgDocument<'_> {
21 pub fn glyphs_range(&self) -> core::ops::RangeInclusive<GlyphId> {
23 self.start_glyph_id..=self.end_glyph_id
24 }
25}
26
27#[derive(Clone, Copy)]
28struct SvgDocumentRecord {
29 start_glyph_id: GlyphId,
30 end_glyph_id: GlyphId,
31 svg_doc_offset: Option<Offset32>,
32 svg_doc_length: u32,
33}
34
35impl SvgDocumentRecord {
36 fn glyphs_range(&self) -> core::ops::RangeInclusive<GlyphId> {
37 self.start_glyph_id..=self.end_glyph_id
38 }
39}
40
41impl FromData for SvgDocumentRecord {
42 const SIZE: usize = 12;
43
44 #[inline]
45 fn parse(data: &[u8]) -> Option<Self> {
46 let mut s = Stream::new(data);
47 Some(SvgDocumentRecord {
48 start_glyph_id: s.read::<GlyphId>()?,
49 end_glyph_id: s.read::<GlyphId>()?,
50 svg_doc_offset: s.read::<Option<Offset32>>()?,
51 svg_doc_length: s.read::<u32>()?,
52 })
53 }
54}
55
56#[derive(Clone, Copy)]
59pub struct SvgDocumentsList<'a> {
60 data: &'a [u8],
61 records: LazyArray16<'a, SvgDocumentRecord>,
62}
63
64impl<'a> SvgDocumentsList<'a> {
65 #[inline]
69 pub fn get(&self, index: u16) -> Option<SvgDocument<'a>> {
70 let record = self.records.get(index)?;
71 let offset = record.svg_doc_offset?.to_usize();
72 self.data
73 .get(offset..offset + usize::num_from(record.svg_doc_length))
74 .map(|data| SvgDocument {
75 data,
76 start_glyph_id: record.start_glyph_id,
77 end_glyph_id: record.end_glyph_id,
78 })
79 }
80
81 #[inline]
83 pub fn find(&self, glyph_id: GlyphId) -> Option<SvgDocument<'a>> {
84 let index = self
85 .records
86 .into_iter()
87 .position(|v| v.glyphs_range().contains(&glyph_id))?;
88 self.get(index as u16)
89 }
90
91 pub fn len(&self) -> u16 {
93 self.records.len()
94 }
95
96 pub fn is_empty(&self) -> bool {
98 self.records.is_empty()
99 }
100}
101
102impl core::fmt::Debug for SvgDocumentsList<'_> {
103 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
104 write!(f, "SvgDocumentsList {{ ... }}")
105 }
106}
107
108impl<'a> IntoIterator for SvgDocumentsList<'a> {
109 type Item = SvgDocument<'a>;
110 type IntoIter = SvgDocumentsListIter<'a>;
111
112 #[inline]
113 fn into_iter(self) -> Self::IntoIter {
114 SvgDocumentsListIter {
115 list: self,
116 index: 0,
117 }
118 }
119}
120
121#[derive(Clone, Copy)]
123#[allow(missing_debug_implementations)]
124pub struct SvgDocumentsListIter<'a> {
125 list: SvgDocumentsList<'a>,
126 index: u16,
127}
128
129impl<'a> Iterator for SvgDocumentsListIter<'a> {
130 type Item = SvgDocument<'a>;
131
132 #[inline]
133 fn next(&mut self) -> Option<Self::Item> {
134 if self.index < self.list.len() {
135 self.index += 1;
136 self.list.get(self.index - 1)
137 } else {
138 None
139 }
140 }
141
142 #[inline]
143 fn count(self) -> usize {
144 usize::from(self.list.len().saturating_sub(self.index))
145 }
146}
147
148#[derive(Clone, Copy, Debug)]
150pub struct Table<'a> {
151 pub documents: SvgDocumentsList<'a>,
153}
154
155impl<'a> Table<'a> {
156 pub fn parse(data: &'a [u8]) -> Option<Self> {
158 let mut s = Stream::new(data);
159 s.skip::<u16>(); let doc_list_offset = s.read::<Option<Offset32>>()??;
161
162 let mut s = Stream::new_at(data, doc_list_offset.to_usize())?;
163 let count = s.read::<u16>()?;
164 let records = s.read_array16::<SvgDocumentRecord>(count)?;
165
166 Some(Table {
167 documents: SvgDocumentsList {
168 data: &data[doc_list_offset.0 as usize..],
169 records,
170 },
171 })
172 }
173}