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;
#[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()
}
}
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;
#[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<GlyphHeader> 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<Self, Self::Error> {
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,
})
}
}
#[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<Self::Item> {
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()
}
}
#[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<u16>;
fn next(&mut self) -> Option<Self::Item> {
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<usize>) {
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()
}
}
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 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 {
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<Self, Self::Error> {
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]))
}
}
#[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<Component<'a>, ReadError>;
fn next(&mut self) -> Option<Self::Item> {
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()
}
}
#[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<GlyphHeader> 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<Self, Self::Error> {
if value.len() < 10 { return Err(ReadError::UnexpectedEof); }
Ok(Self(value))
}
}
#[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<GlyphHeader> 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<Self, Self::Error> {
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()?))
}
}
}
#[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<u32>) -> Result<&'a [u8], Range<u32>> {
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<u32>) -> Result<Glyph<'a>, ReadError> {
match self.glyph_data(range) {
Ok(data) => data.try_into(),
Err(_) => Err(ReadError::UnexpectedEof),
}
}
pub fn glyph(&self, index: u32) -> Option<Result<Glyph<'a>, ReadError>> {
self.loca.map(index).map(|x| self.glyph_at(x))
}
pub fn glyphs(&self) -> impl ExactSizeIterator<Item = Option<Result<Glyph<'a>, 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 }
}
}