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 VertialHeaderTable([u8; 36]); impl<'a> RandomAccess<'a> for &'a VertialHeaderTable { fn bytes(&self) -> &'a [u8] { &self.0 } } impl VertialHeaderTable { pub fn version(&self) -> Version16Dot16 { self.version16dot16(0) } 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_height_max(&self) -> u16 { self.uint16(10) } pub fn min_top_side_bearing(&self) -> i16 { self.int16(12) } pub fn min_bottom_side_bearing(&self) -> i16 { self.int16(14) } pub fn max_y_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_vmetrics(&self) -> u16 { self.uint16(34) } } impl Debug for VertialHeaderTable { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.debug_struct("VertialHeaderTable") .field("version", &self.version()) .field("ascender", &self.ascender()) .field("descender", &self.descender()) .field("line_gap", &self.line_gap()) .field("advance_height_max", &self.advance_height_max()) .field("min_top_side_bearing", &self.min_top_side_bearing()) .field("min_bottom_side_bearing", &self.min_bottom_side_bearing()) .field("max_y_extent", &self.max_y_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_vmetrics", &self.number_of_vmetrics()) .finish() } } impl<'a> TryFrom<&'a [u8]> for &'a VertialHeaderTable { 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 !matches!(version, Version16Dot16(1, 0) | Version16Dot16(1, 0x1000)) { return Err(ReadError::UnsupportedTableVersion16Dot16(version)); } let metrics_data_format = value.metrics_data_format(); if metrics_data_format != 0 { return Err(ReadError::UnsupportedMetricsDataFormat(metrics_data_format)); } Ok(value) } }