/src/fontations/klippa/src/hdmx.rs
Line | Count | Source |
1 | | //! impl subset() for hdmx |
2 | | |
3 | | use crate::serialize::{SerializeErrorFlags, Serializer}; |
4 | | use crate::{Plan, Subset, SubsetError}; |
5 | | use write_fonts::{ |
6 | | read::{ |
7 | | tables::hdmx::{DeviceRecord, Hdmx}, |
8 | | FontRef, TopLevelTable, |
9 | | }, |
10 | | FontBuilder, |
11 | | }; |
12 | | |
13 | 0 | fn ceil_to_4(v: u32) -> u32 { |
14 | 0 | ((v - 1) | 3) + 1 |
15 | 0 | } |
16 | | |
17 | | // reference: subset() for hmtx/hhea in harfbuzz |
18 | | // <https://github.com/harfbuzz/harfbuzz/blob/e451e91ec3608a2ebfec34d0c4f0b3d880e00e33/src/hb-ot-hdmx-table.hh#L116> |
19 | | impl Subset for Hdmx<'_> { |
20 | 0 | fn subset( |
21 | 0 | &self, |
22 | 0 | plan: &Plan, |
23 | 0 | _font: &FontRef, |
24 | 0 | s: &mut Serializer, |
25 | 0 | _builder: &mut FontBuilder, |
26 | 0 | ) -> Result<(), SubsetError> { |
27 | 0 | s.embed(self.version()) |
28 | 0 | .map_err(|_| SubsetError::SubsetTableError(Hdmx::TAG))?; |
29 | 0 | s.embed(self.num_records()) |
30 | 0 | .map_err(|_| SubsetError::SubsetTableError(Hdmx::TAG))?; |
31 | | |
32 | 0 | let size_device_record = ceil_to_4(2 + plan.num_output_glyphs as u32); |
33 | 0 | s.embed(size_device_record) |
34 | 0 | .map_err(|_| SubsetError::SubsetTableError(Hdmx::TAG))?; |
35 | | |
36 | 0 | for record in self.records().iter() { |
37 | 0 | let Ok(r) = record else { |
38 | 0 | return Err(SubsetError::SubsetTableError(Hdmx::TAG)); |
39 | | }; |
40 | 0 | serialize_device_record(&r, s, plan, size_device_record as usize) |
41 | 0 | .map_err(|_| SubsetError::SubsetTableError(Hdmx::TAG))?; |
42 | | } |
43 | 0 | Ok(()) |
44 | 0 | } |
45 | | } |
46 | | |
47 | 0 | fn serialize_device_record( |
48 | 0 | record: &DeviceRecord, |
49 | 0 | s: &mut Serializer, |
50 | 0 | plan: &Plan, |
51 | 0 | size_device_record: usize, |
52 | 0 | ) -> Result<(), SerializeErrorFlags> { |
53 | 0 | s.embed(record.pixel_size())?; |
54 | 0 | let max_width_pos = s.embed(0_u8)?; |
55 | 0 | let widths_array_pos = s.allocate_size(size_device_record - 2, false)?; |
56 | 0 | let mut max_width = 0; |
57 | 0 | for (new_gid, old_gid) in plan.new_to_old_gid_list.iter() { |
58 | 0 | let old_idx = old_gid.to_u32() as usize; |
59 | 0 | let Some(wdth) = record.widths().get(old_idx) else { |
60 | 0 | return Err(SerializeErrorFlags::SERIALIZE_ERROR_OTHER); |
61 | | }; |
62 | | |
63 | 0 | let new_idx = new_gid.to_u32() as usize; |
64 | 0 | s.copy_assign(widths_array_pos + new_idx, *wdth); |
65 | 0 | max_width = max_width.max(*wdth); |
66 | | } |
67 | | |
68 | 0 | s.copy_assign(max_width_pos, max_width); |
69 | 0 | Ok(()) |
70 | 0 | } |