ttf_parser/tables/
svg.rs

1//! An [SVG Table](https://docs.microsoft.com/en-us/typography/opentype/spec/svg) implementation.
2
3use 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/// A list of [SVG documents](
31/// https://docs.microsoft.com/en-us/typography/opentype/spec/svg#svg-document-list).
32#[derive(Clone, Copy)]
33pub struct SvgDocumentsList<'a> {
34    data: &'a [u8],
35    records: LazyArray16<'a, SvgDocumentRecord>,
36}
37
38impl<'a> SvgDocumentsList<'a> {
39    /// Returns SVG document data at index.
40    ///
41    /// `index` is not a GlyphId. You should use [`find()`](SvgDocumentsList::find) instead.
42    #[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    /// Returns a SVG document data by glyph ID.
50    #[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    /// Returns the number of SVG documents in the list.
58    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/// An iterator over [`SvgDocumentsList`] values.
84#[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/// An [SVG Table](https://docs.microsoft.com/en-us/typography/opentype/spec/svg).
112#[derive(Clone, Copy, Debug)]
113pub struct Table<'a> {
114    /// A list of SVG documents.
115    pub documents: SvgDocumentsList<'a>,
116}
117
118impl<'a> Table<'a> {
119    /// Parses a table from raw data.
120    pub fn parse(data: &'a [u8]) -> Option<Self> {
121        let mut s = Stream::new(data);
122        s.skip::<u16>(); // version
123        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}