read_fonts/generated/
generated_post.rs

1// THIS FILE IS AUTOGENERATED.
2// Any changes to this file will be overwritten.
3// For more information about how codegen works, see font-codegen/README.md
4
5#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8/// [post (PostScript)](https://docs.microsoft.com/en-us/typography/opentype/spec/post#header) table
9#[derive(Debug, Clone, Copy)]
10#[doc(hidden)]
11pub struct PostMarker {
12    num_glyphs_byte_start: Option<usize>,
13    glyph_name_index_byte_start: Option<usize>,
14    glyph_name_index_byte_len: Option<usize>,
15    string_data_byte_start: Option<usize>,
16    string_data_byte_len: Option<usize>,
17}
18
19impl PostMarker {
20    pub fn version_byte_range(&self) -> Range<usize> {
21        let start = 0;
22        start..start + Version16Dot16::RAW_BYTE_LEN
23    }
24
25    pub fn italic_angle_byte_range(&self) -> Range<usize> {
26        let start = self.version_byte_range().end;
27        start..start + Fixed::RAW_BYTE_LEN
28    }
29
30    pub fn underline_position_byte_range(&self) -> Range<usize> {
31        let start = self.italic_angle_byte_range().end;
32        start..start + FWord::RAW_BYTE_LEN
33    }
34
35    pub fn underline_thickness_byte_range(&self) -> Range<usize> {
36        let start = self.underline_position_byte_range().end;
37        start..start + FWord::RAW_BYTE_LEN
38    }
39
40    pub fn is_fixed_pitch_byte_range(&self) -> Range<usize> {
41        let start = self.underline_thickness_byte_range().end;
42        start..start + u32::RAW_BYTE_LEN
43    }
44
45    pub fn min_mem_type42_byte_range(&self) -> Range<usize> {
46        let start = self.is_fixed_pitch_byte_range().end;
47        start..start + u32::RAW_BYTE_LEN
48    }
49
50    pub fn max_mem_type42_byte_range(&self) -> Range<usize> {
51        let start = self.min_mem_type42_byte_range().end;
52        start..start + u32::RAW_BYTE_LEN
53    }
54
55    pub fn min_mem_type1_byte_range(&self) -> Range<usize> {
56        let start = self.max_mem_type42_byte_range().end;
57        start..start + u32::RAW_BYTE_LEN
58    }
59
60    pub fn max_mem_type1_byte_range(&self) -> Range<usize> {
61        let start = self.min_mem_type1_byte_range().end;
62        start..start + u32::RAW_BYTE_LEN
63    }
64
65    pub fn num_glyphs_byte_range(&self) -> Option<Range<usize>> {
66        let start = self.num_glyphs_byte_start?;
67        Some(start..start + u16::RAW_BYTE_LEN)
68    }
69
70    pub fn glyph_name_index_byte_range(&self) -> Option<Range<usize>> {
71        let start = self.glyph_name_index_byte_start?;
72        Some(start..start + self.glyph_name_index_byte_len?)
73    }
74
75    pub fn string_data_byte_range(&self) -> Option<Range<usize>> {
76        let start = self.string_data_byte_start?;
77        Some(start..start + self.string_data_byte_len?)
78    }
79}
80
81impl MinByteRange for PostMarker {
82    fn min_byte_range(&self) -> Range<usize> {
83        0..self.max_mem_type1_byte_range().end
84    }
85}
86
87impl TopLevelTable for Post<'_> {
88    /// `post`
89    const TAG: Tag = Tag::new(b"post");
90}
91
92impl<'a> FontRead<'a> for Post<'a> {
93    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
94        let mut cursor = data.cursor();
95        let version: Version16Dot16 = cursor.read()?;
96        cursor.advance::<Fixed>();
97        cursor.advance::<FWord>();
98        cursor.advance::<FWord>();
99        cursor.advance::<u32>();
100        cursor.advance::<u32>();
101        cursor.advance::<u32>();
102        cursor.advance::<u32>();
103        cursor.advance::<u32>();
104        let num_glyphs_byte_start = version
105            .compatible((2u16, 0u16))
106            .then(|| cursor.position())
107            .transpose()?;
108        let num_glyphs = version
109            .compatible((2u16, 0u16))
110            .then(|| cursor.read::<u16>())
111            .transpose()?
112            .unwrap_or_default();
113        let glyph_name_index_byte_start = version
114            .compatible((2u16, 0u16))
115            .then(|| cursor.position())
116            .transpose()?;
117        let glyph_name_index_byte_len = version.compatible((2u16, 0u16)).then_some(
118            (num_glyphs as usize)
119                .checked_mul(u16::RAW_BYTE_LEN)
120                .ok_or(ReadError::OutOfBounds)?,
121        );
122        if let Some(value) = glyph_name_index_byte_len {
123            cursor.advance_by(value);
124        }
125        let string_data_byte_start = version
126            .compatible((2u16, 0u16))
127            .then(|| cursor.position())
128            .transpose()?;
129        let string_data_byte_len = version
130            .compatible((2u16, 0u16))
131            .then_some(cursor.remaining_bytes());
132        if let Some(value) = string_data_byte_len {
133            cursor.advance_by(value);
134        }
135        cursor.finish(PostMarker {
136            num_glyphs_byte_start,
137            glyph_name_index_byte_start,
138            glyph_name_index_byte_len,
139            string_data_byte_start,
140            string_data_byte_len,
141        })
142    }
143}
144
145/// [post (PostScript)](https://docs.microsoft.com/en-us/typography/opentype/spec/post#header) table
146pub type Post<'a> = TableRef<'a, PostMarker>;
147
148#[allow(clippy::needless_lifetimes)]
149impl<'a> Post<'a> {
150    /// 0x00010000 for version 1.0 0x00020000 for version 2.0
151    /// 0x00025000 for version 2.5 (deprecated) 0x00030000 for version
152    /// 3.0
153    pub fn version(&self) -> Version16Dot16 {
154        let range = self.shape.version_byte_range();
155        self.data.read_at(range.start).unwrap()
156    }
157
158    /// Italic angle in counter-clockwise degrees from the vertical.
159    /// Zero for upright text, negative for text that leans to the
160    /// right (forward).
161    pub fn italic_angle(&self) -> Fixed {
162        let range = self.shape.italic_angle_byte_range();
163        self.data.read_at(range.start).unwrap()
164    }
165
166    /// This is the suggested distance of the top of the underline from
167    /// the baseline (negative values indicate below baseline). The
168    /// PostScript definition of this FontInfo dictionary key (the y
169    /// coordinate of the center of the stroke) is not used for
170    /// historical reasons. The value of the PostScript key may be
171    /// calculated by subtracting half the underlineThickness from the
172    /// value of this field.
173    pub fn underline_position(&self) -> FWord {
174        let range = self.shape.underline_position_byte_range();
175        self.data.read_at(range.start).unwrap()
176    }
177
178    /// Suggested values for the underline thickness. In general, the
179    /// underline thickness should match the thickness of the
180    /// underscore character (U+005F LOW LINE), and should also match
181    /// the strikeout thickness, which is specified in the OS/2 table.
182    pub fn underline_thickness(&self) -> FWord {
183        let range = self.shape.underline_thickness_byte_range();
184        self.data.read_at(range.start).unwrap()
185    }
186
187    /// Set to 0 if the font is proportionally spaced, non-zero if the
188    /// font is not proportionally spaced (i.e. monospaced).
189    pub fn is_fixed_pitch(&self) -> u32 {
190        let range = self.shape.is_fixed_pitch_byte_range();
191        self.data.read_at(range.start).unwrap()
192    }
193
194    /// Minimum memory usage when an OpenType font is downloaded.
195    pub fn min_mem_type42(&self) -> u32 {
196        let range = self.shape.min_mem_type42_byte_range();
197        self.data.read_at(range.start).unwrap()
198    }
199
200    /// Maximum memory usage when an OpenType font is downloaded.
201    pub fn max_mem_type42(&self) -> u32 {
202        let range = self.shape.max_mem_type42_byte_range();
203        self.data.read_at(range.start).unwrap()
204    }
205
206    /// Minimum memory usage when an OpenType font is downloaded as a
207    /// Type 1 font.
208    pub fn min_mem_type1(&self) -> u32 {
209        let range = self.shape.min_mem_type1_byte_range();
210        self.data.read_at(range.start).unwrap()
211    }
212
213    /// Maximum memory usage when an OpenType font is downloaded as a
214    /// Type 1 font.
215    pub fn max_mem_type1(&self) -> u32 {
216        let range = self.shape.max_mem_type1_byte_range();
217        self.data.read_at(range.start).unwrap()
218    }
219
220    /// Number of glyphs (this should be the same as numGlyphs in
221    /// 'maxp' table).
222    pub fn num_glyphs(&self) -> Option<u16> {
223        let range = self.shape.num_glyphs_byte_range()?;
224        Some(self.data.read_at(range.start).unwrap())
225    }
226
227    /// Array of indices into the string data. See below for details.
228    pub fn glyph_name_index(&self) -> Option<&'a [BigEndian<u16>]> {
229        let range = self.shape.glyph_name_index_byte_range()?;
230        Some(self.data.read_array(range).unwrap())
231    }
232
233    /// Storage for the string data.
234    pub fn string_data(&self) -> Option<VarLenArray<'a, PString<'a>>> {
235        let range = self.shape.string_data_byte_range()?;
236        Some(VarLenArray::read(self.data.split_off(range.start).unwrap()).unwrap())
237    }
238}
239
240#[cfg(feature = "experimental_traverse")]
241impl<'a> SomeTable<'a> for Post<'a> {
242    fn type_name(&self) -> &str {
243        "Post"
244    }
245    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
246        let version = self.version();
247        match idx {
248            0usize => Some(Field::new("version", self.version())),
249            1usize => Some(Field::new("italic_angle", self.italic_angle())),
250            2usize => Some(Field::new("underline_position", self.underline_position())),
251            3usize => Some(Field::new(
252                "underline_thickness",
253                self.underline_thickness(),
254            )),
255            4usize => Some(Field::new("is_fixed_pitch", self.is_fixed_pitch())),
256            5usize => Some(Field::new("min_mem_type42", self.min_mem_type42())),
257            6usize => Some(Field::new("max_mem_type42", self.max_mem_type42())),
258            7usize => Some(Field::new("min_mem_type1", self.min_mem_type1())),
259            8usize => Some(Field::new("max_mem_type1", self.max_mem_type1())),
260            9usize if version.compatible((2u16, 0u16)) => {
261                Some(Field::new("num_glyphs", self.num_glyphs().unwrap()))
262            }
263            10usize if version.compatible((2u16, 0u16)) => Some(Field::new(
264                "glyph_name_index",
265                self.glyph_name_index().unwrap(),
266            )),
267            11usize if version.compatible((2u16, 0u16)) => {
268                Some(Field::new("string_data", self.traverse_string_data()))
269            }
270            _ => None,
271        }
272    }
273}
274
275#[cfg(feature = "experimental_traverse")]
276#[allow(clippy::needless_lifetimes)]
277impl<'a> std::fmt::Debug for Post<'a> {
278    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
279        (self as &dyn SomeTable<'a>).fmt(f)
280    }
281}