we (web engine): Experimental web browser project to understand the limits of Claude
at object-model 97 lines 3.2 kB view raw
1//! `OS/2` — OS/2 and Windows Metrics table. 2//! 3//! Contains font-wide metrics used for line spacing, weight classification, 4//! and typographic alignment. 5//! Reference: <https://learn.microsoft.com/en-us/typography/opentype/spec/os2> 6 7use crate::font::parse::Reader; 8use crate::font::FontError; 9 10/// Parsed `OS/2` table. 11#[derive(Debug)] 12pub struct Os2Table { 13 /// Table version (0–5). 14 pub version: u16, 15 /// Average weighted advance width of lowercase letters and space. 16 pub x_avg_char_width: i16, 17 /// Visual weight class (100–900). 18 pub us_weight_class: u16, 19 /// Visual width class (1–9). 20 pub us_width_class: u16, 21 /// Font embedding licensing rights. 22 pub fs_type: u16, 23 /// Typographic ascender. 24 pub s_typo_ascender: i16, 25 /// Typographic descender (typically negative). 26 pub s_typo_descender: i16, 27 /// Typographic line gap. 28 pub s_typo_line_gap: i16, 29 /// Strikeout stroke size in font design units. 30 pub y_strikeout_size: i16, 31 /// Strikeout stroke position above baseline. 32 pub y_strikeout_position: i16, 33 /// Subscript vertical offset. 34 pub y_subscript_y_offset: i16, 35 /// Superscript vertical offset. 36 pub y_superscript_y_offset: i16, 37 /// Height of lowercase 'x' (version >= 2, else 0). 38 pub sx_height: i16, 39 /// Height of uppercase letters (version >= 2, else 0). 40 pub s_cap_height: i16, 41} 42 43impl Os2Table { 44 /// Parse the `OS/2` table from raw bytes. 45 pub fn parse(data: &[u8]) -> Result<Os2Table, FontError> { 46 let r = Reader::new(data); 47 48 // Minimum OS/2 table is 78 bytes (version 0). 49 if r.len() < 78 { 50 return Err(FontError::MalformedTable("OS/2: too short")); 51 } 52 53 let version = r.u16(0)?; 54 let x_avg_char_width = r.i16(2)?; 55 let us_weight_class = r.u16(4)?; 56 let us_width_class = r.u16(6)?; 57 let fs_type = r.u16(8)?; 58 59 // Subscript/superscript offsets: offsets 14 and 18 respectively 60 // ySubscriptXSize(10), ySubscriptYSize(12), ySubscriptXOffset(14) 61 let y_subscript_y_offset = r.i16(16)?; 62 // ySuperscriptXSize(18), ySuperscriptYSize(20), ySuperscriptXOffset(22) 63 let y_superscript_y_offset = r.i16(24)?; 64 65 let y_strikeout_size = r.i16(26)?; 66 let y_strikeout_position = r.i16(28)?; 67 68 // sTypoAscender is at offset 68, sTypoDescender at 70, sTypoLineGap at 72 69 let s_typo_ascender = r.i16(68)?; 70 let s_typo_descender = r.i16(70)?; 71 let s_typo_line_gap = r.i16(72)?; 72 73 // sxHeight and sCapHeight are available in version >= 2 at offsets 86 and 88. 74 let (sx_height, s_cap_height) = if version >= 2 && r.len() >= 96 { 75 (r.i16(86)?, r.i16(88)?) 76 } else { 77 (0, 0) 78 }; 79 80 Ok(Os2Table { 81 version, 82 x_avg_char_width, 83 us_weight_class, 84 us_width_class, 85 fs_type, 86 s_typo_ascender, 87 s_typo_descender, 88 s_typo_line_gap, 89 y_strikeout_size, 90 y_strikeout_position, 91 y_subscript_y_offset, 92 y_superscript_y_offset, 93 sx_height, 94 s_cap_height, 95 }) 96 } 97}