lib/filigree/src/fixture/substitution.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const binary = @import("binary.zig");
  3 const layout_fixture = @import("layout.zig");
  4 
  5 const appendI16 = binary.appendI16;
  6 const appendTag = binary.appendTag;
  7 const appendU16 = binary.appendU16;
  8 const appendU24 = binary.appendU24;
  9 const appendU32 = binary.appendU32;
 10 const writeU16 = binary.writeU16;
 11 const writeU32 = binary.writeU32;
 12 
 13 const appendLayoutFeatureList = layout_fixture.appendLayoutFeatureList;
 14 const appendLayoutFeatureListFour = layout_fixture.appendLayoutFeatureListFour;
 15 const appendLayoutFeatureListPair = layout_fixture.appendLayoutFeatureListPair;
 16 const appendLayoutFeatureListWithLookups = layout_fixture.appendLayoutFeatureListWithLookups;
 17 const appendLayoutFeatureVariations = layout_fixture.appendLayoutFeatureVariations;
 18 const appendLayoutFeatureVariationsWithLookups = layout_fixture.appendLayoutFeatureVariationsWithLookups;
 19 const appendLayoutScriptList = layout_fixture.appendLayoutScriptList;
 20 const appendLayoutScriptListWithFeatures = layout_fixture.appendLayoutScriptListWithFeatures;
 21 
 22 pub fn appendGsubSingleSubstitution(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8), lookup_flag: u16) !void {
 23     try appendU16(allocator, out, 1);
 24     try appendU16(allocator, out, 0);
 25     try appendU16(allocator, out, 10);
 26     try appendU16(allocator, out, 28);
 27     try appendU16(allocator, out, 42);
 28 
 29     try appendU16(allocator, out, 1);
 30     try appendTag(allocator, out, "DFLT");
 31     try appendU16(allocator, out, 8);
 32 
 33     try appendU16(allocator, out, 4);
 34     try appendU16(allocator, out, 0);
 35 
 36     try appendU16(allocator, out, 0);
 37     try appendU16(allocator, out, 0);
 38     try appendU16(allocator, out, 0);
 39 
 40     try appendU16(allocator, out, 1);
 41     try appendTag(allocator, out, "rlig");
 42     try appendU16(allocator, out, 8);
 43 
 44     try appendU16(allocator, out, 0);
 45     try appendU16(allocator, out, 1);
 46     try appendU16(allocator, out, 0);
 47 
 48     try appendU16(allocator, out, 1);
 49     try appendU16(allocator, out, 4);
 50 
 51     try appendU16(allocator, out, 1);
 52     try appendU16(allocator, out, lookup_flag);
 53     try appendU16(allocator, out, 1);
 54     try appendU16(allocator, out, 8);
 55 
 56     try appendU16(allocator, out, 2);
 57     try appendU16(allocator, out, 8);
 58     try appendU16(allocator, out, 1);
 59     try appendU16(allocator, out, 'Z' - 31);
 60 
 61     try appendU16(allocator, out, 1);
 62     try appendU16(allocator, out, 1);
 63     try appendU16(allocator, out, 'A' - 31);
 64 }
 65 
 66 pub fn appendGsubAlternateSubstitution(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
 67     try appendU16(allocator, out, 1);
 68     try appendU16(allocator, out, 0);
 69     try appendU16(allocator, out, 10);
 70     try appendU16(allocator, out, 30);
 71     try appendU16(allocator, out, 44);
 72 
 73     try appendU16(allocator, out, 1);
 74     try appendTag(allocator, out, "DFLT");
 75     try appendU16(allocator, out, 8);
 76 
 77     try appendU16(allocator, out, 4);
 78     try appendU16(allocator, out, 0);
 79 
 80     try appendU16(allocator, out, 0);
 81     try appendU16(allocator, out, 0xffff);
 82     try appendU16(allocator, out, 1);
 83     try appendU16(allocator, out, 0);
 84 
 85     try appendU16(allocator, out, 1);
 86     try appendTag(allocator, out, "rlig");
 87     try appendU16(allocator, out, 8);
 88 
 89     try appendU16(allocator, out, 0);
 90     try appendU16(allocator, out, 1);
 91     try appendU16(allocator, out, 0);
 92 
 93     try appendU16(allocator, out, 1);
 94     try appendU16(allocator, out, 4);
 95 
 96     try appendU16(allocator, out, 3);
 97     try appendU16(allocator, out, 0);
 98     try appendU16(allocator, out, 1);
 99     try appendU16(allocator, out, 8);
100 
101     try appendU16(allocator, out, 1);
102     try appendU16(allocator, out, 14);
103     try appendU16(allocator, out, 1);
104     try appendU16(allocator, out, 8);
105 
106     try appendU16(allocator, out, 2);
107     try appendU16(allocator, out, 96);
108     try appendU16(allocator, out, 'Z' - 31);
109 
110     try appendU16(allocator, out, 1);
111     try appendU16(allocator, out, 1);
112     try appendU16(allocator, out, 'A' - 31);
113 }
114 
115 pub fn appendGsubContextualSubstitution(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
116     try appendGsubContextualFeature(allocator, out, "rlig");
117 }
118 
119 pub fn appendGsubContextualAlternates(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
120     try appendGsubContextualFeature(allocator, out, "calt");
121 }
122 
123 pub fn appendGsubRequiredContextualAlternates(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
124     try appendGsubContextualFeature(allocator, out, "rclt");
125 }
126 
127 pub fn appendGsubContextualFeature(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8), comptime feature_tag: []const u8) !void {
128     try appendU16(allocator, out, 1);
129     try appendU16(allocator, out, 0);
130     try appendU16(allocator, out, 10);
131     try appendU16(allocator, out, 30);
132     try appendU16(allocator, out, 44);
133 
134     try appendU16(allocator, out, 1);
135     try appendTag(allocator, out, "DFLT");
136     try appendU16(allocator, out, 8);
137 
138     try appendU16(allocator, out, 4);
139     try appendU16(allocator, out, 0);
140 
141     try appendU16(allocator, out, 0);
142     try appendU16(allocator, out, 0xffff);
143     try appendU16(allocator, out, 1);
144     try appendU16(allocator, out, 0);
145 
146     try appendU16(allocator, out, 1);
147     try appendTag(allocator, out, feature_tag);
148     try appendU16(allocator, out, 8);
149 
150     try appendU16(allocator, out, 0);
151     try appendU16(allocator, out, 1);
152     try appendU16(allocator, out, 0);
153 
154     try appendU16(allocator, out, 2);
155     try appendU16(allocator, out, 6);
156     try appendU16(allocator, out, 44);
157 
158     try appendU16(allocator, out, 5);
159     try appendU16(allocator, out, 0);
160     try appendU16(allocator, out, 1);
161     try appendU16(allocator, out, 8);
162 
163     try appendU16(allocator, out, 1);
164     try appendU16(allocator, out, 8);
165     try appendU16(allocator, out, 1);
166     try appendU16(allocator, out, 14);
167 
168     try appendU16(allocator, out, 1);
169     try appendU16(allocator, out, 1);
170     try appendU16(allocator, out, 'A' - 31);
171 
172     try appendU16(allocator, out, 1);
173     try appendU16(allocator, out, 4);
174 
175     try appendU16(allocator, out, 3);
176     try appendU16(allocator, out, 1);
177     try appendU16(allocator, out, 'B' - 31);
178     try appendU16(allocator, out, 'C' - 31);
179     try appendU16(allocator, out, 1);
180     try appendU16(allocator, out, 1);
181 
182     try appendU16(allocator, out, 1);
183     try appendU16(allocator, out, 0);
184     try appendU16(allocator, out, 1);
185     try appendU16(allocator, out, 8);
186 
187     try appendU16(allocator, out, 2);
188     try appendU16(allocator, out, 8);
189     try appendU16(allocator, out, 1);
190     try appendU16(allocator, out, 'Z' - 31);
191 
192     try appendU16(allocator, out, 1);
193     try appendU16(allocator, out, 1);
194     try appendU16(allocator, out, 'B' - 31);
195 }
196 
197 pub fn appendGsubClassContextualSubstitution(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
198     try appendU16(allocator, out, 1);
199     try appendU16(allocator, out, 0);
200     try appendU16(allocator, out, 10);
201     try appendU16(allocator, out, 30);
202     try appendU16(allocator, out, 44);
203 
204     try appendU16(allocator, out, 1);
205     try appendTag(allocator, out, "DFLT");
206     try appendU16(allocator, out, 8);
207 
208     try appendU16(allocator, out, 4);
209     try appendU16(allocator, out, 0);
210 
211     try appendU16(allocator, out, 0);
212     try appendU16(allocator, out, 0xffff);
213     try appendU16(allocator, out, 1);
214     try appendU16(allocator, out, 0);
215 
216     try appendU16(allocator, out, 1);
217     try appendTag(allocator, out, "rlig");
218     try appendU16(allocator, out, 8);
219 
220     try appendU16(allocator, out, 0);
221     try appendU16(allocator, out, 1);
222     try appendU16(allocator, out, 0);
223 
224     try appendU16(allocator, out, 2);
225     try appendU16(allocator, out, 6);
226     try appendU16(allocator, out, 64);
227 
228     try appendU16(allocator, out, 5);
229     try appendU16(allocator, out, 0);
230     try appendU16(allocator, out, 1);
231     try appendU16(allocator, out, 8);
232 
233     try appendU16(allocator, out, 2);
234     try appendU16(allocator, out, 16);
235     try appendU16(allocator, out, 22);
236     try appendU16(allocator, out, 4);
237     try appendU16(allocator, out, 0);
238     try appendU16(allocator, out, 34);
239     try appendU16(allocator, out, 0);
240     try appendU16(allocator, out, 0);
241 
242     try appendU16(allocator, out, 1);
243     try appendU16(allocator, out, 1);
244     try appendU16(allocator, out, 'A' - 31);
245 
246     try appendU16(allocator, out, 1);
247     try appendU16(allocator, out, 'A' - 31);
248     try appendU16(allocator, out, 3);
249     try appendU16(allocator, out, 1);
250     try appendU16(allocator, out, 2);
251     try appendU16(allocator, out, 3);
252 
253     try appendU16(allocator, out, 1);
254     try appendU16(allocator, out, 4);
255 
256     try appendU16(allocator, out, 3);
257     try appendU16(allocator, out, 1);
258     try appendU16(allocator, out, 2);
259     try appendU16(allocator, out, 3);
260     try appendU16(allocator, out, 1);
261     try appendU16(allocator, out, 1);
262 
263     try appendU16(allocator, out, 1);
264     try appendU16(allocator, out, 0);
265     try appendU16(allocator, out, 1);
266     try appendU16(allocator, out, 8);
267 
268     try appendU16(allocator, out, 2);
269     try appendU16(allocator, out, 8);
270     try appendU16(allocator, out, 1);
271     try appendU16(allocator, out, 'Z' - 31);
272 
273     try appendU16(allocator, out, 1);
274     try appendU16(allocator, out, 1);
275     try appendU16(allocator, out, 'B' - 31);
276 }
277 
278 pub fn appendGsubCoverageContextualSubstitution(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
279     try appendU16(allocator, out, 1);
280     try appendU16(allocator, out, 0);
281     try appendU16(allocator, out, 10);
282     try appendU16(allocator, out, 30);
283     try appendU16(allocator, out, 44);
284 
285     try appendU16(allocator, out, 1);
286     try appendTag(allocator, out, "DFLT");
287     try appendU16(allocator, out, 8);
288 
289     try appendU16(allocator, out, 4);
290     try appendU16(allocator, out, 0);
291 
292     try appendU16(allocator, out, 0);
293     try appendU16(allocator, out, 0xffff);
294     try appendU16(allocator, out, 1);
295     try appendU16(allocator, out, 0);
296 
297     try appendU16(allocator, out, 1);
298     try appendTag(allocator, out, "rlig");
299     try appendU16(allocator, out, 8);
300 
301     try appendU16(allocator, out, 0);
302     try appendU16(allocator, out, 1);
303     try appendU16(allocator, out, 0);
304 
305     try appendU16(allocator, out, 2);
306     try appendU16(allocator, out, 6);
307     try appendU16(allocator, out, 48);
308 
309     try appendU16(allocator, out, 5);
310     try appendU16(allocator, out, 0);
311     try appendU16(allocator, out, 1);
312     try appendU16(allocator, out, 8);
313 
314     try appendU16(allocator, out, 3);
315     try appendU16(allocator, out, 3);
316     try appendU16(allocator, out, 1);
317     try appendU16(allocator, out, 16);
318     try appendU16(allocator, out, 22);
319     try appendU16(allocator, out, 28);
320     try appendU16(allocator, out, 1);
321     try appendU16(allocator, out, 1);
322 
323     try appendU16(allocator, out, 1);
324     try appendU16(allocator, out, 1);
325     try appendU16(allocator, out, 'A' - 31);
326 
327     try appendU16(allocator, out, 1);
328     try appendU16(allocator, out, 1);
329     try appendU16(allocator, out, 'B' - 31);
330 
331     try appendU16(allocator, out, 1);
332     try appendU16(allocator, out, 1);
333     try appendU16(allocator, out, 'C' - 31);
334 
335     try appendU16(allocator, out, 1);
336     try appendU16(allocator, out, 0);
337     try appendU16(allocator, out, 1);
338     try appendU16(allocator, out, 8);
339 
340     try appendU16(allocator, out, 2);
341     try appendU16(allocator, out, 8);
342     try appendU16(allocator, out, 1);
343     try appendU16(allocator, out, 'Z' - 31);
344 
345     try appendU16(allocator, out, 1);
346     try appendU16(allocator, out, 1);
347     try appendU16(allocator, out, 'B' - 31);
348 }
349 
350 pub fn appendGsubChainedSimpleContextualSubstitution(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
351     try appendU16(allocator, out, 1);
352     try appendU16(allocator, out, 0);
353     try appendU16(allocator, out, 10);
354     try appendU16(allocator, out, 30);
355     try appendU16(allocator, out, 44);
356 
357     try appendU16(allocator, out, 1);
358     try appendTag(allocator, out, "DFLT");
359     try appendU16(allocator, out, 8);
360 
361     try appendU16(allocator, out, 4);
362     try appendU16(allocator, out, 0);
363 
364     try appendU16(allocator, out, 0);
365     try appendU16(allocator, out, 0xffff);
366     try appendU16(allocator, out, 1);
367     try appendU16(allocator, out, 0);
368 
369     try appendU16(allocator, out, 1);
370     try appendTag(allocator, out, "rlig");
371     try appendU16(allocator, out, 8);
372 
373     try appendU16(allocator, out, 0);
374     try appendU16(allocator, out, 1);
375     try appendU16(allocator, out, 0);
376 
377     try appendU16(allocator, out, 2);
378     try appendU16(allocator, out, 6);
379     try appendU16(allocator, out, 48);
380 
381     try appendU16(allocator, out, 6);
382     try appendU16(allocator, out, 0);
383     try appendU16(allocator, out, 1);
384     try appendU16(allocator, out, 8);
385 
386     try appendU16(allocator, out, 1);
387     try appendU16(allocator, out, 8);
388     try appendU16(allocator, out, 1);
389     try appendU16(allocator, out, 14);
390 
391     try appendU16(allocator, out, 1);
392     try appendU16(allocator, out, 1);
393     try appendU16(allocator, out, 'B' - 31);
394 
395     try appendU16(allocator, out, 1);
396     try appendU16(allocator, out, 4);
397 
398     try appendU16(allocator, out, 1);
399     try appendU16(allocator, out, 'A' - 31);
400     try appendU16(allocator, out, 1);
401     try appendU16(allocator, out, 1);
402     try appendU16(allocator, out, 'C' - 31);
403     try appendU16(allocator, out, 1);
404     try appendU16(allocator, out, 0);
405     try appendU16(allocator, out, 1);
406 
407     try appendU16(allocator, out, 1);
408     try appendU16(allocator, out, 0);
409     try appendU16(allocator, out, 1);
410     try appendU16(allocator, out, 8);
411 
412     try appendU16(allocator, out, 2);
413     try appendU16(allocator, out, 8);
414     try appendU16(allocator, out, 1);
415     try appendU16(allocator, out, 'Z' - 31);
416 
417     try appendU16(allocator, out, 1);
418     try appendU16(allocator, out, 1);
419     try appendU16(allocator, out, 'B' - 31);
420 }
421 
422 pub fn appendGsubChainedContextualSubstitution(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
423     try appendU16(allocator, out, 1);
424     try appendU16(allocator, out, 0);
425     try appendU16(allocator, out, 10);
426     try appendU16(allocator, out, 30);
427     try appendU16(allocator, out, 44);
428 
429     try appendU16(allocator, out, 1);
430     try appendTag(allocator, out, "DFLT");
431     try appendU16(allocator, out, 8);
432 
433     try appendU16(allocator, out, 4);
434     try appendU16(allocator, out, 0);
435 
436     try appendU16(allocator, out, 0);
437     try appendU16(allocator, out, 0xffff);
438     try appendU16(allocator, out, 1);
439     try appendU16(allocator, out, 0);
440 
441     try appendU16(allocator, out, 1);
442     try appendTag(allocator, out, "rlig");
443     try appendU16(allocator, out, 8);
444 
445     try appendU16(allocator, out, 0);
446     try appendU16(allocator, out, 1);
447     try appendU16(allocator, out, 0);
448 
449     try appendU16(allocator, out, 2);
450     try appendU16(allocator, out, 6);
451     try appendU16(allocator, out, 52);
452 
453     try appendU16(allocator, out, 6);
454     try appendU16(allocator, out, 0);
455     try appendU16(allocator, out, 1);
456     try appendU16(allocator, out, 8);
457 
458     try appendU16(allocator, out, 3);
459     try appendU16(allocator, out, 1);
460     try appendU16(allocator, out, 20);
461     try appendU16(allocator, out, 1);
462     try appendU16(allocator, out, 26);
463     try appendU16(allocator, out, 1);
464     try appendU16(allocator, out, 32);
465     try appendU16(allocator, out, 1);
466     try appendU16(allocator, out, 0);
467     try appendU16(allocator, out, 1);
468 
469     try appendU16(allocator, out, 1);
470     try appendU16(allocator, out, 1);
471     try appendU16(allocator, out, 'A' - 31);
472 
473     try appendU16(allocator, out, 1);
474     try appendU16(allocator, out, 1);
475     try appendU16(allocator, out, 'B' - 31);
476 
477     try appendU16(allocator, out, 1);
478     try appendU16(allocator, out, 1);
479     try appendU16(allocator, out, 'C' - 31);
480 
481     try appendU16(allocator, out, 1);
482     try appendU16(allocator, out, 0);
483     try appendU16(allocator, out, 1);
484     try appendU16(allocator, out, 8);
485 
486     try appendU16(allocator, out, 2);
487     try appendU16(allocator, out, 8);
488     try appendU16(allocator, out, 1);
489     try appendU16(allocator, out, 'Z' - 31);
490 
491     try appendU16(allocator, out, 1);
492     try appendU16(allocator, out, 1);
493     try appendU16(allocator, out, 'B' - 31);
494 }
495 
496 pub fn appendGsubChainedClassContextualSubstitution(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
497     try appendU16(allocator, out, 1);
498     try appendU16(allocator, out, 0);
499     try appendU16(allocator, out, 10);
500     try appendU16(allocator, out, 30);
501     try appendU16(allocator, out, 44);
502 
503     try appendU16(allocator, out, 1);
504     try appendTag(allocator, out, "DFLT");
505     try appendU16(allocator, out, 8);
506 
507     try appendU16(allocator, out, 4);
508     try appendU16(allocator, out, 0);
509 
510     try appendU16(allocator, out, 0);
511     try appendU16(allocator, out, 0xffff);
512     try appendU16(allocator, out, 1);
513     try appendU16(allocator, out, 0);
514 
515     try appendU16(allocator, out, 1);
516     try appendTag(allocator, out, "rlig");
517     try appendU16(allocator, out, 8);
518 
519     try appendU16(allocator, out, 0);
520     try appendU16(allocator, out, 1);
521     try appendU16(allocator, out, 0);
522 
523     try appendU16(allocator, out, 2);
524     try appendU16(allocator, out, 6);
525     try appendU16(allocator, out, 82);
526 
527     try appendU16(allocator, out, 6);
528     try appendU16(allocator, out, 0);
529     try appendU16(allocator, out, 1);
530     try appendU16(allocator, out, 8);
531 
532     try appendU16(allocator, out, 2);
533     try appendU16(allocator, out, 18);
534     try appendU16(allocator, out, 24);
535     try appendU16(allocator, out, 32);
536     try appendU16(allocator, out, 40);
537     try appendU16(allocator, out, 3);
538     try appendU16(allocator, out, 0);
539     try appendU16(allocator, out, 0);
540     try appendU16(allocator, out, 48);
541 
542     try appendU16(allocator, out, 1);
543     try appendU16(allocator, out, 1);
544     try appendU16(allocator, out, 'B' - 31);
545 
546     try appendU16(allocator, out, 1);
547     try appendU16(allocator, out, 'A' - 31);
548     try appendU16(allocator, out, 1);
549     try appendU16(allocator, out, 1);
550 
551     try appendU16(allocator, out, 1);
552     try appendU16(allocator, out, 'B' - 31);
553     try appendU16(allocator, out, 1);
554     try appendU16(allocator, out, 2);
555 
556     try appendU16(allocator, out, 1);
557     try appendU16(allocator, out, 'C' - 31);
558     try appendU16(allocator, out, 1);
559     try appendU16(allocator, out, 3);
560 
561     try appendU16(allocator, out, 1);
562     try appendU16(allocator, out, 4);
563 
564     try appendU16(allocator, out, 1);
565     try appendU16(allocator, out, 1);
566     try appendU16(allocator, out, 1);
567     try appendU16(allocator, out, 1);
568     try appendU16(allocator, out, 3);
569     try appendU16(allocator, out, 1);
570     try appendU16(allocator, out, 0);
571     try appendU16(allocator, out, 1);
572 
573     try appendU16(allocator, out, 1);
574     try appendU16(allocator, out, 0);
575     try appendU16(allocator, out, 1);
576     try appendU16(allocator, out, 8);
577 
578     try appendU16(allocator, out, 2);
579     try appendU16(allocator, out, 8);
580     try appendU16(allocator, out, 1);
581     try appendU16(allocator, out, 'Z' - 31);
582 
583     try appendU16(allocator, out, 1);
584     try appendU16(allocator, out, 1);
585     try appendU16(allocator, out, 'B' - 31);
586 }
587 
588 pub fn appendGsubLigature(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
589     try appendGsubLigatureFeature(allocator, out, "liga");
590 }
591 
592 pub fn appendGsubContextualLigature(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
593     try appendGsubLigatureFeature(allocator, out, "clig");
594 }
595 
596 pub fn appendGsubLigatureFeature(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8), comptime feature_tag: []const u8) !void {
597     try appendU16(allocator, out, 1);
598     try appendU16(allocator, out, 0);
599     try appendU16(allocator, out, 10);
600     try appendU16(allocator, out, 30);
601     try appendU16(allocator, out, 44);
602 
603     try appendU16(allocator, out, 1);
604     try appendTag(allocator, out, "DFLT");
605     try appendU16(allocator, out, 8);
606 
607     try appendU16(allocator, out, 4);
608     try appendU16(allocator, out, 0);
609 
610     try appendU16(allocator, out, 0);
611     try appendU16(allocator, out, 0xffff);
612     try appendU16(allocator, out, 1);
613     try appendU16(allocator, out, 0);
614 
615     try appendU16(allocator, out, 1);
616     try appendTag(allocator, out, feature_tag);
617     try appendU16(allocator, out, 8);
618 
619     try appendU16(allocator, out, 0);
620     try appendU16(allocator, out, 1);
621     try appendU16(allocator, out, 0);
622 
623     try appendU16(allocator, out, 1);
624     try appendU16(allocator, out, 4);
625 
626     try appendGsubLigatureLookup(allocator, out);
627 }
628 
629 pub fn appendGsubLigatureLookup(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
630     try appendU16(allocator, out, 4);
631     try appendU16(allocator, out, 0);
632     try appendU16(allocator, out, 1);
633     try appendU16(allocator, out, 8);
634 
635     try appendU16(allocator, out, 1);
636     try appendU16(allocator, out, 18);
637     try appendU16(allocator, out, 1);
638     try appendU16(allocator, out, 8);
639 
640     try appendU16(allocator, out, 1);
641     try appendU16(allocator, out, 4);
642 
643     try appendU16(allocator, out, 96);
644     try appendU16(allocator, out, 2);
645     try appendU16(allocator, out, 'i' - 31);
646 
647     try appendU16(allocator, out, 1);
648     try appendU16(allocator, out, 1);
649     try appendU16(allocator, out, 'f' - 31);
650 }
651 
652 pub fn appendGsubMultipleSubstitution(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
653     try appendU16(allocator, out, 1);
654     try appendU16(allocator, out, 0);
655     try appendU16(allocator, out, 10);
656     try appendU16(allocator, out, 30);
657     try appendU16(allocator, out, 44);
658 
659     try appendU16(allocator, out, 1);
660     try appendTag(allocator, out, "DFLT");
661     try appendU16(allocator, out, 8);
662 
663     try appendU16(allocator, out, 4);
664     try appendU16(allocator, out, 0);
665 
666     try appendU16(allocator, out, 0);
667     try appendU16(allocator, out, 0xffff);
668     try appendU16(allocator, out, 1);
669     try appendU16(allocator, out, 0);
670 
671     try appendU16(allocator, out, 1);
672     try appendTag(allocator, out, "ccmp");
673     try appendU16(allocator, out, 8);
674 
675     try appendU16(allocator, out, 0);
676     try appendU16(allocator, out, 1);
677     try appendU16(allocator, out, 0);
678 
679     try appendU16(allocator, out, 1);
680     try appendU16(allocator, out, 4);
681 
682     try appendU16(allocator, out, 2);
683     try appendU16(allocator, out, 0);
684     try appendU16(allocator, out, 1);
685     try appendU16(allocator, out, 8);
686 
687     try appendU16(allocator, out, 1);
688     try appendU16(allocator, out, 14);
689     try appendU16(allocator, out, 1);
690     try appendU16(allocator, out, 8);
691 
692     try appendU16(allocator, out, 2);
693     try appendU16(allocator, out, 'X' - 31);
694     try appendU16(allocator, out, 'Y' - 31);
695 
696     try appendU16(allocator, out, 1);
697     try appendU16(allocator, out, 1);
698     try appendU16(allocator, out, 'A' - 31);
699 }
700 
701 pub fn appendGsubReverseChainingSingleSubstitution(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
702     try appendU16(allocator, out, 1);
703     try appendU16(allocator, out, 0);
704     try appendU16(allocator, out, 10);
705     try appendU16(allocator, out, 30);
706     try appendU16(allocator, out, 44);
707 
708     try appendU16(allocator, out, 1);
709     try appendTag(allocator, out, "DFLT");
710     try appendU16(allocator, out, 8);
711 
712     try appendU16(allocator, out, 4);
713     try appendU16(allocator, out, 0);
714 
715     try appendU16(allocator, out, 0);
716     try appendU16(allocator, out, 0xffff);
717     try appendU16(allocator, out, 1);
718     try appendU16(allocator, out, 0);
719 
720     try appendU16(allocator, out, 1);
721     try appendTag(allocator, out, "rlig");
722     try appendU16(allocator, out, 8);
723 
724     try appendU16(allocator, out, 0);
725     try appendU16(allocator, out, 1);
726     try appendU16(allocator, out, 0);
727 
728     try appendU16(allocator, out, 1);
729     try appendU16(allocator, out, 4);
730 
731     try appendU16(allocator, out, 8);
732     try appendU16(allocator, out, 0);
733     try appendU16(allocator, out, 1);
734     try appendU16(allocator, out, 8);
735 
736     try appendU16(allocator, out, 1);
737     try appendU16(allocator, out, 14);
738     try appendU16(allocator, out, 0);
739     try appendU16(allocator, out, 1);
740     try appendU16(allocator, out, 20);
741     try appendU16(allocator, out, 1);
742     try appendU16(allocator, out, 'B' - 31);
743 
744     try appendU16(allocator, out, 1);
745     try appendU16(allocator, out, 1);
746     try appendU16(allocator, out, 'A' - 31);
747 
748     try appendU16(allocator, out, 1);
749     try appendU16(allocator, out, 1);
750     try appendU16(allocator, out, 'A' - 31);
751 }
752 
753 pub fn appendGsubFeatureVariations(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
754     const header = out.items.len;
755     try appendU16(allocator, out, 1);
756     try appendU16(allocator, out, 1);
757     try appendU16(allocator, out, 0);
758     try appendU16(allocator, out, 0);
759     try appendU16(allocator, out, 0);
760     try appendU32(allocator, out, 0);
761 
762     const script_list = out.items.len;
763     writeU16(out.items, header + 4, @intCast(script_list - header));
764     try appendLayoutScriptList(allocator, out);
765 
766     const feature_list = out.items.len;
767     writeU16(out.items, header + 6, @intCast(feature_list - header));
768     try appendLayoutFeatureList(allocator, out, "rlig", 0);
769 
770     const lookup_list = out.items.len;
771     writeU16(out.items, header + 8, @intCast(lookup_list - header));
772     try appendU16(allocator, out, 2);
773     const first_lookup_offset = out.items.len;
774     try appendU16(allocator, out, 0);
775     const second_lookup_offset = out.items.len;
776     try appendU16(allocator, out, 0);
777     writeU16(out.items, first_lookup_offset, @intCast(out.items.len - lookup_list));
778     try appendGsubSingleLookup(allocator, out, 'Z' - 31);
779     writeU16(out.items, second_lookup_offset, @intCast(out.items.len - lookup_list));
780     try appendGsubSingleLookup(allocator, out, 'B' - 31);
781 
782     const feature_variations = out.items.len;
783     writeU32(out.items, header + 10, @intCast(feature_variations - header));
784     try appendLayoutFeatureVariations(allocator, out, feature_variations, 1);
785 }
786 
787 pub fn appendGsubRequiredVariationAlternates(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
788     const header = out.items.len;
789     try appendU16(allocator, out, 1);
790     try appendU16(allocator, out, 1);
791     try appendU16(allocator, out, 0);
792     try appendU16(allocator, out, 0);
793     try appendU16(allocator, out, 0);
794     try appendU32(allocator, out, 0);
795 
796     const script_list = out.items.len;
797     writeU16(out.items, header + 4, @intCast(script_list - header));
798     try appendLayoutScriptList(allocator, out);
799 
800     const feature_list = out.items.len;
801     writeU16(out.items, header + 6, @intCast(feature_list - header));
802     try appendLayoutFeatureListWithLookups(allocator, out, "rvrn", &.{ 0, 2 });
803 
804     const lookup_list = out.items.len;
805     writeU16(out.items, header + 8, @intCast(lookup_list - header));
806     try appendU16(allocator, out, 3);
807     const first_lookup_offset = out.items.len;
808     try appendU16(allocator, out, 0);
809     const second_lookup_offset = out.items.len;
810     try appendU16(allocator, out, 0);
811     const third_lookup_offset = out.items.len;
812     try appendU16(allocator, out, 0);
813     writeU16(out.items, first_lookup_offset, @intCast(out.items.len - lookup_list));
814     try appendGsubSingleLookup(allocator, out, 'Z' - 31);
815     writeU16(out.items, second_lookup_offset, @intCast(out.items.len - lookup_list));
816     try appendGsubSingleLookup(allocator, out, 'B' - 31);
817     writeU16(out.items, third_lookup_offset, @intCast(out.items.len - lookup_list));
818     try appendGsubLigatureLookup(allocator, out);
819 
820     const feature_variations = out.items.len;
821     writeU32(out.items, header + 10, @intCast(feature_variations - header));
822     try appendLayoutFeatureVariationsWithLookups(allocator, out, feature_variations, &.{ 1, 2 });
823 }
824 
825 pub fn appendGsubLocalizedForms(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
826     try appendGsubSingleFeature(allocator, out, "locl", 'Z' - 31);
827 }
828 
829 pub fn appendGsubLeftToRightAlternates(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
830     try appendGsubSingleFeature(allocator, out, "ltra", 'Z' - 31);
831 }
832 
833 pub fn appendGsubLeftToRightMirroredForms(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
834     try appendGsubSingleFeature(allocator, out, "ltrm", 'Z' - 31);
835 }
836 
837 pub fn appendGsubRightToLeftAlternates(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
838     try appendGsubSingleFeature(allocator, out, "rtla", 'Z' - 31);
839 }
840 
841 pub fn appendGsubRightToLeftMirroredForms(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
842     try appendGsubSingleFeature(allocator, out, "rtlm", 'Z' - 31);
843 }
844 
845 pub fn appendGsubFractions(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
846     try appendGsubSingleFeatureTarget(allocator, out, "frac", '1' - 31, 'F' - 31);
847 }
848 
849 pub fn appendGsubFractionComponents(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
850     const header = out.items.len;
851     try appendU16(allocator, out, 1);
852     try appendU16(allocator, out, 0);
853     try appendU16(allocator, out, 0);
854     try appendU16(allocator, out, 0);
855     try appendU16(allocator, out, 0);
856 
857     const script_list = out.items.len;
858     writeU16(out.items, header + 4, @intCast(script_list - header));
859     try appendLayoutScriptListWithFeatures(allocator, out, &.{ 0, 1 });
860 
861     const feature_list = out.items.len;
862     writeU16(out.items, header + 6, @intCast(feature_list - header));
863     try appendLayoutFeatureListPair(allocator, out, "dnom", 1, "numr", 0);
864 
865     const lookup_list = out.items.len;
866     writeU16(out.items, header + 8, @intCast(lookup_list - header));
867     try appendU16(allocator, out, 2);
868     const numr_lookup_offset = out.items.len;
869     try appendU16(allocator, out, 0);
870     const dnom_lookup_offset = out.items.len;
871     try appendU16(allocator, out, 0);
872     writeU16(out.items, numr_lookup_offset, @intCast(out.items.len - lookup_list));
873     try appendGsubSingleLookupFor(allocator, out, '1' - 31, 'N' - 31);
874     writeU16(out.items, dnom_lookup_offset, @intCast(out.items.len - lookup_list));
875     try appendGsubSingleLookupFor(allocator, out, '2' - 31, 'D' - 31);
876 }
877 
878 pub fn appendGsubArabicJoiningForms(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
879     const header = out.items.len;
880     try appendU16(allocator, out, 1);
881     try appendU16(allocator, out, 0);
882     try appendU16(allocator, out, 0);
883     try appendU16(allocator, out, 0);
884     try appendU16(allocator, out, 0);
885 
886     const script_list = out.items.len;
887     writeU16(out.items, header + 4, @intCast(script_list - header));
888     try appendLayoutScriptListWithFeatures(allocator, out, &.{ 0, 1, 2, 3 });
889 
890     const feature_list = out.items.len;
891     writeU16(out.items, header + 6, @intCast(feature_list - header));
892     try appendLayoutFeatureListFour(allocator, out, "isol", 0, "fina", 1, "medi", 2, "init", 3);
893 
894     const lookup_list = out.items.len;
895     writeU16(out.items, header + 8, @intCast(lookup_list - header));
896     try appendU16(allocator, out, 4);
897     const isol_lookup_offset = out.items.len;
898     try appendU16(allocator, out, 0);
899     const fina_lookup_offset = out.items.len;
900     try appendU16(allocator, out, 0);
901     const medi_lookup_offset = out.items.len;
902     try appendU16(allocator, out, 0);
903     const init_lookup_offset = out.items.len;
904     try appendU16(allocator, out, 0);
905     writeU16(out.items, isol_lookup_offset, @intCast(out.items.len - lookup_list));
906     try appendGsubSingleLookupFor(allocator, out, 'A' - 31, 'O' - 31);
907     writeU16(out.items, fina_lookup_offset, @intCast(out.items.len - lookup_list));
908     try appendGsubSingleLookupFor(allocator, out, 'A' - 31, 'F' - 31);
909     writeU16(out.items, medi_lookup_offset, @intCast(out.items.len - lookup_list));
910     try appendGsubSingleLookupFor(allocator, out, 'A' - 31, 'M' - 31);
911     writeU16(out.items, init_lookup_offset, @intCast(out.items.len - lookup_list));
912     try appendGsubSingleLookupFor(allocator, out, 'A' - 31, 'I' - 31);
913 }
914 
915 pub fn appendGsubVerticalAlternates(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
916     try appendGsubSingleFeature(allocator, out, "vert", 'B' - 31);
917 }
918 
919 pub fn appendGsubVerticalRotationAlternates(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) !void {
920     try appendGsubSingleFeature(allocator, out, "vrt2", 'C' - 31);
921 }
922 
923 fn appendGsubSingleLookup(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8), replacement_glyph: u16) !void {
924     try appendGsubSingleLookupFor(allocator, out, 'A' - 31, replacement_glyph);
925 }
926 
927 fn appendGsubSingleLookupFor(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8), target_glyph: u16, replacement_glyph: u16) !void {
928     try appendU16(allocator, out, 1);
929     try appendU16(allocator, out, 0);
930     try appendU16(allocator, out, 1);
931     try appendU16(allocator, out, 8);
932     try appendU16(allocator, out, 2);
933     try appendU16(allocator, out, 8);
934     try appendU16(allocator, out, 1);
935     try appendU16(allocator, out, replacement_glyph);
936     try appendU16(allocator, out, 1);
937     try appendU16(allocator, out, 1);
938     try appendU16(allocator, out, target_glyph);
939 }
940 
941 pub fn appendGsubSingleFeature(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8), comptime feature_tag: []const u8, replacement_glyph: u16) !void {
942     try appendGsubSingleFeatureTarget(allocator, out, feature_tag, 'A' - 31, replacement_glyph);
943 }
944 
945 pub fn appendGsubSingleFeatureTarget(allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8), comptime feature_tag: []const u8, target_glyph: u16, replacement_glyph: u16) !void {
946     const header = out.items.len;
947     try appendU16(allocator, out, 1);
948     try appendU16(allocator, out, 0);
949     try appendU16(allocator, out, 0);
950     try appendU16(allocator, out, 0);
951     try appendU16(allocator, out, 0);
952 
953     const script_list = out.items.len;
954     writeU16(out.items, header + 4, @intCast(script_list - header));
955     try appendLayoutScriptList(allocator, out);
956 
957     const feature_list = out.items.len;
958     writeU16(out.items, header + 6, @intCast(feature_list - header));
959     try appendLayoutFeatureList(allocator, out, feature_tag, 0);
960 
961     const lookup_list = out.items.len;
962     writeU16(out.items, header + 8, @intCast(lookup_list - header));
963     try appendU16(allocator, out, 1);
964     const lookup_offset = out.items.len;
965     try appendU16(allocator, out, 0);
966     writeU16(out.items, lookup_offset, @intCast(out.items.len - lookup_list));
967     try appendGsubSingleLookupFor(allocator, out, target_glyph, replacement_glyph);
968 }