use crate::font::TrueTypeFont;
use crate::Vec;
#[derive(Debug, Clone)]
pub(crate) struct HmtxTable {
pub(crate) h_metrics: Vec<LongHorMetric>,
pub(crate) left_side_bearings: Vec<i16>,
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct LongHorMetric {
pub(crate) advance_width: u16,
pub(crate) left_side_bearing: i16,
}
use crate::font::FontError;
impl HmtxTable {
pub(crate) fn new() -> HmtxTable {
HmtxTable {
h_metrics: Vec::new(),
left_side_bearings: Vec::new(),
}
}
}
impl TrueTypeFont {
pub(crate) fn load_hmtx(&mut self, font_bytes: &[u8]) -> Result<(), FontError> {
for table in &self.tables {
if table.table_tag == "hmtx".as_bytes() {
let table_offset = table.offset as usize;
let mut offset = table_offset;
let mut h_metrics = Vec::new();
for _ in 0..self.hhea.number_of_h_metrics {
if offset + 4 > font_bytes.len() {
return Err(FontError::UnexpectedEndOfFile);
}
h_metrics.push(LongHorMetric {
advance_width: u16::from_be_bytes([font_bytes[offset], font_bytes[offset + 1]]),
left_side_bearing: i16::from_be_bytes([font_bytes[offset + 2], font_bytes[offset + 3]]),
});
offset += 4;
}
let mut left_side_bearings = Vec::new();
for _ in self.hhea.number_of_h_metrics..self.maxp.num_glyphs {
if offset + 2 > font_bytes.len() {
return Err(FontError::UnexpectedEndOfFile);
}
left_side_bearings.push(i16::from_be_bytes([font_bytes[offset], font_bytes[offset + 1]]));
offset += 2;
}
self.hmtx = HmtxTable { h_metrics, left_side_bearings };
return Ok(());
}
}
Err(FontError::TableNotFound("hmtx"))
}
pub(crate) fn get_metrics(&self, glyph_id: &u32, scale: f32) -> (usize, isize) {
let idx = *glyph_id as usize;
if idx < self.hmtx.h_metrics.len() {
let metric = self.hmtx.h_metrics[idx];
((metric.advance_width as f32 * scale) as usize, (metric.left_side_bearing as f32 * scale) as isize)
} else {
let lsb_idx = idx - self.hmtx.h_metrics.len();
if lsb_idx < self.hmtx.left_side_bearings.len() {
let advance = self.hmtx.h_metrics.last().unwrap().advance_width;
let lsb = self.hmtx.left_side_bearings[lsb_idx];
((advance as f32 * scale) as usize, (lsb as f32 * scale) as isize)
} else {
(0, 0)
}
}
}
}