Skip to main content

pfx_input/glyph/
font.rs

1use super::shape::Shape;
2
3pub const UNITS_PER_EM: u16 = 1024;
4pub const UNITS_PER_PX: f32 = 16.0;
5pub const FIRST_CHAR: u32 = 0xe000;
6pub const FAMILY: &str = "PITO Input Glyphs";
7
8struct Glyf {
9    bytes: Vec<u8>,
10    advance: u16,
11    bounds: [i16; 4],
12    points: u16,
13    contours: u16,
14}
15
16fn units(value: f32) -> i16 {
17    (value * UNITS_PER_PX)
18        .round()
19        .clamp(f32::from(i16::MIN), f32::from(i16::MAX)) as i16
20}
21
22fn encode(shape: &Shape) -> Glyf {
23    let advance = units(shape.width).max(0) as u16;
24    let mut ends = Vec::new();
25    let mut flags = Vec::new();
26    let mut xs = Vec::new();
27    let mut ys = Vec::new();
28    let mut count = 0u16;
29    let mut bounds = [i16::MAX, i16::MAX, i16::MIN, i16::MIN];
30    for contour in &shape.contours {
31        if contour.len() < 3 {
32            continue;
33        }
34        for point in contour {
35            let x = units(point.x);
36            let y = units(shape.height - point.y);
37            bounds = [
38                bounds[0].min(x),
39                bounds[1].min(y),
40                bounds[2].max(x),
41                bounds[3].max(y),
42            ];
43            flags.push(u8::from(point.on));
44            xs.push(x);
45            ys.push(y);
46            count += 1;
47        }
48        ends.push(count - 1);
49    }
50    if ends.is_empty() {
51        return Glyf {
52            bytes: Vec::new(),
53            advance,
54            bounds: [0; 4],
55            points: 0,
56            contours: 0,
57        };
58    }
59    let mut bytes = Vec::new();
60    push16(&mut bytes, ends.len() as u16);
61    for value in bounds {
62        push16(&mut bytes, value as u16);
63    }
64    for end in &ends {
65        push16(&mut bytes, *end);
66    }
67    push16(&mut bytes, 0);
68    bytes.extend_from_slice(&flags);
69    let mut previous = 0i16;
70    for x in &xs {
71        push16(&mut bytes, x.wrapping_sub(previous) as u16);
72        previous = *x;
73    }
74    previous = 0;
75    for y in &ys {
76        push16(&mut bytes, y.wrapping_sub(previous) as u16);
77        previous = *y;
78    }
79    while bytes.len() % 4 != 0 {
80        bytes.push(0);
81    }
82    Glyf {
83        bytes,
84        advance,
85        bounds,
86        points: count,
87        contours: ends.len() as u16,
88    }
89}
90
91fn push16(bytes: &mut Vec<u8>, value: u16) {
92    bytes.extend_from_slice(&value.to_be_bytes());
93}
94
95fn push32(bytes: &mut Vec<u8>, value: u32) {
96    bytes.extend_from_slice(&value.to_be_bytes());
97}
98
99pub fn build(shapes: &[Shape]) -> Vec<u8> {
100    let mut glyphs = vec![Glyf {
101        bytes: Vec::new(),
102        advance: UNITS_PER_EM / 2,
103        bounds: [0; 4],
104        points: 0,
105        contours: 0,
106    }];
107    glyphs.extend(shapes.iter().map(encode));
108    let count = glyphs.len() as u16;
109    let mut bounds = [i16::MAX, i16::MAX, i16::MIN, i16::MIN];
110    for glyph in glyphs.iter().filter(|glyph| glyph.contours > 0) {
111        bounds = [
112            bounds[0].min(glyph.bounds[0]),
113            bounds[1].min(glyph.bounds[1]),
114            bounds[2].max(glyph.bounds[2]),
115            bounds[3].max(glyph.bounds[3]),
116        ];
117    }
118    if bounds[0] > bounds[2] {
119        bounds = [0; 4];
120    }
121    let ascender = UNITS_PER_EM as i16;
122    let descender = -(UNITS_PER_EM as i16) / 4;
123
124    let mut glyf = Vec::new();
125    let mut loca = Vec::new();
126    for glyph in &glyphs {
127        push32(&mut loca, glyf.len() as u32);
128        glyf.extend_from_slice(&glyph.bytes);
129    }
130    push32(&mut loca, glyf.len() as u32);
131
132    let mut head = Vec::new();
133    push32(&mut head, 0x0001_0000);
134    push32(&mut head, 0x0001_0000);
135    push32(&mut head, 0);
136    push32(&mut head, 0x5f0f_3cf5);
137    push16(&mut head, 0x000b);
138    push16(&mut head, UNITS_PER_EM);
139    head.extend_from_slice(&[0; 16]);
140    for value in bounds {
141        push16(&mut head, value as u16);
142    }
143    push16(&mut head, 0);
144    push16(&mut head, 8);
145    push16(&mut head, 2);
146    push16(&mut head, 1);
147    push16(&mut head, 0);
148
149    let max_advance = glyphs.iter().map(|glyph| glyph.advance).max().unwrap_or(0);
150    let mut hhea = Vec::new();
151    push32(&mut hhea, 0x0001_0000);
152    push16(&mut hhea, ascender as u16);
153    push16(&mut hhea, descender as u16);
154    push16(&mut hhea, 0);
155    push16(&mut hhea, max_advance);
156    push16(&mut hhea, bounds[0] as u16);
157    push16(&mut hhea, 0);
158    push16(&mut hhea, bounds[2] as u16);
159    push16(&mut hhea, 1);
160    push16(&mut hhea, 0);
161    push16(&mut hhea, 0);
162    hhea.extend_from_slice(&[0; 8]);
163    push16(&mut hhea, 0);
164    push16(&mut hhea, count);
165
166    let mut hmtx = Vec::new();
167    for glyph in &glyphs {
168        push16(&mut hmtx, glyph.advance);
169        push16(&mut hmtx, glyph.bounds[0] as u16);
170    }
171
172    let mut maxp = Vec::new();
173    push32(&mut maxp, 0x0001_0000);
174    push16(&mut maxp, count);
175    push16(
176        &mut maxp,
177        glyphs.iter().map(|glyph| glyph.points).max().unwrap_or(0),
178    );
179    push16(
180        &mut maxp,
181        glyphs.iter().map(|glyph| glyph.contours).max().unwrap_or(0),
182    );
183    push16(&mut maxp, 0);
184    push16(&mut maxp, 0);
185    push16(&mut maxp, 2);
186    for _ in 0..8 {
187        push16(&mut maxp, 0);
188    }
189
190    let last_char = FIRST_CHAR + u32::from(count) - 2;
191    let mut cmap = Vec::new();
192    push16(&mut cmap, 0);
193    push16(&mut cmap, 1);
194    push16(&mut cmap, 3);
195    push16(&mut cmap, 1);
196    push32(&mut cmap, 12);
197    push16(&mut cmap, 4);
198    push16(&mut cmap, 32);
199    push16(&mut cmap, 0);
200    push16(&mut cmap, 4);
201    push16(&mut cmap, 4);
202    push16(&mut cmap, 1);
203    push16(&mut cmap, 0);
204    push16(&mut cmap, last_char as u16);
205    push16(&mut cmap, 0xffff);
206    push16(&mut cmap, 0);
207    push16(&mut cmap, FIRST_CHAR as u16);
208    push16(&mut cmap, 0xffff);
209    push16(&mut cmap, 1u16.wrapping_sub(FIRST_CHAR as u16));
210    push16(&mut cmap, 1);
211    push16(&mut cmap, 0);
212    push16(&mut cmap, 0);
213
214    let mut os2 = Vec::new();
215    push16(&mut os2, 4);
216    push16(&mut os2, max_advance);
217    push16(&mut os2, 400);
218    push16(&mut os2, 5);
219    push16(&mut os2, 0);
220    for value in [650, 600, 0, 75, 650, 600, 0, 350, 50, 260] {
221        push16(&mut os2, value);
222    }
223    push16(&mut os2, 0);
224    os2.extend_from_slice(&[0; 10]);
225    for _ in 0..4 {
226        push32(&mut os2, 0);
227    }
228    os2.extend_from_slice(b"PITO");
229    push16(&mut os2, 0x0040);
230    push16(&mut os2, FIRST_CHAR as u16);
231    push16(&mut os2, last_char as u16);
232    push16(&mut os2, ascender as u16);
233    push16(&mut os2, descender as u16);
234    push16(&mut os2, 0);
235    push16(&mut os2, ascender as u16);
236    push16(&mut os2, (-descender) as u16);
237    push32(&mut os2, 1);
238    push32(&mut os2, 0);
239    push16(&mut os2, UNITS_PER_EM / 2);
240    push16(&mut os2, UNITS_PER_EM * 3 / 4);
241    push16(&mut os2, 0);
242    push16(&mut os2, 0);
243    push16(&mut os2, 1);
244
245    let names = [
246        (1u16, FAMILY.to_owned()),
247        (2, "Regular".to_owned()),
248        (4, format!("{FAMILY} Regular")),
249        (6, "PITOInputGlyphs-Regular".to_owned()),
250    ];
251    let mut strings = Vec::new();
252    let mut name = Vec::new();
253    push16(&mut name, 0);
254    push16(&mut name, names.len() as u16);
255    push16(&mut name, (6 + 12 * names.len()) as u16);
256    for (id, text) in &names {
257        let encoded: Vec<u8> = text.encode_utf16().flat_map(u16::to_be_bytes).collect();
258        push16(&mut name, 3);
259        push16(&mut name, 1);
260        push16(&mut name, 0x0409);
261        push16(&mut name, *id);
262        push16(&mut name, encoded.len() as u16);
263        push16(&mut name, strings.len() as u16);
264        strings.extend_from_slice(&encoded);
265    }
266    name.extend_from_slice(&strings);
267
268    let mut post = Vec::new();
269    push32(&mut post, 0x0003_0000);
270    push32(&mut post, 0);
271    push16(&mut post, (-(UNITS_PER_EM as i16) / 10) as u16);
272    push16(&mut post, UNITS_PER_EM / 20);
273    for _ in 0..5 {
274        push32(&mut post, 0);
275    }
276
277    let tables: [(&[u8; 4], Vec<u8>); 10] = [
278        (b"OS/2", os2),
279        (b"cmap", cmap),
280        (b"glyf", glyf),
281        (b"head", head),
282        (b"hhea", hhea),
283        (b"hmtx", hmtx),
284        (b"loca", loca),
285        (b"maxp", maxp),
286        (b"name", name),
287        (b"post", post),
288    ];
289    let mut font = Vec::new();
290    push32(&mut font, 0x0001_0000);
291    push16(&mut font, tables.len() as u16);
292    push16(&mut font, 128);
293    push16(&mut font, 3);
294    push16(&mut font, (tables.len() * 16 - 128) as u16);
295    let mut offset = 12 + 16 * tables.len();
296    for (tag, data) in &tables {
297        font.extend_from_slice(*tag);
298        push32(&mut font, checksum(data));
299        push32(&mut font, offset as u32);
300        push32(&mut font, data.len() as u32);
301        offset += data.len().next_multiple_of(4);
302    }
303    for (_, data) in &tables {
304        font.extend_from_slice(data);
305        while font.len() % 4 != 0 {
306            font.push(0);
307        }
308    }
309    font
310}
311
312fn checksum(data: &[u8]) -> u32 {
313    data.chunks(4).fold(0u32, |sum, chunk| {
314        let mut word = [0u8; 4];
315        word[..chunk.len()].copy_from_slice(chunk);
316        sum.wrapping_add(u32::from_be_bytes(word))
317    })
318}