use truetype::GlyphID;
use crate::layout::{Class, Coverage};
use crate::Result;
#[derive(Clone, Debug)]
pub enum Context {
Format1(Context1),
Format2(Context2),
Format3(Context3),
}
table! {
@position
pub Context1 { format (u16), coverage_offset (u16), record_count (u16),
record_offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.record_count as usize)
},
coverage (Coverage) |this, tape, position| {
jump_take!(tape, position, this.coverage_offset)
},
records (Vec<Records>) |this, tape, position| {
jump_take!(tape, position, this.record_count, this.record_offsets)
},
}
}
table! {
@position
pub Context2 { format (u16), coverage_offset (u16), class_offset (u16), record_count (u16),
record_offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.record_count as usize)
},
coverage (Coverage) |this, tape, position| {
jump_take!(tape, position, this.coverage_offset)
},
class (Class) |this, tape, position| {
jump_take!(tape, position, this.class_offset)
},
records (Vec<Option<ClassRecords>>) |this, tape, position| {
jump_take_maybe!(tape, position, this.record_count, this.record_offsets)
},
}
}
table! {
@position
pub Context3 { format (u16), glyph_count (u16), action_count (u16),
coverage_offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.glyph_count as usize)
},
actions (Vec<Action>) |this, tape, _| { tape.take_given(this.action_count as usize)
},
coverages (Vec<Coverage>) |this, tape, position| {
jump_take!(tape, position, this.glyph_count, this.coverage_offsets)
},
}
}
#[derive(Clone, Debug)]
pub enum ChainedContext {
Format1(ChainedContext1),
Format2(ChainedContext2),
Format3(ChainedContext3),
}
table! {
@position
pub ChainedContext1 { format (u16), coverage_offset (u16), record_count (u16),
record_offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.record_count as usize)
},
coverage (Coverage) |this, tape, position| {
jump_take!(tape, position, this.coverage_offset)
},
records (Vec<ChainedRecords>) |this, tape, position| {
jump_take!(tape, position, this.record_count, this.record_offsets)
},
}
}
table! {
@position
pub ChainedContext2 { format (u16), coverage_offset (u16), backward_class_offset (u16), class_offset (u16), forward_class_offset (u16), record_count (u16),
record_offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.record_count as usize)
},
coverage (Coverage) |this, tape, position| {
jump_take!(tape, position, this.coverage_offset)
},
backward_class (Class) |this, tape, position| {
jump_take!(tape, position, this.backward_class_offset)
},
class (Class) |this, tape, position| {
jump_take!(tape, position, this.class_offset)
},
forward_class (Class) |this, tape, position| {
jump_take!(tape, position, this.forward_class_offset)
},
records (Vec<Option<ChainedClassRecords>>) |this, tape, position| {
jump_take_maybe!(tape, position, this.record_count, this.record_offsets)
},
}
}
table! {
@position
pub ChainedContext3 { format (u16), backward_glyph_count (u16),
backward_coverage_offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.backward_glyph_count as usize)
},
glyph_count (u16),
coverage_offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.glyph_count as usize)
},
forward_glyph_count (u16),
forward_coverage_offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.forward_glyph_count as usize)
},
action_count (u16),
actions (Vec<Action>) |this, tape, _| { tape.take_given(this.action_count as usize)
},
backward_coverages (Vec<Coverage>) |this, tape, position| {
jump_take!(tape, position, this.backward_glyph_count, this.backward_coverage_offsets)
},
coverages (Vec<Coverage>) |this, tape, position| {
jump_take!(tape, position, this.glyph_count, this.coverage_offsets)
},
forward_coverages (Vec<Coverage>) |this, tape, position| {
jump_take!(tape, position, this.forward_glyph_count, this.forward_coverage_offsets)
},
}
}
table! {
pub Record { glyph_count (u16), action_count (u16),
glyph_ids (Vec<GlyphID>) |this, tape| { if this.glyph_count == 0 {
raise!("found a malformed context record");
}
tape.take_given(this.glyph_count as usize - 1)
},
actions (Vec<Action>) |this, tape| { tape.take_given(this.action_count as usize)
},
}
}
table! {
@position
pub Records { count (u16),
offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.count as usize)
},
records (Vec<Record>) |this, tape, position| {
jump_take!(tape, position, this.count, this.offsets)
},
}
}
table! {
pub ClassRecord { glyph_count (u16), action_count (u16),
indices (Vec<u16>) |this, tape| { if this.glyph_count == 0 {
raise!("found a malformed class context record");
}
tape.take_given(this.glyph_count as usize - 1)
},
actions (Vec<Action>) |this, tape| { tape.take_given(this.action_count as usize)
},
}
}
table! {
@position
pub ClassRecords { count (u16),
offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.count as usize)
},
records (Vec<ClassRecord>) |this, tape, position| {
jump_take!(tape, position, this.count, this.offsets)
},
}
}
table! {
pub ChainedRecord { backward_glyph_count (u16),
backward_glyph_ids (Vec<GlyphID>) |this, tape| { tape.take_given(this.backward_glyph_count as usize)
},
glyph_count (u16),
glyph_ids (Vec<GlyphID>) |this, tape| { if this.glyph_count == 0 {
raise!("found a malformed chained context record");
}
tape.take_given(this.glyph_count as usize - 1)
},
forward_glyph_count (u16),
forward_glyph_ids (Vec<GlyphID>) |this, tape| { tape.take_given(this.forward_glyph_count as usize)
},
action_count (u16),
actions (Vec<Action>) |this, tape| { tape.take_given(this.action_count as usize)
},
}
}
table! {
@position
pub ChainedRecords { count (u16),
offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.count as usize)
},
records (Vec<ChainedRecord>) |this, tape, position| {
jump_take!(tape, position, this.count, this.offsets)
},
}
}
table! {
pub ChainedClassRecord { backward_glyph_count (u16),
backward_indices (Vec<u16>) |this, tape| { tape.take_given(this.backward_glyph_count as usize)
},
glyph_count (u16),
indices (Vec<u16>) |this, tape| { if this.glyph_count == 0 {
raise!("found a malformed chained class context record");
}
tape.take_given(this.glyph_count as usize - 1)
},
forward_glyph_count (u16),
forward_indices (Vec<u16>) |this, tape| { tape.take_given(this.forward_glyph_count as usize)
},
action_count (u16),
actions (Vec<Action>) |this, tape| { tape.take_given(this.action_count as usize)
},
}
}
table! {
@position
pub ChainedClassRecords { count (u16),
offsets (Vec<u16>) |this, tape, _| { tape.take_given(this.count as usize)
},
records (Vec<ChainedClassRecord>) |this, tape, position| {
jump_take!(tape, position, this.count, this.offsets)
},
}
}
table! {
#[derive(Copy)]
pub Action { position_index (u16), lookup_index (u16), }
}
impl crate::value::Read for Context {
fn read<T: crate::tape::Read>(tape: &mut T) -> Result<Self> {
Ok(match tape.peek::<u16>()? {
1 => Self::Format1(tape.take()?),
2 => Self::Format2(tape.take()?),
3 => Self::Format3(tape.take()?),
value => raise!("found an unknown format of the context table ({value})"),
})
}
}
impl crate::value::Read for ChainedContext {
fn read<T: crate::tape::Read>(tape: &mut T) -> Result<Self> {
Ok(match tape.peek::<u16>()? {
1 => Self::Format1(tape.take()?),
2 => Self::Format2(tape.take()?),
3 => Self::Format3(tape.take()?),
value => {
raise!("found an unknown format of the chained context table ({value})")
}
})
}
}