write_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(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Post {
12    /// 0x00010000 for version 1.0 0x00020000 for version 2.0
13    /// 0x00025000 for version 2.5 (deprecated) 0x00030000 for version
14    /// 3.0
15    pub version: Version16Dot16,
16    /// Italic angle in counter-clockwise degrees from the vertical.
17    /// Zero for upright text, negative for text that leans to the
18    /// right (forward).
19    pub italic_angle: Fixed,
20    /// This is the suggested distance of the top of the underline from
21    /// the baseline (negative values indicate below baseline). The
22    /// PostScript definition of this FontInfo dictionary key (the y
23    /// coordinate of the center of the stroke) is not used for
24    /// historical reasons. The value of the PostScript key may be
25    /// calculated by subtracting half the underlineThickness from the
26    /// value of this field.
27    pub underline_position: FWord,
28    /// Suggested values for the underline thickness. In general, the
29    /// underline thickness should match the thickness of the
30    /// underscore character (U+005F LOW LINE), and should also match
31    /// the strikeout thickness, which is specified in the OS/2 table.
32    pub underline_thickness: FWord,
33    /// Set to 0 if the font is proportionally spaced, non-zero if the
34    /// font is not proportionally spaced (i.e. monospaced).
35    pub is_fixed_pitch: u32,
36    /// Minimum memory usage when an OpenType font is downloaded.
37    pub min_mem_type42: u32,
38    /// Maximum memory usage when an OpenType font is downloaded.
39    pub max_mem_type42: u32,
40    /// Minimum memory usage when an OpenType font is downloaded as a
41    /// Type 1 font.
42    pub min_mem_type1: u32,
43    /// Maximum memory usage when an OpenType font is downloaded as a
44    /// Type 1 font.
45    pub max_mem_type1: u32,
46    /// Number of glyphs (this should be the same as numGlyphs in
47    /// 'maxp' table).
48    pub num_glyphs: Option<u16>,
49    /// Array of indices into the string data. See below for details.
50    pub glyph_name_index: Option<Vec<u16>>,
51    /// Storage for the string data.
52    pub string_data: Option<Vec<PString>>,
53}
54
55impl Default for Post {
56    fn default() -> Self {
57        Self {
58            version: Version16Dot16::VERSION_1_0,
59            italic_angle: Default::default(),
60            underline_position: Default::default(),
61            underline_thickness: Default::default(),
62            is_fixed_pitch: Default::default(),
63            min_mem_type42: Default::default(),
64            max_mem_type42: Default::default(),
65            min_mem_type1: Default::default(),
66            max_mem_type1: Default::default(),
67            num_glyphs: Default::default(),
68            glyph_name_index: Default::default(),
69            string_data: Default::default(),
70        }
71    }
72}
73
74impl Post {
75    /// Construct a new `Post`
76    #[allow(clippy::too_many_arguments)]
77    pub fn new(
78        italic_angle: Fixed,
79        underline_position: FWord,
80        underline_thickness: FWord,
81        is_fixed_pitch: u32,
82        min_mem_type42: u32,
83        max_mem_type42: u32,
84        min_mem_type1: u32,
85        max_mem_type1: u32,
86    ) -> Self {
87        Self {
88            italic_angle,
89            underline_position,
90            underline_thickness,
91            is_fixed_pitch,
92            min_mem_type42,
93            max_mem_type42,
94            min_mem_type1,
95            max_mem_type1,
96            ..Default::default()
97        }
98    }
99}
100
101impl FontWrite for Post {
102    fn write_into(&self, writer: &mut TableWriter) {
103        let version = self.version;
104        version.write_into(writer);
105        self.italic_angle.write_into(writer);
106        self.underline_position.write_into(writer);
107        self.underline_thickness.write_into(writer);
108        self.is_fixed_pitch.write_into(writer);
109        self.min_mem_type42.write_into(writer);
110        self.max_mem_type42.write_into(writer);
111        self.min_mem_type1.write_into(writer);
112        self.max_mem_type1.write_into(writer);
113        version.compatible((2u16, 0u16)).then(|| {
114            self.num_glyphs
115                .as_ref()
116                .expect("missing conditional field should have failed validation")
117                .write_into(writer)
118        });
119        version.compatible((2u16, 0u16)).then(|| {
120            self.glyph_name_index
121                .as_ref()
122                .expect("missing conditional field should have failed validation")
123                .write_into(writer)
124        });
125        version.compatible((2u16, 0u16)).then(|| {
126            self.string_data
127                .as_ref()
128                .expect("missing conditional field should have failed validation")
129                .write_into(writer)
130        });
131    }
132    fn table_type(&self) -> TableType {
133        TableType::TopLevel(Post::TAG)
134    }
135}
136
137impl Validate for Post {
138    fn validate_impl(&self, ctx: &mut ValidationCtx) {
139        ctx.in_table("Post", |ctx| {
140            let version = self.version;
141            ctx.in_field("num_glyphs", |ctx| {
142                if version.compatible((2u16, 0u16)) && self.num_glyphs.is_none() {
143                    ctx.report(format!("field must be present for version {version}"));
144                }
145            });
146            ctx.in_field("glyph_name_index", |ctx| {
147                if version.compatible((2u16, 0u16)) && self.glyph_name_index.is_none() {
148                    ctx.report(format!("field must be present for version {version}"));
149                }
150                if self.glyph_name_index.is_some()
151                    && self.glyph_name_index.as_ref().unwrap().len() > (u16::MAX as usize)
152                {
153                    ctx.report("array exceeds max length");
154                }
155            });
156        })
157    }
158}
159
160impl TopLevelTable for Post {
161    const TAG: Tag = Tag::new(b"post");
162}
163
164impl<'a> FromObjRef<read_fonts::tables::post::Post<'a>> for Post {
165    fn from_obj_ref(obj: &read_fonts::tables::post::Post<'a>, _: FontData) -> Self {
166        let offset_data = obj.offset_data();
167        Post {
168            version: obj.version(),
169            italic_angle: obj.italic_angle(),
170            underline_position: obj.underline_position(),
171            underline_thickness: obj.underline_thickness(),
172            is_fixed_pitch: obj.is_fixed_pitch(),
173            min_mem_type42: obj.min_mem_type42(),
174            max_mem_type42: obj.max_mem_type42(),
175            min_mem_type1: obj.min_mem_type1(),
176            max_mem_type1: obj.max_mem_type1(),
177            num_glyphs: obj.num_glyphs(),
178            glyph_name_index: obj.glyph_name_index().to_owned_obj(offset_data),
179            string_data: obj.string_data().map(|obj| {
180                obj.iter()
181                    .filter_map(|x| x.map(|x| FromObjRef::from_obj_ref(&x, offset_data)).ok())
182                    .collect()
183            }),
184        }
185    }
186}
187
188#[allow(clippy::needless_lifetimes)]
189impl<'a> FromTableRef<read_fonts::tables::post::Post<'a>> for Post {}
190
191impl<'a> FontRead<'a> for Post {
192    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
193        <read_fonts::tables::post::Post as FontRead>::read(data).map(|x| x.to_owned_table())
194    }
195}