Skip to main content

write_fonts/tables/
postscript.rs

1//! Postscript (CFF/CFF2) table related code.
2
3include!("../../generated/generated_postscript.rs");
4
5impl Index2 {
6    /// Construct an `Index2` from a list of byte items.
7    pub fn from_items(items: Vec<Vec<u8>>) -> Self {
8        if items.is_empty() {
9            return Index2::new(0, 1, vec![1], vec![]);
10        }
11
12        let count = items.len() as u32;
13
14        // Calculate offsets (1-based per CFF2 spec)
15        let mut offset_values = Vec::with_capacity(items.len() + 1);
16        let mut current_offset = 1u32;
17        offset_values.push(current_offset);
18        for item in &items {
19            current_offset += item.len() as u32;
20            offset_values.push(current_offset);
21        }
22
23        // Determine off_size (minimum bytes needed for largest offset)
24        let max_offset = *offset_values.last().unwrap();
25        let off_size = if max_offset <= 0xFF {
26            1u8
27        } else if max_offset <= 0xFFFF {
28            2u8
29        } else if max_offset <= 0xFFFFFF {
30            3u8
31        } else {
32            4u8
33        };
34
35        // Pack offsets based on off_size
36        let mut offsets = Vec::with_capacity(offset_values.len() * off_size as usize);
37        for offset in &offset_values {
38            match off_size {
39                1 => offsets.push(*offset as u8),
40                2 => offsets.extend((*offset as u16).to_be_bytes()),
41                3 => {
42                    let bytes = offset.to_be_bytes();
43                    offsets.extend(&bytes[1..4]);
44                }
45                4 => offsets.extend(offset.to_be_bytes()),
46                _ => unreachable!(),
47            }
48        }
49
50        // Concatenate item data
51        let data: Vec<u8> = items.into_iter().flatten().collect();
52
53        Index2::new(count, off_size, offsets, data)
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn test_index2_from_items() {
63        let items = vec![vec![1, 2, 3], vec![4, 5]];
64        let index = Index2::from_items(items);
65        assert_eq!(index.count, 2);
66    }
67}