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