use crate::{
hvar::{serialize_index_maps, HvarVvarSubsetPlan, ListupIndexMaps},
offset::SerializeSubset,
serialize::Serializer,
Plan, Subset, SubsetError,
};
use fontcull_write_fonts::{
read::{
tables::{variations::DeltaSetIndexMap, vvar::Vvar},
FontRef, ReadError, TopLevelTable,
},
types::Offset32,
FontBuilder,
};
impl Subset for Vvar<'_> {
fn subset(
&self,
plan: &Plan,
_font: &FontRef,
s: &mut Serializer,
_builder: &mut FontBuilder,
) -> Result<(), SubsetError> {
let var_store = self
.item_variation_store()
.map_err(|_| SubsetError::SubsetTableError(Vvar::TAG))?;
let index_maps = self
.listup_index_maps()
.map_err(|_| SubsetError::SubsetTableError(Vvar::TAG))?;
let vvar_subset_plan = HvarVvarSubsetPlan::new(plan, &var_store, &index_maps)
.map_err(|_| SubsetError::SubsetTableError(Vvar::TAG))?;
s.embed(self.version())
.map_err(|_| SubsetError::SubsetTableError(Vvar::TAG))?;
let var_store_offset_pos = s
.embed(0_u32)
.map_err(|_| SubsetError::SubsetTableError(Vvar::TAG))?;
Offset32::serialize_subset(
&var_store,
s,
plan,
vvar_subset_plan.inner_maps(),
var_store_offset_pos,
)
.map_err(|_| SubsetError::SubsetTableError(Vvar::TAG))?;
serialize_index_maps(
s,
plan,
&index_maps,
vvar_subset_plan.index_map_subset_plans(),
)
.map_err(|_| SubsetError::SubsetTableError(Vvar::TAG))
}
}
impl ListupIndexMaps for Vvar<'_> {
fn listup_index_maps(&self) -> Result<Vec<Option<DeltaSetIndexMap<'_>>>, ReadError> {
let out = vec![
self.advance_height_mapping().transpose()?,
self.tsb_mapping().transpose()?,
self.bsb_mapping().transpose()?,
self.v_org_mapping().transpose()?,
];
Ok(out)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::SubsetFlags;
use fontcull_write_fonts::{
read::{FontData, FontRead},
types::GlyphId,
};
#[test]
fn test_subset_vvar_noop() {
let raw_bytes: [u8; 102] = [
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x04,
0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x00, 0x04, 0x02, 0x01, 0x00, 0x03, 0x00, 0x01,
0x00, 0x00, 0x00, 0x2e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x10,
0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x01, 0x0b, 0x02,
0x0c, 0x03, 0x0d, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x20, 0x11,
0x00, 0x0e, 0x00, 0x01, 0x00, 0x02, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x40, 0x00,
];
let vvar = Vvar::read(FontData::new(&raw_bytes)).unwrap();
let mut builder = FontBuilder::new();
let font = FontRef::new(&raw_bytes).unwrap();
let mut plan = Plan::default();
plan.new_to_old_gid_list
.push((GlyphId::NOTDEF, GlyphId::NOTDEF));
plan.new_to_old_gid_list
.push((GlyphId::from(1_u32), GlyphId::from(1_u32)));
plan.new_to_old_gid_list
.push((GlyphId::from(2_u32), GlyphId::from(2_u32)));
plan.new_to_old_gid_list
.push((GlyphId::from(3_u32), GlyphId::from(3_u32)));
plan.glyphset
.insert_range(GlyphId::NOTDEF..=GlyphId::from(3_u32));
let mut s = Serializer::new(1024);
assert_eq!(s.start_serialize(), Ok(()));
let ret = vvar.subset(&plan, &font, &mut s, &mut builder);
assert!(ret.is_ok());
assert!(!s.in_error());
s.end_serialize();
let subsetted_data = s.copy_bytes();
assert_eq!(subsetted_data, raw_bytes);
}
#[test]
fn test_subset_vvar() {
let raw_bytes: [u8; 102] = [
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x04,
0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x00, 0x04, 0x02, 0x01, 0x00, 0x03, 0x00, 0x01,
0x00, 0x00, 0x00, 0x2e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x10,
0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x01, 0x0b, 0x02,
0x0c, 0x03, 0x0d, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x20, 0x11,
0x00, 0x0e, 0x00, 0x01, 0x00, 0x02, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x40, 0x00,
];
let vvar = Vvar::read(FontData::new(&raw_bytes)).unwrap();
let mut builder = FontBuilder::new();
let font = FontRef::new(&raw_bytes).unwrap();
let mut plan = Plan::default();
plan.new_to_old_gid_list
.push((GlyphId::NOTDEF, GlyphId::NOTDEF));
plan.new_to_old_gid_list
.push((GlyphId::from(1_u32), GlyphId::from(1_u32)));
plan.new_to_old_gid_list
.push((GlyphId::from(2_u32), GlyphId::from(3_u32)));
plan.glyphset.insert(GlyphId::NOTDEF);
plan.glyphset.insert(GlyphId::from(1_u32));
plan.glyphset.insert(GlyphId::from(3_u32));
let mut s = Serializer::new(1024);
assert_eq!(s.start_serialize(), Ok(()));
let ret = vvar.subset(&plan, &font, &mut s, &mut builder);
assert!(ret.is_ok());
assert!(!s.in_error());
s.end_serialize();
let subsetted_data = s.copy_bytes();
let expected_data: [u8; 97] = [
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x03,
0x04, 0x05, 0x06, 0x00, 0x01, 0x00, 0x03, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00,
0x00, 0x2b, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x01, 0x0b, 0x02, 0x0d, 0x04,
0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x11, 0x00, 0x0e, 0x00, 0x01, 0x00,
0x02, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00,
];
assert_eq!(subsetted_data, expected_data);
}
#[test]
fn test_subset_vvar_retain_gids() {
let raw_bytes: [u8; 102] = [
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x04,
0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x00, 0x04, 0x02, 0x01, 0x00, 0x03, 0x00, 0x01,
0x00, 0x00, 0x00, 0x2e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x10,
0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x01, 0x0b, 0x02,
0x0c, 0x03, 0x0d, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x20, 0x11,
0x00, 0x0e, 0x00, 0x01, 0x00, 0x02, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x40, 0x00,
];
let vvar = Vvar::read(FontData::new(&raw_bytes)).unwrap();
let mut builder = FontBuilder::new();
let font = FontRef::new(&raw_bytes).unwrap();
let mut plan = Plan::default();
plan.new_to_old_gid_list
.push((GlyphId::NOTDEF, GlyphId::NOTDEF));
plan.new_to_old_gid_list
.push((GlyphId::from(1_u32), GlyphId::from(1_u32)));
plan.new_to_old_gid_list
.push((GlyphId::from(3_u32), GlyphId::from(3_u32)));
plan.glyphset.insert(GlyphId::NOTDEF);
plan.glyphset.insert(GlyphId::from(1_u32));
plan.glyphset.insert(GlyphId::from(3_u32));
plan.subset_flags |= SubsetFlags::SUBSET_FLAGS_RETAIN_GIDS;
let mut s = Serializer::new(1024);
assert_eq!(s.start_serialize(), Ok(()));
let ret = vvar.subset(&plan, &font, &mut s, &mut builder);
assert!(ret.is_ok());
assert!(!s.in_error());
s.end_serialize();
let subsetted_data = s.copy_bytes();
let expected_data: [u8; 99] = [
00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x04, 0x04,
0x05, 0x00, 0x06, 0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
0x00, 0x00, 0x2b, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x01, 0x0b, 0x02, 0x0d,
0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x11, 0x00, 0x0e, 0x00, 0x01,
0x00, 0x02, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00,
];
assert_eq!(subsetted_data, expected_data);
}
}