Skip to main content

font_test_data/
ift.rs

1//! Test data for the IFT table
2//!
3//! Used for incremental font transfer. Specification:
4//! <https://w3c.github.io/IFT/Overview.html>
5
6use std::iter;
7
8use font_types::{Int24, Tag, Uint24};
9
10use crate::{be_buffer, bebuffer::BeBuffer};
11
12pub static IFT_BASE: &[u8] = include_bytes!("../test_data/ttf/ift_base.ttf");
13
14pub static CFF_FONT: &[u8] = include_bytes!("../test_data/ttf/NotoSansJP-Regular.subset.otf");
15pub static CFF2_FONT: &[u8] = include_bytes!("../test_data/ttf/NotoSansJP-VF.subset.otf");
16
17pub const CFF_FONT_CHARSTRINGS_OFFSET: u32 = 0x1b9;
18pub const CFF2_FONT_CHARSTRINGS_OFFSET: u32 = 0x8f;
19
20// Using opcode format: https://w3c.github.io/IFT/Overview.html#url-templates
21pub const RELATIVE_URL_TEMPLATE: &[u8] = b"\x04foo/\x80";
22pub const ABSOLUTE_URL_TEMPLATE: &[u8] = b"\x0a//foo.bar/\x80";
23
24// Format specification: https://w3c.github.io/IFT/Overview.html#patch-map-format-2
25pub fn codepoints_only() -> BeBuffer {
26    let mut buffer = be_buffer! {
27      {2u8: "format"},    // format
28
29      0u32,               // reserved
30
31      {1u32: "compat_id[0]"},
32      {2u32: "compat_id[1]"},
33      {3u32: "compat_id[2]"},
34      {4u32: "compat_id[3]"},
35
36      3u8,                // default patch encoding
37      {(Uint24::new(4)): "entry_count"},
38      {0u32: "entries_offset"},
39      0u32,               // entry string data offset
40
41      6u16, // urlTemplateLength
42      [4, b'f', b'o', b'o', b'/', 128u8],  // urlTemplate[6]
43
44      /* ### Entries Array ### */
45      // Entry id = 1
46      {0b00010000u8: "entries[0]"},           // format = CODEPOINT_BIT_1
47      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [0..17]
48
49      // Entry id = 2
50      {0b01100000u8: "entries[1]"},           // format = IGNORED | CODEPOINT_BIT_2
51      5u16,                                   // bias
52      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [5..22]
53
54      // Entry id = 3
55      {0b00100000u8: "entries[2]"},            // format = CODEPOINT_BIT_2
56      5u16,                                    // bias
57      [0b00001101, 0b00000011, 0b00110001u8],  // codepoints = [5..22]
58
59      // Entry id = 4
60      {0b00110000u8: "entries[3]"},            // format = CODEPOINT_BIT_1 | CODEPOINT_BIT_2
61      (Uint24::new(80_000)),                   // bias
62      [0b00001101, 0b00000011, 0b00110001u8]   // codepoints = [80_005..80_022]
63    };
64
65    let offset = buffer.offset_for("entries[0]") as u32;
66    buffer.write_at("entries_offset", offset);
67
68    buffer
69}
70
71pub fn with_one_charstrings_offset() -> BeBuffer {
72    let mut buffer = be_buffer! {
73      2u8,                // format
74
75      0u8, 0u8, 0u8,                 // reserved
76      {0b00000001u8: "field_flags"}, // has charstrings offset
77
78      {1u32: "compat_id[0]"},
79      {2u32: "compat_id[1]"},
80      {3u32: "compat_id[2]"},
81      {4u32: "compat_id[3]"},
82
83      3u8,                // default patch encoding
84      (Uint24::new(1)),   // entry count
85      {0u32: "entries_offset"},
86      0u32,               // entry string data offset
87
88      8u16, // urlTemplateLength
89      [b'A', b'B', b'C', b'D', b'E', b'F', 0xc9, 0xa4],  // urlTemplate[8]
90
91      {456u32: "charstrings_offset"}, // charstrings offset [0]
92
93      /* ### Entries Array ### */
94      // Entry id = 1
95      {0b00010000u8: "entries[0]"},           // format = CODEPOINT_BIT_1
96      [0b00001101, 0b00000011, 0b00110001u8]  // codepoints = [0..17]
97    };
98
99    let offset = buffer.offset_for("entries[0]") as u32;
100    buffer.write_at("entries_offset", offset);
101
102    buffer
103}
104
105pub fn with_two_charstrings_offset() -> BeBuffer {
106    let mut buffer = be_buffer! {
107      2u8,                // format
108
109      0u8, 0u8, 0u8,          // reserved
110      0b00000011u8,           // has cff and cff2 charstrings offset
111
112      {1u32: "compat_id[0]"},
113      {2u32: "compat_id[1]"},
114      {3u32: "compat_id[2]"},
115      {4u32: "compat_id[3]"},
116
117      3u8,                // default patch encoding
118      (Uint24::new(1)),   // entry count
119      {0u32: "entries_offset"},
120      0u32,               // entry string data offset
121
122      8u16, // urlTemplateLength
123      [b'A', b'B', b'C', b'D', b'E', b'F', 0xc9, 0xa4],  // urlTemplate[8]
124
125      456u32, // charstrings offset [0]
126      789u32, // charstrings offset [1]
127
128      /* ### Entries Array ### */
129      // Entry id = 1
130      {0b00010000u8: "entries[0]"},           // format = CODEPOINT_BIT_1
131      [0b00001101, 0b00000011, 0b00110001u8]  // codepoints = [0..17]
132    };
133
134    let offset = buffer.offset_for("entries[0]") as u32;
135    buffer.write_at("entries_offset", offset);
136
137    buffer
138}
139
140pub fn features_and_design_space() -> BeBuffer {
141    let mut buffer = be_buffer! {
142      2u8, // format
143
144      0u32, // reserved
145
146      [1, 2, 3, 4u32], // compat id
147
148      {3u8: "patch_format"}, // default patch encoding
149      (Uint24::new(3)), // entry count
150      {0u32: "entries_offset"},
151      0u32, // entry id string data offset
152
153      6u16, // urlTemplateLength
154      [4, b'f', b'o', b'o', b'/', 128u8],  // urlTemplate[6]
155
156      /* ### Entries Array ### */
157      // Entry id = 1
158      {0b00010001u8: "entries[0]"},          // format = CODEPOINT_BIT_1 | FEATURES_AND_DESIGN_SPACE
159
160      2u8,                                // feature count = 2
161      (Tag::new(b"liga")),                // feature[0] = liga
162      (Tag::new(b"smcp")),                // feature[1] = smcp
163
164      1u16,                               // design space count
165      (Tag::new(b"wdth")),                // tag = wdth
166      {0x8000u32: "wdth start"},          // start = 0.5
167      0x10000u32,                         // end = 1.0
168
169      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [0..17]
170
171      // Entry id = 2
172      {0b00010001u8: "entries[1]"},       // format = CODEPOINT_BIT_1 | FEATURES_AND_DESIGN_SPACE
173
174      1u8,                                // feature count
175      (Tag::new(b"rlig")),                // feature[0]
176
177      0u16,                               // design space count
178
179      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [0..17]
180
181      // Entry id = 3
182      {0b000100001u8: "entries[2]"},      // format = CODEPOINT_BIT_2 | FEATURES_AND_DESIGN_SPACE
183
184      1u8,                                // feature count = 1
185      (Tag::new(b"smcp")),                // feature[0] = smcp
186
187      3u16,                               // design space count
188      (Tag::new(b"wght")),                // tag = wght
189      0x00C8_0000u32,                     // start = 200
190      0x02BC_0000u32,                     // end = 700
191
192      (Tag::new(b"wdth")),                // tag = wdth
193      0x0u32,                             // start = 0.0
194      0x8000u32,                          // end = 0.5
195
196      (Tag::new(b"wdth")),                // tag = wdth
197      0x0002_0000u32,                     // start = 2.0
198      0x0002_8000u32,                     // end = 2.5
199
200      5u16,                               // bias = 5
201      [0b00001101, 0b00000011, 0b00110001u8] // codepoints = [5..22]
202    };
203
204    let offset = buffer.offset_for("entries[0]") as u32;
205    buffer.write_at("entries_offset", offset);
206
207    buffer
208}
209
210pub fn child_indices() -> BeBuffer {
211    let mut buffer = be_buffer! {
212      2u8,                      // format
213
214      0u32,                     // reserved
215
216      [1, 2, 3, 4u32],          // compat id
217
218      {3u8: "encoding"},          // default patch encoding = glyph keyed
219      (Uint24::new(9)),         // entry count
220      {0u32: "entries_offset"}, // entries offset
221      0u32,                     // entry id string data offset
222
223      6u16, // urlTemplateLength
224      [4, b'f', b'o', b'o', b'/', 128u8],  // urlTemplate[6]
225
226      // Entries Array
227
228      // Entry id = 1
229      {0b01100000u8: "entries[0]"},           // format = CODEPOINT_BIT_2 | IGNORED
230      5u16,                                   // bias = 5
231      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [5..22]
232
233      // Entry id = 2
234      {0b00100000u8: "entries[1]"},           // format = CODEPOINT_BIT_2
235      50u16,                                  // bias
236      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [50..67]
237
238      // Entry id = 3
239      {0b00000001u8: "entries[2]"},           // format = FEATURES_AND_DESIGN_SPACE
240
241      1u8,                                    // feature count = 1
242      (Tag::new(b"rlig")),                    // feature[0] = rlig
243
244      1u16,                                   // design space count = 1
245      (Tag::new(b"wght")),                    // tag = wght
246      0x00C8_0000u32,                         // start = 200
247      0x02BC_0000u32,                         // end = 700
248
249      // Entry id = 4
250      {0b00000001u8: "entries[3]"},           // format = FEATURES_AND_DESIGN_SPACE
251
252      1u8,                                    // feature count
253      (Tag::new(b"liga")),                    // feature[0] = liga
254
255      1u16,                                   // design space count
256      (Tag::new(b"wght")),                    // tag = wght
257      0x0032_0000,                            // start = 50
258      0x0064_0000,                            // end = 100
259
260      // Entry id = 5
261      {0b00000010u8: "entries[4]"},           // format = CHILD_INDICES
262      1u8,                                    // child count
263      (Uint24::new(0)),                       // child[0] = 0
264
265      // Entry id = 6
266      {0b00000010u8: "entries[5]"},           // format = CHILD_INDICES
267      1u8,                                    // child count
268      (Uint24::new(2)),                       // child
269
270      // Entry id = 7
271      {0b00000010u8: "entries[6]"},           // format = CHILD_INDICES
272      {4u8: "entries[6]_child_count"},        // child count
273      (Uint24::new(3)),                       // child[0] = 3
274      {(Uint24::new(2)): "entries[6]_child"}, // child[1] = 2
275      (Uint24::new(1)),                       // child[2] = 1
276      (Uint24::new(0)),                       // child[3] = 0
277
278      // Entry id = 8
279      {0b00000010u8: "entries[7]"},           // format = CHILD_INDICES
280      2u8,                                    // child count
281      (Uint24::new(4)),                       // child[0] = 4
282      (Uint24::new(5)),                       // child[1] = 5
283
284      // Entry id = 9
285      {0b00100010u8: "entries[8]"},           // format = CODEPOINT_BIT_2 | CHILD_INDICES
286      1u8,                                    // child count
287      (Uint24::new(0)),                       // chil[0] = 0
288      100u16,                                 // bias
289      [0b00001101, 0b00000011, 0b00110001u8]  // codepoints = [100..117]
290    };
291
292    let offset = buffer.offset_for("entries[0]") as u32;
293    buffer.write_at("entries_offset", offset);
294
295    buffer
296}
297
298// Format specification: https://w3c.github.io/IFT/Overview.html#patch-map-format-2
299pub fn custom_ids() -> BeBuffer {
300    let mut buffer = be_buffer! {
301      2u8,                               // format
302
303      0u32,                              // reserved
304
305      {1u32: "compat_id[0]"},
306      {2u32: "compat_id[1]"},
307      {3u32: "compat_id[2]"},
308      {4u32: "compat_id[3]"},
309
310      3u8,                               // default patch encoding = glyph keyed
311      {(Uint24::new(4)): "entry_count"}, // entry count
312      {0u32: "entries_offset"},          // entries offset
313      0u32,                              // entry id string data offset
314
315      6u16, // urlTemplateLength
316      [4, b'f', b'o', b'o', b'/', 128u8],  // urlTemplate[6]
317
318      // Entries Array
319      // Entry id = 0
320      {0b00010100u8: "entries[0]"},           // format = CODEPOINT_BIT_1 | ID_DELTA
321      {(Int24::new(-2)): "entries[0].id_delta"}, // id delta = -1
322      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [0..17]
323
324      // Entry id = 6
325      {0b00100100u8: "entries[1]"},            // format = CODEPOINT_BIT_2 | ID_DELTA
326      {(Int24::new(10)): "entries[1].id_delta"},           // id delta = 5
327      5u16,                                   // bias
328      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [5..22]
329
330      // Entry id = 14
331      {0b01000100u8: "entries[2]"},                  // format = ID_DELTA | IGNORED
332      {(Int24::new(14)): "id delta - ignored entry"}, // id delta = 7
333
334      // Entry id = 15
335      {0b00101000u8: "entries[3]"},           // format = CODEPOINT_BIT_2 | PATCH_FORMAT
336      {3u8: "entry[4] encoding"},             // patch encoding = Glyph Keyed
337      10u16,                                  // bias
338      [0b00001101, 0b00000011, 0b00110001u8]  // codepoints = [10..27]
339    };
340
341    let offset = buffer.offset_for("entries[0]") as u32;
342    buffer.write_at("entries_offset", offset);
343
344    buffer
345}
346
347// Format specification: https://w3c.github.io/IFT/Overview.html#patch-map-format-2
348pub fn string_ids() -> BeBuffer {
349    let mut buffer = be_buffer! {
350      2u8,                      // format
351
352      0u32,                     // reserved
353
354      [1, 2, 3, 4u32],          // compat id
355
356      3u8,                      // default patch encoding = glyph keyed
357      (Uint24::new(6)),         // entry count
358      {0u32: "entries_offset"}, // entries offset
359      {0u32: "string_data_offset"},                     // entry id string data offset
360
361      6u16, // urlTemplateLength
362      [4, b'f', b'o', b'o', b'/', 128u8],  // urlTemplate[6]
363
364      /* ### Entry Data ### */
365
366      // Entry id = ""
367      {0b00000000u8: "entries"},              // format = {}
368
369      // Entry id = abc
370      0b00000100u8,                           // format = ID_DELTA
371      (Uint24::new(3)),                       // id length
372
373      // Entry id = defg
374      0b00000100u8,                           // format = ID_DELTA
375      (Uint24::new(4)),                       // id length
376
377      // Entry id = defg
378      0b00000000u8,                           // format = {}
379
380      // Entry id = hij
381      0b00000100u8,                           // format = ID_DELTA
382      {(Uint24::new(3)): "entry[4] id length"},           // id length
383
384      // Entry id = ""
385      0b00000100u8,                           // format = ID_DELTA
386      (Uint24::new(0)),                                   // id length
387
388      /* ### String Data ### */
389      {b'a': "string_data"},
390      [b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j']
391    };
392
393    let offset = buffer.offset_for("string_data") as u32;
394    buffer.write_at("string_data_offset", offset);
395
396    let offset = buffer.offset_for("entries") as u32;
397    buffer.write_at("entries_offset", offset);
398
399    buffer
400}
401
402pub fn string_ids_with_preloads() -> BeBuffer {
403    const CONTINUE_MASK: u32 = 1 << 23;
404    let mut buffer = be_buffer! {
405      2u8,                      // format
406
407      0u32,                     // reserved
408
409      [1, 2, 3, 4u32],          // compat id
410
411      3u8,                      // default patch encoding = glyph keyed
412      (Uint24::new(5)),         // entry count
413      {0u32: "entries_offset"}, // entries offset
414      {0u32: "string_data_offset"},                     // entry id string data offset
415
416      6u16, // urlTemplateLength
417      [4, b'f', b'o', b'o', b'/', 128u8],  // urlTemplate[6]
418
419      /* ### Entry Data ### */
420
421      // Entry id = ""
422      {0b00000000u8: "entries"},              // format = {}
423
424      // Entry id = {abc, "", defg}
425      0b00000100u8,                           // format = ID_DELTA
426      (Uint24::new(CONTINUE_MASK | 3)),       // id length 3
427      (Uint24::new(CONTINUE_MASK)),           // id length 0
428      (Uint24::new(4)),                       // id length 4
429
430      // Entry id = defg
431      0b00000000u8,                           // format = {}
432
433      // Entry id = hij
434      0b00000100u8,                           // format = ID_DELTA
435      {(Uint24::new(3)): "entry[4] id length"},           // id length
436
437      // Entry id = ""
438      0b00000100u8,                           // format = ID_DELTA
439      (Uint24::new(0)),                                   // id length
440
441      /* ### String Data ### */
442      {b'a': "string_data"},
443      [b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j']
444    };
445
446    let offset = buffer.offset_for("string_data") as u32;
447    buffer.write_at("string_data_offset", offset);
448
449    let offset = buffer.offset_for("entries") as u32;
450    buffer.write_at("entries_offset", offset);
451
452    buffer
453}
454
455// Format specification: https://w3c.github.io/IFT/Overview.html#patch-map-format-2
456pub fn table_keyed() -> BeBuffer {
457    let mut buffer = be_buffer! {
458      2u8,                // format
459
460      0u32,               // reserved
461
462      {1u32: "compat_id[0]"},
463      {2u32: "compat_id[1]"},
464      {3u32: "compat_id[2]"},
465      {4u32: "compat_id[3]"},
466
467      {1u8: "encoding"},  // default patch encoding
468      {(Uint24::new(1)): "entry_count"},   // entry count
469      {0u32: "entries_offset"},
470      0u32,               // entry string data offset
471
472      6u16, // urlTemplateLength
473      [4u8, b'f', b'o', b'o', b'/'],
474      {128u8: "url_template_var_end"}, // urlTemplate[6]
475
476      /* ### Entries Array ### */
477      // Entry id = 1
478      {0b00100100u8: "entries"},              // format = CODEPOINT_BIT_2
479      {(Int24::new(0)): "id_delta"},
480      {0u16: "bias"},                         // bias = 0
481      [0b00001101, 0b00000011, 0b00110001u8]  // codepoints = [0..17]
482    };
483
484    let offset = buffer.offset_for("entries") as u32;
485    buffer.write_at("entries_offset", offset);
486
487    buffer
488}
489
490pub fn table_keyed_with_preload_urls() -> BeBuffer {
491    let mut buffer = be_buffer! {
492      2u8,                // format
493
494      0u32,               // reserved
495
496      {1u32: "compat_id[0]"},
497      {2u32: "compat_id[1]"},
498      {3u32: "compat_id[2]"},
499      {4u32: "compat_id[3]"},
500
501      {3u8: "encoding"},  // default patch encoding = Glyph Keyed
502      (Uint24::new(4)),   // entry count
503      {0u32: "entries_offset"},
504      0u32,               // entry string data offset
505
506      6u16, // urlTemplateLength
507      [4, b'f', b'o', b'o', b'/', 128u8],  // urlTemplate[6]
508
509      /* ### Entries Array ### */
510
511      // Entry id = 1
512      {0b00010000u8: "entries[0]"},           // format = CODEPOINT_BIT_1
513      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [0..17]
514
515      // Entry id = {9, 10, 6}
516      {0b00010100u8: "entries[1]"},           // format = CODEPOINT_BIT_1
517      (Int24::new(15)),                       // delta +7
518      (Int24::new(1)),                        // delta +0
519      (Int24::new(-10)),                      // delta -5
520      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [0..17]
521
522      // Entry id = {2, 3}
523      {0b00010100u8: "entries[2]"},              // format = CODEPOINT_BIT_1
524      (Int24::new(-11)),                      // delta -5
525      (Int24::new(0)),                        // delta +0
526      [0b00001101, 0b00000011, 0b00110001u8], // codepoints = [0..17]
527
528      // Entry id = 4
529      {0b00010000u8: "entries[3]"},           // format = CODEPOINT_BIT_1
530      [0b00001101, 0b00000011, 0b00110001u8]  // codepoints = [0..17]
531    };
532
533    let offset = buffer.offset_for("entries[0]") as u32;
534    buffer.write_at("entries_offset", offset);
535
536    buffer
537}
538
539// Format specification: https://w3c.github.io/IFT/Overview.html#table-keyed
540pub fn table_keyed_patch() -> BeBuffer {
541    let mut buffer = be_buffer! {
542        {(Tag::new(b"iftk")): "tag"},
543        0u32,                 // reserved
544        {1u32: "compat_id"},
545        [2, 3, 4u32],       // compat id
546        3u16,                 // patch count
547
548        // patch_offsets[3]
549        {0u32: "patch_off[0]"},
550        {0u32: "patch_off[1]"},
551        {0u32: "patch_off[2]"},
552        {0u32: "patch_off[3]"},
553
554        // patch[0]
555        {(Tag::new(b"tab1")): "patch[0]"},
556        0u8,       // flags
557        {29u32: "decompressed_len[0]"},     // max decompressed length
558        // brotli stream (w/ shared dict)
559        [0xa1, 0xe0, 0x00, 0xc0, 0x2f, 0x3a, 0x38, 0xf4, 0x01, 0xd1, 0xaf, 0x54, 0x84, 0x14, 0x71,
560         0x2a, 0x80, 0x04, 0xa2, 0x1c, 0xd3, 0xdd, 0x07u8],
561
562         // patch[1]
563        {(Tag::new(b"tab2")): "patch[1]"},
564        {1u8: "flags[1]"},  // flags (REPLACEMENT)
565        30u32,              // max decompressed length
566        // brotli stream (w/o shared dict)
567        [0xa1, 0xe8, 0x00, 0xc0, 0xef, 0x48, 0x9d, 0xfa, 0xdc, 0xf1, 0xc2, 0xac, 0xc5, 0xde, 0xe4, 0xf4,
568         0xb4, 0x02, 0x48, 0x98, 0x98, 0x52, 0x64, 0xa8, 0x50, 0x20, 0x29, 0x75, 0x0bu8],
569
570         // patch[2]
571        {(Tag::new(b"tab3")): "patch[2]"},
572        {2u8: "flags[2]"}, // flags (DROP)
573        {0u32: "end"}      // max decompressed length
574    };
575
576    let offset = buffer.offset_for("patch[0]") as u32;
577    buffer.write_at("patch_off[0]", offset);
578
579    let offset = buffer.offset_for("patch[1]") as u32;
580    buffer.write_at("patch_off[1]", offset);
581
582    let offset = buffer.offset_for("patch[2]") as u32;
583    buffer.write_at("patch_off[2]", offset);
584
585    let offset = (buffer.offset_for("end") + 4) as u32;
586    buffer.write_at("patch_off[3]", offset);
587
588    buffer
589}
590
591// Format specification: https://w3c.github.io/IFT/Overview.html#table-keyed
592pub fn noop_table_keyed_patch() -> BeBuffer {
593    be_buffer! {
594        {(Tag::new(b"iftk")): "tag"},
595        0u32,                 // reserved
596        [1, 2, 3, 4u32],       // compat id
597        0u16,                 // patch count
598
599        // patch_offsets[1]
600        {0u32: "patch_off[0]"}
601    }
602}
603
604// Format specification: https://w3c.github.io/IFT/Overview.html#glyph-keyed
605pub fn glyph_keyed_patch_header() -> BeBuffer {
606    be_buffer! {
607      {(Tag::new(b"ifgk")): "format"}, // format
608      0u32,                // reserved
609      0u8,                 // flags (0 = u16 gids)
610      {6u32: "compatibility_id"},
611      [7, 8, 9u32],     // compatibility id
612      {0u32: "max_uncompressed_length"}
613    }
614}
615
616// Format specification: https://w3c.github.io/IFT/Overview.html#glyphpatches
617pub fn noop_glyf_glyph_patches() -> BeBuffer {
618    be_buffer! {
619      0u32,       // glyph count
620      {1u8: "table_count"},        // table count
621
622      (Tag::new(b"glyf")),   // tables * 1
623
624      // glyph data offsets * 1
625      0u32
626    }
627}
628
629// Format specification: https://w3c.github.io/IFT/Overview.html#glyphpatches
630pub fn glyf_u16_glyph_patches() -> BeBuffer {
631    let mut buffer = be_buffer! {
632      5u32,       // glyph count
633      {1u8: "table_count"},        // table count
634
635      // glyph ids * 5
636      [2, 7u16],
637      {8u16: "gid_8"},
638      [9u16],
639      {13u16: "gid_13"},
640
641      (Tag::new(b"glyf")),   // tables * 1
642
643      // glyph data offsets * 6
644      {0u32: "gid_2_offset"},
645      {0u32: "gid_7_offset"},
646      {0u32: "gid_8_offset"},
647      {0u32: "gid_9_offset"},
648      {0u32: "gid_13_offset"},
649      {0u32: "end_offset"},
650
651      // data blocks
652      {b'a': "gid_2_data"},
653      [b'b', b'c'],
654
655      {b'd': "gid_7_data"},
656      [b'e', b'f', b'g'],
657
658      {b'h': "gid_8_and_9_data"},
659      [b'i', b'j', b'k', b'l'],
660
661      {b'm': "gid_13_data"},
662      [b'n']
663    };
664
665    let offset = buffer.offset_for("gid_2_data") as u32;
666    buffer.write_at("gid_2_offset", offset);
667
668    let offset = buffer.offset_for("gid_7_data") as u32;
669    buffer.write_at("gid_7_offset", offset);
670
671    let offset = buffer.offset_for("gid_8_and_9_data") as u32;
672    buffer.write_at("gid_8_offset", offset);
673
674    let offset = buffer.offset_for("gid_8_and_9_data") as u32;
675    buffer.write_at("gid_9_offset", offset);
676
677    let offset = buffer.offset_for("gid_13_data") as u32;
678    buffer.write_at("gid_13_offset", offset);
679    buffer.write_at("end_offset", offset + 2);
680
681    buffer
682}
683
684// Format specification: https://w3c.github.io/IFT/Overview.html#glyphpatches
685pub fn glyf_u16_glyph_patches_2() -> BeBuffer {
686    let mut buffer = be_buffer! {
687      3u32,       // glyph count
688      {1u8: "table_count"},        // table count
689
690      // glyph ids * 3
691      7u16,
692      12u16,
693      14u16,
694
695      (Tag::new(b"glyf")),   // tables * 1
696
697      // glyph data offsets * 6
698      {0u32: "gid_7_offset"},
699      {0u32: "gid_12_offset"},
700      {0u32: "gid_14_offset"},
701      {0u32: "end_offset"},
702
703      // data blocks
704      {b'q': "gid_7_data"},
705      [b'r'],
706
707      {b's': "gid_12_data"},
708      [b't', b'u'],
709
710      {b'v': "gid_14_data"}
711    };
712
713    let offset = buffer.offset_for("gid_7_data") as u32;
714    buffer.write_at("gid_7_offset", offset);
715
716    let offset = buffer.offset_for("gid_12_data") as u32;
717    buffer.write_at("gid_12_offset", offset);
718
719    let offset = buffer.offset_for("gid_14_data") as u32;
720    buffer.write_at("gid_14_offset", offset);
721    buffer.write_at("end_offset", offset + 1);
722
723    buffer
724}
725
726// Format specification: https://w3c.github.io/IFT/Overview.html#glyphpatches
727pub fn glyf_u24_glyph_patches() -> BeBuffer {
728    let mut buffer = be_buffer! {
729      5u32,       // glyph count
730      1u8,        // table count
731      (Uint24::new(2)), (Uint24::new(7)), (Uint24::new(8)), (Uint24::new(9)), (Uint24::new(13)),   // glyph ids * 5
732      (Tag::new(b"glyf")),   // tables * 1
733
734      // glyph data offsets * 6
735      {0u32: "gid_2_offset"},
736      {0u32: "gid_7_offset"},
737      {0u32: "gid_8_offset"},
738      {0u32: "gid_9_offset"},
739      {0u32: "gid_13_offset"},
740      {0u32: "end_offset"},
741
742      // data blocks
743      {b'a': "gid_2_data"},
744      [b'b', b'c'],
745
746      {b'd': "gid_7_data"},
747      [b'e', b'f', b'g'],
748
749      {b'h': "gid_8_and_9_data"},
750      [b'i', b'j', b'k', b'l'],
751
752      {b'm': "gid_13_data"},
753      [b'n']
754    };
755
756    let offset = buffer.offset_for("gid_2_data") as u32;
757    buffer.write_at("gid_2_offset", offset);
758
759    let offset = buffer.offset_for("gid_7_data") as u32;
760    buffer.write_at("gid_7_offset", offset);
761
762    let offset = buffer.offset_for("gid_8_and_9_data") as u32;
763    buffer.write_at("gid_8_offset", offset);
764
765    let offset = buffer.offset_for("gid_8_and_9_data") as u32;
766    buffer.write_at("gid_9_offset", offset);
767
768    let offset = buffer.offset_for("gid_13_data") as u32;
769    buffer.write_at("gid_13_offset", offset);
770    buffer.write_at("end_offset", offset + 2);
771
772    buffer
773}
774
775// Format specification: https://w3c.github.io/IFT/Overview.html#glyphpatches
776pub fn glyf_and_gvar_u16_glyph_patches() -> BeBuffer {
777    let mut buffer = be_buffer! {
778      3u32,       // glyph count
779      2u8,        // table count
780      [2, 7, 8u16],   // glyph ids * 3
781      {(Tag::new(b"glyf")): "glyf_tag"}, // tables[0]
782      {(Tag::new(b"gvar")): "gvar_tag"}, // tables[1]
783
784      // glyph data offsets * 7
785      {0u32: "glyf_gid_2_offset"},
786      {0u32: "glyf_gid_7_offset"},
787      {0u32: "glyf_gid_8_offset"},
788      {0u32: "gvar_gid_2_offset"},
789      {0u32: "gvar_gid_7_offset"},
790      {0u32: "gvar_gid_8_offset"},
791      {0u32: "end_offset"},
792
793      // data blocks
794      {b'a': "glyf_gid_2_data"},
795      [b'b', b'c'],
796
797      {b'd': "glyf_gid_7_data"},
798      [b'e', b'f', b'g'],
799
800      {b'h': "glyf_gid_8_data"},
801      [b'i', b'j', b'k', b'l'],
802
803      {b'm': "gvar_gid_2_data"},
804      [b'n'],
805
806      {b'o': "gvar_gid_7_data"},
807      [b'p', b'q'],
808
809      {b'r': "gvar_gid_8_data"}
810    };
811
812    let offset = buffer.offset_for("glyf_gid_2_data") as u32;
813    buffer.write_at("glyf_gid_2_offset", offset);
814    let offset = buffer.offset_for("glyf_gid_7_data") as u32;
815    buffer.write_at("glyf_gid_7_offset", offset);
816    let offset = buffer.offset_for("glyf_gid_8_data") as u32;
817    buffer.write_at("glyf_gid_8_offset", offset);
818
819    let offset = buffer.offset_for("gvar_gid_2_data") as u32;
820    buffer.write_at("gvar_gid_2_offset", offset);
821    let offset = buffer.offset_for("gvar_gid_7_data") as u32;
822    buffer.write_at("gvar_gid_7_offset", offset);
823    let offset = buffer.offset_for("gvar_gid_8_data") as u32;
824    buffer.write_at("gvar_gid_8_offset", offset);
825    buffer.write_at("end_offset", offset + 1);
826
827    buffer
828}
829
830pub fn cff_u16_glyph_patches() -> BeBuffer {
831    let mut buffer = be_buffer! {
832      4u32,       // glyph count
833      {1u8: "table_count"},        // table count
834
835      // 4 glyph ids
836      [1,      // first gid
837       38,
838       47,
839       59u16], // last gid
840
841      {(Tag::new(b"CFF ")): "tag"},   // tables * 1
842
843      // 5 glyph data offsets
844      {0u32: "gid_1_offset"},
845      {0u32: "gid_38_offset"},
846      {0u32: "gid_47_offset"},
847      {0u32: "gid_59_offset"},
848      {0u32: "end_offset"},
849
850      // data blocks
851      {b'a': "gid_1_data"},
852      [b'b', b'c'],
853
854      {b'd': "gid_38_data"},
855      [b'e', b'f', b'g'],
856
857      {b'h': "gid_47_data"},
858      [b'i', b'j', b'k', b'l'],
859
860      {b'm': "gid_59_data"},
861      [b'n']
862    };
863
864    let offset = buffer.offset_for("gid_1_data") as u32;
865    buffer.write_at("gid_1_offset", offset);
866
867    let offset = buffer.offset_for("gid_38_data") as u32;
868    buffer.write_at("gid_38_offset", offset);
869
870    let offset = buffer.offset_for("gid_47_data") as u32;
871    buffer.write_at("gid_47_offset", offset);
872
873    let offset = buffer.offset_for("gid_59_data") as u32;
874    buffer.write_at("gid_59_offset", offset);
875    buffer.write_at("end_offset", offset + 2);
876
877    buffer
878}
879
880/// <https://learn.microsoft.com/en-us/typography/opentype/spec/gvar>
881pub fn short_gvar_with_shared_tuples() -> BeBuffer {
882    // This gvar has the correct header and tuple structure but the per glyph variation data is not valid.
883    // Meant for testing with IFT glyph keyed patching which treats the per glyph data as opaque blobs.
884    let mut buffer = be_buffer! {
885      // HEADER
886      1u16, // major version
887      0u16, // minor version
888      1u16, // axis count
889      3u16, // sharedTupleCount
890      {0u32: "shared_tuples_offset"},
891      15u16, // glyph count
892      0u16,  // flags
893      {0u32: "glyph_variation_data_offset"},
894
895      // OFFSETS
896      {0u16: "glyph_offset[0]"},
897      {0u16: "glyph_offset[1]"},
898      {0u16: "glyph_offset[2]"},
899      {0u16: "glyph_offset[3]"},
900      {0u16: "glyph_offset[4]"},
901      {0u16: "glyph_offset[5]"},
902      {0u16: "glyph_offset[6]"},
903      {0u16: "glyph_offset[7]"},
904      {0u16: "glyph_offset[8]"},
905      {0u16: "glyph_offset[9]"},
906      {0u16: "glyph_offset[10]"},
907      {0u16: "glyph_offset[11]"},
908      {0u16: "glyph_offset[12]"},
909      {0u16: "glyph_offset[13]"},
910      {0u16: "glyph_offset[14]"},
911      {0u16: "glyph_offset[15]"},
912
913      // SHARED TUPLES
914      {42u16: "sharedTuples[0]"},
915      13u16,
916      25u16,
917
918      // GLYPH VARIATION DATA
919      {1u8: "glyph_0"}, [2, 3, 4u8],
920      {5u8: "glyph_8"}, [6, 7, 8, 9u8], {10u8: "end"}
921    };
922
923    let offset = buffer.offset_for("sharedTuples[0]") as u32;
924    buffer.write_at("shared_tuples_offset", offset);
925
926    let data_offset = buffer.offset_for("glyph_0");
927    buffer.write_at("glyph_variation_data_offset", data_offset as u32);
928
929    let glyph0_offset = ((buffer.offset_for("glyph_0") - data_offset) / 2) as u16;
930    let glyph8_offset = ((buffer.offset_for("glyph_8") - data_offset) / 2) as u16;
931    let end_offset = ((buffer.offset_for("end") + 1 - data_offset) / 2) as u16;
932
933    buffer.write_at("glyph_offset[0]", glyph0_offset);
934    buffer.write_at("glyph_offset[1]", glyph8_offset);
935    buffer.write_at("glyph_offset[2]", glyph8_offset);
936    buffer.write_at("glyph_offset[3]", glyph8_offset);
937    buffer.write_at("glyph_offset[4]", glyph8_offset);
938    buffer.write_at("glyph_offset[5]", glyph8_offset);
939    buffer.write_at("glyph_offset[6]", glyph8_offset);
940    buffer.write_at("glyph_offset[7]", glyph8_offset);
941    buffer.write_at("glyph_offset[8]", glyph8_offset);
942    buffer.write_at("glyph_offset[9]", end_offset);
943    buffer.write_at("glyph_offset[10]", end_offset);
944    buffer.write_at("glyph_offset[11]", end_offset);
945    buffer.write_at("glyph_offset[12]", end_offset);
946    buffer.write_at("glyph_offset[13]", end_offset);
947    buffer.write_at("glyph_offset[14]", end_offset);
948    buffer.write_at("glyph_offset[15]", end_offset);
949
950    buffer
951}
952
953/// <https://learn.microsoft.com/en-us/typography/opentype/spec/gvar>
954pub fn long_gvar_with_shared_tuples() -> BeBuffer {
955    // This gvar has the correct header and tuple structure but the per glyph variation data is not valid.
956    // Meant for testing with IFT glyph keyed patching which treats the per glyph data as opaque blobs.
957    let mut buffer = be_buffer! {
958      // HEADER
959      1u16, // major version
960      0u16, // minor version
961      1u16, // axis count
962      3u16, // sharedTupleCount
963      {0u32: "shared_tuples_offset"},
964      15u16, // glyph count
965      0b00000000_00000001u16,  // flags
966      {0u32: "glyph_variation_data_offset"},
967
968      // OFFSETS
969      {0u32: "glyph_offset[0]"},
970      {0u32: "glyph_offset[1]"},
971      {0u32: "glyph_offset[2]"},
972      {0u32: "glyph_offset[3]"},
973      {0u32: "glyph_offset[4]"},
974      {0u32: "glyph_offset[5]"},
975      {0u32: "glyph_offset[6]"},
976      {0u32: "glyph_offset[7]"},
977      {0u32: "glyph_offset[8]"},
978      {0u32: "glyph_offset[9]"},
979      {0u32: "glyph_offset[10]"},
980      {0u32: "glyph_offset[11]"},
981      {0u32: "glyph_offset[12]"},
982      {0u32: "glyph_offset[13]"},
983      {0u32: "glyph_offset[14]"},
984      {0u32: "glyph_offset[15]"},
985
986      // SHARED TUPLES
987      {42u16: "sharedTuples[0]"},
988      13u16,
989      25u16,
990
991      // GLYPH VARIATION DATA
992      {1u8: "glyph_0"}, [2, 3, 4u8],
993      {5u8: "glyph_8"}, [6, 7, 8, 9u8], {10u8: "end"}
994    };
995
996    let offset = buffer.offset_for("sharedTuples[0]") as u32;
997    buffer.write_at("shared_tuples_offset", offset);
998
999    let data_offset = buffer.offset_for("glyph_0");
1000    buffer.write_at("glyph_variation_data_offset", data_offset as u32);
1001
1002    let glyph0_offset = (buffer.offset_for("glyph_0") - data_offset) as u32;
1003    let glyph8_offset = (buffer.offset_for("glyph_8") - data_offset) as u32;
1004    let end_offset = (buffer.offset_for("end") + 1 - data_offset) as u32;
1005
1006    buffer.write_at("glyph_offset[0]", glyph0_offset);
1007    buffer.write_at("glyph_offset[1]", glyph8_offset);
1008    buffer.write_at("glyph_offset[2]", glyph8_offset);
1009    buffer.write_at("glyph_offset[3]", glyph8_offset);
1010    buffer.write_at("glyph_offset[4]", glyph8_offset);
1011    buffer.write_at("glyph_offset[5]", glyph8_offset);
1012    buffer.write_at("glyph_offset[6]", glyph8_offset);
1013    buffer.write_at("glyph_offset[7]", glyph8_offset);
1014    buffer.write_at("glyph_offset[8]", glyph8_offset);
1015    buffer.write_at("glyph_offset[9]", end_offset);
1016    buffer.write_at("glyph_offset[10]", end_offset);
1017    buffer.write_at("glyph_offset[11]", end_offset);
1018    buffer.write_at("glyph_offset[12]", end_offset);
1019    buffer.write_at("glyph_offset[13]", end_offset);
1020    buffer.write_at("glyph_offset[14]", end_offset);
1021    buffer.write_at("glyph_offset[15]", end_offset);
1022
1023    buffer
1024}
1025
1026pub fn short_gvar_with_no_shared_tuples() -> BeBuffer {
1027    // This gvar has the correct header and tuple structure but the per glyph variation data is not valid.
1028    // Meant for testing with IFT glyph keyed patching which treats the per glyph data as opaque blobs.
1029    let mut buffer = be_buffer! {
1030      // HEADER
1031      1u16,  // major version
1032      0u16,  // minor version
1033      1u16,  // axis count
1034      {0u16: "shared_tuple_count"},
1035      {0u32: "shared_tuples_offset"},
1036      15u16, // glyph count
1037      0u16,  // flags
1038      {0u32: "glyph_variation_data_offset"},
1039
1040      // OFFSETS
1041      {0u16: "glyph_offset[0]"},
1042      {0u16: "glyph_offset[1]"},
1043      {0u16: "glyph_offset[2]"},
1044      {0u16: "glyph_offset[3]"},
1045      {0u16: "glyph_offset[4]"},
1046      {0u16: "glyph_offset[5]"},
1047      {0u16: "glyph_offset[6]"},
1048      {0u16: "glyph_offset[7]"},
1049      {0u16: "glyph_offset[8]"},
1050      {0u16: "glyph_offset[9]"},
1051      {0u16: "glyph_offset[10]"},
1052      {0u16: "glyph_offset[11]"},
1053      {0u16: "glyph_offset[12]"},
1054      {0u16: "glyph_offset[13]"},
1055      {0u16: "glyph_offset[14]"},
1056      {0u16: "glyph_offset[15]"},
1057
1058      // GLYPH VARIATION DATA
1059      {1u8: "glyph_0"}, [2, 3, 4u8],
1060      {5u8: "glyph_8"}, [6, 7, 8, 9u8], {10u8: "end"}
1061    };
1062
1063    let data_offset = buffer.offset_for("glyph_0");
1064    buffer.write_at("shared_tuples_offset", data_offset as u32);
1065    buffer.write_at("glyph_variation_data_offset", data_offset as u32);
1066
1067    let glyph0_offset = ((buffer.offset_for("glyph_0") - data_offset) / 2) as u16;
1068    let glyph8_offset = ((buffer.offset_for("glyph_8") - data_offset) / 2) as u16;
1069    let end_offset = ((buffer.offset_for("end") + 1 - data_offset) / 2) as u16;
1070
1071    buffer.write_at("glyph_offset[0]", glyph0_offset);
1072    buffer.write_at("glyph_offset[1]", glyph8_offset);
1073    buffer.write_at("glyph_offset[2]", glyph8_offset);
1074    buffer.write_at("glyph_offset[3]", glyph8_offset);
1075    buffer.write_at("glyph_offset[4]", glyph8_offset);
1076    buffer.write_at("glyph_offset[5]", glyph8_offset);
1077    buffer.write_at("glyph_offset[6]", glyph8_offset);
1078    buffer.write_at("glyph_offset[7]", glyph8_offset);
1079    buffer.write_at("glyph_offset[8]", glyph8_offset);
1080    buffer.write_at("glyph_offset[9]", end_offset);
1081    buffer.write_at("glyph_offset[10]", end_offset);
1082    buffer.write_at("glyph_offset[11]", end_offset);
1083    buffer.write_at("glyph_offset[12]", end_offset);
1084    buffer.write_at("glyph_offset[13]", end_offset);
1085    buffer.write_at("glyph_offset[14]", end_offset);
1086    buffer.write_at("glyph_offset[15]", end_offset);
1087
1088    buffer
1089}
1090
1091pub fn short_gvar_near_maximum_offset_size() -> BeBuffer {
1092    // This is a short offset gvar table whose glyph data is at the maximum representable size with short offsets
1093
1094    // This gvar has the correct header and tuple structure but the per glyph variation data is not valid.
1095    // Meant for testing with IFT glyph keyed patching which treats the per glyph data as opaque blobs.
1096    let buffer = be_buffer! {
1097      // HEADER
1098      1u16,  // major version
1099      0u16,  // minor version
1100      1u16,  // axis count
1101      {0u16: "shared_tuple_count"},
1102      {0u32: "shared_tuples_offset"},
1103      15u16, // glyph count
1104      0u16,  // flags
1105      {0u32: "glyph_variation_data_offset"},
1106
1107      // OFFSETS
1108      {0u16: "glyph_offset[0]"},
1109      {0u16: "glyph_offset[1]"},
1110      {0u16: "glyph_offset[2]"},
1111      {0u16: "glyph_offset[3]"},
1112      {0u16: "glyph_offset[4]"},
1113      {0u16: "glyph_offset[5]"},
1114      {0u16: "glyph_offset[6]"},
1115      {0u16: "glyph_offset[7]"},
1116      {0u16: "glyph_offset[8]"},
1117      {0u16: "glyph_offset[9]"},
1118      {0u16: "glyph_offset[10]"},
1119      {0u16: "glyph_offset[11]"},
1120      {0u16: "glyph_offset[12]"},
1121      {0u16: "glyph_offset[13]"},
1122      {0u16: "glyph_offset[14]"},
1123      {0u16: "glyph_offset[15]"},
1124
1125      // GLYPH VARIATION DATA
1126      {1u8: "glyph_0"}
1127    };
1128
1129    // Glyph 0
1130    let mut buffer = buffer.extend(iter::repeat_n(1u8, 131065));
1131
1132    let data_offset = buffer.offset_for("glyph_0");
1133    buffer.write_at("shared_tuples_offset", data_offset as u32);
1134    buffer.write_at("glyph_variation_data_offset", data_offset as u32);
1135
1136    buffer.write_at("glyph_offset[0]", 0u16);
1137    buffer.write_at("glyph_offset[1]", 65533u16);
1138    buffer.write_at("glyph_offset[2]", 65533u16);
1139    buffer.write_at("glyph_offset[3]", 65533u16);
1140    buffer.write_at("glyph_offset[4]", 65533u16);
1141    buffer.write_at("glyph_offset[5]", 65533u16);
1142    buffer.write_at("glyph_offset[6]", 65533u16);
1143    buffer.write_at("glyph_offset[7]", 65533u16);
1144    buffer.write_at("glyph_offset[8]", 65533u16);
1145    buffer.write_at("glyph_offset[9]", 65533u16);
1146    buffer.write_at("glyph_offset[10]", 65533u16);
1147    buffer.write_at("glyph_offset[11]", 65533u16);
1148    buffer.write_at("glyph_offset[12]", 65533u16);
1149    buffer.write_at("glyph_offset[13]", 65533u16);
1150    buffer.write_at("glyph_offset[14]", 65533u16);
1151    buffer.write_at("glyph_offset[15]", 65533u16);
1152
1153    buffer
1154}
1155
1156/// <https://learn.microsoft.com/en-us/typography/opentype/spec/gvar>
1157pub fn out_of_order_gvar_with_shared_tuples() -> BeBuffer {
1158    let mut buffer = be_buffer! {
1159      // HEADER
1160      1u16, // major version
1161      0u16, // minor version
1162      1u16, // axis count
1163      3u16, // sharedTupleCount
1164      {0u32: "shared_tuples_offset"},
1165      15u16, // glyph count
1166      0u16,  // flags
1167      {0u32: "glyph_variation_data_offset"},
1168
1169      // OFFSETS
1170      {0u16: "glyph_offset[0]"},
1171      {0u16: "glyph_offset[1]"},
1172      {0u16: "glyph_offset[2]"},
1173      {0u16: "glyph_offset[3]"},
1174      {0u16: "glyph_offset[4]"},
1175      {0u16: "glyph_offset[5]"},
1176      {0u16: "glyph_offset[6]"},
1177      {0u16: "glyph_offset[7]"},
1178      {0u16: "glyph_offset[8]"},
1179      {0u16: "glyph_offset[9]"},
1180      {0u16: "glyph_offset[10]"},
1181      {0u16: "glyph_offset[11]"},
1182      {0u16: "glyph_offset[12]"},
1183      {0u16: "glyph_offset[13]"},
1184      {0u16: "glyph_offset[14]"},
1185      {0u16: "glyph_offset[15]"},
1186
1187      // GLYPH VARIATION DATA
1188      {1u8: "glyph_0"}, [2, 3, 4u8],
1189      {5u8: "glyph_8"}, [6, 7, 8, 9u8], {10u8: "end"},
1190
1191      // SHARED TUPLES
1192      {42u16: "sharedTuples[0]"},
1193      13u16,
1194      25u16
1195    };
1196
1197    let offset = buffer.offset_for("sharedTuples[0]") as u32;
1198    buffer.write_at("shared_tuples_offset", offset);
1199
1200    let data_offset = buffer.offset_for("glyph_0");
1201    buffer.write_at("glyph_variation_data_offset", data_offset as u32);
1202
1203    let glyph0_offset = ((buffer.offset_for("glyph_0") - data_offset) / 2) as u16;
1204    let glyph8_offset = ((buffer.offset_for("glyph_8") - data_offset) / 2) as u16;
1205    let end_offset = ((buffer.offset_for("end") + 1 - data_offset) / 2) as u16;
1206
1207    buffer.write_at("glyph_offset[0]", glyph0_offset);
1208    buffer.write_at("glyph_offset[1]", glyph8_offset);
1209    buffer.write_at("glyph_offset[2]", glyph8_offset);
1210    buffer.write_at("glyph_offset[3]", glyph8_offset);
1211    buffer.write_at("glyph_offset[4]", glyph8_offset);
1212    buffer.write_at("glyph_offset[5]", glyph8_offset);
1213    buffer.write_at("glyph_offset[6]", glyph8_offset);
1214    buffer.write_at("glyph_offset[7]", glyph8_offset);
1215    buffer.write_at("glyph_offset[8]", glyph8_offset);
1216    buffer.write_at("glyph_offset[9]", end_offset);
1217    buffer.write_at("glyph_offset[10]", end_offset);
1218    buffer.write_at("glyph_offset[11]", end_offset);
1219    buffer.write_at("glyph_offset[12]", end_offset);
1220    buffer.write_at("glyph_offset[13]", end_offset);
1221    buffer.write_at("glyph_offset[14]", end_offset);
1222    buffer.write_at("glyph_offset[15]", end_offset);
1223
1224    buffer
1225}