/ node_modules / opentype.js / .reify-cache / d2b5c9b87970980829712373716cf91d2efd4574.js
d2b5c9b87970980829712373716cf91d2efd4574.js
  1  "use strict";var assert;module.watch(require('assert'),{default(v){assert=v}},0);var hex,unhex;module.watch(require('./testutil'),{hex(v){hex=v},unhex(v){unhex=v}},1);var decode,encode,sizeOf;module.watch(require('../src/types'),{decode(v){decode=v},encode(v){encode=v},sizeOf(v){sizeOf=v}},2);
  2  
  3  
  4  
  5  describe('types.js', function() {
  6      it('can handle BYTE', function() {
  7          assert.equal(hex(encode.BYTE(0xFE)), 'FE');
  8          assert.equal(sizeOf.BYTE(0xFE), 1);
  9      });
 10  
 11      it('can handle CHAR', function() {
 12          assert.equal(hex(encode.CHAR('@')), '40');
 13          assert.equal(sizeOf.CHAR('@'), 1);
 14      });
 15  
 16      it('can handle CHARARRAY', function() {
 17          assert.equal(hex(encode.CHARARRAY('A/B')), '41 2F 42');
 18          assert.equal(sizeOf.CHARARRAY('A/B'), 3);
 19      });
 20  
 21      it('can handle USHORT', function() {
 22          assert.equal(hex(encode.USHORT(0xCAFE)), 'CA FE');
 23          assert.equal(sizeOf.USHORT(0xCAFE), 2);
 24      });
 25  
 26      it('can handle SHORT', function() {
 27          assert.equal(hex(encode.USHORT(-345)), 'FE A7');
 28          assert.equal(sizeOf.SHORT(-345), 2);
 29      });
 30  
 31      it('can handle UINT24', function() {
 32          assert.equal(hex(encode.UINT24(0xABCDEF)), 'AB CD EF');
 33          assert.equal(sizeOf.UINT24(0xABCDEF), 3);
 34      });
 35  
 36      it('can handle ULONG', function() {
 37          assert.equal(hex(encode.ULONG(0xDEADBEEF)), 'DE AD BE EF');
 38          assert.equal(sizeOf.ULONG(0xDEADBEEF), 4);
 39      });
 40  
 41      it('can handle LONG', function() {
 42          assert.equal(hex(encode.LONG(-123456789)), 'F8 A4 32 EB');
 43          assert.equal(sizeOf.LONG(-123456789), 4);
 44      });
 45  
 46      it('can handle FIXED', function() {
 47          assert.equal(hex(encode.FIXED(0xBEEFCAFE)), 'BE EF CA FE');
 48          assert.equal(sizeOf.FIXED(0xBEEFCAFE), 4);
 49      });
 50  
 51      it('can handle FWORD', function() {
 52          assert.equal(hex(encode.FWORD(-8193)), 'DF FF');
 53          assert.equal(sizeOf.FWORD(-8193), 2);
 54      });
 55  
 56      it('can handle UFWORD', function() {
 57          assert.equal(hex(encode.UFWORD(0xDEED)), 'DE ED');
 58          assert.equal(sizeOf.UFWORD(0xDEED), 2);
 59      });
 60  
 61      // FIXME: Test LONGDATETIME when it gets implemented.
 62  
 63      it('can handle TAG', function() {
 64          assert.equal(hex(encode.TAG('Font')), '46 6F 6E 74');
 65          assert.equal(sizeOf.TAG('Font'), 4);
 66      });
 67  
 68      it('can handle Card8', function() {
 69          assert.equal(hex(encode.Card8(0xFE)), 'FE');
 70          assert.equal(sizeOf.Card8(0xFE), 1);
 71      });
 72  
 73      it('can handle Card16', function() {
 74          assert.equal(hex(encode.Card16(0xCAFE)), 'CA FE');
 75          assert.equal(sizeOf.Card16(0xCAFE), 2);
 76      });
 77  
 78      it('can handle OffSize', function() {
 79          assert.equal(hex(encode.OffSize(0xFE)), 'FE');
 80          assert.equal(sizeOf.OffSize(0xFE), 1);
 81      });
 82  
 83      it('can handle SID', function() {
 84          assert.equal(hex(encode.SID(0xCAFE)), 'CA FE');
 85          assert.equal(sizeOf.SID(0xCAFE), 2);
 86      });
 87  
 88      it('can handle NUMBER', function() {
 89          assert.equal(hex(encode.NUMBER(-32769)), '1D FF FF 7F FF');
 90          assert.equal(hex(encode.NUMBER(-32768)), '1C 80 00');
 91          assert.equal(hex(encode.NUMBER(-32767)), '1C 80 01');
 92          assert.equal(hex(encode.NUMBER(-1133)), '1C FB 93');
 93          assert.equal(hex(encode.NUMBER(-1132)), '1C FB 94');
 94          assert.equal(hex(encode.NUMBER(-1131)), 'FE FF');
 95          assert.equal(hex(encode.NUMBER(-109)), 'FB 01');
 96          assert.equal(hex(encode.NUMBER(-108)), 'FB 00');
 97          assert.equal(hex(encode.NUMBER(-107)), '20');
 98          assert.equal(hex(encode.NUMBER(-106)), '21');
 99          assert.equal(hex(encode.NUMBER(0)), '8B');
100          assert.equal(hex(encode.NUMBER(107)), 'F6');
101          assert.equal(hex(encode.NUMBER(108)), 'F7 00');
102          assert.equal(hex(encode.NUMBER(109)), 'F7 01');
103          assert.equal(hex(encode.NUMBER(1131)), 'FA FF');
104          assert.equal(hex(encode.NUMBER(1132)), '1C 04 6C');
105          assert.equal(hex(encode.NUMBER(1133)), '1C 04 6D');
106          assert.equal(hex(encode.NUMBER(32767)), '1C 7F FF');
107          assert.equal(hex(encode.NUMBER(32768)), '1D 00 00 80 00');
108          assert.equal(hex(encode.NUMBER(32769)), '1D 00 00 80 01');
109  
110          assert.equal(sizeOf.NUMBER(-32769), 5);
111          assert.equal(sizeOf.NUMBER(-32768), 3);
112          assert.equal(sizeOf.NUMBER(-32767), 3);
113          assert.equal(sizeOf.NUMBER(-1133), 3);
114          assert.equal(sizeOf.NUMBER(-1132), 3);
115          assert.equal(sizeOf.NUMBER(-1131), 2);
116          assert.equal(sizeOf.NUMBER(-109), 2);
117          assert.equal(sizeOf.NUMBER(-108), 2);
118          assert.equal(sizeOf.NUMBER(-107), 1);
119          assert.equal(sizeOf.NUMBER(-106), 1);
120          assert.equal(sizeOf.NUMBER(0), 1);
121          assert.equal(sizeOf.NUMBER(107), 1);
122          assert.equal(sizeOf.NUMBER(108), 2);
123          assert.equal(sizeOf.NUMBER(109), 2);
124          assert.equal(sizeOf.NUMBER(1131), 2);
125          assert.equal(sizeOf.NUMBER(1132), 3);
126          assert.equal(sizeOf.NUMBER(1133), 3);
127          assert.equal(sizeOf.NUMBER(32767), 3);
128          assert.equal(sizeOf.NUMBER(32768), 5);
129          assert.equal(sizeOf.NUMBER(32769), 5);
130      });
131  
132      it('can handle NUMBER16', function() {
133          assert.equal(hex(encode.NUMBER16(-32768)), '1C 80 00');
134          assert.equal(hex(encode.NUMBER16(-1133)), '1C FB 93');
135          assert.equal(hex(encode.NUMBER16(-108)), '1C FF 94');
136          assert.equal(hex(encode.NUMBER16(0)), '1C 00 00');
137          assert.equal(hex(encode.NUMBER16(108)), '1C 00 6C');
138          assert.equal(hex(encode.NUMBER16(1133)), '1C 04 6D');
139          assert.equal(hex(encode.NUMBER16(32767)), '1C 7F FF');
140  
141          assert.equal(sizeOf.NUMBER16(-32768), 3);
142          assert.equal(sizeOf.NUMBER16(-1133), 3);
143          assert.equal(sizeOf.NUMBER16(-108), 3);
144          assert.equal(sizeOf.NUMBER16(0), 3);
145          assert.equal(sizeOf.NUMBER16(108), 3);
146          assert.equal(sizeOf.NUMBER16(1133), 3);
147          assert.equal(sizeOf.NUMBER16(32767), 3);
148      });
149  
150      it('can handle NUMBER32', function() {
151          assert.equal(hex(encode.NUMBER32(-1)), '1D FF FF FF FF');
152          assert.equal(hex(encode.NUMBER32(0)), '1D 00 00 00 00');
153          assert.equal(hex(encode.NUMBER32(0xDEADBEEF)), '1D DE AD BE EF');
154  
155          assert.equal(sizeOf.NUMBER32(-1), 5);
156          assert.equal(sizeOf.NUMBER32(0), 5);
157          assert.equal(sizeOf.NUMBER32(0xDEADBEEF), 5);
158      });
159  
160      it('can handle REAL', function() {
161          // FIXME: It would be good if somebody who actually understands
162          // how REAL.encode() works could write tests for edge cases.
163          assert.equal(hex(encode.REAL(0.0)), '1E 0F');
164          assert.equal(sizeOf.REAL(0.0), 2);
165  
166          assert.equal(hex(encode.REAL(0.1)), '1E 0A 1F');
167          assert.equal(sizeOf.REAL(0.1), 3);
168  
169          assert.equal(hex(encode.REAL(99.999)), '1E 99 A9 99 FF');
170          assert.equal(sizeOf.REAL(99.999), 5);
171  
172          assert.equal(hex(encode.REAL(-123456.78)), '1E E1 23 45 6A 78 FF');
173          assert.equal(sizeOf.REAL(-123456.78), 7);
174      });
175  
176      it('can handle NAME', function() {
177          assert.equal(hex(encode.NAME('hello')), '68 65 6C 6C 6F');
178          assert.equal(sizeOf.NAME('hello'), 5);
179      });
180  
181      it('can handle STRING', function() {
182          assert.equal(hex(encode.STRING('hello')), '68 65 6C 6C 6F');
183          assert.equal(sizeOf.STRING('hello'), 5);
184      });
185  
186      it('can handle UTF16', function() {
187          assert.equal(decode.UTF16(unhex('DE AD 5B 57 4F 53'), 2, 4), '字体');
188          assert.equal(hex(encode.UTF16('字体')), '5B 57 4F 53');
189          assert.equal(sizeOf.UTF16('字体'), 4);
190  
191          // In JavaScript, characters outside the Basic Multilingual Plane
192          // are represented with surrogate pairs. For example, U+1F404 COW
193          // is stored as the surrogate pair U+D83D U+DC04. This is also
194          // exactly what we need for representing U+1F404 in UTF-16.
195          assert.equal(decode.UTF16(unhex('DE AD D8 3D DC 04'), 2, 4), '\uD83D\uDC04');
196          assert.equal(hex(encode.UTF16('\uD83D\uDC04')), 'D8 3D DC 04');
197          assert.equal(sizeOf.UTF16('\uD83D\uDC04'), 4);
198      });
199  
200      it('can handle MACSTRING in Central European encoding', function() {
201          const encoding = 'x-mac-ce';
202          const data = '42 65 74 F5 74 92 70 75 73';
203  
204          assert.equal(
205              decode.MACSTRING(unhex('DE AD BE EF ' + data), 4, 9, encoding),
206              'Betűtípus');
207  
208          assert.equal(hex(encode.MACSTRING('Betűtípus', encoding)), data);  // not in cache
209          assert.equal(hex(encode.MACSTRING('Betűtípus', encoding)), data);  // likely cached
210          assert.equal(encode.MACSTRING('Betűtípus 字体', encoding), undefined);  // not encodable
211  
212          assert.equal(sizeOf.MACSTRING('Betűtípus', encoding), 9);
213          assert.equal(sizeOf.MACSTRING('Betűtípus 字体', encoding), 0);
214      });
215  
216      it('can handle MACSTRING in Croatian encoding', function() {
217          const encoding = 'x-mac-croatian';
218          const data = 'A9 74 61 6D 70 61 E8';
219  
220          assert.equal(
221              decode.MACSTRING(unhex('DE AD BE EF ' + data), 4, 7, encoding),
222              'Štampač');
223  
224          assert.equal(hex(encode.MACSTRING('Štampač', encoding)), data);  // not in cache
225          assert.equal(hex(encode.MACSTRING('Štampač', encoding)), data);  // likely cached
226          assert.equal(encode.MACSTRING('Štampač 字体', encoding), undefined);  // not encodable
227  
228          assert.equal(sizeOf.MACSTRING('Štampač', encoding), 7);
229          assert.equal(sizeOf.MACSTRING('Štampač 字体', encoding), 0);
230      });
231  
232      it('can handle MACSTRING in Cyrillic encoding', function() {
233          const encoding = 'x-mac-cyrillic';
234          const data = '98 F0 E8 F4 F2 20 46 6F 6F';
235  
236          assert.equal(
237              decode.MACSTRING(unhex('DE AD BE EF ' + data), 4, 9, encoding),
238              'Шрифт Foo');
239  
240          assert.equal(hex(encode.MACSTRING('Шрифт Foo', encoding)), data);  // not in cache
241          assert.equal(hex(encode.MACSTRING('Шрифт Foo', encoding)), data);  // likely cached
242          assert.equal(encode.MACSTRING('Шрифт 字体', encoding), undefined);  // not encodable
243  
244          assert.equal(sizeOf.MACSTRING('Шрифт Foo', encoding), 9);
245          assert.equal(sizeOf.MACSTRING('Шрифт 字体', encoding), 0);
246      });
247  
248      it('can handle MACSTRING in Gaelic encoding', function() {
249          const encoding = 'x-mac-gaelic';
250          const data = '44 9C 69 E0 B6 92';
251  
252          assert.equal(
253              decode.MACSTRING(unhex('DE AD BE EF ' + data), 4, 6, encoding),
254              'Dúiṫċí');
255  
256          assert.equal(hex(encode.MACSTRING('Dúiṫċí', encoding)), data);  // not in cache
257          assert.equal(hex(encode.MACSTRING('Dúiṫċí', encoding)), data);  // likely cached
258          assert.equal(encode.MACSTRING('Dúiṫċí 字体', encoding), undefined);
259  
260          assert.equal(sizeOf.MACSTRING('Dúiṫċí Foo', encoding), 10);
261          assert.equal(sizeOf.MACSTRING('Dúiṫċí 字体', encoding), 0);
262      });
263  
264      it('can handle MACSTRING in Greek encoding', function() {
265          const encoding = 'x-mac-greek';
266          const data = 'A1 F2 E1 ED ED E1 F4 EF F3 E5 E9 F2 C0 20 2E 85 2E';
267  
268          assert.equal(
269              decode.MACSTRING(unhex('DE AD BE EF ' + data), 4, 17, encoding),
270              'Γραμματοσειρά .Ö.');
271  
272          assert.equal(hex(encode.MACSTRING('Γραμματοσειρά .Ö.', encoding)), data);  // not in cache
273          assert.equal(hex(encode.MACSTRING('Γραμματοσειρά .Ö.', encoding)), data);  // likely cached
274          assert.equal(encode.MACSTRING('Γραμματοσειρά 字体', encoding), undefined);  // not encodable
275  
276          assert.equal(sizeOf.MACSTRING('Γραμματοσειρά .Ö.', encoding), 17);
277          assert.equal(sizeOf.MACSTRING('Γραμματοσειρά 字体', encoding), 0);
278      });
279  
280      it('can handle MACSTRING in Icelandic encoding', function() {
281          const encoding = 'x-mac-icelandic';
282          const data = 'DE 97 72 69 73 64 97 74 74 69 72 20 DF 97 20 61 DD 8E 67';
283  
284          assert.equal(
285              decode.MACSTRING(unhex('DE AD BE EF ' + data), 4, 19, encoding),
286              'Þórisdóttir þó aðég');
287  
288          assert.equal(hex(encode.MACSTRING('Þórisdóttir þó aðég', encoding)), data);  // not in cache
289          assert.equal(hex(encode.MACSTRING('Þórisdóttir þó aðég', encoding)), data);  // likely cached
290          assert.equal(encode.MACSTRING('Þórisdóttir 字体', encoding), undefined);  // not encodable
291  
292          assert.equal(sizeOf.MACSTRING('Þórisdóttir þó aðég', encoding), 19);
293          assert.equal(sizeOf.MACSTRING('Þórisdóttir 字体', encoding), 0);
294      });
295  
296      it('can handle MACSTRING in Inuit encoding', function() {
297          const encoding = 'x-mac-inuit';
298          const data = '8A 80 8C 8B AB DA CC C6 93';
299  
300          assert.equal(
301              decode.MACSTRING(unhex('DE AD BE EF ' + data), 4, 9, encoding),
302              'ᐸᐃᑉᐹᒨᕆᔾᔪᑦ');
303  
304          assert.equal(hex(encode.MACSTRING('ᐸᐃᑉᐹᒨᕆᔾᔪᑦ', encoding)), data);  // not in cache
305          assert.equal(hex(encode.MACSTRING('ᐸᐃᑉᐹᒨᕆᔾᔪᑦ', encoding)), data);  // likely cached
306          assert.equal(encode.MACSTRING('ᐸᐃᑉᐹᒨᕆᔾᔪᑦ 字体', encoding), undefined);
307  
308          assert.equal(sizeOf.MACSTRING('ᐸᐃᑉᐹᒨᕆᔾᔪᑦ Foo', encoding), 13);
309          assert.equal(sizeOf.MACSTRING('ᐸᐃᑉᐹᒨᕆᔾᔪᑦ 字体', encoding), 0);
310      });
311  
312      it('can handle MACSTRING in Roman encoding', function() {
313          const encoding = 'macintosh';
314          const data = '86 65 74 6C 69 62 8A 72 67';
315  
316          assert.equal(
317              decode.MACSTRING(unhex('DE AD BE EF ' + data), 4, 9, encoding),
318              'Üetlibärg');
319  
320          assert.equal(hex(encode.MACSTRING('Üetlibärg', encoding)), data);  // not in cache
321          assert.equal(hex(encode.MACSTRING('Üetlibärg', encoding)), data);  // likely cached
322          assert.equal(encode.MACSTRING('Üetlibärg 字体', encoding), undefined);  // not encodable
323  
324          assert.equal(sizeOf.MACSTRING('Üetlibärg', encoding), 9);
325          assert.equal(sizeOf.MACSTRING('Üetlibärg 字体', encoding), 0);
326      });
327  
328      it('can handle MACSTRING in Romanian encoding', function() {
329          const encoding = 'x-mac-romanian';
330          const data = '54 69 70 BE 72 69 72 65';
331  
332          assert.equal(
333              decode.MACSTRING(unhex('DE AD BE EF ' + data), 4, 8, encoding),
334              'Tipărire');
335  
336          assert.equal(hex(encode.MACSTRING('Tipărire', encoding)), data);  // not in cache
337          assert.equal(hex(encode.MACSTRING('Tipărire', encoding)), data);  // likely cached
338          assert.equal(encode.MACSTRING('Tipărire 字体', encoding), undefined);  // not encodable
339  
340          assert.equal(sizeOf.MACSTRING('Tipărire', encoding), 8);
341          assert.equal(sizeOf.MACSTRING('Tipărire 字体', encoding), 0);
342      });
343  
344      it('can handle MACSTRING in Turkish encoding', function() {
345          const encoding = 'x-mac-turkish';
346          const data = '42 61 73 DD 6C 6D DD DF';
347  
348          assert.equal(
349              decode.MACSTRING(unhex('DE AD BE EF ' + data), 4, 8, encoding),
350              'Basılmış');
351  
352          assert.equal(hex(encode.MACSTRING('Basılmış', encoding)), data);  // not in cache
353          assert.equal(hex(encode.MACSTRING('Basılmış', encoding)), data);  // likely cached
354          assert.equal(encode.MACSTRING('Basılmış 字体', encoding), undefined);  // not encodable
355  
356          assert.equal(sizeOf.MACSTRING('Basılmış', encoding), 8);
357          assert.equal(sizeOf.MACSTRING('Basılmış 字体', encoding), 0);
358      });
359  
360      it('rejects MACSTRING in unsupported encodings', function() {
361          const encoding = 'KOI8-R';
362          assert.equal(decode.MACSTRING(unhex('41 42'), 0, 1, encoding), undefined);
363          assert.equal(encode.MACSTRING('AB', encoding), undefined);
364          assert.equal(sizeOf.MACSTRING('AB', encoding), 0);
365      });
366  
367      it('can handle INDEX', function() {
368          assert.equal(hex(encode.INDEX([])), '00 00');
369          assert.equal(sizeOf.INDEX([]), 2);
370  
371          const foo = {name: 'foo', type: 'STRING', value: 'hello'};
372          const bar = {name: 'bar', type: 'NUMBER', value: 23};
373          assert.equal(hex(encode.INDEX([foo, bar])),
374                       '00 02 01 01 06 07 68 65 6C 6C 6F A2');
375          assert.equal(sizeOf.INDEX([foo, bar]), 12);
376      });
377  
378      it('can handle DICT', function() {
379          assert.equal(hex(encode.DICT({})), '');
380          assert.equal(sizeOf.DICT({}), 0);
381  
382          const foo = {name: 'foo', type: 'number', value: -1131};
383          const bar = {name: 'bar', type: 'number', value: 1131};
384          assert.equal(hex(encode.DICT({7: foo, 42: bar})), 'FE FF 07 FA FF 2A');
385          assert.equal(sizeOf.DICT({7: foo, 42: bar}), 6);
386      });
387  
388      it('can handle OPERATOR', function() {
389          // FIXME: Somebody who knows CFF should double-check this.
390          // Are there edge cases we should test here?
391          assert.deepEqual(encode.OPERATOR(1199), [1199]);
392          assert.deepEqual(encode.OPERATOR(1200), [12, 0]);
393          assert.deepEqual(encode.OPERATOR(2399), [12, 1199]);
394      });
395  
396      it('can handle OPERAND', function() {
397          // FIXME: Somebody who knows CFF should double-check this.
398          // Is it really the case that a SID operand becomes a single byte,
399          // even though encode.SID would return '00 A2' here?
400          assert.equal(hex(encode.OPERAND(23, 'SID')), 'A2');
401          assert.equal(hex(encode.OPERAND(23, 'offset')), '1D 00 00 00 17');
402          assert.equal(hex(encode.OPERAND(23, 'number')), 'A2');
403          assert.equal(hex(encode.OPERAND(23.0, 'real')), '1E 23 FF');
404      });
405  
406      it('can handle OP', function() {
407          assert.equal(hex(encode.OP(0x42)), '42');
408          assert.equal(sizeOf.OP(0x42), 1);
409      });
410  
411      it('can handle CHARSTRING', function() {
412          assert.equal(hex(encode.CHARSTRING([])), '');
413          assert.equal(sizeOf.CHARSTRING([]), 0);
414  
415          // FIXME: Somebody who knows CFF should double-check this;
416          // the result seems a little short.
417          const ops = [
418              {name: 'width', type: 'NUMBER', value: 42},
419              {name: 'dx', type: 'NUMBER', value: 17},
420              {name: 'dy', type: 'NUMBER', value: -23},
421              {name: 'rlineto', type: 'OP', value: 5}
422          ];
423  
424          // Because encode.CHARSTRING uses a cache, we call it twice
425          // for testing both the uncached and the (likely) cached case.
426          assert.equal(hex(encode.CHARSTRING(ops)), 'B5 9C 74 05');
427          assert.equal(hex(encode.CHARSTRING(ops)), 'B5 9C 74 05');
428          assert.equal(sizeOf.CHARSTRING(ops), 4);
429      });
430  
431      it('can handle OBJECT', function() {
432          const obj = {type: 'TAG', value: 'Font'};
433          assert.equal(hex(encode.OBJECT(obj)), '46 6F 6E 74');
434          assert.equal(sizeOf.OBJECT(obj), 4);
435      });
436  
437      it('can handle TABLE', function() {
438          const table = {
439              fields: [
440                  {name: 'version', type: 'FIXED', value: 0x01234567},
441                  {name: 'flags', type: 'USHORT', value: 0xBEEF}
442              ]
443          };
444          assert.equal(hex(encode.TABLE(table)), '01 23 45 67 BE EF');
445          assert.equal(sizeOf.TABLE(table), 6);
446      });
447  
448      it('can handle subTABLEs', function() {
449          const table = {
450              fields: [
451                  {name: 'version', type: 'FIXED', value: 0x01234567},
452                  {
453                      name: 'subtable', type: 'TABLE', value: {
454                          fields: [
455                              {name: 'flags', type: 'USHORT', value: 0xBEEF}
456                          ]
457                      }
458                  }
459              ]
460          };
461          assert.equal(hex(encode.TABLE(table)), '01 23 45 67 00 06 BE EF');
462          assert.equal(sizeOf.TABLE(table), 8);
463      });
464  
465      it('can handle deeply nested TABLEs', function() {
466          // First 58 bytes of Roboto-Black.ttf GSUB table.
467          const expected = '00 01 00 00 00 0A 00 20 00 3A ' +                                           // header
468              '00 01 44 46 4C 54 00 08 00 04 00 00 00 00 FF FF 00 02 00 00 00 01 ' +                  // script list
469              '00 02 6C 69 67 61 00 0E 73 6D 63 70 00 14 00 00 00 01 00 01 00 00 00 01 00 00';        // feature list
470  
471          const table = {
472              fields: [
473                  {name: 'version', type: 'FIXED', value: 0x00010000},
474                  {name: 'scriptList', type: 'TABLE'},
475                  {name: 'featureList', type: 'TABLE'},
476                  {name: 'lookupList', type: 'TABLE'}
477              ],
478              scriptList: {
479                  fields: [
480                      {name: 'scriptCount', type: 'USHORT', value: 1},
481                      {name: 'scriptTag_0', type: 'TAG', value: 'DFLT'},
482                      {
483                          name: 'script_0', type: 'TABLE', value: {
484                              fields: [
485                              {
486                                  name: 'defaultLangSys', type: 'TABLE', value: {
487                                      fields: [
488                                          {name: 'lookupOrder', type: 'USHORT', value: 0},
489                                          {name: 'reqFeatureIndex', type: 'USHORT', value: 0xffff},
490                                          {name: 'featureCount', type: 'USHORT', value: 2},
491                                          {name: 'featureIndex_0', type: 'USHORT', value: 0},
492                                          {name: 'featureIndex_1', type: 'USHORT', value: 1}
493                                      ]
494                                  }
495                              },
496                              {name: 'langSysCount', type: 'USHORT', value: 0}
497                              ]
498                          }
499                      }
500                  ]
501              },
502              featureList: {
503                  fields: [
504                      {name: 'featureCount', type: 'USHORT', value: 2},
505                      {name: 'featureTag_0', type: 'TAG', value: 'liga'},
506                      {
507                          name: 'feature_0', type: 'TABLE', value: {
508                              fields: [
509                                  {name: 'featureParams', type: 'USHORT', value: 0},
510                                  {name: 'lookupCount', type: 'USHORT', value: 1},
511                                  {name: 'lookupListIndex', type: 'USHORT', value: 1}
512                              ]
513                          }
514                      },
515                      {name: 'featureTag_1', type: 'TAG', value: 'smcp'},
516                      {
517                          name: 'feature_1', type: 'TABLE', value: {
518                              fields: [
519                                  {name: 'featureParams', type: 'USHORT', value: 0},
520                                  {name: 'lookupCount', type: 'USHORT', value: 1},
521                                  {name: 'lookupListIndex', type: 'USHORT', value: 0}
522                              ]
523                          }
524                      }
525                  ]
526              },
527              lookupList: {fields: []}
528          };
529  
530          assert.equal(hex(encode.TABLE(table)), expected);
531          assert.equal(sizeOf.TABLE(table), 58);
532      });
533  
534      it('can handle RECORD', function() {
535          const table = {
536              fields: [
537                  {name: 'version', type: 'FIXED', value: 0x01234567},
538                  {name: 'record', type: 'RECORD'}
539              ]
540          };
541  
542          table.record = {
543              fields: [
544                  {name: 'flags_0', type: 'USHORT', value: 0xDEAF},
545                  {name: 'flags_1', type: 'USHORT', value: 0xCAFE}
546              ]
547          };
548  
549          assert.equal(hex(encode.TABLE(table)), '01 23 45 67 DE AF CA FE');
550          assert.equal(sizeOf.TABLE(table), 8);
551      });
552  
553      it('can handle LITERAL', function() {
554          assert.equal(hex(encode.LITERAL([])), '');
555          assert.equal(sizeOf.LITERAL([]), 0);
556  
557          assert.equal(hex(encode.LITERAL([0xff, 0x23, 0xA7])), 'FF 23 A7');
558          assert.equal(sizeOf.LITERAL([0xff, 0x23, 0xA7]), 3);
559      });
560  
561      it('can encode VARDELTAS', function() {
562          const e = function (deltas) {
563              return hex(encode.VARDELTAS(deltas));
564          };
565          assert.equal(e([]), '');
566  
567          // zeroes
568          assert.equal(e([0]), '80');
569          assert.equal(e(new Array(64).fill(0)), 'BF');
570          assert.equal(e(new Array(65).fill(0)), 'BF 80');
571          assert.equal(e(new Array(100).fill(0)), 'BF A3');
572          assert.equal(e(new Array(256).fill(0)), 'BF BF BF BF');
573  
574          // bytes
575          assert.equal(e([1]), '00 01');
576          assert.equal(e([1, 2, 3, 127, -128, -1, -2]), '06 01 02 03 7F 80 FF FE');
577          assert.equal(e(new Array(64).fill(127)),
578                       '3F ' + (new Array(64).fill('7F')).join(' '));
579          assert.equal(e(new Array(65).fill(127)),
580                       '3F ' + (new Array(64).fill('7F')).join(' ') + ' 00 7F');
581  
582          // words
583          assert.equal(e([0x6666]), '40 66 66');
584          assert.equal(e([0x6666, 32767, -1, -32768]), '43 66 66 7F FF FF FF 80 00');
585          assert.equal(e(new Array(64).fill(0x1122)),
586                       '7F ' + (new Array(64).fill('11 22')).join(' '));
587          assert.equal(e(new Array(65).fill(0x1122)),
588                       '7F ' + (new Array(64).fill('11 22')).join(' ') + ' 40 11 22');
589  
590          // bytes, zeroes
591          assert.equal(e([1, 0]), '01 01 00');
592          assert.equal(e([1, 0, 0]), '00 01 81');
593  
594          // bytes, zeroes, bytes:
595          // a single zero is more compact when encoded within the bytes run
596          assert.equal(e([127, 127, 0, 127, 127]), '04 7F 7F 00 7F 7F');
597          // multiple zeroes are more compact when encoded into their own run
598          assert.equal(e([127, 127, 0, 0, 127, 127]), '01 7F 7F 81 01 7F 7F');
599          assert.equal(e([127, 127, 0, 0, 0, 127, 127]), '01 7F 7F 82 01 7F 7F');
600          assert.equal(e([127, 127, 0, 0, 0, 0, 127, 127]), '01 7F 7F 83 01 7F 7F');
601  
602          // words, zeroes
603          assert.equal(e([0x6789, 0]), '40 67 89 80');
604          assert.equal(e([0x6666, 0, 0]), '40 66 66 81');
605  
606          // words, zeroes, bytes
607          assert.equal(e([0x6666, 0, 1, 2, 3]), '40 66 66 80 02 01 02 03');
608          assert.equal(e([0x6666, 0, 0, 1, 2, 3]), '40 66 66 81 02 01 02 03');
609          assert.equal(e([0x6666, 0, 0, 0, 1, 2, 3]), '40 66 66 82 02 01 02 03');
610  
611          // words, zeroes, words
612          assert.equal(e([0x6666, 0, 0x7777]), '40 66 66 80 40 77 77');
613          assert.equal(e([0x6666, 0, 0, 0x7777]), '40 66 66 81 40 77 77');
614          assert.equal(e([0x6666, 0, 0, 0, 0x7777]), '40 66 66 82 40 77 77');
615  
616          // words, bytes, words:
617          // a single byte-encodable word is more compact when encoded within the words run
618          assert.equal(e([0x6666, 2, 0x7777]), '42 66 66 00 02 77 77');
619          // multiple byte-encodable words are more compacted when forming their own run
620          assert.equal(e([0x6666, 2, 2, 0x7777]), '40 66 66 01 02 02 40 77 77');
621      });
622  });