Coverage Report

Created: 2026-04-01 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fontations/write-fonts/generated/generated_os2.rs
Line
Count
Source
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)]
6
use crate::codegen_prelude::*;
7
8
pub use read_fonts::tables::os2::SelectionFlags;
9
10
impl FontWrite for SelectionFlags {
11
0
    fn write_into(&self, writer: &mut TableWriter) {
12
0
        writer.write_slice(&self.bits().to_be_bytes())
13
0
    }
14
}
15
16
/// [`OS/2`](https://docs.microsoft.com/en-us/typography/opentype/spec/os2)
17
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19
pub struct Os2 {
20
    /// [Average weighted escapement](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#xavgcharwidth).
21
    ///
22
    /// The Average Character Width parameter specifies the arithmetic average
23
    /// of the escapement (width) of all non-zero width glyphs in the font.
24
    pub x_avg_char_width: i16,
25
    /// [Weight class](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass).
26
    ///
27
    /// Indicates the visual weight (degree of blackness or thickness of
28
    /// strokes) of the characters in the font. Values from 1 to 1000 are valid.
29
    pub us_weight_class: u16,
30
    /// [Width class](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass).
31
    ///
32
    /// Indicates a relative change from the normal aspect ratio (width to height
33
    /// ratio) as specified by a font designer for the glyphs in a font.
34
    pub us_width_class: u16,
35
    /// [Type flags](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#fstype).
36
    ///
37
    /// Indicates font embedding licensing rights for the font.
38
    pub fs_type: u16,
39
    /// The recommended horizontal size in font design units for subscripts for
40
    /// this font.
41
    pub y_subscript_x_size: i16,
42
    /// The recommended vertical size in font design units for subscripts for
43
    /// this font.
44
    pub y_subscript_y_size: i16,
45
    /// The recommended horizontal offset in font design units for subscripts
46
    /// for this font.
47
    pub y_subscript_x_offset: i16,
48
    /// The recommended vertical offset in font design units for subscripts
49
    /// for this font.
50
    pub y_subscript_y_offset: i16,
51
    /// The recommended horizontal size in font design units for superscripts
52
    /// for this font.
53
    pub y_superscript_x_size: i16,
54
    /// The recommended vertical size in font design units for superscripts
55
    /// for this font.
56
    pub y_superscript_y_size: i16,
57
    /// The recommended horizontal offset in font design units for superscripts
58
    /// for this font.
59
    pub y_superscript_x_offset: i16,
60
    /// The recommended vertical offset in font design units for superscripts
61
    /// for this font.
62
    pub y_superscript_y_offset: i16,
63
    /// Thickness of the strikeout stroke in font design units.
64
    pub y_strikeout_size: i16,
65
    /// The position of the top of the strikeout stroke relative to the
66
    /// baseline in font design units.
67
    pub y_strikeout_position: i16,
68
    /// [Font-family class and subclass](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#sfamilyclass).
69
    /// This parameter is a classification of font-family design.
70
    pub s_family_class: i16,
71
    /// [PANOSE classification number](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#panose).
72
    ///
73
    /// Additional specifications are required for PANOSE to classify non-Latin
74
    /// character sets.
75
    pub panose_10: [u8; 10],
76
    /// [Unicode Character Range](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#ulunicoderange1-bits-031ulunicoderange2-bits-3263ulunicoderange3-bits-6495ulunicoderange4-bits-96127).
77
    ///
78
    /// Unicode Character Range (bits 0-31).
79
    pub ul_unicode_range_1: u32,
80
    /// Unicode Character Range (bits 32-63).
81
    pub ul_unicode_range_2: u32,
82
    /// Unicode Character Range (bits 64-95).
83
    pub ul_unicode_range_3: u32,
84
    /// Unicode Character Range (bits 96-127).
85
    pub ul_unicode_range_4: u32,
86
    /// [Font Vendor Identification](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#achvendid).
87
    ///
88
    /// The four-character identifier for the vendor of the given type face.
89
    pub ach_vend_id: Tag,
90
    /// [Font selection flags](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#fsselection).
91
    ///
92
    /// Contains information concerning the nature of the font patterns.
93
    pub fs_selection: SelectionFlags,
94
    /// The minimum Unicode index (character code) in this font.
95
    pub us_first_char_index: u16,
96
    /// The maximum Unicode index (character code) in this font.
97
    pub us_last_char_index: u16,
98
    /// The typographic ascender for this font.
99
    pub s_typo_ascender: i16,
100
    /// The typographic descender for this font.
101
    pub s_typo_descender: i16,
102
    /// The typographic line gap for this font.
103
    pub s_typo_line_gap: i16,
104
    /// The “Windows ascender” metric.
105
    ///
106
    /// This should be used to specify the height above the baseline for a
107
    /// clipping region.
108
    pub us_win_ascent: u16,
109
    /// The “Windows descender” metric.
110
    ///
111
    /// This should be used to specify the vertical extent below the baseline
112
    /// for a clipping region.
113
    pub us_win_descent: u16,
114
    /// Code page character range bits 0-31.
115
    pub ul_code_page_range_1: Option<u32>,
116
    /// Code page character range bits 32-63.
117
    pub ul_code_page_range_2: Option<u32>,
118
    /// This metric specifies the distance between the baseline and the
119
    /// approximate height of non-ascending lowercase letters measured in
120
    /// FUnits.
121
    pub sx_height: Option<i16>,
122
    /// This metric specifies the distance between the baseline and the
123
    /// approximate height of uppercase letters measured in FUnits.
124
    pub s_cap_height: Option<i16>,
125
    /// This is the Unicode codepoint, in UTF-16 encoding, of a character that
126
    /// can be used for a default glyph.
127
    pub us_default_char: Option<u16>,
128
    /// This is the Unicode codepoint, in UTF-16 encoding, of a character that
129
    /// can be used as a default break character.
130
    pub us_break_char: Option<u16>,
131
    /// This field is used for fonts with multiple optical styles.
132
    pub us_max_context: Option<u16>,
133
    /// This field is used for fonts with multiple optical styles.
134
    pub us_lower_optical_point_size: Option<u16>,
135
    /// This field is used for fonts with multiple optical styles.
136
    pub us_upper_optical_point_size: Option<u16>,
137
}
138
139
impl Default for Os2 {
140
0
    fn default() -> Self {
141
0
        Self {
142
0
            x_avg_char_width: Default::default(),
143
0
            us_weight_class: 400,
144
0
            us_width_class: 5,
145
0
            fs_type: Default::default(),
146
0
            y_subscript_x_size: Default::default(),
147
0
            y_subscript_y_size: Default::default(),
148
0
            y_subscript_x_offset: Default::default(),
149
0
            y_subscript_y_offset: Default::default(),
150
0
            y_superscript_x_size: Default::default(),
151
0
            y_superscript_y_size: Default::default(),
152
0
            y_superscript_x_offset: Default::default(),
153
0
            y_superscript_y_offset: Default::default(),
154
0
            y_strikeout_size: Default::default(),
155
0
            y_strikeout_position: Default::default(),
156
0
            s_family_class: Default::default(),
157
0
            panose_10: Default::default(),
158
0
            ul_unicode_range_1: Default::default(),
159
0
            ul_unicode_range_2: Default::default(),
160
0
            ul_unicode_range_3: Default::default(),
161
0
            ul_unicode_range_4: Default::default(),
162
0
            ach_vend_id: Default::default(),
163
0
            fs_selection: Default::default(),
164
0
            us_first_char_index: Default::default(),
165
0
            us_last_char_index: Default::default(),
166
0
            s_typo_ascender: Default::default(),
167
0
            s_typo_descender: Default::default(),
168
0
            s_typo_line_gap: Default::default(),
169
0
            us_win_ascent: Default::default(),
170
0
            us_win_descent: Default::default(),
171
0
            ul_code_page_range_1: Default::default(),
172
0
            ul_code_page_range_2: Default::default(),
173
0
            sx_height: Default::default(),
174
0
            s_cap_height: Default::default(),
175
0
            us_default_char: Default::default(),
176
0
            us_break_char: Default::default(),
177
0
            us_max_context: Default::default(),
178
0
            us_lower_optical_point_size: Default::default(),
179
0
            us_upper_optical_point_size: Default::default(),
180
0
        }
181
0
    }
182
}
183
184
impl FontWrite for Os2 {
185
    #[allow(clippy::unnecessary_cast)]
186
0
    fn write_into(&self, writer: &mut TableWriter) {
187
0
        let version = self.compute_version() as u16;
188
0
        version.write_into(writer);
189
0
        self.x_avg_char_width.write_into(writer);
190
0
        self.us_weight_class.write_into(writer);
191
0
        self.us_width_class.write_into(writer);
192
0
        self.fs_type.write_into(writer);
193
0
        self.y_subscript_x_size.write_into(writer);
194
0
        self.y_subscript_y_size.write_into(writer);
195
0
        self.y_subscript_x_offset.write_into(writer);
196
0
        self.y_subscript_y_offset.write_into(writer);
197
0
        self.y_superscript_x_size.write_into(writer);
198
0
        self.y_superscript_y_size.write_into(writer);
199
0
        self.y_superscript_x_offset.write_into(writer);
200
0
        self.y_superscript_y_offset.write_into(writer);
201
0
        self.y_strikeout_size.write_into(writer);
202
0
        self.y_strikeout_position.write_into(writer);
203
0
        self.s_family_class.write_into(writer);
204
0
        self.panose_10.write_into(writer);
205
0
        self.ul_unicode_range_1.write_into(writer);
206
0
        self.ul_unicode_range_2.write_into(writer);
207
0
        self.ul_unicode_range_3.write_into(writer);
208
0
        self.ul_unicode_range_4.write_into(writer);
209
0
        self.ach_vend_id.write_into(writer);
210
0
        self.fs_selection.write_into(writer);
211
0
        self.us_first_char_index.write_into(writer);
212
0
        self.us_last_char_index.write_into(writer);
213
0
        self.s_typo_ascender.write_into(writer);
214
0
        self.s_typo_descender.write_into(writer);
215
0
        self.s_typo_line_gap.write_into(writer);
216
0
        self.us_win_ascent.write_into(writer);
217
0
        self.us_win_descent.write_into(writer);
218
0
        version.compatible(1u16).then(|| {
219
0
            self.ul_code_page_range_1
220
0
                .as_ref()
221
0
                .expect("missing conditional field should have failed validation")
222
0
                .write_into(writer)
223
0
        });
224
0
        version.compatible(1u16).then(|| {
225
0
            self.ul_code_page_range_2
226
0
                .as_ref()
227
0
                .expect("missing conditional field should have failed validation")
228
0
                .write_into(writer)
229
0
        });
230
0
        version.compatible(2u16).then(|| {
231
0
            self.sx_height
232
0
                .as_ref()
233
0
                .expect("missing conditional field should have failed validation")
234
0
                .write_into(writer)
235
0
        });
236
0
        version.compatible(2u16).then(|| {
237
0
            self.s_cap_height
238
0
                .as_ref()
239
0
                .expect("missing conditional field should have failed validation")
240
0
                .write_into(writer)
241
0
        });
242
0
        version.compatible(2u16).then(|| {
243
0
            self.us_default_char
244
0
                .as_ref()
245
0
                .expect("missing conditional field should have failed validation")
246
0
                .write_into(writer)
247
0
        });
248
0
        version.compatible(2u16).then(|| {
249
0
            self.us_break_char
250
0
                .as_ref()
251
0
                .expect("missing conditional field should have failed validation")
252
0
                .write_into(writer)
253
0
        });
254
0
        version.compatible(2u16).then(|| {
255
0
            self.us_max_context
256
0
                .as_ref()
257
0
                .expect("missing conditional field should have failed validation")
258
0
                .write_into(writer)
259
0
        });
260
0
        version.compatible(5u16).then(|| {
261
0
            self.us_lower_optical_point_size
262
0
                .as_ref()
263
0
                .expect("missing conditional field should have failed validation")
264
0
                .write_into(writer)
265
0
        });
266
0
        version.compatible(5u16).then(|| {
267
0
            self.us_upper_optical_point_size
268
0
                .as_ref()
269
0
                .expect("missing conditional field should have failed validation")
270
0
                .write_into(writer)
271
0
        });
272
0
    }
273
0
    fn table_type(&self) -> TableType {
274
0
        TableType::TopLevel(Os2::TAG)
275
0
    }
276
}
277
278
impl Validate for Os2 {
279
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
280
0
        ctx.in_table("Os2", |ctx| {
281
0
            let version: u16 = self.compute_version();
282
0
            ctx.in_field("ul_code_page_range_1", |ctx| {
283
0
                if version.compatible(1u16) && self.ul_code_page_range_1.is_none() {
284
0
                    ctx.report(format!("field must be present for version {version}"));
285
0
                }
286
0
            });
287
0
            ctx.in_field("ul_code_page_range_2", |ctx| {
288
0
                if version.compatible(1u16) && self.ul_code_page_range_2.is_none() {
289
0
                    ctx.report(format!("field must be present for version {version}"));
290
0
                }
291
0
            });
292
0
            ctx.in_field("sx_height", |ctx| {
293
0
                if version.compatible(2u16) && self.sx_height.is_none() {
294
0
                    ctx.report(format!("field must be present for version {version}"));
295
0
                }
296
0
            });
297
0
            ctx.in_field("s_cap_height", |ctx| {
298
0
                if version.compatible(2u16) && self.s_cap_height.is_none() {
299
0
                    ctx.report(format!("field must be present for version {version}"));
300
0
                }
301
0
            });
302
0
            ctx.in_field("us_default_char", |ctx| {
303
0
                if version.compatible(2u16) && self.us_default_char.is_none() {
304
0
                    ctx.report(format!("field must be present for version {version}"));
305
0
                }
306
0
            });
307
0
            ctx.in_field("us_break_char", |ctx| {
308
0
                if version.compatible(2u16) && self.us_break_char.is_none() {
309
0
                    ctx.report(format!("field must be present for version {version}"));
310
0
                }
311
0
            });
312
0
            ctx.in_field("us_max_context", |ctx| {
313
0
                if version.compatible(2u16) && self.us_max_context.is_none() {
314
0
                    ctx.report(format!("field must be present for version {version}"));
315
0
                }
316
0
            });
317
0
            ctx.in_field("us_lower_optical_point_size", |ctx| {
318
0
                if version.compatible(5u16) && self.us_lower_optical_point_size.is_none() {
319
0
                    ctx.report(format!("field must be present for version {version}"));
320
0
                }
321
0
            });
322
0
            ctx.in_field("us_upper_optical_point_size", |ctx| {
323
0
                if version.compatible(5u16) && self.us_upper_optical_point_size.is_none() {
324
0
                    ctx.report(format!("field must be present for version {version}"));
325
0
                }
326
0
            });
327
0
        })
328
0
    }
329
}
330
331
impl TopLevelTable for Os2 {
332
    const TAG: Tag = Tag::new(b"OS/2");
333
}
334
335
impl<'a> FromObjRef<read_fonts::tables::os2::Os2<'a>> for Os2 {
336
0
    fn from_obj_ref(obj: &read_fonts::tables::os2::Os2<'a>, _: FontData) -> Self {
337
0
        Os2 {
338
0
            x_avg_char_width: obj.x_avg_char_width(),
339
0
            us_weight_class: obj.us_weight_class(),
340
0
            us_width_class: obj.us_width_class(),
341
0
            fs_type: obj.fs_type(),
342
0
            y_subscript_x_size: obj.y_subscript_x_size(),
343
0
            y_subscript_y_size: obj.y_subscript_y_size(),
344
0
            y_subscript_x_offset: obj.y_subscript_x_offset(),
345
0
            y_subscript_y_offset: obj.y_subscript_y_offset(),
346
0
            y_superscript_x_size: obj.y_superscript_x_size(),
347
0
            y_superscript_y_size: obj.y_superscript_y_size(),
348
0
            y_superscript_x_offset: obj.y_superscript_x_offset(),
349
0
            y_superscript_y_offset: obj.y_superscript_y_offset(),
350
0
            y_strikeout_size: obj.y_strikeout_size(),
351
0
            y_strikeout_position: obj.y_strikeout_position(),
352
0
            s_family_class: obj.s_family_class(),
353
0
            panose_10: convert_panose(obj.panose_10()),
354
0
            ul_unicode_range_1: obj.ul_unicode_range_1(),
355
0
            ul_unicode_range_2: obj.ul_unicode_range_2(),
356
0
            ul_unicode_range_3: obj.ul_unicode_range_3(),
357
0
            ul_unicode_range_4: obj.ul_unicode_range_4(),
358
0
            ach_vend_id: obj.ach_vend_id(),
359
0
            fs_selection: obj.fs_selection(),
360
0
            us_first_char_index: obj.us_first_char_index(),
361
0
            us_last_char_index: obj.us_last_char_index(),
362
0
            s_typo_ascender: obj.s_typo_ascender(),
363
0
            s_typo_descender: obj.s_typo_descender(),
364
0
            s_typo_line_gap: obj.s_typo_line_gap(),
365
0
            us_win_ascent: obj.us_win_ascent(),
366
0
            us_win_descent: obj.us_win_descent(),
367
0
            ul_code_page_range_1: obj.ul_code_page_range_1(),
368
0
            ul_code_page_range_2: obj.ul_code_page_range_2(),
369
0
            sx_height: obj.sx_height(),
370
0
            s_cap_height: obj.s_cap_height(),
371
0
            us_default_char: obj.us_default_char(),
372
0
            us_break_char: obj.us_break_char(),
373
0
            us_max_context: obj.us_max_context(),
374
0
            us_lower_optical_point_size: obj.us_lower_optical_point_size(),
375
0
            us_upper_optical_point_size: obj.us_upper_optical_point_size(),
376
0
        }
377
0
    }
378
}
379
380
#[allow(clippy::needless_lifetimes)]
381
impl<'a> FromTableRef<read_fonts::tables::os2::Os2<'a>> for Os2 {}
382
383
impl<'a> FontRead<'a> for Os2 {
384
0
    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
385
0
        <read_fonts::tables::os2::Os2 as FontRead>::read(data).map(|x| x.to_owned_table())
386
0
    }
387
}