allsorts_subset_browser/tables/glyf/
subset.rs1use rustc_hash::FxHashMap;
2
3use super::{GlyfRecord, GlyfTable, Glyph, ParseError};
4use crate::subset::SubsetGlyphs;
5use crate::tables::glyf::CompositeGlyph;
6
7#[derive(Clone)]
8pub struct SubsetGlyph<'a> {
9 pub old_id: u16,
10 pub record: GlyfRecord<'a>,
11}
12
13#[derive(Clone)]
15pub struct SubsetGlyf<'a> {
16 glyphs: Vec<SubsetGlyph<'a>>,
17 old_to_new_id: FxHashMap<u16, u16>,
19}
20
21impl<'a> GlyfTable<'a> {
22 pub fn subset(&self, glyph_ids: &[u16]) -> Result<SubsetGlyf<'a>, ParseError> {
24 let mut glyph_ids = glyph_ids.to_vec();
25 let mut records = Vec::with_capacity(glyph_ids.len());
26
27 let mut i = 0;
28 while i < glyph_ids.len() {
29 let glyph_id = glyph_ids[i];
30 let mut record = self
31 .records
32 .get(usize::from(glyph_id))
33 .ok_or(ParseError::BadIndex)?
34 .clone();
35 if record.is_composite() {
36 record.parse()?;
37 let GlyfRecord::Parsed(Glyph::Composite(composite)) = &mut record else {
38 unreachable!("not a composite glyph")
39 };
40 add_glyph(&mut glyph_ids, composite);
41 }
42 records.push(SubsetGlyph {
43 old_id: glyph_id,
44 record,
45 });
46 i += 1;
47 }
48 let old_to_new_id = records
50 .iter()
51 .enumerate()
52 .map(|(new_id, glyph)| (glyph.old_id, new_id as u16))
53 .collect();
54 Ok(SubsetGlyf {
55 glyphs: records,
56 old_to_new_id,
57 })
58 }
59}
60
61impl<'a> SubsetGlyphs for SubsetGlyf<'a> {
62 fn len(&self) -> usize {
63 self.glyphs.len()
64 }
65
66 fn old_id(&self, new_id: u16) -> u16 {
67 self.glyphs[usize::from(new_id)].old_id
68 }
69
70 fn new_id(&self, old_id: u16) -> u16 {
71 self.old_to_new_id.get(&old_id).copied().unwrap_or(0)
72 }
73}
74
75impl<'a> From<SubsetGlyf<'a>> for GlyfTable<'a> {
76 fn from(subset_glyphs: SubsetGlyf<'a>) -> Self {
77 let records = subset_glyphs
78 .glyphs
79 .into_iter()
80 .map(|subset_record| subset_record.record)
81 .collect();
82
83 GlyfTable { records }
84 }
85}
86
87fn add_glyph(glyph_ids: &mut Vec<u16>, composite: &mut CompositeGlyph<'_>) {
91 for composite_glyph in composite.glyphs.iter_mut() {
92 let new_id = glyph_ids
93 .iter()
94 .position(|&id| id == composite_glyph.glyph_index)
95 .unwrap_or_else(|| {
96 let new_id = glyph_ids.len();
98 glyph_ids.push(composite_glyph.glyph_index);
99 new_id
100 });
101 composite_glyph.glyph_index = new_id as u16;
102 }
103}