use truetype::GlyphID;
use crate::layout::Correction;
use crate::Result;
#[derive(Clone, Debug)]
pub enum Anchor {
Format1(Anchor1),
Format2(Anchor2),
Format3(Anchor3),
}
table! {
#[derive(Copy)]
pub Anchor1 { format (u16), x (i16), y (i16), }
}
table! {
#[derive(Copy)]
pub Anchor2 { format (u16), x (i16), y (i16), index (u16), }
}
table! {
@position
pub Anchor3 { format (u16), x (i16), y (i16), x_correction_offset (u16), y_correction_offset (u16), x_correction (Option<Correction>) |this, tape, position| {
jump_take_maybe!(tape, position, this.x_correction_offset)
},
y_correction (Option<Correction>) |this, tape, position| {
jump_take_maybe!(tape, position, this.y_correction_offset)
},
}
}
table! {
@define
pub Base { anchor_offsets (Vec<u16>), anchors (Vec<Option<Anchor>>),
}
}
table! {
@define
pub Bases { count (u16 ), records (Vec<Base>), }
}
table! {
@define
pub Component { anchor_offsets (Vec<u16>), anchors (Vec<Option<Anchor>>),
}
}
table! {
@define
pub Connection { start_anchor_offset (u16), end_anchor_offset (u16), start_anchor (Option<Anchor>),
end_anchor (Option<Anchor>),
}
}
table! {
@define
pub Ligature { count (u16 ), components (Vec<Component>), }
}
table! {
@define
pub Ligatures { count (u16 ), offsets (Vec<u16>), records (Vec<Ligature>),
}
}
table! {
@define
pub Mark1 { class_id (u16), anchor_offset (u16), anchor (Anchor),
}
}
table! {
@position
pub Mark1s { count (u16), records (Vec<Mark1>) |this, tape, position| { (0..this.count).map(|_| tape.take_given(position)).collect()
},
}
}
table! {
@define
pub Mark2 { anchor_offsets (Vec<u16>), anchors (Vec<Option<Anchor>>),
}
}
table! {
@define
pub Mark2s { count (u16 ), records (Vec<Mark2>), }
}
table! {
@define
pub Pair1 { glyph2_id (GlyphID ), value1 (Option<Single>), value2 (Option<Single>), }
}
table! {
@define
pub Pair1s { count (u16 ), records (Vec<Pair1>), }
}
table! {
@define
pub Pair2 { value1 (Option<Single>), value2 (Option<Single>), }
}
table! {
@define
pub Pair2s { records (Vec<Pair2>), }
}
table! {
@define
pub Single { x_placement (Option<i16>), y_placement (Option<i16>), x_advance (Option<i16>), y_advance (Option<i16>), x_placement_correction_offset (Option<u16>), y_placement_correction_offset (Option<u16>), x_advance_correction_offset (Option<u16>), y_advance_correction_offset (Option<u16>), x_placement_correction (Option<Correction>),
y_placement_correction (Option<Correction>),
x_advance_correction (Option<Correction>),
y_advance_correction (Option<Correction>),
}
}
flags! {
pub Flags(u16) { 0b0000_0000_0000_0001 => has_x_placement,
0b0000_0000_0000_0010 => has_y_placement,
0b0000_0000_0000_0100 => has_x_advance,
0b0000_0000_0000_1000 => has_y_advance,
0b0000_0000_0001_0000 => has_x_placement_correction,
0b0000_0000_0010_0000 => has_y_placement_correction,
0b0000_0000_0100_0000 => has_x_advance_correction,
0b0000_0000_1000_0000 => has_y_advance_correction,
0b1111_1111_0000_0000 => is_invalid,
}
}
impl Default for Anchor {
#[inline]
fn default() -> Self {
Anchor::Format1(Anchor1::default())
}
}
impl crate::value::Read for Anchor {
fn read<T: crate::tape::Read>(tape: &mut T) -> Result<Self> {
Ok(match tape.peek::<u16>()? {
1 => Anchor::Format1(tape.take()?),
2 => Anchor::Format2(tape.take()?),
3 => Anchor::Format3(tape.take()?),
value => raise!("found an unknown format of the anchor table ({value})"),
})
}
}
impl crate::walue::Read<'static> for Base {
type Parameter = (u64, u16);
fn read<T: crate::tape::Read>(
tape: &mut T,
(position, mark_class_count): Self::Parameter,
) -> Result<Self> {
let anchor_offsets: Vec<u16> = tape.take_given(mark_class_count as usize)?;
let anchors =
tape.stay(|tape| jump_take_maybe!(tape, position, mark_class_count, anchor_offsets))?;
Ok(Self {
anchor_offsets,
anchors,
})
}
}
impl crate::walue::Read<'static> for Bases {
type Parameter = u16;
fn read<T: crate::tape::Read>(tape: &mut T, mark_class_count: Self::Parameter) -> Result<Self> {
let position = tape.position()?;
let count = tape.take()?;
let records = (0..count)
.map(|_| tape.take_given((position, mark_class_count)))
.collect::<Result<Vec<_>>>()?;
Ok(Self { count, records })
}
}
impl crate::walue::Read<'static> for Component {
type Parameter = (u64, u16);
fn read<T: crate::tape::Read>(
tape: &mut T,
(position, mark_class_count): Self::Parameter,
) -> Result<Self> {
let anchor_offsets: Vec<u16> = tape.take_given(mark_class_count as usize)?;
let anchors =
tape.stay(|tape| jump_take_maybe!(tape, position, mark_class_count, anchor_offsets))?;
Ok(Self {
anchor_offsets,
anchors,
})
}
}
impl crate::walue::Read<'static> for Ligature {
type Parameter = u16;
fn read<T: crate::tape::Read>(tape: &mut T, mark_class_count: Self::Parameter) -> Result<Self> {
let position = tape.position()?;
let count = tape.take()?;
let components = (0..count)
.map(|_| tape.take_given((position, mark_class_count)))
.collect::<Result<Vec<_>>>()?;
Ok(Self { count, components })
}
}
impl crate::walue::Read<'static> for Ligatures {
type Parameter = u16;
fn read<T: crate::tape::Read>(tape: &mut T, mark_class_count: Self::Parameter) -> Result<Self> {
let position = tape.position()?;
let count = tape.take()?;
let offsets: Vec<u16> = tape.take_given(count as usize)?;
let records =
tape.stay(|tape| jump_take_given!(tape, position, count, offsets, mark_class_count))?;
Ok(Self {
count,
offsets,
records,
})
}
}
impl crate::walue::Read<'static> for Mark1 {
type Parameter = u64;
fn read<T: crate::tape::Read>(tape: &mut T, position: Self::Parameter) -> Result<Self> {
let class_id = tape.take()?;
let anchor_offset = tape.take()?;
#[cfg(not(feature = "ignore-incomplete-marks"))]
let anchor = tape.stay(|tape| jump_take!(tape, position, anchor_offset))?;
#[cfg(feature = "ignore-incomplete-marks")]
let anchor = tape
.stay(|tape| jump_take_maybe!(tape, position, anchor_offset))?
.unwrap_or_default();
Ok(Self {
class_id,
anchor_offset,
anchor,
})
}
}
impl crate::walue::Read<'static> for Mark2 {
type Parameter = (u64, u16);
fn read<T: crate::tape::Read>(
tape: &mut T,
(position, mark_class_count): Self::Parameter,
) -> Result<Self> {
let anchor_offsets: Vec<u16> = tape.take_given(mark_class_count as usize)?;
let anchors =
tape.stay(|tape| jump_take_maybe!(tape, position, mark_class_count, anchor_offsets))?;
Ok(Self {
anchor_offsets,
anchors,
})
}
}
impl crate::walue::Read<'static> for Mark2s {
type Parameter = u16;
fn read<T: crate::tape::Read>(tape: &mut T, mark_class_count: Self::Parameter) -> Result<Self> {
let position = tape.position()?;
let count = tape.take()?;
let records = (0..count)
.map(|_| tape.take_given((position, mark_class_count)))
.collect::<Result<Vec<_>>>()?;
Ok(Self { count, records })
}
}
impl crate::walue::Read<'static> for Pair1 {
type Parameter = (u64, Flags, Flags);
fn read<T: crate::tape::Read>(
tape: &mut T,
(position, value1_flags, value2_flags): Self::Parameter,
) -> Result<Self> {
Ok(Self {
glyph2_id: tape.take()?,
value1: if value1_flags.0 > 0 {
Some(tape.take_given((position, value1_flags))?)
} else {
None
},
value2: if value2_flags.0 > 0 {
Some(tape.take_given((position, value2_flags))?)
} else {
None
},
})
}
}
impl crate::walue::Read<'static> for Pair1s {
type Parameter = (Flags, Flags);
fn read<T: crate::tape::Read>(
tape: &mut T,
(value1_flags, value2_flags): Self::Parameter,
) -> Result<Self> {
let position = tape.position()?;
let count = tape.take()?;
let records = (0..count)
.map(|_| tape.take_given((position, value1_flags, value2_flags)))
.collect::<Result<Vec<_>>>()?;
Ok(Self { count, records })
}
}
impl crate::walue::Read<'static> for Pair2 {
type Parameter = (u64, Flags, Flags);
fn read<T: crate::tape::Read>(
tape: &mut T,
(position, value1_flags, value2_flags): Self::Parameter,
) -> Result<Self> {
Ok(Self {
value1: if value1_flags.0 > 0 {
Some(tape.take_given((position, value1_flags))?)
} else {
None
},
value2: if value2_flags.0 > 0 {
Some(tape.take_given((position, value2_flags))?)
} else {
None
},
})
}
}
impl crate::walue::Read<'static> for Pair2s {
type Parameter = (u64, u16, Flags, Flags);
fn read<T: crate::tape::Read>(
tape: &mut T,
(position, class2_count, value1_flags, value2_flags): Self::Parameter,
) -> Result<Self> {
let records = (0..class2_count)
.map(|_| tape.take_given((position, value1_flags, value2_flags)))
.collect::<Result<Vec<_>>>()?;
Ok(Self { records })
}
}
impl crate::walue::Read<'static> for Connection {
type Parameter = u64;
fn read<T: crate::tape::Read>(tape: &mut T, position: u64) -> Result<Self> {
let start_anchor_offset = tape.take()?;
let end_anchor_offset = tape.take()?;
let (start_anchor, end_anchor) = tape.stay(|tape| {
Ok((
jump_take_maybe!(@unwrap tape, position, start_anchor_offset),
jump_take_maybe!(@unwrap tape, position, end_anchor_offset),
))
})?;
Ok(Self {
start_anchor_offset,
end_anchor_offset,
start_anchor,
end_anchor,
})
}
}
impl crate::walue::Read<'static> for Single {
type Parameter = (u64, Flags);
fn read<T: crate::tape::Read>(
tape: &mut T,
(position, flags): Self::Parameter,
) -> Result<Self> {
macro_rules! take(
($flag:ident) => (if flags.$flag() { Some(tape.take()?) } else { None });
);
let x_placement = take!(has_x_placement);
let y_placement = take!(has_y_placement);
let x_advance = take!(has_x_advance);
let y_advance = take!(has_y_advance);
let x_placement_correction_offset = take!(has_x_placement_correction);
let y_placement_correction_offset = take!(has_y_placement_correction);
let x_advance_correction_offset = take!(has_x_advance_correction);
let y_advance_correction_offset = take!(has_y_advance_correction);
let (
x_placement_correction,
y_placement_correction,
x_advance_correction,
y_advance_correction,
) = tape.stay(|tape| {
macro_rules! take(
($offset:ident) => (match $offset {
Some(offset) => jump_take_maybe!(@unwrap tape, position, offset),
_ => None,
});
);
Ok((
take!(x_placement_correction_offset),
take!(y_placement_correction_offset),
take!(x_advance_correction_offset),
take!(y_advance_correction_offset),
))
})?;
Ok(Self {
x_placement,
y_placement,
x_advance,
y_advance,
x_placement_correction_offset,
y_placement_correction_offset,
x_advance_correction_offset,
y_advance_correction_offset,
x_placement_correction,
y_placement_correction,
x_advance_correction,
y_advance_correction,
})
}
}