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}