we (web engine): Experimental web browser project to understand the limits of Claude
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

at object-model 55 lines 1.8 kB view raw
1//! `hmtx` — Horizontal Metrics table. 2//! 3//! Contains per-glyph horizontal metrics (advance width + left side bearing). 4//! Reference: <https://learn.microsoft.com/en-us/typography/opentype/spec/hmtx> 5 6use crate::font::parse::Reader; 7use crate::font::FontError; 8 9/// Parsed `hmtx` table. 10/// 11/// Both `advances` and `lsbs` are indexed by glyph ID and have exactly 12/// `num_glyphs` entries. 13#[derive(Debug)] 14pub struct HmtxTable { 15 /// Advance widths for each glyph (in font units). 16 pub advances: Vec<u16>, 17 /// Left side bearings for each glyph (in font units). 18 pub lsbs: Vec<i16>, 19} 20 21impl HmtxTable { 22 /// Parse the `hmtx` table from raw bytes. 23 /// 24 /// `num_long_hor_metrics` comes from `hhea`, `num_glyphs` from `maxp`. 25 pub fn parse( 26 data: &[u8], 27 num_long_hor_metrics: u16, 28 num_glyphs: u16, 29 ) -> Result<HmtxTable, FontError> { 30 let r = Reader::new(data); 31 let n_long = num_long_hor_metrics as usize; 32 let n_glyphs = num_glyphs as usize; 33 34 let mut advances = Vec::with_capacity(n_glyphs); 35 let mut lsbs = Vec::with_capacity(n_glyphs); 36 37 // First n_long entries are (advance_width: u16, lsb: i16) pairs. 38 for i in 0..n_long { 39 let offset = i * 4; 40 advances.push(r.u16(offset)?); 41 lsbs.push(r.i16(offset + 2)?); 42 } 43 44 // Remaining glyphs share the last advance width, but have individual lsbs. 45 let last_advance = advances.last().copied().unwrap_or(0); 46 let remaining = n_glyphs.saturating_sub(n_long); 47 let lsb_offset = n_long * 4; 48 for i in 0..remaining { 49 advances.push(last_advance); 50 lsbs.push(r.i16(lsb_offset + i * 2)?); 51 } 52 53 Ok(HmtxTable { advances, lsbs }) 54 } 55}