use std::fmt::{ Debug, Formatter, Result as FmtResult }; use bytemuck::{ Zeroable, Pod }; use super::ReadError; use super::core::*; #[derive(Clone, Copy, Zeroable, Pod)] #[repr(transparent)] pub struct HorizontalHeaderTable([u8; 36]); impl<'a> RandomAccess<'a> for &'a HorizontalHeaderTable { fn bytes(&self) -> &'a [u8] { &self.0 } } impl HorizontalHeaderTable { pub fn version(&self) -> (u16, u16) { (self.uint16(0), self.uint16(2)) } pub fn ascender(&self) -> i16 { self.int16(4) } pub fn descender(&self) -> i16 { self.int16(6) } pub fn line_gap(&self) -> i16 { self.int16(8) } pub fn advance_width_max(&self) -> u16 { self.uint16(10) } pub fn min_left_side_bearing(&self) -> i16 { self.int16(12) } pub fn min_right_side_bearing(&self) -> i16 { self.int16(14) } pub fn max_x_extent(&self) -> i16 { self.int16(16) } pub fn caret_slope_rise(&self) -> i16 { self.int16(18) } pub fn caret_slope_run(&self) -> i16 { self.int16(20) } pub fn caret_offset(&self) -> i16 { self.int16(22) } pub fn metrics_data_format(&self) -> i16 { self.int16(32) } pub fn number_of_hmetrics(&self) -> u16 { self.uint16(34) } } impl Debug for HorizontalHeaderTable { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.debug_struct("HorizontalHeaderTable") .field("version", &self.version()) .field("ascender", &self.ascender()) .field("descender", &self.descender()) .field("line_gap", &self.line_gap()) .field("advance_width_max", &self.advance_width_max()) .field("min_left_side_bearing", &self.min_left_side_bearing()) .field("min_right_side_bearing", &self.min_right_side_bearing()) .field("max_x_extent", &self.max_x_extent()) .field("caret_slope_rise", &self.caret_slope_rise()) .field("caret_slope_run", &self.caret_slope_run()) .field("caret_offset", &self.caret_offset()) .field("metrics_data_format", &self.metrics_data_format()) .field("number_of_hmetrics", &self.number_of_hmetrics()) .finish() } } impl<'a> TryFrom<&'a [u8]> for &'a HorizontalHeaderTable { type Error = ReadError; fn try_from(value: &'a [u8]) -> Result { if value.len() < 36 { return Err(ReadError::UnexpectedEof); } let value: Self = bytemuck::from_bytes(&value[0..36]); let version = value.version(); if version != (1, 0) { return Err(ReadError::UnsupportedTableVersionPair(version.0, version.1)); } let metrics_data_format = value.metrics_data_format(); if metrics_data_format != 0 { return Err(ReadError::UnsupportedMetricsDataFormat(metrics_data_format)); } Ok(value) } }