use std::ops::{ Deref, Range }; use std::fmt::{ Debug, Formatter, Result as FmtResult }; use bytemuck::{ Zeroable, Pod }; use super::ReadError; use super::core::*; use super::loca::IndexToLocationTable; // Glyph Header #[derive(Clone, Copy, Zeroable, Pod)] #[repr(transparent)] pub struct GlyphHeader([u8; 10]); impl<'a> RandomAccess<'a> for &'a GlyphHeader { fn bytes(&self) -> &'a [u8] { &self.0 } } impl GlyphHeader { pub fn contour_count(&self) -> i16 { self.int16(0) } pub fn bounding_box(&self) -> (i16, i16, i16, i16) { let min_x = self.int16(2); let min_y = self.int16(4); let max_x = self.int16(6); let max_y = self.int16(8); (min_x, min_y, max_x, max_y) } } impl Debug for GlyphHeader { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.debug_struct("GlyphHeader") .field("contour_count", &self.contour_count()) .field("bounding_box", &self.bounding_box()) .finish() } } // Simple Glyph const ON_CURVE_POINT: u8 = 0x01; const X_SHORT_VECTOR: u8 = 0x02; const Y_SHORT_VECTOR: u8 = 0x04; const REPEAT_FLAG: u8 = 0x08; const X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR: u8 = 0x10; const Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR: u8 = 0x20; //const OVERLAP_SIMPLE: u8 = 0x40; #[derive(Clone, Copy)] pub struct SimpleGlyph<'a> { data: &'a [u8], instructions_offset: u32, flags_offset: u32, x_data_offset: u32, y_data_offset: u32, } impl<'a> RandomAccess<'a> for SimpleGlyph<'a> { fn bytes(&self) -> &'a [u8] { self.data } } impl AsRef for SimpleGlyph<'_> { fn as_ref(&self) -> &GlyphHeader { bytemuck::from_bytes(&self.data[0..10]) } } impl Deref for SimpleGlyph<'_> { type Target = GlyphHeader; fn deref(&self) -> &Self::Target { self.as_ref() } } impl<'a> SimpleGlyph<'a> { pub fn endpoints(&self) -> U16Array<'a> { self.uint16_array(10, self.contour_count() as usize) } pub fn instructions(&self) -> &'a [u8] { &self.data[self.instructions_offset as usize..self.flags_offset as usize] } pub fn flags(&self) -> &'a [u8] { &self.data[self.flags_offset as usize..self.x_data_offset as usize] } pub fn x_data(&self) -> &'a [u8] { &self.data[self.x_data_offset as usize..self.y_data_offset as usize] } pub fn y_data(&self) -> &'a [u8] { &self.data[self.y_data_offset as usize..] } pub fn point_count(&self) -> u16 { self.endpoints().get(self.contour_count() as usize - 1) + 1 } pub fn points(&self) -> Points<'a> { Points::new(self.flags(), self.x_data(), self.y_data(), self.point_count()) } pub fn contours(&self) -> Contours<'a> { Contours::new(self.endpoints()) } } impl Debug for SimpleGlyph<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.debug_struct("SimpleGlyph") .field("contour_count", &self.contour_count()) .field("bounding_box", &self.bounding_box()) .field("instructions", &self.instructions()) .field("points", &self.points()) .field("contours", &self.contours()) .finish() } } impl<'a> TryFrom<&'a [u8]> for SimpleGlyph<'a> { type Error = ReadError; fn try_from(value: &'a [u8]) -> Result { if value.len() < 10 { return Err(ReadError::UnexpectedEof); } let contour_count = value.uint16(0) as usize; let endpoints_stop = 10 + contour_count * 2; let point_count = value.uint16(endpoints_stop - 2) + 1; let instruction_count = value.uint16(endpoints_stop) as usize; let instructions_offset = endpoints_stop + 2; let flags_offset = instructions_offset + instruction_count; let mut flags_length: usize = 0; let mut x_length: usize = 0; let mut y_length: usize = 0; let mut flag = 0; let mut repeat_count = 0; for _ in 0..point_count { if repeat_count > 0 { repeat_count -= 1; } else { flag = value[flags_offset + flags_length]; flags_length += 1; if (flag & REPEAT_FLAG) != 0 { repeat_count = value[flags_offset + flags_length]; flags_length += 1; } } if (flag & X_SHORT_VECTOR) != 0 { x_length += 1; } else if (flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) == 0 { x_length += 2; } if (flag & Y_SHORT_VECTOR) != 0 { y_length += 1; } else if (flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) == 0 { y_length += 2; } } let x_data_offset = flags_offset + flags_length; let y_data_offset = x_data_offset + x_length; let size = y_data_offset + y_length; Ok(Self { data: &value[0..size], instructions_offset: instructions_offset as u32, flags_offset: flags_offset as u32, x_data_offset: x_data_offset as u32, y_data_offset: y_data_offset as u32, }) } } // Points #[derive(Clone, Copy, Debug)] pub struct Point { pub x: i16, pub y: i16, pub on_curve: bool, } #[derive(Clone)] pub struct Points<'a> { flags: &'a [u8], x_data: &'a [u8], y_data: &'a [u8], remaining: u16, current_flags: u8, repeat_count: u8, current_x: i16, current_y: i16, } impl<'a> Points<'a> { pub fn new(flags: &'a [u8], x_data: &'a [u8], y_data: &'a [u8], point_count: u16) -> Self { Self { flags, x_data, y_data, remaining: point_count, current_flags: 0, repeat_count: 0, current_x: 0, current_y: 0, } } fn next_flags(&mut self) { if self.repeat_count > 0 { self.repeat_count -= 1; } else { self.current_flags = self.flags[0]; if (self.current_flags & REPEAT_FLAG) != 0 { self.repeat_count = self.flags[1]; self.flags = &self.flags[2..]; } else { self.flags = &self.flags[1..]; } } } fn next_x(&mut self) { if (self.current_flags & X_SHORT_VECTOR) != 0 { let delta = self.x_data[0] as i16; self.x_data = &self.x_data[1..]; if (self.current_flags & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) != 0 { self.current_x += delta; } else { self.current_x -= delta; } } else if (self.current_flags & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) == 0 { let delta = self.x_data.int16(0); self.x_data = &self.x_data[2..]; self.current_x += delta; } } fn next_y(&mut self) { if (self.current_flags & Y_SHORT_VECTOR) != 0 { let delta = self.y_data[0] as i16; self.y_data = &self.y_data[1..]; if (self.current_flags & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) != 0 { self.current_y += delta; } else { self.current_y -= delta; } } else if (self.current_flags & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) == 0 { let delta = self.y_data.int16(0); self.y_data = &self.y_data[2..]; self.current_y += delta; } } } impl<'a> Iterator for Points<'a> { type Item = Point; fn next(&mut self) -> Option { if self.remaining > 0 { self.remaining -= 1; self.next_flags(); self.next_x(); self.next_y(); Some(Point { x: self.current_x, y: self.current_y, on_curve: (self.current_flags & ON_CURVE_POINT) != 0 }) } else { None } } } impl Debug for Points<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.debug_list() .entries(self.clone()) .finish() } } // Contours #[derive(Clone)] pub struct Contours<'a> { endpoints: U16Array<'a>, index: u16, offset: u16, } impl<'a> Contours<'a> { pub fn new(endpoints: U16Array<'a>) -> Self { Self { endpoints, index: 0, offset: 0, } } } impl<'a> Iterator for Contours<'a> { type Item = Range; fn next(&mut self) -> Option { let index = self.index as usize; if index < self.endpoints.len() { let start = self.offset; let stop = self.endpoints.get(index) + 1; self.index += 1; self.offset = stop; Some(start..stop) } else { None } } fn size_hint(&self) -> (usize, Option) { let len = self.endpoints.len(); (len, Some(len)) } } impl<'a> ExactSizeIterator for Contours<'a> {} impl Debug for Contours<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.debug_list() .entries(self.clone()) .finish() } } // Component Glyph const ARG_1_AND_2_ARE_WORDS: u16 = 0x0001; const ARGS_ARE_XY_VALUES: u16 = 0x0002; const ROUND_XY_TO_GRID: u16 = 0x0004; const WE_HAVE_A_SCALE: u16 = 0x0008; const MORE_COMPONENTS: u16 = 0x0020; const WE_HAVE_AN_X_AND_Y_SCALE: u16 = 0x0040; const WE_HAVE_A_TWO_BY_TWO: u16 = 0x0080; const WE_HAVE_INSTRUCTIONS: u16 = 0x0100; const USE_MY_METRICS: u16 = 0x0200; //const OVERLAP_COMPOUND: u16 = 0x0400; const SCALED_COMPONENT_OFFSET: u16 = 0x0800; const UNSCALED_COMPONENT_OFFSET: u16 = 0x1000; #[derive(Debug, Clone, Copy)] pub enum ComponentGlyphPosition { Offset8 { x: i8, y: i8, round_to_grid: bool, }, Offset16 { x: i16, y: i16, round_to_grid: bool, }, Align8 { parent_point: u8, component_point: u8, }, Align16 { parent_point: u16, component_point: u16, }, } #[derive(Clone, Copy)] pub enum ComponentGlyphTransform { Identity, Scale(F2Dot14), ScaleXY(F2Dot14, F2Dot14), Matrix(F2Dot14, F2Dot14, F2Dot14, F2Dot14), } impl ComponentGlyphTransform { // TODO check if correct pub fn matrix(&self) -> (F2Dot14, F2Dot14, F2Dot14, F2Dot14) { match self { Self::Identity => (F2Dot14::ONE, F2Dot14::ZERO, F2Dot14::ZERO, F2Dot14::ONE), Self::Scale(x) => (*x, F2Dot14::ZERO, F2Dot14::ZERO, *x), Self::ScaleXY(x, y) => (*x, F2Dot14::ZERO, F2Dot14::ZERO, *y), Self::Matrix(a, b, c, d) => (*a, *b, *c, *d), } } pub fn simplify(&self) -> Self { match self { Self::Identity => Self::Identity, Self::Scale(x) => if *x == F2Dot14::ONE { Self::Identity } else { Self::Scale(*x) }, Self::ScaleXY(x, y) => { if *x == *y { if *x == F2Dot14::ONE { Self::Identity } else { Self::Scale(*x) } } else { Self::ScaleXY(*x, *y) } }, Self::Matrix(a, b, c, d) => { if *b == F2Dot14::ZERO && *c == F2Dot14::ZERO { if *a == *d { if *a == F2Dot14::ONE { Self::Identity } else { Self::Scale(*a) } } else { Self::ScaleXY(*a, *d) } } else { Self::Matrix(*a, *b, *c, *d) } }, } } } impl Debug for ComponentGlyphTransform { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { self.matrix().fmt(f) } } #[derive(Debug, Clone, Copy)] pub enum ComponentOffsetMode { Default, Scaled, Unscaled, } #[derive(Clone, Copy)] pub struct ComponentGlyph<'a>(&'a [u8]); impl<'a> RandomAccess<'a> for ComponentGlyph<'a> { fn bytes(&self) -> &'a [u8] { self.0 } } impl<'a> ComponentGlyph<'a> { fn flags(&self) -> u16 { self.uint16(0) } pub fn use_my_metrics(&self) -> bool { (self.flags() & USE_MY_METRICS) != 0 } pub fn glyph_index(&self) -> u16 { self.uint16(2) } pub fn offset_mode(&self) -> ComponentOffsetMode { if (self.flags() & SCALED_COMPONENT_OFFSET) != 0 { ComponentOffsetMode::Scaled } else if (self.flags() & UNSCALED_COMPONENT_OFFSET) != 0 { ComponentOffsetMode::Unscaled } else { ComponentOffsetMode::Default } } pub fn position(&self) -> ComponentGlyphPosition { let flags = self.flags(); if (flags & ARGS_ARE_XY_VALUES) != 0 { if (flags & ARG_1_AND_2_ARE_WORDS) != 0 { ComponentGlyphPosition::Offset16 { x: self.int16(4), y: self.int16(6), round_to_grid: (flags & ROUND_XY_TO_GRID) != 0, } } else { ComponentGlyphPosition::Offset8 { x: self.int8(4), y: self.int8(5), round_to_grid: (flags & ROUND_XY_TO_GRID) != 0, } } } else if (flags & ARG_1_AND_2_ARE_WORDS) != 0 { ComponentGlyphPosition::Align16 { parent_point: self.uint16(4), component_point: self.uint16(6), } } else { ComponentGlyphPosition::Align8 { parent_point: self.uint8(4), component_point: self.uint8(5), } } } pub fn transform(&self) -> ComponentGlyphTransform { let flags = self.flags(); let offset = if (flags & ARG_1_AND_2_ARE_WORDS) != 0 { 8 } else { 6 }; if (flags & WE_HAVE_A_SCALE) != 0 { ComponentGlyphTransform::Scale(self.f2dot14(offset)) } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0 { ComponentGlyphTransform::ScaleXY(self.f2dot14(offset), self.f2dot14(offset + 2)) } else if (flags & WE_HAVE_A_TWO_BY_TWO) != 0 { ComponentGlyphTransform::Matrix(self.f2dot14(offset), self.f2dot14(offset + 2), self.f2dot14(offset + 4), self.f2dot14(offset + 6)) } else { ComponentGlyphTransform::Identity } } } impl Debug for ComponentGlyph<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.debug_struct("ComponentGlyph") .field("use_my_metrics", &self.use_my_metrics()) .field("glyph_index", &self.glyph_index()) .field("offset_mode", &self.offset_mode()) .field("position", &self.position()) .field("transform", &self.transform()) .finish() } } impl<'a> TryFrom<&'a [u8]> for ComponentGlyph<'a> { type Error = ReadError; fn try_from(value: &'a [u8]) -> Result { if value.len() < 6 { return Err(ReadError::UnexpectedEof); } let flags = value.uint16(0); let mut size = 6; if (flags & ARG_1_AND_2_ARE_WORDS) != 0 { size += 2; } if (flags & WE_HAVE_A_SCALE) != 0 { size += 2; } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0 { size += 4; } else if (flags & WE_HAVE_A_TWO_BY_TWO) != 0 { size += 8; } if value.len() < size { return Err(ReadError::UnexpectedEof); } Ok(Self(&value[0..size])) } } // Components #[derive(Debug, Clone, Copy)] pub enum Component<'a> { Glyph(ComponentGlyph<'a>), Instructions(&'a [u8]), } #[derive(Clone)] pub struct Components<'a> { data: &'a [u8], flags: u16, } impl<'a> Components<'a> { pub fn new(data: &'a [u8]) -> Self { Self { data, flags: MORE_COMPONENTS, } } } impl<'a> Iterator for Components<'a> { type Item = Result, ReadError>; fn next(&mut self) -> Option { if (self.flags & MORE_COMPONENTS) != 0 { match ComponentGlyph::try_from(self.data) { Ok(glyph) => { self.flags = glyph.flags(); self.data = &self.data[glyph.0.len()..]; Some(Ok(Component::Glyph(glyph))) }, Err(err) => { self.flags = 0; Some(Err(err)) }, } } else if (self.flags & WE_HAVE_INSTRUCTIONS) != 0 { let count = self.data.uint16(0); let length = count as usize + 2; let instructions = &self.data[2..length]; self.flags = 0; self.data = &self.data[length..]; Some(Ok(Component::Instructions(instructions))) } else { None } } } impl Debug for Components<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.debug_list() .entries(self.clone()) .finish() } } // Composite Glyph #[derive(Clone, Copy)] pub struct CompositeGlyph<'a>(&'a [u8]); impl<'a> RandomAccess<'a> for CompositeGlyph<'a> { fn bytes(&self) -> &'a [u8] { self.0 } } impl AsRef for CompositeGlyph<'_> { fn as_ref(&self) -> &GlyphHeader { bytemuck::from_bytes(&self.0[0..10]) } } impl Deref for CompositeGlyph<'_> { type Target = GlyphHeader; fn deref(&self) -> &Self::Target { self.as_ref() } } impl<'a> CompositeGlyph<'a> { pub fn components(&self) -> Components<'a> { Components::new(&self.0[10..]) } } impl Debug for CompositeGlyph<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.debug_struct("CompositeGlyph") .field("bounding_box", &self.bounding_box()) .field("components", &self.components()) .finish() } } impl<'a> TryFrom<&'a [u8]> for CompositeGlyph<'a> { type Error = ReadError; fn try_from(value: &'a [u8]) -> Result { if value.len() < 10 { return Err(ReadError::UnexpectedEof); } Ok(Self(value)) } } // Glyph #[derive(Clone, Copy)] pub enum Glyph<'a> { Simple(SimpleGlyph<'a>), Composite(CompositeGlyph<'a>), } impl<'a> RandomAccess<'a> for Glyph<'a> { fn bytes(&self) -> &'a [u8] { match self { Self::Simple(x) => x.bytes(), Self::Composite(x) => x.bytes(), } } } impl AsRef for Glyph<'_> { fn as_ref(&self) -> &GlyphHeader { match self { Self::Simple(x) => x.as_ref(), Self::Composite(x) => x.as_ref(), } } } impl Deref for Glyph<'_> { type Target = GlyphHeader; fn deref(&self) -> &Self::Target { self.as_ref() } } impl Debug for Glyph<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { match self { Self::Simple(x) => x.fmt(f), Self::Composite(x) => x.fmt(f), } } } impl<'a> TryFrom<&'a [u8]> for Glyph<'a> { type Error = ReadError; fn try_from(value: &'a [u8]) -> Result { if value.len() < 10 { return Err(ReadError::UnexpectedEof); } if value.int16(0) >= 0 { Ok(Self::Simple(value.try_into()?)) } else { Ok(Self::Composite(value.try_into()?)) } } } // Glyph Data Table #[derive(Clone, Copy)] pub struct GlyphDataTable<'a> { data: &'a [u8], loca: IndexToLocationTable<'a>, } impl<'a> RandomAccess<'a> for GlyphDataTable<'a> { fn bytes(&self) -> &'a [u8] { self.data } } impl<'a> GlyphDataTable<'a> { pub fn glyph_data(&self, range: Range) -> Result<&'a [u8], Range> { let start = range.start as usize; let stop = range.end as usize; let data = self.bytes(); if stop <= data.len() { Ok(&data[start..stop]) } else { Err(range) } } pub fn glyph_at(&self, range: Range) -> Result, ReadError> { match self.glyph_data(range) { Ok(data) => data.try_into(), Err(_) => Err(ReadError::UnexpectedEof), } } pub fn glyph(&self, index: u32) -> Option, ReadError>> { self.loca.map(index).map(|x| self.glyph_at(x)) } pub fn glyphs(&self) -> impl ExactSizeIterator, ReadError>>> + '_ { self.loca.iter().map(|x| x.map(|x| self.glyph_at(x))) } } impl<'a> Debug for GlyphDataTable<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.debug_list() .entries(self.glyphs()) .finish() } } impl<'a> GlyphDataTable<'a> { pub fn from(data: &'a [u8], loca: IndexToLocationTable<'a>) -> Self { Self { data, loca } } }