use crate::gpos::Device;
use crate::opentype_layout::Coverage;
use crate::parser::{
FromData, FromSlice, LazyArray16, LazyOffsetArray16, Offset, Offset16, Stream,
};
use crate::GlyphId;
#[derive(Clone, Copy, Debug)]
pub struct MathValue<'a> {
pub value: i16,
pub device: Option<Device<'a>>,
}
impl<'a> MathValue<'a> {
fn parse(data: &'a [u8], parent: &'a [u8]) -> Option<Self> {
Some(MathValueRecord::parse(data)?.get(parent))
}
}
#[derive(Clone, Copy)]
struct MathValueRecord {
value: i16,
device_offset: Option<Offset16>,
}
impl FromData for MathValueRecord {
const SIZE: usize = 4;
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
let value = s.read::<i16>()?;
let device_offset = s.read::<Option<Offset16>>()?;
Some(MathValueRecord {
value,
device_offset,
})
}
}
impl MathValueRecord {
fn get(self, data: &[u8]) -> MathValue {
let device = self
.device_offset
.and_then(|offset| data.get(offset.to_usize()..))
.and_then(Device::parse);
MathValue {
value: self.value,
device,
}
}
}
#[derive(Clone, Copy)]
pub struct MathValues<'a> {
data: &'a [u8],
coverage: Coverage<'a>,
records: LazyArray16<'a, MathValueRecord>,
}
impl<'a> FromSlice<'a> for MathValues<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let coverage = s.parse_at_offset16::<Coverage>(data)?;
let count = s.read::<u16>()?;
let records = s.read_array16::<MathValueRecord>(count)?;
Some(MathValues {
data,
coverage,
records,
})
}
}
impl<'a> MathValues<'a> {
#[inline]
pub fn get(&self, glyph: GlyphId) -> Option<MathValue<'a>> {
let index = self.coverage.get(glyph)?;
Some(self.records.get(index)?.get(self.data))
}
}
impl core::fmt::Debug for MathValues<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "MathValues {{ ... }}")
}
}
#[derive(Clone, Copy)]
pub struct Constants<'a> {
data: &'a [u8],
}
impl<'a> FromSlice<'a> for Constants<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
Some(Constants { data })
}
}
impl core::fmt::Debug for Constants<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "Constants {{ ... }}")
}
}
const SCRIPT_PERCENT_SCALE_DOWN_OFFSET: usize = 0;
const SCRIPT_SCRIPT_PERCENT_SCALE_DOWN_OFFSET: usize = 2;
const DELIMITED_SUB_FORMULA_MIN_HEIGHT_OFFSET: usize = 4;
const DISPLAY_OPERATOR_MIN_HEIGHT_OFFSET: usize = 6;
const MATH_LEADING_OFFSET: usize = 8;
const AXIS_HEIGHT_OFFSET: usize = 12;
const ACCENT_BASE_HEIGHT_OFFSET: usize = 16;
const FLATTENED_ACCENT_BASE_HEIGHT_OFFSET: usize = 20;
const SUBSCRIPT_SHIFT_DOWN_OFFSET: usize = 24;
const SUBSCRIPT_TOP_MAX_OFFSET: usize = 28;
const SUBSCRIPT_BASELINE_DROP_MIN_OFFSET: usize = 32;
const SUPERSCRIPT_SHIFT_UP_OFFSET: usize = 36;
const SUPERSCRIPT_SHIFT_UP_CRAMPED_OFFSET: usize = 40;
const SUPERSCRIPT_BOTTOM_MIN_OFFSET: usize = 44;
const SUPERSCRIPT_BASELINE_DROP_MAX_OFFSET: usize = 48;
const SUB_SUPERSCRIPT_GAP_MIN_OFFSET: usize = 52;
const SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT_OFFSET: usize = 56;
const SPACE_AFTER_SCRIPT_OFFSET: usize = 60;
const UPPER_LIMIT_GAP_MIN_OFFSET: usize = 64;
const UPPER_LIMIT_BASELINE_RISE_MIN_OFFSET: usize = 68;
const LOWER_LIMIT_GAP_MIN_OFFSET: usize = 72;
const LOWER_LIMIT_BASELINE_DROP_MIN_OFFSET: usize = 76;
const STACK_TOP_SHIFT_UP_OFFSET: usize = 80;
const STACK_TOP_DISPLAY_STYLE_SHIFT_UP_OFFSET: usize = 84;
const STACK_BOTTOM_SHIFT_DOWN_OFFSET: usize = 88;
const STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN_OFFSET: usize = 92;
const STACK_GAP_MIN_OFFSET: usize = 96;
const STACK_DISPLAY_STYLE_GAP_MIN_OFFSET: usize = 100;
const STRETCH_STACK_TOP_SHIFT_UP_OFFSET: usize = 104;
const STRETCH_STACK_BOTTOM_SHIFT_DOWN_OFFSET: usize = 108;
const STRETCH_STACK_GAP_ABOVE_MIN_OFFSET: usize = 112;
const STRETCH_STACK_GAP_BELOW_MIN_OFFSET: usize = 116;
const FRACTION_NUMERATOR_SHIFT_UP_OFFSET: usize = 120;
const FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP_OFFSET: usize = 124;
const FRACTION_DENOMINATOR_SHIFT_DOWN_OFFSET: usize = 128;
const FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN_OFFSET: usize = 132;
const FRACTION_NUMERATOR_GAP_MIN_OFFSET: usize = 136;
const FRACTION_NUM_DISPLAY_STYLE_GAP_MIN_OFFSET: usize = 140;
const FRACTION_RULE_THICKNESS_OFFSET: usize = 144;
const FRACTION_DENOMINATOR_GAP_MIN_OFFSET: usize = 148;
const FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN_OFFSET: usize = 152;
const SKEWED_FRACTION_HORIZONTAL_GAP_OFFSET: usize = 156;
const SKEWED_FRACTION_VERTICAL_GAP_OFFSET: usize = 160;
const OVERBAR_VERTICAL_GAP_OFFSET: usize = 164;
const OVERBAR_RULE_THICKNESS_OFFSET: usize = 168;
const OVERBAR_EXTRA_ASCENDER_OFFSET: usize = 172;
const UNDERBAR_VERTICAL_GAP_OFFSET: usize = 176;
const UNDERBAR_RULE_THICKNESS_OFFSET: usize = 180;
const UNDERBAR_EXTRA_DESCENDER_OFFSET: usize = 184;
const RADICAL_VERTICAL_GAP_OFFSET: usize = 188;
const RADICAL_DISPLAY_STYLE_VERTICAL_GAP_OFFSET: usize = 192;
const RADICAL_RULE_THICKNESS_OFFSET: usize = 196;
const RADICAL_EXTRA_ASCENDER_OFFSET: usize = 200;
const RADICAL_KERN_BEFORE_DEGREE_OFFSET: usize = 204;
const RADICAL_KERN_AFTER_DEGREE_OFFSET: usize = 208;
const RADICAL_DEGREE_BOTTOM_RAISE_PERCENT_OFFSET: usize = 212;
impl<'a> Constants<'a> {
#[inline]
pub fn script_percent_scale_down(&self) -> i16 {
self.read_i16(SCRIPT_PERCENT_SCALE_DOWN_OFFSET)
}
#[inline]
pub fn script_script_percent_scale_down(&self) -> i16 {
self.read_i16(SCRIPT_SCRIPT_PERCENT_SCALE_DOWN_OFFSET)
}
#[inline]
pub fn delimited_sub_formula_min_height(&self) -> u16 {
self.read_u16(DELIMITED_SUB_FORMULA_MIN_HEIGHT_OFFSET)
}
#[inline]
pub fn display_operator_min_height(&self) -> u16 {
self.read_u16(DISPLAY_OPERATOR_MIN_HEIGHT_OFFSET)
}
#[inline]
pub fn math_leading(&self) -> MathValue<'a> {
self.read_record(MATH_LEADING_OFFSET)
}
#[inline]
pub fn axis_height(&self) -> MathValue<'a> {
self.read_record(AXIS_HEIGHT_OFFSET)
}
#[inline]
pub fn accent_base_height(&self) -> MathValue<'a> {
self.read_record(ACCENT_BASE_HEIGHT_OFFSET)
}
#[inline]
pub fn flattened_accent_base_height(&self) -> MathValue<'a> {
self.read_record(FLATTENED_ACCENT_BASE_HEIGHT_OFFSET)
}
#[inline]
pub fn subscript_shift_down(&self) -> MathValue<'a> {
self.read_record(SUBSCRIPT_SHIFT_DOWN_OFFSET)
}
#[inline]
pub fn subscript_top_max(&self) -> MathValue<'a> {
self.read_record(SUBSCRIPT_TOP_MAX_OFFSET)
}
#[inline]
pub fn subscript_baseline_drop_min(&self) -> MathValue<'a> {
self.read_record(SUBSCRIPT_BASELINE_DROP_MIN_OFFSET)
}
#[inline]
pub fn superscript_shift_up(&self) -> MathValue<'a> {
self.read_record(SUPERSCRIPT_SHIFT_UP_OFFSET)
}
#[inline]
pub fn superscript_shift_up_cramped(&self) -> MathValue<'a> {
self.read_record(SUPERSCRIPT_SHIFT_UP_CRAMPED_OFFSET)
}
#[inline]
pub fn superscript_bottom_min(&self) -> MathValue<'a> {
self.read_record(SUPERSCRIPT_BOTTOM_MIN_OFFSET)
}
#[inline]
pub fn superscript_baseline_drop_max(&self) -> MathValue<'a> {
self.read_record(SUPERSCRIPT_BASELINE_DROP_MAX_OFFSET)
}
#[inline]
pub fn sub_superscript_gap_min(&self) -> MathValue<'a> {
self.read_record(SUB_SUPERSCRIPT_GAP_MIN_OFFSET)
}
#[inline]
pub fn superscript_bottom_max_with_subscript(&self) -> MathValue<'a> {
self.read_record(SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT_OFFSET)
}
#[inline]
pub fn space_after_script(&self) -> MathValue<'a> {
self.read_record(SPACE_AFTER_SCRIPT_OFFSET)
}
#[inline]
pub fn upper_limit_gap_min(&self) -> MathValue<'a> {
self.read_record(UPPER_LIMIT_GAP_MIN_OFFSET)
}
#[inline]
pub fn upper_limit_baseline_rise_min(&self) -> MathValue<'a> {
self.read_record(UPPER_LIMIT_BASELINE_RISE_MIN_OFFSET)
}
#[inline]
pub fn lower_limit_gap_min(&self) -> MathValue<'a> {
self.read_record(LOWER_LIMIT_GAP_MIN_OFFSET)
}
#[inline]
pub fn lower_limit_baseline_drop_min(&self) -> MathValue<'a> {
self.read_record(LOWER_LIMIT_BASELINE_DROP_MIN_OFFSET)
}
#[inline]
pub fn stack_top_shift_up(&self) -> MathValue<'a> {
self.read_record(STACK_TOP_SHIFT_UP_OFFSET)
}
#[inline]
pub fn stack_top_display_style_shift_up(&self) -> MathValue<'a> {
self.read_record(STACK_TOP_DISPLAY_STYLE_SHIFT_UP_OFFSET)
}
#[inline]
pub fn stack_bottom_shift_down(&self) -> MathValue<'a> {
self.read_record(STACK_BOTTOM_SHIFT_DOWN_OFFSET)
}
#[inline]
pub fn stack_bottom_display_style_shift_down(&self) -> MathValue<'a> {
self.read_record(STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN_OFFSET)
}
#[inline]
pub fn stack_gap_min(&self) -> MathValue<'a> {
self.read_record(STACK_GAP_MIN_OFFSET)
}
#[inline]
pub fn stack_display_style_gap_min(&self) -> MathValue<'a> {
self.read_record(STACK_DISPLAY_STYLE_GAP_MIN_OFFSET)
}
#[inline]
pub fn stretch_stack_top_shift_up(&self) -> MathValue<'a> {
self.read_record(STRETCH_STACK_TOP_SHIFT_UP_OFFSET)
}
#[inline]
pub fn stretch_stack_bottom_shift_down(&self) -> MathValue<'a> {
self.read_record(STRETCH_STACK_BOTTOM_SHIFT_DOWN_OFFSET)
}
#[inline]
pub fn stretch_stack_gap_above_min(&self) -> MathValue<'a> {
self.read_record(STRETCH_STACK_GAP_ABOVE_MIN_OFFSET)
}
#[inline]
pub fn stretch_stack_gap_below_min(&self) -> MathValue<'a> {
self.read_record(STRETCH_STACK_GAP_BELOW_MIN_OFFSET)
}
#[inline]
pub fn fraction_numerator_shift_up(&self) -> MathValue<'a> {
self.read_record(FRACTION_NUMERATOR_SHIFT_UP_OFFSET)
}
#[inline]
pub fn fraction_numerator_display_style_shift_up(&self) -> MathValue<'a> {
self.read_record(FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP_OFFSET)
}
#[inline]
pub fn fraction_denominator_shift_down(&self) -> MathValue<'a> {
self.read_record(FRACTION_DENOMINATOR_SHIFT_DOWN_OFFSET)
}
#[inline]
pub fn fraction_denominator_display_style_shift_down(&self) -> MathValue<'a> {
self.read_record(FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN_OFFSET)
}
#[inline]
pub fn fraction_numerator_gap_min(&self) -> MathValue<'a> {
self.read_record(FRACTION_NUMERATOR_GAP_MIN_OFFSET)
}
#[inline]
pub fn fraction_num_display_style_gap_min(&self) -> MathValue<'a> {
self.read_record(FRACTION_NUM_DISPLAY_STYLE_GAP_MIN_OFFSET)
}
#[inline]
pub fn fraction_rule_thickness(&self) -> MathValue<'a> {
self.read_record(FRACTION_RULE_THICKNESS_OFFSET)
}
#[inline]
pub fn fraction_denominator_gap_min(&self) -> MathValue<'a> {
self.read_record(FRACTION_DENOMINATOR_GAP_MIN_OFFSET)
}
#[inline]
pub fn fraction_denom_display_style_gap_min(&self) -> MathValue<'a> {
self.read_record(FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN_OFFSET)
}
#[inline]
pub fn skewed_fraction_horizontal_gap(&self) -> MathValue<'a> {
self.read_record(SKEWED_FRACTION_HORIZONTAL_GAP_OFFSET)
}
#[inline]
pub fn skewed_fraction_vertical_gap(&self) -> MathValue<'a> {
self.read_record(SKEWED_FRACTION_VERTICAL_GAP_OFFSET)
}
#[inline]
pub fn overbar_vertical_gap(&self) -> MathValue<'a> {
self.read_record(OVERBAR_VERTICAL_GAP_OFFSET)
}
#[inline]
pub fn overbar_rule_thickness(&self) -> MathValue<'a> {
self.read_record(OVERBAR_RULE_THICKNESS_OFFSET)
}
#[inline]
pub fn overbar_extra_ascender(&self) -> MathValue<'a> {
self.read_record(OVERBAR_EXTRA_ASCENDER_OFFSET)
}
#[inline]
pub fn underbar_vertical_gap(&self) -> MathValue<'a> {
self.read_record(UNDERBAR_VERTICAL_GAP_OFFSET)
}
#[inline]
pub fn underbar_rule_thickness(&self) -> MathValue<'a> {
self.read_record(UNDERBAR_RULE_THICKNESS_OFFSET)
}
#[inline]
pub fn underbar_extra_descender(&self) -> MathValue<'a> {
self.read_record(UNDERBAR_EXTRA_DESCENDER_OFFSET)
}
#[inline]
pub fn radical_vertical_gap(&self) -> MathValue<'a> {
self.read_record(RADICAL_VERTICAL_GAP_OFFSET)
}
#[inline]
pub fn radical_display_style_vertical_gap(&self) -> MathValue<'a> {
self.read_record(RADICAL_DISPLAY_STYLE_VERTICAL_GAP_OFFSET)
}
#[inline]
pub fn radical_rule_thickness(&self) -> MathValue<'a> {
self.read_record(RADICAL_RULE_THICKNESS_OFFSET)
}
#[inline]
pub fn radical_extra_ascender(&self) -> MathValue<'a> {
self.read_record(RADICAL_EXTRA_ASCENDER_OFFSET)
}
#[inline]
pub fn radical_kern_before_degree(&self) -> MathValue<'a> {
self.read_record(RADICAL_KERN_BEFORE_DEGREE_OFFSET)
}
#[inline]
pub fn radical_kern_after_degree(&self) -> MathValue<'a> {
self.read_record(RADICAL_KERN_AFTER_DEGREE_OFFSET)
}
#[inline]
pub fn radical_degree_bottom_raise_percent(&self) -> i16 {
self.read_i16(RADICAL_DEGREE_BOTTOM_RAISE_PERCENT_OFFSET)
}
#[inline]
fn read_i16(&self, offset: usize) -> i16 {
Stream::read_at(self.data, offset).unwrap_or(0)
}
#[inline]
fn read_u16(&self, offset: usize) -> u16 {
Stream::read_at(self.data, offset).unwrap_or(0)
}
#[inline]
fn read_record(&self, offset: usize) -> MathValue<'a> {
self.data
.get(offset..)
.and_then(|data| MathValue::parse(data, self.data))
.unwrap_or(MathValue {
value: 0,
device: None,
})
}
}
#[derive(Clone)]
pub struct Kern<'a> {
data: &'a [u8],
heights: LazyArray16<'a, MathValueRecord>,
kerns: LazyArray16<'a, MathValueRecord>,
}
impl<'a> Kern<'a> {
pub fn count(&self) -> u16 {
self.heights.len()
}
pub fn height(&self, index: u16) -> Option<MathValue<'a>> {
Some(self.heights.get(index)?.get(self.data))
}
pub fn kern(&self, index: u16) -> Option<MathValue<'a>> {
Some(self.kerns.get(index)?.get(self.data))
}
}
impl<'a> FromSlice<'a> for Kern<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let count = s.read::<u16>()?;
let heights = s.read_array16::<MathValueRecord>(count)?;
let kerns = s.read_array16::<MathValueRecord>(count + 1)?;
Some(Kern {
data,
heights,
kerns,
})
}
}
impl core::fmt::Debug for Kern<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "Kern {{ ... }}")
}
}
#[derive(Clone, Copy)]
struct KernInfoRecord {
top_right: Option<Offset16>,
top_left: Option<Offset16>,
bottom_right: Option<Offset16>,
bottom_left: Option<Offset16>,
}
impl FromData for KernInfoRecord {
const SIZE: usize = 8;
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(KernInfoRecord {
top_right: s.read::<Option<Offset16>>()?,
top_left: s.read::<Option<Offset16>>()?,
bottom_right: s.read::<Option<Offset16>>()?,
bottom_left: s.read::<Option<Offset16>>()?,
})
}
}
impl KernInfoRecord {
fn get<'a>(&self, data: &'a [u8]) -> KernInfo<'a> {
let parse_field = |offset: Option<Offset16>| {
offset
.and_then(|offset| data.get(offset.to_usize()..))
.and_then(Kern::parse)
};
KernInfo {
top_right: parse_field(self.top_right),
top_left: parse_field(self.top_left),
bottom_right: parse_field(self.bottom_right),
bottom_left: parse_field(self.bottom_left),
}
}
}
#[derive(Clone, Debug)]
pub struct KernInfo<'a> {
pub top_right: Option<Kern<'a>>,
pub top_left: Option<Kern<'a>>,
pub bottom_right: Option<Kern<'a>>,
pub bottom_left: Option<Kern<'a>>,
}
#[derive(Clone, Copy)]
pub struct KernInfos<'a> {
data: &'a [u8],
coverage: Coverage<'a>,
records: LazyArray16<'a, KernInfoRecord>,
}
impl<'a> FromSlice<'a> for KernInfos<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let coverage = s.parse_at_offset16::<Coverage>(data)?;
let count = s.read::<u16>()?;
let records = s.read_array16::<KernInfoRecord>(count)?;
Some(KernInfos {
data,
coverage,
records,
})
}
}
impl<'a> KernInfos<'a> {
#[inline]
pub fn get(&self, glyph: GlyphId) -> Option<KernInfo<'a>> {
let index = self.coverage.get(glyph)?;
Some(self.records.get(index)?.get(self.data))
}
}
impl core::fmt::Debug for KernInfos<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "KernInfos {{ ... }}")
}
}
#[derive(Clone, Copy, Debug)]
pub struct GlyphInfo<'a> {
pub italic_corrections: Option<MathValues<'a>>,
pub top_accent_attachments: Option<MathValues<'a>>,
pub extended_shapes: Option<Coverage<'a>>,
pub kern_infos: Option<KernInfos<'a>>,
}
impl<'a> FromSlice<'a> for GlyphInfo<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(GlyphInfo {
italic_corrections: s.parse_at_offset16::<MathValues>(data),
top_accent_attachments: s.parse_at_offset16::<MathValues>(data),
extended_shapes: s.parse_at_offset16::<Coverage>(data),
kern_infos: s.parse_at_offset16::<KernInfos>(data),
})
}
}
#[derive(Clone, Copy, Debug)]
pub struct PartFlags(pub u16);
#[allow(missing_docs)]
impl PartFlags {
#[inline]
pub fn extender(self) -> bool {
self.0 & 0x0001 != 0
}
}
impl FromData for PartFlags {
const SIZE: usize = 2;
fn parse(data: &[u8]) -> Option<Self> {
u16::parse(data).map(PartFlags)
}
}
#[derive(Clone, Copy, Debug)]
pub struct GlyphPart {
pub glyph_id: GlyphId,
pub start_connector_length: u16,
pub end_connector_length: u16,
pub full_advance: u16,
pub part_flags: PartFlags,
}
impl FromData for GlyphPart {
const SIZE: usize = 10;
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(GlyphPart {
glyph_id: s.read::<GlyphId>()?,
start_connector_length: s.read::<u16>()?,
end_connector_length: s.read::<u16>()?,
full_advance: s.read::<u16>()?,
part_flags: s.read::<PartFlags>()?,
})
}
}
#[derive(Clone, Copy, Debug)]
pub struct GlyphAssembly<'a> {
pub italics_correction: MathValue<'a>,
pub parts: LazyArray16<'a, GlyphPart>,
}
impl<'a> FromSlice<'a> for GlyphAssembly<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let italics_correction = s.read::<MathValueRecord>()?.get(data);
let count = s.read::<u16>()?;
let parts = s.read_array16::<GlyphPart>(count)?;
Some(GlyphAssembly {
italics_correction,
parts,
})
}
}
#[derive(Clone, Copy, Debug)]
pub struct GlyphVariant {
pub variant_glyph: GlyphId,
pub advance_measurement: u16,
}
impl FromData for GlyphVariant {
const SIZE: usize = 4;
fn parse(data: &[u8]) -> Option<Self> {
let mut s = Stream::new(data);
Some(GlyphVariant {
variant_glyph: s.read::<GlyphId>()?,
advance_measurement: s.read::<u16>()?,
})
}
}
#[derive(Clone, Copy, Debug)]
pub struct GlyphConstruction<'a> {
pub assembly: Option<GlyphAssembly<'a>>,
pub variants: LazyArray16<'a, GlyphVariant>,
}
impl<'a> FromSlice<'a> for GlyphConstruction<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let assembly = s.parse_at_offset16::<GlyphAssembly>(data);
let variant_count = s.read::<u16>()?;
let variants = s.read_array16::<GlyphVariant>(variant_count)?;
Some(GlyphConstruction { assembly, variants })
}
}
#[derive(Clone, Copy)]
pub struct GlyphConstructions<'a> {
coverage: Coverage<'a>,
constructions: LazyOffsetArray16<'a, GlyphConstruction<'a>>,
}
impl<'a> GlyphConstructions<'a> {
fn new(
data: &'a [u8],
coverage: Option<Coverage<'a>>,
offsets: LazyArray16<'a, Option<Offset16>>,
) -> Self {
GlyphConstructions {
coverage: coverage.unwrap_or(Coverage::Format1 {
glyphs: LazyArray16::new(&[]),
}),
constructions: LazyOffsetArray16::new(data, offsets),
}
}
#[inline]
pub fn get(&self, glyph: GlyphId) -> Option<GlyphConstruction<'a>> {
let index = self.coverage.get(glyph)?;
self.constructions.get(index)
}
}
impl core::fmt::Debug for GlyphConstructions<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "GlyphConstructions {{ ... }}")
}
}
#[derive(Clone, Copy, Debug)]
pub struct Variants<'a> {
pub min_connector_overlap: u16,
pub vertical_constructions: GlyphConstructions<'a>,
pub horizontal_constructions: GlyphConstructions<'a>,
}
impl<'a> FromSlice<'a> for Variants<'a> {
fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let min_connector_overlap = s.read::<u16>()?;
let vertical_coverage = s.parse_at_offset16::<Coverage>(data);
let horizontal_coverage = s.parse_at_offset16::<Coverage>(data);
let vertical_count = s.read::<u16>()?;
let horizontal_count = s.read::<u16>()?;
let vertical_offsets = s.read_array16::<Option<Offset16>>(vertical_count)?;
let horizontal_offsets = s.read_array16::<Option<Offset16>>(horizontal_count)?;
Some(Variants {
min_connector_overlap,
vertical_constructions: GlyphConstructions::new(
data,
vertical_coverage,
vertical_offsets,
),
horizontal_constructions: GlyphConstructions::new(
data,
horizontal_coverage,
horizontal_offsets,
),
})
}
}
#[derive(Clone, Copy, Debug)]
pub struct Table<'a> {
pub constants: Option<Constants<'a>>,
pub glyph_info: Option<GlyphInfo<'a>>,
pub variants: Option<Variants<'a>>,
}
impl<'a> Table<'a> {
pub fn parse(data: &'a [u8]) -> Option<Self> {
let mut s = Stream::new(data);
let major_version = s.read::<u16>()? as u8;
s.skip::<u16>(); if major_version != 1 {
return None;
}
Some(Table {
constants: s.parse_at_offset16::<Constants>(data),
glyph_info: s.parse_at_offset16::<GlyphInfo>(data),
variants: s.parse_at_offset16::<Variants>(data),
})
}
}
trait StreamExt<'a> {
fn parse_at_offset16<T: FromSlice<'a>>(&mut self, data: &'a [u8]) -> Option<T>;
}
impl<'a> StreamExt<'a> for Stream<'a> {
fn parse_at_offset16<T: FromSlice<'a>>(&mut self, data: &'a [u8]) -> Option<T> {
let offset = self.read::<Option<Offset16>>()??.to_usize();
data.get(offset..).and_then(T::parse)
}
}