allsorts_subset_browser/tables/variable_fonts/
hvar.rs1use crate::binary::read::{ReadBinary, ReadCtxt, ReadScope};
10use crate::error::ParseError;
11use crate::tables::variable_fonts::{
12 DeltaSetIndexMap, DeltaSetIndexMapEntry, ItemVariationStore, OwnedTuple,
13};
14use crate::SafeFrom;
15
16pub struct HvarTable<'a> {
18 pub major_version: u16,
20 pub minor_version: u16,
22 item_variation_store: ItemVariationStore<'a>,
24 advance_width_mapping: Option<DeltaSetIndexMap<'a>>,
26 lsb_mapping: Option<DeltaSetIndexMap<'a>>,
28 rsb_mapping: Option<DeltaSetIndexMap<'a>>,
30}
31
32impl<'a> HvarTable<'a> {
33 pub fn advance_delta(&self, instance: &OwnedTuple, glyph_id: u16) -> Result<f32, ParseError> {
35 let delta_set_entry =
41 Self::delta_set_entry_for_glyph(glyph_id, self.advance_width_mapping.as_ref())?
42 .unwrap_or_else(|| DeltaSetIndexMapEntry {
43 outer_index: 0,
44 inner_index: glyph_id,
45 });
46 self.item_variation_store
47 .adjustment(delta_set_entry, instance)
48 }
49
50 pub fn left_side_bearing_delta(
53 &self,
54 instance: &OwnedTuple,
55 glyph_id: u16,
56 ) -> Result<Option<f32>, ParseError> {
57 Self::delta_set_entry_for_glyph(glyph_id, self.lsb_mapping.as_ref())?
58 .map(|delta_set_entry| {
59 self.item_variation_store
60 .adjustment(delta_set_entry, instance)
61 })
62 .transpose()
63 }
64
65 pub fn right_side_bearing_delta(
68 &self,
69 instance: &OwnedTuple,
70 glyph_id: u16,
71 ) -> Result<Option<f32>, ParseError> {
72 Self::delta_set_entry_for_glyph(glyph_id, self.rsb_mapping.as_ref())?
73 .map(|delta_set_entry| {
74 self.item_variation_store
75 .adjustment(delta_set_entry, instance)
76 })
77 .transpose()
78 }
79
80 fn delta_set_entry_for_glyph(
81 glyph_id: u16,
82 delta_set_index_map: Option<&DeltaSetIndexMap<'_>>,
83 ) -> Result<Option<DeltaSetIndexMapEntry>, ParseError> {
84 delta_set_index_map
85 .map(|mapping| mapping.entry(u32::from(glyph_id)))
86 .transpose()
87 }
88}
89
90impl ReadBinary for HvarTable<'_> {
91 type HostType<'a> = HvarTable<'a>;
92
93 fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
94 let scope = ctxt.scope();
95 let major_version = ctxt.read_u16be()?;
96 ctxt.check_version(major_version == 1)?;
97 let minor_version = ctxt.read_u16be()?;
98 let item_variation_store_offset = ctxt.read_u32be()?;
99 let advance_width_mapping_offset = ctxt.read_u32be()?;
100 let lsb_mapping_offset = ctxt.read_u32be()?;
101 let rsb_mapping_offset = ctxt.read_u32be()?;
102
103 let item_variation_store = scope
104 .offset(usize::safe_from(item_variation_store_offset))
105 .read::<ItemVariationStore<'_>>()?;
106 let advance_width_mapping = read_optional_index_map(scope, advance_width_mapping_offset)?;
107 let lsb_mapping = read_optional_index_map(scope, lsb_mapping_offset)?;
108 let rsb_mapping = read_optional_index_map(scope, rsb_mapping_offset)?;
109
110 Ok(HvarTable {
111 major_version,
112 minor_version,
113 item_variation_store,
114 advance_width_mapping,
115 lsb_mapping,
116 rsb_mapping,
117 })
118 }
119}
120
121fn read_optional_index_map(
122 scope: ReadScope<'_>,
123 offset: u32,
124) -> Result<Option<DeltaSetIndexMap<'_>>, ParseError> {
125 (offset > 0)
126 .then(|| {
127 scope
128 .offset(usize::safe_from(offset))
129 .read::<DeltaSetIndexMap<'_>>()
130 })
131 .transpose()
132}