@flighthq/font-formats 0.3.1-next.209.43ef1bc

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/cffCharstring.d.ts +13 -0
  2. package/dist/cffCharstring.d.ts.map +1 -0
  3. package/dist/cffCharstring.js +336 -0
  4. package/dist/cffCharstring.js.map +1 -0
  5. package/dist/cffDict.d.ts +8 -0
  6. package/dist/cffDict.d.ts.map +1 -0
  7. package/dist/cffDict.js +118 -0
  8. package/dist/cffDict.js.map +1 -0
  9. package/dist/cffFdSelect.d.ts +2 -0
  10. package/dist/cffFdSelect.d.ts.map +1 -0
  11. package/dist/cffFdSelect.js +60 -0
  12. package/dist/cffFdSelect.js.map +1 -0
  13. package/dist/cffIndex.d.ts +3 -0
  14. package/dist/cffIndex.d.ts.map +1 -0
  15. package/dist/cffIndex.js +52 -0
  16. package/dist/cffIndex.js.map +1 -0
  17. package/dist/cffTable.d.ts +3 -0
  18. package/dist/cffTable.d.ts.map +1 -0
  19. package/dist/cffTable.js +134 -0
  20. package/dist/cffTable.js.map +1 -0
  21. package/dist/contract.d.ts +15 -0
  22. package/dist/contract.d.ts.map +1 -0
  23. package/dist/contract.js +15 -0
  24. package/dist/contract.js.map +1 -0
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +2 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/openTypeCmap.d.ts +5 -0
  30. package/dist/openTypeCmap.d.ts.map +1 -0
  31. package/dist/openTypeCmap.js +161 -0
  32. package/dist/openTypeCmap.js.map +1 -0
  33. package/dist/openTypeGlyf.d.ts +4 -0
  34. package/dist/openTypeGlyf.d.ts.map +1 -0
  35. package/dist/openTypeGlyf.js +229 -0
  36. package/dist/openTypeGlyf.js.map +1 -0
  37. package/dist/openTypeGlyphOutlineSource.d.ts +4 -0
  38. package/dist/openTypeGlyphOutlineSource.d.ts.map +1 -0
  39. package/dist/openTypeGlyphOutlineSource.js +168 -0
  40. package/dist/openTypeGlyphOutlineSource.js.map +1 -0
  41. package/dist/openTypeMetrics.d.ts +6 -0
  42. package/dist/openTypeMetrics.d.ts.map +1 -0
  43. package/dist/openTypeMetrics.js +74 -0
  44. package/dist/openTypeMetrics.js.map +1 -0
  45. package/dist/openTypeTestHelper.d.ts +26 -0
  46. package/dist/openTypeTestHelper.d.ts.map +1 -0
  47. package/dist/openTypeTestHelper.js +494 -0
  48. package/dist/openTypeTestHelper.js.map +1 -0
  49. package/dist/sfntAssembly.d.ts +7 -0
  50. package/dist/sfntAssembly.d.ts.map +1 -0
  51. package/dist/sfntAssembly.js +77 -0
  52. package/dist/sfntAssembly.js.map +1 -0
  53. package/dist/sfntTableDirectory.d.ts +4 -0
  54. package/dist/sfntTableDirectory.d.ts.map +1 -0
  55. package/dist/sfntTableDirectory.js +39 -0
  56. package/dist/sfntTableDirectory.js.map +1 -0
  57. package/dist/woff2Font.d.ts +6 -0
  58. package/dist/woff2Font.d.ts.map +1 -0
  59. package/dist/woff2Font.js +210 -0
  60. package/dist/woff2Font.js.map +1 -0
  61. package/dist/woff2GlyfTransform.d.ts +6 -0
  62. package/dist/woff2GlyfTransform.d.ts.map +1 -0
  63. package/dist/woff2GlyfTransform.js +104 -0
  64. package/dist/woff2GlyfTransform.js.map +1 -0
  65. package/dist/woffFont.d.ts +6 -0
  66. package/dist/woffFont.d.ts.map +1 -0
  67. package/dist/woffFont.js +112 -0
  68. package/dist/woffFont.js.map +1 -0
  69. package/package.json +50 -0
  70. package/src/cffCharstring.test.ts +177 -0
  71. package/src/cffDict.test.ts +67 -0
  72. package/src/cffFdSelect.test.ts +84 -0
  73. package/src/cffIndex.test.ts +97 -0
  74. package/src/cffTable.test.ts +84 -0
  75. package/src/openTypeCmap.test.ts +124 -0
  76. package/src/openTypeGlyf.test.ts +168 -0
  77. package/src/openTypeGlyphOutlineSource.test.ts +298 -0
  78. package/src/openTypeMetrics.test.ts +103 -0
  79. package/src/sfntAssembly.test.ts +92 -0
  80. package/src/sfntTableDirectory.test.ts +64 -0
  81. package/src/woff2Font.test.ts +125 -0
  82. package/src/woff2GlyfTransform.test.ts +88 -0
  83. package/src/woffFont.test.ts +167 -0
@@ -0,0 +1,494 @@
1
+ // Synthetic fonts, assembled byte by byte.
2
+ //
3
+ // THIS FILE IS THE TESTING STRATEGY, NOT A CONVENIENCE. Vendoring a real font into the repository is
4
+ // forbidden, and a font this file builds is Flight's own bytes with no provenance attached to them.
5
+ // Building the fixture also means every test states the exact table contents its assertion depends on,
6
+ // so a failure names a field rather than "the font changed".
7
+ //
8
+ // Only the tables the reader needs are emitted, with the layout the format specifies.
9
+ // A charstring operand in the one-byte range, which covers -107..107 — enough for every fixture here.
10
+ export function cffOperand(value) {
11
+ return value + 139;
12
+ }
13
+ // A complete, readable TrueType font carrying the requested glyphs.
14
+ export function createSyntheticFont(options = {}) {
15
+ const flavor = options.flavor ?? 'truetype';
16
+ const unitsPerEm = options.unitsPerEm ?? 1000;
17
+ const glyphs = options.glyphs ?? [emptySyntheticGlyph()];
18
+ const charstrings = options.charstrings ?? [new Uint8Array([14])];
19
+ // In a CFF font the CHARSTRINGS are the glyphs, so the declared glyph count and the advance table must
20
+ // follow them. Counting `glyphs` in both flavors would make every CFF fixture internally inconsistent —
21
+ // the source would refuse indices the charstrings index really has.
22
+ const glyphCount = flavor === 'truetype' ? glyphs.length : charstrings.length;
23
+ const advances = options.advances ?? Array.from({ length: glyphCount }, () => 500);
24
+ const glyphData = glyphs.map((glyph) => encodeSyntheticGlyph(glyph));
25
+ const locaOffsets = [0];
26
+ let running = 0;
27
+ for (const data of glyphData) {
28
+ running += data.length;
29
+ locaOffsets.push(running);
30
+ }
31
+ const tables = new Map();
32
+ tables.set('head', encodeSyntheticHead(unitsPerEm));
33
+ tables.set('hhea', encodeSyntheticHhea(advances.length));
34
+ tables.set('maxp', encodeSyntheticMaxp(glyphCount));
35
+ tables.set('hmtx', encodeSyntheticHmtx(advances));
36
+ tables.set('cmap', encodeSyntheticCmap(options.codepoints ?? new Map()));
37
+ if (flavor === 'truetype') {
38
+ tables.set('loca', encodeSyntheticLoca(locaOffsets));
39
+ tables.set('glyf', concatenateBytes(glyphData));
40
+ }
41
+ else {
42
+ tables.set('CFF ', encodeSyntheticCff(charstrings, options.cid));
43
+ }
44
+ if (options.omitTable !== undefined)
45
+ tables.delete(options.omitTable);
46
+ return assembleSfnt(flavor === 'truetype' ? 0x00010000 : 0x4f54544f, tables);
47
+ }
48
+ export function emptySyntheticGlyph() {
49
+ return { endPoints: [], points: [] };
50
+ }
51
+ // Builds a real `CFF ` table: header, the four fixed INDEXes, and a charstrings INDEX reached by an
52
+ // offset from the top DICT. Assembled byte by byte like every other fixture here, so the CFF reader is
53
+ // proved against the layout the format specifies rather than against a stub that resembles it.
54
+ export function encodeSyntheticCff(charstrings, cid) {
55
+ const name = encodeCffIndex([new Uint8Array([0x46])]);
56
+ const strings = encodeCffIndex([]);
57
+ const gsubrs = encodeCffIndex([]);
58
+ const charstringsIndex = encodeCffIndex(charstrings);
59
+ // The top DICT holds one operator whose operand is the charstrings offset from the table start. The
60
+ // operand is written five-wide (a 32-bit integer) so its size does not change as the offset does,
61
+ // which would otherwise make the offset depend on its own encoding.
62
+ const topDictBody = (offset) => {
63
+ const out = new Uint8Array(6);
64
+ out[0] = 29;
65
+ new DataView(out.buffer).setInt32(1, offset);
66
+ out[5] = 17;
67
+ return out;
68
+ };
69
+ const header = new Uint8Array([1, 0, 4, 1]);
70
+ if (cid === undefined) {
71
+ const probe = encodeCffIndex([topDictBody(0)]);
72
+ const charstringsAt = header.length + name.length + probe.length + strings.length + gsubrs.length;
73
+ const topDicts = encodeCffIndex([topDictBody(charstringsAt)]);
74
+ return concatenateBytes([header, name, topDicts, strings, gsubrs, charstringsIndex]);
75
+ }
76
+ // A CID font: an FDArray of font DICTs each pointing at its own private DICT, plus an FDSelect. Every
77
+ // offset is table-relative except the private DICT's subrs offset, which is private-relative — the two
78
+ // bases the reader must not confuse, so the fixture exercises both.
79
+ const fdSelect = encodeSyntheticFdSelect(cid.fdSelect);
80
+ const cidTop = (charstringsAt, fdArrayAt, fdSelectAt) => {
81
+ const out = [];
82
+ // ROS takes three operands; the two string ids are irrelevant to outline reading.
83
+ out.push(139, 139, 139, 12, 30);
84
+ out.push(29, ...int32(charstringsAt), 17);
85
+ out.push(29, ...int32(fdArrayAt), 12, 36);
86
+ out.push(29, ...int32(fdSelectAt), 12, 37);
87
+ return new Uint8Array(out);
88
+ };
89
+ // Each pool becomes a private DICT (subrs offset, private-relative) followed by its subrs INDEX.
90
+ const privates = cid.pools.map((pool) => {
91
+ const subrs = encodeCffIndex(pool);
92
+ const dict = new Uint8Array([29, ...int32(6), 19]);
93
+ return { bytes: concatenateBytes([dict, subrs]), dictSize: dict.length };
94
+ });
95
+ const probeTop = encodeCffIndex([cidTop(0, 0, 0)]);
96
+ const fixed = header.length + name.length + probeTop.length + strings.length + gsubrs.length;
97
+ const charstringsAt = fixed;
98
+ const privatesAt = charstringsAt + charstringsIndex.length;
99
+ let running = privatesAt;
100
+ const privateAt = privates.map((entry) => {
101
+ const at = running;
102
+ running += entry.bytes.length;
103
+ return at;
104
+ });
105
+ const fdArray = encodeCffIndex(privates.map((entry, index) => new Uint8Array([29, ...int32(entry.dictSize), 29, ...int32(privateAt[index]), 18])));
106
+ const fdArrayAt = running;
107
+ const fdSelectAt = fdArrayAt + fdArray.length;
108
+ const topDicts = encodeCffIndex([cidTop(charstringsAt, fdArrayAt, fdSelectAt)]);
109
+ return concatenateBytes([
110
+ header,
111
+ name,
112
+ topDicts,
113
+ strings,
114
+ gsubrs,
115
+ charstringsIndex,
116
+ ...privates.map((entry) => entry.bytes),
117
+ fdArray,
118
+ fdSelect,
119
+ ]);
120
+ }
121
+ function int32(value) {
122
+ const out = new Uint8Array(4);
123
+ new DataView(out.buffer).setInt32(0, value);
124
+ return [...out];
125
+ }
126
+ // FDSelect format 0: one byte per glyph.
127
+ function encodeSyntheticFdSelect(perGlyph) {
128
+ const bytes = new Uint8Array(1 + perGlyph.length);
129
+ perGlyph.forEach((fd, index) => (bytes[1 + index] = fd));
130
+ return bytes;
131
+ }
132
+ // A CFF INDEX: count, offset width, count+1 one-based offsets, then the data.
133
+ function encodeCffIndex(entries) {
134
+ if (entries.length === 0)
135
+ return new Uint8Array([0, 0]);
136
+ const offsets = [1];
137
+ for (const entry of entries)
138
+ offsets.push(offsets[offsets.length - 1] + entry.length);
139
+ const bytes = new Uint8Array(3 + offsets.length * 4 + offsets[offsets.length - 1] - 1);
140
+ const view = new DataView(bytes.buffer);
141
+ view.setUint16(0, entries.length);
142
+ view.setUint8(2, 4);
143
+ offsets.forEach((offset, index) => view.setUint32(3 + index * 4, offset));
144
+ let cursor = 3 + offsets.length * 4;
145
+ for (const entry of entries) {
146
+ bytes.set(entry, cursor);
147
+ cursor += entry.length;
148
+ }
149
+ return bytes;
150
+ }
151
+ // Wraps a plain sfnt as a WOFF, storing every table UNCOMPRESSED (the format's own equal-lengths case).
152
+ // Building the fixture uncompressed keeps the container test independent of any codec: it proves the
153
+ // unwrap-and-reassemble path on its own, and the compressed path is proved separately with a registered
154
+ // decompressor.
155
+ // `reverseTableOrder` emits the WOFF directory in DESCENDING tag order. Without it the fixture is already
156
+ // sorted, so a test asserting the rebuild sorts would pass even if the rebuild did nothing — which is
157
+ // exactly what mutation testing caught.
158
+ export function encodeSyntheticWoff(sfnt, reverseTableOrder = false) {
159
+ const view = new DataView(sfnt.buffer, sfnt.byteOffset, sfnt.byteLength);
160
+ const tableCount = view.getUint16(4);
161
+ const header = 44 + tableCount * 20;
162
+ let total = header;
163
+ const entries = [];
164
+ for (let index = 0; index < tableCount; index += 1) {
165
+ const record = 12 + index * 16;
166
+ const tag = view.getUint32(record);
167
+ const offset = view.getUint32(record + 8);
168
+ const length = view.getUint32(record + 12);
169
+ entries.push({ data: sfnt.subarray(offset, offset + length), tag });
170
+ total += (length + 3) & ~3;
171
+ }
172
+ if (reverseTableOrder)
173
+ entries.reverse();
174
+ const out = new Uint8Array(total);
175
+ const outView = new DataView(out.buffer);
176
+ outView.setUint32(0, 0x774f4646);
177
+ outView.setUint32(4, view.getUint32(0));
178
+ outView.setUint32(8, total);
179
+ outView.setUint16(12, tableCount);
180
+ let dataAt = header;
181
+ entries.forEach((entry, index) => {
182
+ const record = 44 + index * 20;
183
+ outView.setUint32(record, entry.tag);
184
+ outView.setUint32(record + 4, dataAt);
185
+ // Equal compressed and original lengths is how the format says "stored, not deflated".
186
+ outView.setUint32(record + 8, entry.data.byteLength);
187
+ outView.setUint32(record + 12, entry.data.byteLength);
188
+ // A truthful checksum, so a fixture does not claim zero for tables that sum to something else.
189
+ // Restated here rather than imported from the reader on purpose: an encoder that shared the
190
+ // reader's arithmetic could not disagree with it, and agreement between two copies of one
191
+ // mistake is what a fixture must not be able to manufacture.
192
+ outView.setUint32(record + 16, syntheticTableChecksum(entry.data, entry.tag === 0x68656164));
193
+ out.set(entry.data, dataAt);
194
+ dataAt += (entry.data.byteLength + 3) & ~3;
195
+ });
196
+ return out;
197
+ }
198
+ function assembleSfnt(sfntVersion, tables) {
199
+ const tags = [...tables.keys()].sort();
200
+ const headerBytes = 12 + tags.length * 16;
201
+ let total = headerBytes;
202
+ for (const tag of tags)
203
+ total += align4(tables.get(tag).length);
204
+ const bytes = new Uint8Array(total);
205
+ const view = new DataView(bytes.buffer);
206
+ view.setUint32(0, sfntVersion);
207
+ view.setUint16(4, tags.length);
208
+ let dataOffset = headerBytes;
209
+ tags.forEach((tag, index) => {
210
+ const record = 12 + index * 16;
211
+ for (let character = 0; character < 4; character += 1)
212
+ bytes[record + character] = tag.charCodeAt(character);
213
+ const data = tables.get(tag);
214
+ view.setUint32(record + 8, dataOffset);
215
+ view.setUint32(record + 12, data.length);
216
+ bytes.set(data, dataOffset);
217
+ dataOffset += align4(data.length);
218
+ });
219
+ return bytes;
220
+ }
221
+ function align4(value) {
222
+ return (value + 3) & ~3;
223
+ }
224
+ function concatenateBytes(chunks) {
225
+ let total = 0;
226
+ for (const chunk of chunks)
227
+ total += chunk.length;
228
+ const out = new Uint8Array(total);
229
+ let offset = 0;
230
+ for (const chunk of chunks) {
231
+ out.set(chunk, offset);
232
+ offset += chunk.length;
233
+ }
234
+ return out;
235
+ }
236
+ // Format 4, one segment per contiguous codepoint run, using the delta form. The required 0xFFFF
237
+ // terminator segment is emitted because a reader is entitled to expect it.
238
+ function encodeSyntheticCmap(codepoints) {
239
+ const entries = [...codepoints.entries()].sort((a, b) => a[0] - b[0]);
240
+ const segments = entries.map(([codePoint, glyph]) => ({
241
+ delta: (glyph - codePoint) & 0xffff,
242
+ end: codePoint,
243
+ start: codePoint,
244
+ }));
245
+ segments.push({ delta: 1, end: 0xffff, start: 0xffff });
246
+ const segmentCount = segments.length;
247
+ const subtableLength = 16 + segmentCount * 8;
248
+ const bytes = new Uint8Array(4 + 8 + subtableLength);
249
+ const view = new DataView(bytes.buffer);
250
+ view.setUint16(2, 1);
251
+ view.setUint16(4, 3);
252
+ view.setUint16(6, 1);
253
+ view.setUint32(8, 12);
254
+ const table = 12;
255
+ view.setUint16(table, 4);
256
+ view.setUint16(table + 2, subtableLength);
257
+ view.setUint16(table + 6, segmentCount * 2);
258
+ const ends = table + 14;
259
+ const starts = ends + segmentCount * 2 + 2;
260
+ const deltas = starts + segmentCount * 2;
261
+ const ranges = deltas + segmentCount * 2;
262
+ segments.forEach((segment, index) => {
263
+ view.setUint16(ends + index * 2, segment.end);
264
+ view.setUint16(starts + index * 2, segment.start);
265
+ view.setUint16(deltas + index * 2, segment.delta);
266
+ view.setUint16(ranges + index * 2, 0);
267
+ });
268
+ return bytes;
269
+ }
270
+ // One glyph: the contour count and bounding box, then end points, an empty hinting program, flags, and
271
+ // the delta-encoded coordinates. Flags are written one per point rather than run-length encoded, which
272
+ // is valid and keeps the fixture readable.
273
+ function encodeSyntheticGlyph(glyph) {
274
+ if (glyph.points.length === 0)
275
+ return new Uint8Array(0);
276
+ const contourCount = glyph.endPoints.length;
277
+ const pointCount = glyph.points.length;
278
+ const bytes = new Uint8Array(10 + contourCount * 2 + 2 + pointCount * 5);
279
+ const view = new DataView(bytes.buffer);
280
+ view.setInt16(0, contourCount);
281
+ let cursor = 10;
282
+ for (const end of glyph.endPoints) {
283
+ view.setUint16(cursor, end);
284
+ cursor += 2;
285
+ }
286
+ view.setUint16(cursor, 0);
287
+ cursor += 2;
288
+ // Flag 0x01 = on-curve. Neither short bit is set, so every coordinate is a signed 16-bit delta.
289
+ for (const point of glyph.points) {
290
+ view.setUint8(cursor, point[2] ? 0x01 : 0x00);
291
+ cursor += 1;
292
+ }
293
+ let previous = 0;
294
+ for (const point of glyph.points) {
295
+ view.setInt16(cursor, point[0] - previous);
296
+ previous = point[0];
297
+ cursor += 2;
298
+ }
299
+ previous = 0;
300
+ for (const point of glyph.points) {
301
+ view.setInt16(cursor, point[1] - previous);
302
+ previous = point[1];
303
+ cursor += 2;
304
+ }
305
+ return bytes;
306
+ }
307
+ function encodeSyntheticHead(unitsPerEm) {
308
+ const bytes = new Uint8Array(54);
309
+ const view = new DataView(bytes.buffer);
310
+ view.setUint32(0, 0x00010000);
311
+ view.setUint16(18, unitsPerEm);
312
+ // indexToLocFormat 1 — 32-bit `loca` entries, so the fixture never depends on the halving rule.
313
+ view.setInt16(50, 1);
314
+ return bytes;
315
+ }
316
+ function encodeSyntheticHhea(longMetricCount) {
317
+ const bytes = new Uint8Array(36);
318
+ const view = new DataView(bytes.buffer);
319
+ view.setInt16(4, 800);
320
+ // Stored negative, as the format states; the reader flips it to a positive descent.
321
+ view.setInt16(6, -200);
322
+ view.setInt16(8, 100);
323
+ view.setUint16(34, longMetricCount);
324
+ return bytes;
325
+ }
326
+ function encodeSyntheticHmtx(advances) {
327
+ const bytes = new Uint8Array(advances.length * 4);
328
+ const view = new DataView(bytes.buffer);
329
+ advances.forEach((advance, index) => view.setUint16(index * 4, advance));
330
+ return bytes;
331
+ }
332
+ function encodeSyntheticLoca(offsets) {
333
+ const bytes = new Uint8Array(offsets.length * 4);
334
+ const view = new DataView(bytes.buffer);
335
+ offsets.forEach((offset, index) => view.setUint32(index * 4, offset));
336
+ return bytes;
337
+ }
338
+ function encodeSyntheticMaxp(glyphCount) {
339
+ const bytes = new Uint8Array(6);
340
+ const view = new DataView(bytes.buffer);
341
+ view.setUint32(0, 0x00010000);
342
+ view.setUint16(4, glyphCount);
343
+ return bytes;
344
+ }
345
+ // Wraps a plain sfnt as a WOFF2, storing the table stream UNCOMPRESSED so a test can pass an identity
346
+ // decompressor and exercise the container without depending on a Brotli implementation. That is the same
347
+ // reason `encodeSyntheticWoff` stores its tables uncompressed: the reader treats the decompressor as an
348
+ // opaque function, so the container logic is fully reachable without a codec.
349
+ //
350
+ // `transformTags` names tables to mark as transformed — their stored bytes are left as-is, which is what
351
+ // lets a test drive the transform seam without a real transform existing.
352
+ export function encodeSyntheticWoff2(sfnt, transformTags = []) {
353
+ const view = new DataView(sfnt.buffer, sfnt.byteOffset, sfnt.byteLength);
354
+ const count = view.getUint16(4);
355
+ const tables = [];
356
+ for (let index = 0; index < count; index += 1) {
357
+ const record = 12 + index * 16;
358
+ const tag = String.fromCharCode(view.getUint8(record), view.getUint8(record + 1), view.getUint8(record + 2), view.getUint8(record + 3));
359
+ const offset = view.getUint32(record + 8);
360
+ const length = view.getUint32(record + 12);
361
+ tables.push({ data: sfnt.slice(offset, offset + length), tag });
362
+ }
363
+ const directory = [];
364
+ for (const table of tables) {
365
+ const known = WOFF2_KNOWN_TAGS.indexOf(table.tag);
366
+ const transformed = transformTags.includes(table.tag);
367
+ const isGlyphPair = table.tag === 'glyf' || table.tag === 'loca';
368
+ // The version's meaning is inverted for the glyph pair, so the encoder must invert it too or the
369
+ // fixture would declare the opposite of what it means.
370
+ const version = isGlyphPair ? (transformed ? 0 : 3) : transformed ? 1 : 0;
371
+ directory.push(((version & 3) << 6) | (known < 0 ? 0x3f : known));
372
+ if (known < 0)
373
+ for (let i = 0; i < 4; i += 1)
374
+ directory.push(table.tag.padEnd(4, ' ').charCodeAt(i));
375
+ directory.push(...base128(table.data.byteLength));
376
+ if (transformed)
377
+ directory.push(...base128(table.data.byteLength));
378
+ }
379
+ const stream = concatenateBytes(tables.map((t) => t.data));
380
+ const out = new Uint8Array(48 + directory.length + stream.byteLength);
381
+ const outView = new DataView(out.buffer);
382
+ outView.setUint32(0, 0x774f4632);
383
+ outView.setUint32(4, view.getUint32(0));
384
+ outView.setUint32(8, out.byteLength);
385
+ outView.setUint16(12, tables.length);
386
+ outView.setUint32(16, sfnt.byteLength);
387
+ outView.setUint32(20, stream.byteLength);
388
+ out.set(directory, 48);
389
+ out.set(stream, 48 + directory.length);
390
+ return out;
391
+ }
392
+ // A square, all points on-curve — the simplest shape whose corners a reader cannot fudge.
393
+ export function squareSyntheticGlyph(size) {
394
+ return {
395
+ endPoints: [3],
396
+ points: [
397
+ [0, 0, true],
398
+ [size, 0, true],
399
+ [size, size, true],
400
+ [0, size, true],
401
+ ],
402
+ };
403
+ }
404
+ // UIntBase128, most significant group first, high bit set on every byte but the last.
405
+ function base128(value) {
406
+ const groups = [];
407
+ let remaining = value;
408
+ do {
409
+ groups.unshift(remaining & 0x7f);
410
+ remaining = Math.floor(remaining / 128);
411
+ } while (remaining > 0);
412
+ return groups.map((group, index) => (index === groups.length - 1 ? group : group | 0x80));
413
+ }
414
+ const WOFF2_KNOWN_TAGS = [
415
+ 'cmap',
416
+ 'head',
417
+ 'hhea',
418
+ 'hmtx',
419
+ 'maxp',
420
+ 'name',
421
+ 'OS/2',
422
+ 'post',
423
+ 'cvt ',
424
+ 'fpgm',
425
+ 'glyf',
426
+ 'loca',
427
+ 'prep',
428
+ 'CFF ',
429
+ 'VORG',
430
+ 'EBDT',
431
+ 'EBLC',
432
+ 'gasp',
433
+ 'hdmx',
434
+ 'kern',
435
+ 'LTSH',
436
+ 'PCLT',
437
+ 'VDMX',
438
+ 'vhea',
439
+ 'vmtx',
440
+ 'BASE',
441
+ 'GDEF',
442
+ 'GPOS',
443
+ 'GSUB',
444
+ 'EBSC',
445
+ 'JSTF',
446
+ 'MATH',
447
+ 'CBDT',
448
+ 'CBLC',
449
+ 'COLR',
450
+ 'CPAL',
451
+ 'SVG ',
452
+ 'sbix',
453
+ 'acnt',
454
+ 'avar',
455
+ 'bdat',
456
+ 'bloc',
457
+ 'bsln',
458
+ 'cvar',
459
+ 'fdsc',
460
+ 'feat',
461
+ 'fmtx',
462
+ 'fvar',
463
+ 'gvar',
464
+ 'hsty',
465
+ 'just',
466
+ 'lcar',
467
+ 'mort',
468
+ 'morx',
469
+ 'opbd',
470
+ 'prop',
471
+ 'trak',
472
+ 'Zapf',
473
+ 'Silf',
474
+ 'Glat',
475
+ 'Gloc',
476
+ 'Feat',
477
+ 'Sill',
478
+ ];
479
+ // The sfnt table checksum: big-endian uint32 words summed modulo 2^32, zero-padded at the tail. For
480
+ // `head`, checkSumAdjustment at byte 8 counts as zero — otherwise the field would contain a function
481
+ // of itself and every real font would appear to mismatch.
482
+ function syntheticTableChecksum(data, isHead) {
483
+ let sum = 0;
484
+ for (let at = 0; at < data.byteLength; at += 4) {
485
+ let word = 0;
486
+ for (let byte = 0; byte < 4; byte += 1)
487
+ word = word * 256 + (data[at + byte] ?? 0);
488
+ if (isHead && at === 8)
489
+ word = 0;
490
+ sum = (sum + word) % 0x100000000;
491
+ }
492
+ return sum >>> 0;
493
+ }
494
+ //# sourceMappingURL=openTypeTestHelper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openTypeTestHelper.js","sourceRoot":"","sources":["../src/openTypeTestHelper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function assembleSfntFont(flavor: number, tables: readonly Readonly<{
2
+ data: Readonly<Uint8Array>;
3
+ tag: number;
4
+ }>[]): Uint8Array;
5
+ export declare function computeSfntTableChecksum(data: Readonly<Uint8Array>, isHeadTable?: boolean): number;
6
+ export declare function packSfntTag(tag: string): number;
7
+ //# sourceMappingURL=sfntAssembly.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sfntAssembly.d.ts","sourceRoot":"","sources":["../src/sfntAssembly.ts"],"names":[],"mappings":"AAkBA,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,QAAQ,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,GACvE,UAAU,CA8BZ;AASD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,WAAW,UAAQ,GAAG,MAAM,CAWhG;AAKD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS/C"}
@@ -0,0 +1,77 @@
1
+ // Writing a plain sfnt from tables somebody else unpacked.
2
+ //
3
+ // Both compressed wrappers end the same way: once WOFF has inflated its tables, or WOFF2 has
4
+ // decompressed and un-transformed its own, what is left is the identical job of laying out an sfnt.
5
+ // That job is the primitive, so it lives here rather than once per wrapper — an assembled font is a
6
+ // composition of the same parts however it arrived, and a second copy is where the two would drift.
7
+ const SFNT_HEADER_BYTES = 12;
8
+ const SFNT_DIRECTORY_ENTRY_BYTES = 16;
9
+ // Writes a header, a directory sorted by tag, then each table's data on a four-byte boundary.
10
+ //
11
+ // Sorting is required rather than cosmetic — the sfnt directory is defined as being in tag order, and a
12
+ // reader entitled to binary-search it would otherwise find the wrong table. Alignment follows the
13
+ // convention every real font is written with; it is not known to be enforced by consumers.
14
+ //
15
+ // `tag` is the four-character tag packed big-endian into a uint32, which is the form it is compared and
16
+ // sorted in, so no reader has to round-trip it through a string to order a directory.
17
+ export function assembleSfntFont(flavor, tables) {
18
+ const sorted = [...tables].sort((a, b) => a.tag - b.tag);
19
+ const headerBytes = SFNT_HEADER_BYTES + sorted.length * SFNT_DIRECTORY_ENTRY_BYTES;
20
+ let total = headerBytes;
21
+ for (const table of sorted)
22
+ total += (table.data.byteLength + 3) & ~3;
23
+ const out = new Uint8Array(total);
24
+ const view = new DataView(out.buffer);
25
+ view.setUint32(0, flavor);
26
+ view.setUint16(4, sorted.length);
27
+ // searchRange, entrySelector and rangeShift are derived values a reader can recompute; the reader in
28
+ // this package walks the directory linearly and never consults them, so they are left zero rather than
29
+ // written with values nothing checks.
30
+ let dataAt = headerBytes;
31
+ sorted.forEach((table, index) => {
32
+ const record = SFNT_HEADER_BYTES + index * SFNT_DIRECTORY_ENTRY_BYTES;
33
+ view.setUint32(record, table.tag);
34
+ // The real checksum, computed from the bytes being written. An assembled font that carried zeros
35
+ // here would be making a false statement about tables it holds, and any consumer that does check
36
+ // would read the zero as a mismatch.
37
+ view.setUint32(record + 4, computeSfntTableChecksum(table.data, table.tag === HEAD_TAG));
38
+ view.setUint32(record + 8, dataAt);
39
+ view.setUint32(record + 12, table.data.byteLength);
40
+ out.set(table.data, dataAt);
41
+ dataAt += (table.data.byteLength + 3) & ~3;
42
+ });
43
+ return out;
44
+ }
45
+ // The checksum an sfnt directory stores for a table: the sum of its bytes read as big-endian uint32
46
+ // words, zero-padded to a four-byte boundary, taken modulo 2^32. An interface fact about the format.
47
+ //
48
+ // ★ `head` IS THE ONE EXCEPTION AND OMITTING IT MAKES EVERY REAL FONT REPORT A MISMATCH. The table
49
+ // carries `checkSumAdjustment` at byte 8, a value derived from the whole font's checksum, and the
50
+ // format defines the table's own checksum as being computed with that field treated as ZERO —
51
+ // otherwise the value would have to contain a function of itself.
52
+ export function computeSfntTableChecksum(data, isHeadTable = false) {
53
+ let sum = 0;
54
+ for (let at = 0; at < data.byteLength; at += 4) {
55
+ // Bytes past the end read as zero, which is the padding the format defines rather than a guard.
56
+ const zeroed = isHeadTable && at === HEAD_CHECKSUM_ADJUSTMENT_OFFSET;
57
+ const word = zeroed
58
+ ? 0
59
+ : (data[at] ?? 0) * 0x1000000 + (data[at + 1] ?? 0) * 0x10000 + (data[at + 2] ?? 0) * 0x100 + (data[at + 3] ?? 0);
60
+ sum = (sum + word) % 0x100000000;
61
+ }
62
+ return sum >>> 0;
63
+ }
64
+ // Packs a four-character tag into the uint32 an sfnt directory stores it as. Tags shorter than four
65
+ // characters are padded with spaces, which is how the format spells `cvt ` and `CFF ` — a caller
66
+ // passing the unpadded name gets the same value the font carries rather than a silent mismatch.
67
+ export function packSfntTag(tag) {
68
+ const padded = tag.padEnd(4, ' ');
69
+ return (((padded.charCodeAt(0) << 24) |
70
+ (padded.charCodeAt(1) << 16) |
71
+ (padded.charCodeAt(2) << 8) |
72
+ padded.charCodeAt(3)) >>>
73
+ 0);
74
+ }
75
+ const HEAD_TAG = 0x68656164;
76
+ const HEAD_CHECKSUM_ADJUSTMENT_OFFSET = 8;
77
+ //# sourceMappingURL=sfntAssembly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sfntAssembly.js","sourceRoot":"","sources":["../src/sfntAssembly.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SfntTableDirectory } from '@flighthq/types/contract';
2
+ export declare function readSfntTableDirectory(bytes: Readonly<Uint8Array>): SfntTableDirectory | null;
3
+ export declare function readSfntTag(bytes: Readonly<Uint8Array>, offset: number): string;
4
+ //# sourceMappingURL=sfntTableDirectory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sfntTableDirectory.d.ts","sourceRoot":"","sources":["../src/sfntTableDirectory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAiBnE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,kBAAkB,GAAG,IAAI,CAoB7F;AAKD,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE/E"}