1use crate::GlyphId;
4use crate::parser::{FromData, LazyArray16, NumFrom, Offset, Offset32, Stream};
5
6#[derive(Clone, Copy)]
7struct SvgDocumentRecord {
8 start_glyph_id: GlyphId,
9 end_glyph_id: GlyphId,
10 svg_doc_offset: Option<Offset32>,
11 svg_doc_length: u32,
12}
13
14impl FromData for SvgDocumentRecord {
15 const SIZE: usize = 12;
16
17 #[inline]
18 fn parse(data: &[u8]) -> Option<Self> {
19 let mut s = Stream::new(data);
20 Some(SvgDocumentRecord {
21 start_glyph_id: s.read::<GlyphId>()?,
22 end_glyph_id: s.read::<GlyphId>()?,
23 svg_doc_offset: s.read::<Option<Offset32>>()?,
24 svg_doc_length: s.read::<u32>()?,
25 })
26 }
27}
28
29
30#[derive(Clone, Copy)]
33pub struct SvgDocumentsList<'a> {
34 data: &'a [u8],
35 records: LazyArray16<'a, SvgDocumentRecord>,
36}
37
38impl<'a> SvgDocumentsList<'a> {
39 #[inline]
43 pub fn get(&self, index: u16) -> Option<&'a [u8]> {
44 let record = self.records.get(index)?;
45 let offset = record.svg_doc_offset?.to_usize();
46 self.data.get(offset..offset + usize::num_from(record.svg_doc_length))
47 }
48
49 #[inline]
51 pub fn find(&self, glyph_id: GlyphId) -> Option<&'a [u8]> {
52 let index = self.records.into_iter()
53 .position(|v| (v.start_glyph_id..=v.end_glyph_id).contains(&glyph_id))?;
54 self.get(index as u16)
55 }
56
57 pub fn len(&self) -> u16 {
59 self.records.len()
60 }
61}
62
63impl core::fmt::Debug for SvgDocumentsList<'_> {
64 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
65 write!(f, "SvgDocumentsList {{ ... }}")
66 }
67}
68
69impl<'a> IntoIterator for SvgDocumentsList<'a,> {
70 type Item = &'a [u8];
71 type IntoIter = SvgDocumentsListIter<'a>;
72
73 #[inline]
74 fn into_iter(self) -> Self::IntoIter {
75 SvgDocumentsListIter {
76 list: self,
77 index: 0,
78 }
79 }
80}
81
82
83#[derive(Clone, Copy)]
85#[allow(missing_debug_implementations)]
86pub struct SvgDocumentsListIter<'a> {
87 list: SvgDocumentsList<'a>,
88 index: u16,
89}
90
91impl<'a> Iterator for SvgDocumentsListIter<'a> {
92 type Item = &'a [u8];
93
94 #[inline]
95 fn next(&mut self) -> Option<Self::Item> {
96 if self.index < self.list.len() {
97 self.index += 1;
98 self.list.get(self.index - 1)
99 } else {
100 None
101 }
102 }
103
104 #[inline]
105 fn count(self) -> usize {
106 usize::from(self.list.len().checked_sub(self.index).unwrap_or(0))
107 }
108}
109
110
111#[derive(Clone, Copy, Debug)]
113pub struct Table<'a> {
114 pub documents: SvgDocumentsList<'a>,
116}
117
118impl<'a> Table<'a> {
119 pub fn parse(data: &'a [u8]) -> Option<Self> {
121 let mut s = Stream::new(data);
122 s.skip::<u16>(); let doc_list_offset = s.read::<Option<Offset32>>()??;
124
125 let mut s = Stream::new_at(data, doc_list_offset.to_usize())?;
126 let count = s.read::<u16>()?;
127 let records = s.read_array16::<SvgDocumentRecord>(count)?;
128
129 Some(Table {
130 documents: SvgDocumentsList {
131 data: &data[doc_list_offset.0 as usize..],
132 records,
133 }
134 })
135 }
136}