woff2-decode 0.1.2 → 0.1.4
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.
- package/README.md +8 -5
- package/dist/buffer.d.ts +1 -0
- package/dist/buffer.d.ts.map +1 -1
- package/dist/decode.d.ts.map +1 -1
- package/dist/index.cjs +306 -288
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +303 -285
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["Buffer","Buffer","brotliDecompressPure","brotliDecompress"],"sources":["../src/brotli.ts","../src/buffer.ts","../src/known-tags.ts","../src/variable-length.ts","../src/decode.ts"],"sourcesContent":["// Import only the decompress function to avoid loading the encoder\n// which has browser-specific code that fails in Node test environments\nimport brotliDecompress from 'brotli/decompress';\n\ntype DecompressFn = (buf: Uint8Array) => Uint8Array;\n\n// Native zlib Brotli (Node 11.7+)\nlet nativeBrotli: DecompressFn | null = null;\n\n// Attempt to load native implementation synchronously\n// This runs at module load time in Node, fails silently in browsers\nfunction tryLoadNative(): DecompressFn | null {\n try {\n // require() works synchronously in Node ESM via createRequire\n // but we can just check if we're in Node and use the global\n if (typeof process !== 'undefined' && process.versions?.node) {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const zlib = require('node:zlib');\n if (typeof zlib.brotliDecompressSync === 'function') {\n return (buf: Uint8Array) => {\n const result = zlib.brotliDecompressSync(buf);\n return new Uint8Array(result.buffer, result.byteOffset, result.byteLength);\n };\n }\n }\n } catch {\n // Not in Node or zlib unavailable\n }\n return null;\n}\n\nnativeBrotli = tryLoadNative();\n\nexport function decompress(data: Uint8Array): Uint8Array {\n if (nativeBrotli) {\n return nativeBrotli(data);\n }\n return brotliDecompress(data);\n}\n\n// Explicit implementations for benchmarking\nexport function decompressNative(data: Uint8Array): Uint8Array {\n if (!nativeBrotli) {\n throw new Error('Native Brotli not available');\n }\n return nativeBrotli(data);\n}\n\nexport function decompressPure(data: Uint8Array): Uint8Array {\n return brotliDecompress(data);\n}\n\nexport const hasNative = nativeBrotli !== null;\n","// Binary reader with bounds checking\nexport class Buffer {\n private view: DataView;\n private pos: number = 0;\n\n constructor(data: ArrayBuffer | Uint8Array, offset: number = 0, length?: number) {\n if (data instanceof Uint8Array) {\n const len = length ?? data.byteLength - offset;\n this.view = new DataView(data.buffer, data.byteOffset + offset, len);\n } else {\n const len = length ?? data.byteLength - offset;\n this.view = new DataView(data, offset, len);\n }\n }\n\n get offset(): number {\n return this.pos;\n }\n\n get length(): number {\n return this.view.byteLength;\n }\n\n get remaining(): number {\n return this.view.byteLength - this.pos;\n }\n\n get buffer(): DataView {\n return this.view;\n }\n\n skip(n: number): boolean {\n if (this.pos + n > this.view.byteLength || this.pos + n < this.pos) {\n return false;\n }\n this.pos += n;\n return true;\n }\n\n seek(offset: number): boolean {\n if (offset > this.view.byteLength || offset < 0) {\n return false;\n }\n this.pos = offset;\n return true;\n }\n\n readU8(): number | null {\n if (this.pos + 1 > this.view.byteLength) return null;\n return this.view.getUint8(this.pos++);\n }\n\n readU16(): number | null {\n if (this.pos + 2 > this.view.byteLength) return null;\n const val = this.view.getUint16(this.pos, false); // big-endian\n this.pos += 2;\n return val;\n }\n\n readS16(): number | null {\n if (this.pos + 2 > this.view.byteLength) return null;\n const val = this.view.getInt16(this.pos, false); // big-endian\n this.pos += 2;\n return val;\n }\n\n readU32(): number | null {\n if (this.pos + 4 > this.view.byteLength) return null;\n const val = this.view.getUint32(this.pos, false); // big-endian\n this.pos += 4;\n return val;\n }\n\n readS32(): number | null {\n if (this.pos + 4 > this.view.byteLength) return null;\n const val = this.view.getInt32(this.pos, false); // big-endian\n this.pos += 4;\n return val;\n }\n\n readBytes(n: number): Uint8Array | null {\n if (this.pos + n > this.view.byteLength || n < 0) return null;\n const result = new Uint8Array(this.view.buffer, this.view.byteOffset + this.pos, n);\n this.pos += n;\n return result;\n }\n\n peekU8(offset: number = 0): number | null {\n const idx = this.pos + offset;\n if (idx >= this.view.byteLength || idx < 0) return null;\n return this.view.getUint8(idx);\n }\n\n subarray(offset: number, length: number): Uint8Array | null {\n if (offset + length > this.view.byteLength || offset < 0 || length < 0) {\n return null;\n }\n return new Uint8Array(this.view.buffer, this.view.byteOffset + offset, length);\n }\n}\n","// Tables with index < 63 use single-byte encoding in WOFF2\n// Order matches the reference implementation\nexport const KNOWN_TAGS: readonly number[] = [\n 0x636d6170, // 0 cmap\n 0x68656164, // 1 head\n 0x68686561, // 2 hhea\n 0x686d7478, // 3 hmtx\n 0x6d617870, // 4 maxp\n 0x6e616d65, // 5 name\n 0x4f532f32, // 6 OS/2\n 0x706f7374, // 7 post\n 0x63767420, // 8 cvt \n 0x6670676d, // 9 fpgm\n 0x676c7966, // 10 glyf\n 0x6c6f6361, // 11 loca\n 0x70726570, // 12 prep\n 0x43464620, // 13 CFF \n 0x564f5247, // 14 VORG\n 0x45424454, // 15 EBDT\n 0x45424c43, // 16 EBLC\n 0x67617370, // 17 gasp\n 0x68646d78, // 18 hdmx\n 0x6b65726e, // 19 kern\n 0x4c545348, // 20 LTSH\n 0x50434c54, // 21 PCLT\n 0x56444d58, // 22 VDMX\n 0x76686561, // 23 vhea\n 0x766d7478, // 24 vmtx\n 0x42415345, // 25 BASE\n 0x47444546, // 26 GDEF\n 0x47504f53, // 27 GPOS\n 0x47535542, // 28 GSUB\n 0x45425343, // 29 EBSC\n 0x4a535446, // 30 JSTF\n 0x4d415448, // 31 MATH\n 0x43424454, // 32 CBDT\n 0x43424c43, // 33 CBLC\n 0x434f4c52, // 34 COLR\n 0x4350414c, // 35 CPAL\n 0x53564720, // 36 SVG \n 0x73626978, // 37 sbix\n 0x61636e74, // 38 acnt\n 0x61766172, // 39 avar\n 0x62646174, // 40 bdat\n 0x626c6f63, // 41 bloc\n 0x62736c6e, // 42 bsln\n 0x63766172, // 43 cvar\n 0x66647363, // 44 fdsc\n 0x66656174, // 45 feat\n 0x666d7478, // 46 fmtx\n 0x66766172, // 47 fvar\n 0x67766172, // 48 gvar\n 0x68737479, // 49 hsty\n 0x6a757374, // 50 just\n 0x6c636172, // 51 lcar\n 0x6d6f7274, // 52 mort\n 0x6d6f7278, // 53 morx\n 0x6f706264, // 54 opbd\n 0x70726f70, // 55 prop\n 0x7472616b, // 56 trak\n 0x5a617066, // 57 Zapf\n 0x53696c66, // 58 Silf\n 0x476c6174, // 59 Glat\n 0x476c6f63, // 60 Gloc\n 0x46656174, // 61 Feat\n 0x53696c6c, // 62 Sill\n] as const;\n\n// Table tag constants for quick access\nexport const TAG_GLYF = 0x676c7966;\nexport const TAG_LOCA = 0x6c6f6361;\nexport const TAG_HMTX = 0x686d7478;\nexport const TAG_HHEA = 0x68686561;\nexport const TAG_HEAD = 0x68656164;\nexport const TAG_CFF = 0x43464620;\nexport const TAG_CFF2 = 0x43464632;\n\n// TTC flavor\nexport const TTC_FLAVOR = 0x74746366; // 'ttcf'\n\n// WOFF2 signature\nexport const WOFF2_SIGNATURE = 0x774f4632; // 'wOF2'\n\n// Transform flag bit\nexport const WOFF2_FLAGS_TRANSFORM = 1 << 5;\n\nexport function tagToString(tag: number): string {\n return String.fromCharCode(\n (tag >> 24) & 0xff,\n (tag >> 16) & 0xff,\n (tag >> 8) & 0xff,\n tag & 0xff\n );\n}\n","import { Buffer } from './buffer';\n\n// Variable length encoding for values 0-65535 (WOFF2 spec 6.1.1)\nexport function read255UShort(buf: Buffer): number | null {\n const code = buf.readU8();\n if (code === null) return null;\n\n if (code === 253) {\n // Word follows\n return buf.readU16();\n } else if (code === 255) {\n // One more byte, value = 253 + next byte\n const next = buf.readU8();\n if (next === null) return null;\n return 253 + next;\n } else if (code === 254) {\n // One more byte, value = 506 + next byte\n const next = buf.readU8();\n if (next === null) return null;\n return 253 * 2 + next;\n } else {\n return code;\n }\n}\n\n// Variable length encoding for larger values (WOFF2 spec 6.1.2)\nexport function readBase128(buf: Buffer): number | null {\n let result = 0;\n\n for (let i = 0; i < 5; i++) {\n const code = buf.readU8();\n if (code === null) return null;\n\n // Leading zeros are invalid\n if (i === 0 && code === 0x80) {\n return null;\n }\n\n // Check for overflow - if any of the top 7 bits are set, we'll overflow\n if ((result & 0xfe000000) !== 0) {\n return null;\n }\n\n result = (result << 7) | (code & 0x7f);\n\n // If high bit is not set, we're done\n if ((code & 0x80) === 0) {\n return result;\n }\n }\n\n // Too many bytes\n return null;\n}\n\nexport function write255UShort(value: number): Uint8Array {\n if (value < 253) {\n return new Uint8Array([value]);\n } else if (value < 506) {\n return new Uint8Array([255, value - 253]);\n } else if (value < 762) {\n return new Uint8Array([254, value - 506]);\n } else {\n return new Uint8Array([253, (value >> 8) & 0xff, value & 0xff]);\n }\n}\n\nexport function size255UShort(value: number): number {\n if (value < 253) return 1;\n if (value < 762) return 2;\n return 3;\n}\n","import { decompress as brotliDecompress, decompressPure as brotliDecompressPure } from './brotli';\nimport { Buffer } from './buffer';\nimport {\n KNOWN_TAGS,\n TAG_GLYF,\n TAG_LOCA,\n TAG_HMTX,\n TAG_HHEA,\n TAG_HEAD,\n TTC_FLAVOR,\n WOFF2_SIGNATURE,\n WOFF2_FLAGS_TRANSFORM,\n tagToString,\n} from './known-tags';\nimport { readBase128, read255UShort } from './variable-length';\n\n// SFNT constants\nconst SFNT_HEADER_SIZE = 12;\nconst SFNT_ENTRY_SIZE = 16;\n\ninterface Table {\n tag: number;\n flags: number;\n origLength: number;\n transformLength: number;\n srcOffset: number;\n srcLength: number;\n dstOffset: number;\n dstLength: number;\n}\n\ninterface FontInfo {\n numGlyphs: number;\n indexFormat: number;\n numHMetrics: number;\n xMins: Int16Array;\n tableEntryByTag: Map<number, number>;\n}\n\ninterface TtcFont {\n flavor: number;\n dstOffset: number;\n headerChecksum: number;\n tableIndices: number[];\n}\n\ninterface Woff2Header {\n flavor: number;\n headerVersion: number;\n numTables: number;\n compressedOffset: number;\n compressedLength: number;\n uncompressedSize: number;\n tables: Table[];\n ttcFonts: TtcFont[];\n}\n\nexport interface DecodeOptions {\n forcePureBrotli?: boolean;\n}\n\n// Decode a WOFF2 font to TTF/OTF format\nexport function decode(data: ArrayBuffer | Uint8Array, options?: DecodeOptions): Uint8Array {\n const input = data instanceof Uint8Array ? data : new Uint8Array(data);\n const buf = new Buffer(input);\n\n // Read and validate header\n const header = readHeader(buf, input.byteLength);\n if (!header) {\n throw new Error('Failed to read WOFF2 header');\n }\n\n // Decompress table data\n const compressedData = input.subarray(\n header.compressedOffset,\n header.compressedOffset + header.compressedLength\n );\n\n const decompressFn = options?.forcePureBrotli ? brotliDecompressPure : brotliDecompress;\n const decompressed = decompressFn(compressedData);\n if (!decompressed || decompressed.byteLength !== header.uncompressedSize) {\n throw new Error(\n `Brotli decompression failed: expected ${header.uncompressedSize} bytes, got ${decompressed?.byteLength ?? 0}`\n );\n }\n\n // Calculate output size\n const firstTableOffset = computeOffsetToFirstTable(header);\n let outputSize = firstTableOffset;\n for (const table of header.tables) {\n outputSize += table.origLength;\n outputSize += (4 - (table.origLength % 4)) % 4; // padding\n }\n\n // Allocate output buffer\n const output = new Uint8Array(outputSize);\n const outView = new DataView(output.buffer);\n\n // Write headers\n const fontInfos = writeHeaders(header, output, outView);\n\n // Track written tables by (tag, srcOffset) to handle TTC table sharing\n const writtenTables = new Map<string, { dstOffset: number; dstLength: number; checksum: number }>();\n let nextTableOffset = computeOffsetToFirstTable(header);\n\n // Reconstruct font(s)\n if (header.ttcFonts.length > 0) {\n // TTC - multiple fonts\n for (let i = 0; i < header.ttcFonts.length; i++) {\n nextTableOffset = reconstructFont(\n decompressed, header, i, fontInfos[i], output, outView,\n writtenTables, nextTableOffset\n );\n }\n } else {\n // Single font\n reconstructFont(\n decompressed, header, 0, fontInfos[0], output, outView,\n writtenTables, nextTableOffset\n );\n }\n\n return output;\n}\n\nfunction readHeader(buf: Buffer, totalLength: number): Woff2Header | null {\n const signature = buf.readU32();\n if (signature !== WOFF2_SIGNATURE) {\n return null;\n }\n\n const flavor = buf.readU32();\n if (flavor === null) return null;\n\n const length = buf.readU32();\n if (length === null || length !== totalLength) return null;\n\n const numTables = buf.readU16();\n if (numTables === null || numTables === 0) return null;\n\n // Skip reserved\n if (!buf.skip(2)) return null;\n\n // Skip totalSfntSize (we compute it ourselves)\n if (!buf.skip(4)) return null;\n\n const compressedLength = buf.readU32();\n if (compressedLength === null) return null;\n\n // Skip majorVersion, minorVersion\n if (!buf.skip(4)) return null;\n\n const metaOffset = buf.readU32();\n const metaLength = buf.readU32();\n const metaOrigLength = buf.readU32();\n if (metaOffset === null || metaLength === null || metaOrigLength === null) return null;\n\n if (metaOffset !== 0) {\n if (metaOffset >= totalLength || totalLength - metaOffset < metaLength) {\n return null;\n }\n }\n\n const privOffset = buf.readU32();\n const privLength = buf.readU32();\n if (privOffset === null || privLength === null) return null;\n\n if (privOffset !== 0) {\n if (privOffset >= totalLength || totalLength - privOffset < privLength) {\n return null;\n }\n }\n\n // Read table directory\n const tables = readTableDirectory(buf, numTables);\n if (!tables) return null;\n\n // Calculate uncompressed size from last table\n const lastTable = tables[tables.length - 1];\n const uncompressedSize = lastTable.srcOffset + lastTable.srcLength;\n\n let headerVersion = 0;\n const ttcFonts: TtcFont[] = [];\n\n // Handle TTC (font collection)\n if (flavor === TTC_FLAVOR) {\n headerVersion = buf.readU32() ?? 0;\n if (headerVersion !== 0x00010000 && headerVersion !== 0x00020000) {\n return null;\n }\n\n const numFonts = read255UShort(buf);\n if (numFonts === null || numFonts === 0) return null;\n\n for (let i = 0; i < numFonts; i++) {\n const fontNumTables = read255UShort(buf);\n if (fontNumTables === null || fontNumTables === 0) return null;\n\n const fontFlavor = buf.readU32();\n if (fontFlavor === null) return null;\n\n const tableIndices: number[] = [];\n for (let j = 0; j < fontNumTables; j++) {\n const idx = read255UShort(buf);\n if (idx === null || idx >= tables.length) return null;\n tableIndices.push(idx);\n }\n\n ttcFonts.push({\n flavor: fontFlavor,\n dstOffset: 0,\n headerChecksum: 0,\n tableIndices,\n });\n }\n }\n\n return {\n flavor,\n headerVersion,\n numTables,\n compressedOffset: buf.offset,\n compressedLength,\n uncompressedSize,\n tables,\n ttcFonts,\n };\n}\n\nfunction readTableDirectory(buf: Buffer, numTables: number): Table[] | null {\n const tables: Table[] = [];\n let srcOffset = 0;\n\n for (let i = 0; i < numTables; i++) {\n const flagByte = buf.readU8();\n if (flagByte === null) return null;\n\n let tag: number;\n if ((flagByte & 0x3f) === 0x3f) {\n // Arbitrary tag follows\n tag = buf.readU32() ?? 0;\n if (tag === 0) return null;\n } else {\n tag = KNOWN_TAGS[flagByte & 0x3f];\n }\n\n const xformVersion = (flagByte >> 6) & 0x03;\n let flags = 0;\n\n // glyf/loca: xform version 0 means transform applied\n // others: xform version != 0 means transform applied\n if (tag === TAG_GLYF || tag === TAG_LOCA) {\n if (xformVersion === 0) {\n flags |= WOFF2_FLAGS_TRANSFORM;\n }\n } else if (xformVersion !== 0) {\n flags |= WOFF2_FLAGS_TRANSFORM;\n }\n flags |= xformVersion;\n\n const origLength = readBase128(buf);\n if (origLength === null) return null;\n\n let transformLength = origLength;\n if ((flags & WOFF2_FLAGS_TRANSFORM) !== 0) {\n transformLength = readBase128(buf) ?? 0;\n if (transformLength === 0 && tag !== TAG_LOCA) return null;\n if (tag === TAG_LOCA && transformLength !== 0) return null;\n }\n\n tables.push({\n tag,\n flags,\n origLength,\n transformLength,\n srcOffset,\n srcLength: transformLength,\n dstOffset: 0,\n dstLength: origLength,\n });\n\n srcOffset += transformLength;\n }\n\n return tables;\n}\n\nfunction computeOffsetToFirstTable(header: Woff2Header): number {\n if (header.ttcFonts.length === 0) {\n return SFNT_HEADER_SIZE + SFNT_ENTRY_SIZE * header.numTables;\n }\n\n // TTC header size\n let offset = 12; // ttcTag, version, numFonts\n offset += 4 * header.ttcFonts.length; // offset table\n if (header.headerVersion === 0x00020000) {\n offset += 12; // DSIG fields\n }\n\n // Offset tables for each font\n for (const ttcFont of header.ttcFonts) {\n offset += SFNT_HEADER_SIZE;\n offset += SFNT_ENTRY_SIZE * ttcFont.tableIndices.length;\n }\n\n return offset;\n}\n\nfunction writeHeaders(\n header: Woff2Header,\n output: Uint8Array,\n outView: DataView\n): FontInfo[] {\n const fontInfos: FontInfo[] = [];\n let offset = 0;\n\n if (header.ttcFonts.length > 0) {\n // TTC header\n outView.setUint32(offset, header.flavor); // ttcTag\n offset += 4;\n outView.setUint32(offset, header.headerVersion);\n offset += 4;\n outView.setUint32(offset, header.ttcFonts.length);\n offset += 4;\n\n const offsetTableStart = offset;\n offset += 4 * header.ttcFonts.length; // Space for offset table\n\n if (header.headerVersion === 0x00020000) {\n // DSIG fields (zeroed)\n offset += 12;\n }\n\n // Write each font's offset table\n for (let i = 0; i < header.ttcFonts.length; i++) {\n const ttcFont = header.ttcFonts[i];\n outView.setUint32(offsetTableStart + i * 4, offset);\n ttcFont.dstOffset = offset;\n\n const numTables = ttcFont.tableIndices.length;\n offset = writeOffsetTable(outView, offset, ttcFont.flavor, numTables);\n\n // Sort table indices by tag for this font\n const sortedIndices = [...ttcFont.tableIndices].sort(\n (a, b) => header.tables[a].tag - header.tables[b].tag\n );\n\n const tableEntryByTag = new Map<number, number>();\n for (const tableIdx of sortedIndices) {\n const table = header.tables[tableIdx];\n tableEntryByTag.set(table.tag, offset);\n offset = writeTableEntry(outView, offset, table.tag);\n }\n\n // Update tableIndices to sorted order for later reconstruction\n ttcFont.tableIndices = sortedIndices;\n\n ttcFont.headerChecksum = computeChecksum(\n output,\n ttcFont.dstOffset,\n offset - ttcFont.dstOffset\n );\n\n fontInfos.push({\n numGlyphs: 0,\n indexFormat: 0,\n numHMetrics: 0,\n xMins: new Int16Array(0),\n tableEntryByTag,\n });\n }\n } else {\n // Single font\n offset = writeOffsetTable(outView, offset, header.flavor, header.numTables);\n\n // Sort tables by tag for output\n const sortedTables = [...header.tables].sort((a, b) => a.tag - b.tag);\n const tableEntryByTag = new Map<number, number>();\n\n for (const table of sortedTables) {\n tableEntryByTag.set(table.tag, offset);\n offset = writeTableEntry(outView, offset, table.tag);\n }\n\n fontInfos.push({\n numGlyphs: 0,\n indexFormat: 0,\n numHMetrics: 0,\n xMins: new Int16Array(0),\n tableEntryByTag,\n });\n }\n\n return fontInfos;\n}\n\nfunction writeOffsetTable(\n view: DataView,\n offset: number,\n flavor: number,\n numTables: number\n): number {\n view.setUint32(offset, flavor);\n view.setUint16(offset + 4, numTables);\n\n let maxPow2 = 0;\n while ((1 << (maxPow2 + 1)) <= numTables) {\n maxPow2++;\n }\n const searchRange = (1 << maxPow2) * 16;\n\n view.setUint16(offset + 6, searchRange);\n view.setUint16(offset + 8, maxPow2);\n view.setUint16(offset + 10, numTables * 16 - searchRange);\n\n return offset + SFNT_HEADER_SIZE;\n}\n\nfunction writeTableEntry(view: DataView, offset: number, tag: number): number {\n view.setUint32(offset, tag);\n view.setUint32(offset + 4, 0); // checksum placeholder\n view.setUint32(offset + 8, 0); // offset placeholder\n view.setUint32(offset + 12, 0); // length placeholder\n return offset + SFNT_ENTRY_SIZE;\n}\n\nfunction reconstructFont(\n decompressed: Uint8Array,\n header: Woff2Header,\n fontIndex: number,\n fontInfo: FontInfo,\n output: Uint8Array,\n outView: DataView,\n writtenTables: Map<string, { dstOffset: number; dstLength: number; checksum: number }>,\n dstOffset: number\n): number {\n const tables =\n header.ttcFonts.length > 0\n ? header.ttcFonts[fontIndex].tableIndices.map((i) => header.tables[i])\n : header.tables;\n\n // Sort tables for processing\n const sortedTables = [...tables].sort((a, b) => a.tag - b.tag);\n\n // First pass: find glyf/loca and hhea for metadata\n const glyfTable = sortedTables.find((t) => t.tag === TAG_GLYF);\n const locaTable = sortedTables.find((t) => t.tag === TAG_LOCA);\n const hheaTable = sortedTables.find((t) => t.tag === TAG_HHEA);\n\n if (hheaTable) {\n const hheaData = decompressed.subarray(\n hheaTable.srcOffset,\n hheaTable.srcOffset + hheaTable.srcLength\n );\n if (hheaData.byteLength >= 36) {\n const hheaView = new DataView(hheaData.buffer, hheaData.byteOffset);\n fontInfo.numHMetrics = hheaView.getUint16(34);\n }\n }\n\n // Initialize font checksum for TTC (for single fonts, we compute at the end)\n let fontChecksum = header.ttcFonts.length > 0\n ? header.ttcFonts[fontIndex].headerChecksum\n : 0;\n const isTTC = header.ttcFonts.length > 0;\n\n // Write each table\n for (const table of sortedTables) {\n const entryOffset = fontInfo.tableEntryByTag.get(table.tag);\n if (entryOffset === undefined) continue;\n\n // Check if this table was already written (TTC table sharing)\n const tableKey = `${table.tag}:${table.srcOffset}`;\n const existing = writtenTables.get(tableKey);\n if (existing) {\n // Reuse the existing table\n updateTableEntry(outView, entryOffset, existing.checksum, existing.dstOffset, existing.dstLength);\n if (isTTC) {\n // Add its checksum to font checksum\n fontChecksum = (fontChecksum + existing.checksum) >>> 0;\n // Add checksum of the 12-byte table entry update\n fontChecksum = (fontChecksum + computeTableEntryChecksum(existing.checksum, existing.dstOffset, existing.dstLength)) >>> 0;\n }\n continue;\n }\n\n table.dstOffset = dstOffset;\n\n let tableData: Uint8Array;\n let checksum: number;\n\n if ((table.flags & WOFF2_FLAGS_TRANSFORM) !== 0) {\n if (table.tag === TAG_GLYF && glyfTable && locaTable) {\n // Reconstruct glyf/loca\n const result = reconstructGlyf(\n decompressed,\n glyfTable,\n locaTable,\n fontInfo\n );\n tableData = result.glyfData;\n glyfTable.dstLength = result.glyfData.byteLength;\n locaTable.dstOffset = dstOffset + pad4(result.glyfData.byteLength);\n locaTable.dstLength = result.locaData.byteLength;\n\n // Write glyf\n output.set(tableData, dstOffset);\n checksum = computeChecksum(output, dstOffset, tableData.byteLength);\n updateTableEntry(outView, entryOffset, checksum, dstOffset, tableData.byteLength);\n if (isTTC) {\n fontChecksum = (fontChecksum + checksum) >>> 0;\n fontChecksum = (fontChecksum + computeTableEntryChecksum(checksum, dstOffset, tableData.byteLength)) >>> 0;\n }\n writtenTables.set(tableKey, { dstOffset, dstLength: tableData.byteLength, checksum });\n dstOffset += pad4(tableData.byteLength);\n\n // Write loca\n const locaEntryOffset = fontInfo.tableEntryByTag.get(TAG_LOCA);\n if (locaEntryOffset !== undefined) {\n output.set(result.locaData, dstOffset);\n const locaChecksum = computeChecksum(output, dstOffset, result.locaData.byteLength);\n updateTableEntry(outView, locaEntryOffset, locaChecksum, dstOffset, result.locaData.byteLength);\n if (isTTC) {\n fontChecksum = (fontChecksum + locaChecksum) >>> 0;\n fontChecksum = (fontChecksum + computeTableEntryChecksum(locaChecksum, dstOffset, result.locaData.byteLength)) >>> 0;\n }\n const locaKey = `${TAG_LOCA}:${locaTable.srcOffset}`;\n writtenTables.set(locaKey, { dstOffset, dstLength: result.locaData.byteLength, checksum: locaChecksum });\n dstOffset += pad4(result.locaData.byteLength);\n }\n continue;\n } else if (table.tag === TAG_LOCA) {\n // Already handled with glyf\n continue;\n } else if (table.tag === TAG_HMTX) {\n // Reconstruct hmtx\n tableData = reconstructHmtx(\n decompressed,\n table,\n fontInfo.numGlyphs,\n fontInfo.numHMetrics,\n fontInfo.xMins\n );\n } else {\n throw new Error(`Unknown transform for table ${tagToString(table.tag)}`);\n }\n } else {\n // No transform, copy directly\n tableData = decompressed.subarray(\n table.srcOffset,\n table.srcOffset + table.srcLength\n );\n\n // Zero out checkSumAdjustment in head table\n if (table.tag === TAG_HEAD && tableData.byteLength >= 12) {\n tableData = new Uint8Array(tableData); // Copy to avoid modifying decompressed\n const headView = new DataView(tableData.buffer, tableData.byteOffset);\n headView.setUint32(8, 0);\n }\n }\n\n output.set(tableData, dstOffset);\n checksum = computeChecksum(output, dstOffset, tableData.byteLength);\n table.dstLength = tableData.byteLength;\n\n updateTableEntry(outView, entryOffset, checksum, dstOffset, tableData.byteLength);\n if (isTTC) {\n fontChecksum = (fontChecksum + checksum) >>> 0;\n fontChecksum = (fontChecksum + computeTableEntryChecksum(checksum, dstOffset, tableData.byteLength)) >>> 0;\n }\n writtenTables.set(tableKey, { dstOffset, dstLength: tableData.byteLength, checksum });\n dstOffset += pad4(tableData.byteLength);\n }\n\n // Update head checkSumAdjustment\n const headTable = sortedTables.find((t) => t.tag === TAG_HEAD);\n if (headTable) {\n const headEntry = writtenTables.get(`${TAG_HEAD}:${headTable.srcOffset}`);\n if (headEntry && headEntry.dstLength >= 12) {\n // For single fonts, compute checksum over entire output\n // For TTC, use accumulated fontChecksum\n const finalChecksum = isTTC\n ? fontChecksum\n : computeChecksum(output, 0, dstOffset);\n outView.setUint32(headEntry.dstOffset + 8, (0xb1b0afba - finalChecksum) >>> 0);\n }\n }\n\n return dstOffset;\n}\n\nfunction computeTableEntryChecksum(checksum: number, offset: number, length: number): number {\n return (checksum + offset + length) >>> 0;\n}\n\nfunction reconstructGlyf(\n data: Uint8Array,\n glyfTable: Table,\n locaTable: Table,\n fontInfo: FontInfo\n): { glyfData: Uint8Array; locaData: Uint8Array } {\n const buf = new Buffer(data, glyfTable.srcOffset, glyfTable.transformLength);\n\n // Read glyf header\n const version = buf.readU16();\n const optionFlags = buf.readU16();\n const numGlyphs = buf.readU16();\n const indexFormat = buf.readU16();\n\n if (version === null || optionFlags === null || numGlyphs === null || indexFormat === null) {\n throw new Error('Invalid glyf transform header');\n }\n\n fontInfo.numGlyphs = numGlyphs;\n fontInfo.indexFormat = indexFormat;\n\n // Read substream sizes\n const nContourStreamSize = buf.readU32();\n const nPointsStreamSize = buf.readU32();\n const flagStreamSize = buf.readU32();\n const glyphStreamSize = buf.readU32();\n const compositeStreamSize = buf.readU32();\n const bboxStreamSize = buf.readU32();\n const instructionStreamSize = buf.readU32();\n\n if (\n nContourStreamSize === null ||\n nPointsStreamSize === null ||\n flagStreamSize === null ||\n glyphStreamSize === null ||\n compositeStreamSize === null ||\n bboxStreamSize === null ||\n instructionStreamSize === null\n ) {\n throw new Error('Invalid glyf substream sizes');\n }\n\n // Calculate substream offsets\n let offset = buf.offset;\n const nContourStream = new Buffer(data, glyfTable.srcOffset + offset, nContourStreamSize);\n offset += nContourStreamSize;\n const nPointsStream = new Buffer(data, glyfTable.srcOffset + offset, nPointsStreamSize);\n offset += nPointsStreamSize;\n const flagStream = new Buffer(data, glyfTable.srcOffset + offset, flagStreamSize);\n offset += flagStreamSize;\n const glyphStream = new Buffer(data, glyfTable.srcOffset + offset, glyphStreamSize);\n offset += glyphStreamSize;\n const compositeStream = new Buffer(data, glyfTable.srcOffset + offset, compositeStreamSize);\n offset += compositeStreamSize;\n const bboxStream = new Buffer(data, glyfTable.srcOffset + offset, bboxStreamSize);\n offset += bboxStreamSize;\n const instructionStream = new Buffer(data, glyfTable.srcOffset + offset, instructionStreamSize);\n\n // Overlap bitmap\n const hasOverlapBitmap = (optionFlags & 1) !== 0;\n let overlapBitmap: Uint8Array | null = null;\n if (hasOverlapBitmap) {\n const overlapBitmapLength = (numGlyphs + 7) >> 3;\n overlapBitmap = data.subarray(\n glyfTable.srcOffset + offset + instructionStreamSize,\n glyfTable.srcOffset + offset + instructionStreamSize + overlapBitmapLength\n );\n }\n\n // Read bbox bitmap\n const bboxBitmapLength = ((numGlyphs + 31) >> 5) << 2;\n const bboxBitmap = bboxStream.readBytes(bboxBitmapLength);\n if (!bboxBitmap) {\n throw new Error('Failed to read bbox bitmap');\n }\n\n // Estimate output size (will be resized if needed)\n let glyfOutput = new Uint8Array(glyfTable.origLength * 2);\n let glyfOffset = 0;\n\n const locaValues: number[] = [];\n fontInfo.xMins = new Int16Array(numGlyphs);\n\n // Process each glyph\n for (let glyphId = 0; glyphId < numGlyphs; glyphId++) {\n locaValues.push(glyfOffset);\n\n const nContours = nContourStream.readS16();\n if (nContours === null) {\n throw new Error(`Failed to read nContours for glyph ${glyphId}`);\n }\n\n const haveBbox = (bboxBitmap[glyphId >> 3] & (0x80 >> (glyphId & 7))) !== 0;\n\n if (nContours === 0) {\n // Empty glyph\n if (haveBbox) {\n throw new Error(`Empty glyph ${glyphId} has bbox`);\n }\n continue;\n }\n\n if (nContours === -1) {\n // Composite glyph\n if (!haveBbox) {\n throw new Error(`Composite glyph ${glyphId} missing bbox`);\n }\n\n const { compositeData, haveInstructions } = readCompositeGlyph(compositeStream);\n\n let instructionSize = 0;\n if (haveInstructions) {\n instructionSize = read255UShort(glyphStream) ?? 0;\n }\n\n const glyphSize = 10 + compositeData.byteLength + (haveInstructions ? 2 + instructionSize : 0);\n ensureCapacity(glyphSize);\n\n // Write glyph header\n const glyphView = new DataView(glyfOutput.buffer, glyfOffset);\n glyphView.setInt16(0, -1); // nContours\n \n // Write bbox\n const bbox = bboxStream.readBytes(8);\n if (!bbox) throw new Error('Failed to read bbox');\n glyfOutput.set(bbox, glyfOffset + 2);\n\n // Store xMin\n fontInfo.xMins[glyphId] = new DataView(bbox.buffer, bbox.byteOffset).getInt16(0);\n\n // Write composite data\n glyfOutput.set(compositeData, glyfOffset + 10);\n\n if (haveInstructions) {\n const instrOffset = glyfOffset + 10 + compositeData.byteLength;\n new DataView(glyfOutput.buffer, instrOffset).setUint16(0, instructionSize);\n const instructions = instructionStream.readBytes(instructionSize);\n if (!instructions) throw new Error('Failed to read instructions');\n glyfOutput.set(instructions, instrOffset + 2);\n }\n\n glyfOffset += glyphSize;\n glyfOffset = pad4(glyfOffset);\n } else {\n // Simple glyph\n const result = reconstructSimpleGlyph(\n nContours,\n haveBbox,\n (overlapBitmap?.[glyphId >> 3] ?? 0) & (0x80 >> (glyphId & 7)),\n nPointsStream,\n flagStream,\n glyphStream,\n bboxStream,\n instructionStream\n );\n\n ensureCapacity(result.byteLength);\n glyfOutput.set(result, glyfOffset);\n\n // Store xMin\n if (result.byteLength >= 4) {\n fontInfo.xMins[glyphId] = new DataView(result.buffer, result.byteOffset).getInt16(2);\n }\n\n glyfOffset += result.byteLength;\n glyfOffset = pad4(glyfOffset);\n }\n }\n\n // Final loca entry\n locaValues.push(glyfOffset);\n\n // Build loca table\n const locaSize = indexFormat ? (numGlyphs + 1) * 4 : (numGlyphs + 1) * 2;\n const locaData = new Uint8Array(locaSize);\n const locaView = new DataView(locaData.buffer);\n\n for (let i = 0; i <= numGlyphs; i++) {\n if (indexFormat) {\n locaView.setUint32(i * 4, locaValues[i]);\n } else {\n locaView.setUint16(i * 2, locaValues[i] >> 1);\n }\n }\n\n return {\n glyfData: glyfOutput.subarray(0, glyfOffset),\n locaData,\n };\n\n function ensureCapacity(needed: number): void {\n if (glyfOffset + needed > glyfOutput.byteLength) {\n const newOutput = new Uint8Array((glyfOffset + needed) * 2);\n newOutput.set(glyfOutput);\n glyfOutput = newOutput;\n }\n }\n}\n\nfunction readCompositeGlyph(stream: Buffer): {\n compositeData: Uint8Array;\n haveInstructions: boolean;\n} {\n const FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0;\n const FLAG_WE_HAVE_A_SCALE = 1 << 3;\n const FLAG_MORE_COMPONENTS = 1 << 5;\n const FLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6;\n const FLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7;\n const FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8;\n\n const startOffset = stream.offset;\n let haveInstructions = false;\n let flags = FLAG_MORE_COMPONENTS;\n\n while (flags & FLAG_MORE_COMPONENTS) {\n flags = stream.readU16() ?? 0;\n haveInstructions = haveInstructions || (flags & FLAG_WE_HAVE_INSTRUCTIONS) !== 0;\n\n let argSize = 2; // glyph index\n if (flags & FLAG_ARG_1_AND_2_ARE_WORDS) {\n argSize += 4;\n } else {\n argSize += 2;\n }\n if (flags & FLAG_WE_HAVE_A_SCALE) {\n argSize += 2;\n } else if (flags & FLAG_WE_HAVE_AN_X_AND_Y_SCALE) {\n argSize += 4;\n } else if (flags & FLAG_WE_HAVE_A_TWO_BY_TWO) {\n argSize += 8;\n }\n\n stream.skip(argSize);\n }\n\n const compositeData = stream.subarray(startOffset, stream.offset - startOffset);\n if (!compositeData) {\n throw new Error('Failed to read composite glyph data');\n }\n\n return { compositeData, haveInstructions };\n}\n\nfunction reconstructSimpleGlyph(\n nContours: number,\n haveBbox: boolean,\n hasOverlapBit: number,\n nPointsStream: Buffer,\n flagStream: Buffer,\n glyphStream: Buffer,\n bboxStream: Buffer,\n instructionStream: Buffer\n): Uint8Array {\n // Read number of points per contour\n const pointsPerContour: number[] = [];\n let totalPoints = 0;\n for (let i = 0; i < nContours; i++) {\n const n = read255UShort(nPointsStream);\n if (n === null) throw new Error('Failed to read points count');\n pointsPerContour.push(n);\n totalPoints += n;\n }\n\n // Decode points using triplet encoding\n const points = decodeTriplets(flagStream, glyphStream, totalPoints);\n\n // Read instruction size\n const instructionSize = read255UShort(glyphStream) ?? 0;\n\n // Calculate glyph size\n // Header: 2 (nContours) + 8 (bbox) = 10\n // End points: 2 * nContours\n // Instructions: 2 + instructionSize\n // Flags + coordinates: variable\n const flagsAndCoords = encodePointsToGlyf(points, hasOverlapBit !== 0);\n const glyphSize = 10 + 2 * nContours + 2 + instructionSize + flagsAndCoords.byteLength;\n\n const output = new Uint8Array(glyphSize);\n const view = new DataView(output.buffer);\n let offset = 0;\n\n // nContours\n view.setInt16(offset, nContours);\n offset += 2;\n\n // Bbox\n if (haveBbox) {\n const bbox = bboxStream.readBytes(8);\n if (!bbox) throw new Error('Failed to read bbox');\n output.set(bbox, offset);\n } else {\n // Compute bbox from points\n let xMin = 0, yMin = 0, xMax = 0, yMax = 0;\n if (points.length > 0) {\n xMin = xMax = points[0].x;\n yMin = yMax = points[0].y;\n for (const p of points) {\n xMin = Math.min(xMin, p.x);\n xMax = Math.max(xMax, p.x);\n yMin = Math.min(yMin, p.y);\n yMax = Math.max(yMax, p.y);\n }\n }\n view.setInt16(offset, xMin);\n view.setInt16(offset + 2, yMin);\n view.setInt16(offset + 4, xMax);\n view.setInt16(offset + 6, yMax);\n }\n offset += 8;\n\n // End points of contours\n let endPoint = -1;\n for (let i = 0; i < nContours; i++) {\n endPoint += pointsPerContour[i];\n view.setUint16(offset, endPoint);\n offset += 2;\n }\n\n // Instructions\n view.setUint16(offset, instructionSize);\n offset += 2;\n if (instructionSize > 0) {\n const instructions = instructionStream.readBytes(instructionSize);\n if (!instructions) throw new Error('Failed to read instructions');\n output.set(instructions, offset);\n offset += instructionSize;\n }\n\n // Flags and coordinates\n output.set(flagsAndCoords, offset);\n\n return output;\n}\n\ninterface Point {\n x: number;\n y: number;\n onCurve: boolean;\n}\n\nfunction decodeTriplets(\n flagStream: Buffer,\n glyphStream: Buffer,\n nPoints: number\n): Point[] {\n const points: Point[] = [];\n let x = 0;\n let y = 0;\n\n for (let i = 0; i < nPoints; i++) {\n const flag = flagStream.readU8();\n if (flag === null) throw new Error('Failed to read triplet flag');\n\n const onCurve = (flag & 0x80) === 0;\n const flagLow = flag & 0x7f;\n\n let dx: number, dy: number;\n\n if (flagLow < 10) {\n // dx = 0\n dx = 0;\n const b = glyphStream.readU8();\n if (b === null) throw new Error('Failed to read triplet data');\n dy = ((flagLow & 14) << 7) + b;\n if ((flagLow & 1) === 0) dy = -dy;\n } else if (flagLow < 20) {\n // dy = 0\n const b = glyphStream.readU8();\n if (b === null) throw new Error('Failed to read triplet data');\n dx = (((flagLow - 10) & 14) << 7) + b;\n if ((flagLow & 1) === 0) dx = -dx;\n dy = 0;\n } else if (flagLow < 84) {\n // 1 byte packed\n const b = glyphStream.readU8();\n if (b === null) throw new Error('Failed to read triplet data');\n const b0 = flagLow - 20;\n dx = 1 + (b0 & 0x30) + (b >> 4);\n dy = 1 + ((b0 & 0x0c) << 2) + (b & 0x0f);\n if ((flagLow & 1) === 0) dx = -dx;\n if ((flagLow & 2) === 0) dy = -dy;\n } else if (flagLow < 120) {\n // 2 bytes\n const b0 = glyphStream.readU8();\n const b1 = glyphStream.readU8();\n if (b0 === null || b1 === null) throw new Error('Failed to read triplet data');\n const idx = flagLow - 84;\n dx = 1 + (Math.floor(idx / 12) << 8) + b0;\n dy = 1 + (((idx % 12) >> 2) << 8) + b1;\n if ((flagLow & 1) === 0) dx = -dx;\n if ((flagLow & 2) === 0) dy = -dy;\n } else if (flagLow < 124) {\n // 3 bytes\n const b0 = glyphStream.readU8();\n const b1 = glyphStream.readU8();\n const b2 = glyphStream.readU8();\n if (b0 === null || b1 === null || b2 === null) throw new Error('Failed to read triplet data');\n dx = (b0 << 4) + (b1 >> 4);\n dy = ((b1 & 0x0f) << 8) + b2;\n if ((flagLow & 1) === 0) dx = -dx;\n if ((flagLow & 2) === 0) dy = -dy;\n } else {\n // 4 bytes\n const b0 = glyphStream.readU8();\n const b1 = glyphStream.readU8();\n const b2 = glyphStream.readU8();\n const b3 = glyphStream.readU8();\n if (b0 === null || b1 === null || b2 === null || b3 === null) {\n throw new Error('Failed to read triplet data');\n }\n dx = (b0 << 8) + b1;\n dy = (b2 << 8) + b3;\n if ((flagLow & 1) === 0) dx = -dx;\n if ((flagLow & 2) === 0) dy = -dy;\n }\n\n x += dx;\n y += dy;\n points.push({ x, y, onCurve });\n }\n\n return points;\n}\n\nfunction encodePointsToGlyf(points: Point[], hasOverlapBit: boolean): Uint8Array {\n // TrueType glyph point encoding\n const FLAG_ON_CURVE = 1;\n const FLAG_X_SHORT = 1 << 1;\n const FLAG_Y_SHORT = 1 << 2;\n const FLAG_REPEAT = 1 << 3;\n const FLAG_X_SAME = 1 << 4;\n const FLAG_Y_SAME = 1 << 5;\n const FLAG_OVERLAP_SIMPLE = 1 << 6;\n\n if (points.length === 0) return new Uint8Array(0);\n\n // First pass: calculate flags and coordinate sizes\n const flags: number[] = [];\n const xCoords: number[] = [];\n const yCoords: number[] = [];\n\n let lastX = 0;\n let lastY = 0;\n\n for (let i = 0; i < points.length; i++) {\n const p = points[i];\n let flag = p.onCurve ? FLAG_ON_CURVE : 0;\n\n // Set overlap bit on first point if needed\n if (hasOverlapBit && i === 0) {\n flag |= FLAG_OVERLAP_SIMPLE;\n }\n\n const dx = p.x - lastX;\n const dy = p.y - lastY;\n\n if (dx === 0) {\n flag |= FLAG_X_SAME;\n } else if (dx >= -255 && dx <= 255) {\n flag |= FLAG_X_SHORT;\n if (dx > 0) flag |= FLAG_X_SAME;\n xCoords.push(Math.abs(dx));\n } else {\n xCoords.push(dx);\n }\n\n if (dy === 0) {\n flag |= FLAG_Y_SAME;\n } else if (dy >= -255 && dy <= 255) {\n flag |= FLAG_Y_SHORT;\n if (dy > 0) flag |= FLAG_Y_SAME;\n yCoords.push(Math.abs(dy));\n } else {\n yCoords.push(dy);\n }\n\n flags.push(flag);\n lastX = p.x;\n lastY = p.y;\n }\n\n // Encode flags with run-length compression (matching reference woff2 decoder)\n // The reference implementation writes the flag first, then on seeing a repeat,\n // sets the REPEAT bit on the previous flag and increments repeat_count.\n // At the end or when seeing a different flag, it writes the repeat_count.\n const encodedFlags: number[] = [];\n let lastFlag = -1;\n let repeatCount = 0;\n\n for (let i = 0; i < flags.length; i++) {\n const flag = flags[i];\n\n if (flag === lastFlag && repeatCount < 255) {\n // Set REPEAT bit on previous flag\n encodedFlags[encodedFlags.length - 1] |= FLAG_REPEAT;\n repeatCount++;\n } else {\n // Write repeat count if we had repeats\n if (repeatCount > 0) {\n encodedFlags.push(repeatCount);\n }\n // Write new flag\n encodedFlags.push(flag);\n repeatCount = 0;\n }\n lastFlag = flag;\n }\n\n // Write final repeat count if needed\n if (repeatCount > 0) {\n encodedFlags.push(repeatCount);\n }\n\n // Calculate total size\n let xSize = 0;\n let ySize = 0;\n let xIdx = 0;\n let yIdx = 0;\n\n for (const flag of flags) {\n if ((flag & FLAG_X_SHORT) !== 0) {\n xSize += 1;\n xIdx++;\n } else if ((flag & FLAG_X_SAME) === 0) {\n xSize += 2;\n xIdx++;\n }\n\n if ((flag & FLAG_Y_SHORT) !== 0) {\n ySize += 1;\n yIdx++;\n } else if ((flag & FLAG_Y_SAME) === 0) {\n ySize += 2;\n yIdx++;\n }\n }\n\n const output = new Uint8Array(encodedFlags.length + xSize + ySize);\n let offset = 0;\n\n // Write flags\n for (const f of encodedFlags) {\n output[offset++] = f;\n }\n\n // Write x coordinates\n xIdx = 0;\n for (const flag of flags) {\n if ((flag & FLAG_X_SHORT) !== 0) {\n output[offset++] = xCoords[xIdx++];\n } else if ((flag & FLAG_X_SAME) === 0) {\n const val = xCoords[xIdx++];\n output[offset++] = (val >> 8) & 0xff;\n output[offset++] = val & 0xff;\n }\n }\n\n // Write y coordinates\n yIdx = 0;\n for (const flag of flags) {\n if ((flag & FLAG_Y_SHORT) !== 0) {\n output[offset++] = yCoords[yIdx++];\n } else if ((flag & FLAG_Y_SAME) === 0) {\n const val = yCoords[yIdx++];\n output[offset++] = (val >> 8) & 0xff;\n output[offset++] = val & 0xff;\n }\n }\n\n return output;\n}\n\nfunction reconstructHmtx(\n data: Uint8Array,\n table: Table,\n numGlyphs: number,\n numHMetrics: number,\n xMins: Int16Array\n): Uint8Array {\n const buf = new Buffer(data, table.srcOffset, table.srcLength);\n\n const hmtxFlags = buf.readU8();\n if (hmtxFlags === null) throw new Error('Failed to read hmtx flags');\n\n const hasProportionalLsbs = (hmtxFlags & 1) === 0;\n const hasMonospaceLsbs = (hmtxFlags & 2) === 0;\n\n // Read advance widths\n const advanceWidths: number[] = [];\n for (let i = 0; i < numHMetrics; i++) {\n const w = buf.readU16();\n if (w === null) throw new Error('Failed to read advance width');\n advanceWidths.push(w);\n }\n\n // Read LSBs\n const lsbs: number[] = [];\n\n for (let i = 0; i < numHMetrics; i++) {\n if (hasProportionalLsbs) {\n const lsb = buf.readS16();\n if (lsb === null) throw new Error('Failed to read proportional LSB');\n lsbs.push(lsb);\n } else {\n lsbs.push(xMins[i]);\n }\n }\n\n for (let i = numHMetrics; i < numGlyphs; i++) {\n if (hasMonospaceLsbs) {\n const lsb = buf.readS16();\n if (lsb === null) throw new Error('Failed to read monospace LSB');\n lsbs.push(lsb);\n } else {\n lsbs.push(xMins[i]);\n }\n }\n\n // Build output\n const outputSize = numHMetrics * 4 + (numGlyphs - numHMetrics) * 2;\n const output = new Uint8Array(outputSize);\n const view = new DataView(output.buffer);\n let offset = 0;\n\n for (let i = 0; i < numGlyphs; i++) {\n if (i < numHMetrics) {\n view.setUint16(offset, advanceWidths[i]);\n offset += 2;\n }\n view.setInt16(offset, lsbs[i]);\n offset += 2;\n }\n\n return output;\n}\n\nfunction updateTableEntry(\n view: DataView,\n entryOffset: number,\n checksum: number,\n offset: number,\n length: number\n): void {\n view.setUint32(entryOffset + 4, checksum);\n view.setUint32(entryOffset + 8, offset);\n view.setUint32(entryOffset + 12, length);\n}\n\nfunction computeChecksum(data: Uint8Array, offset: number, length: number): number {\n let sum = 0;\n const end = offset + length;\n const view = new DataView(data.buffer, data.byteOffset);\n\n // Process 4-byte aligned words\n const alignedEnd = offset + (length & ~3);\n for (let i = offset; i < alignedEnd; i += 4) {\n sum = (sum + view.getUint32(i)) >>> 0;\n }\n\n // Handle remaining bytes\n if (end > alignedEnd) {\n let last = 0;\n for (let i = alignedEnd; i < end; i++) {\n last = (last << 8) | data[i];\n }\n last <<= (4 - (end - alignedEnd)) * 8;\n sum = (sum + last) >>> 0;\n }\n\n return sum;\n}\n\nfunction pad4(n: number): number {\n return (n + 3) & ~3;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["Buffer","Buffer","brotliDecompressPure","brotliDecompress"],"sources":["../src/brotli.ts","../src/buffer.ts","../src/known-tags.ts","../src/variable-length.ts","../src/decode.ts"],"sourcesContent":["// Import only the decompress function to avoid loading the encoder\n// which has browser-specific code that fails in Node test environments\nimport brotliDecompress from 'brotli/decompress.js';\n\ntype DecompressFn = (buf: Uint8Array) => Uint8Array;\n\n// Native zlib Brotli (Node 11.7+)\nlet nativeBrotli: DecompressFn | null = null;\n\n// Attempt to load native implementation synchronously\n// This runs at module load time in Node, fails silently in browsers\nfunction tryLoadNative(): DecompressFn | null {\n try {\n // require() works synchronously in Node ESM via createRequire\n // but we can just check if we're in Node and use the global\n if (typeof process !== 'undefined' && process.versions?.node) {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const zlib = require('node:zlib');\n if (typeof zlib.brotliDecompressSync === 'function') {\n return (buf: Uint8Array) => {\n const result = zlib.brotliDecompressSync(buf);\n return new Uint8Array(result.buffer, result.byteOffset, result.byteLength);\n };\n }\n }\n } catch {\n // Not in Node or zlib unavailable\n }\n return null;\n}\n\nnativeBrotli = tryLoadNative();\n\nexport function decompress(data: Uint8Array): Uint8Array {\n if (nativeBrotli) {\n return nativeBrotli(data);\n }\n return brotliDecompress(data);\n}\n\n// Explicit implementations for benchmarking\nexport function decompressNative(data: Uint8Array): Uint8Array {\n if (!nativeBrotli) {\n throw new Error('Native Brotli not available');\n }\n return nativeBrotli(data);\n}\n\nexport function decompressPure(data: Uint8Array): Uint8Array {\n return brotliDecompress(data);\n}\n\nexport const hasNative = nativeBrotli !== null;\n","// Binary reader with bounds checking\nexport class Buffer {\n private view: DataView;\n private u8: Uint8Array;\n private pos: number = 0;\n\n constructor(data: ArrayBuffer | Uint8Array, offset: number = 0, length?: number) {\n if (data instanceof Uint8Array) {\n const len = length ?? data.byteLength - offset;\n this.u8 = data.subarray(offset, offset + len);\n this.view = new DataView(data.buffer, data.byteOffset + offset, len);\n } else {\n const len = length ?? data.byteLength - offset;\n this.u8 = new Uint8Array(data, offset, len);\n this.view = new DataView(data, offset, len);\n }\n }\n\n get offset(): number {\n return this.pos;\n }\n\n get length(): number {\n return this.u8.byteLength;\n }\n\n get remaining(): number {\n return this.u8.byteLength - this.pos;\n }\n\n get buffer(): DataView {\n return this.view;\n }\n\n skip(n: number): boolean {\n if (this.pos + n > this.u8.byteLength || this.pos + n < this.pos) {\n return false;\n }\n this.pos += n;\n return true;\n }\n\n seek(offset: number): boolean {\n if (offset > this.u8.byteLength || offset < 0) {\n return false;\n }\n this.pos = offset;\n return true;\n }\n\n readU8(): number | null {\n if (this.pos + 1 > this.u8.byteLength) return null;\n return this.u8[this.pos++];\n }\n\n readU16(): number | null {\n if (this.pos + 2 > this.u8.byteLength) return null;\n const idx = this.pos;\n this.pos = idx + 2;\n return (this.u8[idx] << 8) | this.u8[idx + 1];\n }\n\n readS16(): number | null {\n if (this.pos + 2 > this.u8.byteLength) return null;\n const idx = this.pos;\n this.pos = idx + 2;\n const val = (this.u8[idx] << 8) | this.u8[idx + 1];\n return (val & 0x8000) !== 0 ? val - 0x10000 : val;\n }\n\n readU32(): number | null {\n if (this.pos + 4 > this.u8.byteLength) return null;\n const idx = this.pos;\n this.pos = idx + 4;\n return (\n (this.u8[idx] * 0x1000000 +\n ((this.u8[idx + 1] << 16) | (this.u8[idx + 2] << 8) | this.u8[idx + 3])) >>>\n 0\n );\n }\n\n readS32(): number | null {\n if (this.pos + 4 > this.u8.byteLength) return null;\n const idx = this.pos;\n this.pos = idx + 4;\n return (\n (this.u8[idx] << 24) |\n (this.u8[idx + 1] << 16) |\n (this.u8[idx + 2] << 8) |\n this.u8[idx + 3]\n );\n }\n\n readBytes(n: number): Uint8Array | null {\n if (this.pos + n > this.u8.byteLength || n < 0) return null;\n const result = this.u8.subarray(this.pos, this.pos + n);\n this.pos += n;\n return result;\n }\n\n peekU8(offset: number = 0): number | null {\n const idx = this.pos + offset;\n if (idx >= this.u8.byteLength || idx < 0) return null;\n return this.u8[idx];\n }\n\n subarray(offset: number, length: number): Uint8Array | null {\n if (offset + length > this.u8.byteLength || offset < 0 || length < 0) {\n return null;\n }\n return this.u8.subarray(offset, offset + length);\n }\n}\n","// Tables with index < 63 use single-byte encoding in WOFF2\n// Order matches the reference implementation\nexport const KNOWN_TAGS: readonly number[] = [\n 0x636d6170, // 0 cmap\n 0x68656164, // 1 head\n 0x68686561, // 2 hhea\n 0x686d7478, // 3 hmtx\n 0x6d617870, // 4 maxp\n 0x6e616d65, // 5 name\n 0x4f532f32, // 6 OS/2\n 0x706f7374, // 7 post\n 0x63767420, // 8 cvt \n 0x6670676d, // 9 fpgm\n 0x676c7966, // 10 glyf\n 0x6c6f6361, // 11 loca\n 0x70726570, // 12 prep\n 0x43464620, // 13 CFF \n 0x564f5247, // 14 VORG\n 0x45424454, // 15 EBDT\n 0x45424c43, // 16 EBLC\n 0x67617370, // 17 gasp\n 0x68646d78, // 18 hdmx\n 0x6b65726e, // 19 kern\n 0x4c545348, // 20 LTSH\n 0x50434c54, // 21 PCLT\n 0x56444d58, // 22 VDMX\n 0x76686561, // 23 vhea\n 0x766d7478, // 24 vmtx\n 0x42415345, // 25 BASE\n 0x47444546, // 26 GDEF\n 0x47504f53, // 27 GPOS\n 0x47535542, // 28 GSUB\n 0x45425343, // 29 EBSC\n 0x4a535446, // 30 JSTF\n 0x4d415448, // 31 MATH\n 0x43424454, // 32 CBDT\n 0x43424c43, // 33 CBLC\n 0x434f4c52, // 34 COLR\n 0x4350414c, // 35 CPAL\n 0x53564720, // 36 SVG \n 0x73626978, // 37 sbix\n 0x61636e74, // 38 acnt\n 0x61766172, // 39 avar\n 0x62646174, // 40 bdat\n 0x626c6f63, // 41 bloc\n 0x62736c6e, // 42 bsln\n 0x63766172, // 43 cvar\n 0x66647363, // 44 fdsc\n 0x66656174, // 45 feat\n 0x666d7478, // 46 fmtx\n 0x66766172, // 47 fvar\n 0x67766172, // 48 gvar\n 0x68737479, // 49 hsty\n 0x6a757374, // 50 just\n 0x6c636172, // 51 lcar\n 0x6d6f7274, // 52 mort\n 0x6d6f7278, // 53 morx\n 0x6f706264, // 54 opbd\n 0x70726f70, // 55 prop\n 0x7472616b, // 56 trak\n 0x5a617066, // 57 Zapf\n 0x53696c66, // 58 Silf\n 0x476c6174, // 59 Glat\n 0x476c6f63, // 60 Gloc\n 0x46656174, // 61 Feat\n 0x53696c6c, // 62 Sill\n] as const;\n\n// Table tag constants for quick access\nexport const TAG_GLYF = 0x676c7966;\nexport const TAG_LOCA = 0x6c6f6361;\nexport const TAG_HMTX = 0x686d7478;\nexport const TAG_HHEA = 0x68686561;\nexport const TAG_HEAD = 0x68656164;\nexport const TAG_CFF = 0x43464620;\nexport const TAG_CFF2 = 0x43464632;\n\n// TTC flavor\nexport const TTC_FLAVOR = 0x74746366; // 'ttcf'\n\n// WOFF2 signature\nexport const WOFF2_SIGNATURE = 0x774f4632; // 'wOF2'\n\n// Transform flag bit\nexport const WOFF2_FLAGS_TRANSFORM = 1 << 5;\n\nexport function tagToString(tag: number): string {\n return String.fromCharCode(\n (tag >> 24) & 0xff,\n (tag >> 16) & 0xff,\n (tag >> 8) & 0xff,\n tag & 0xff\n );\n}\n","import { Buffer } from './buffer';\n\n// Variable length encoding for values 0-65535 (WOFF2 spec 6.1.1)\nexport function read255UShort(buf: Buffer): number | null {\n const code = buf.readU8();\n if (code === null) return null;\n\n if (code === 253) {\n // Word follows\n return buf.readU16();\n } else if (code === 255) {\n // One more byte, value = 253 + next byte\n const next = buf.readU8();\n if (next === null) return null;\n return 253 + next;\n } else if (code === 254) {\n // One more byte, value = 506 + next byte\n const next = buf.readU8();\n if (next === null) return null;\n return 253 * 2 + next;\n } else {\n return code;\n }\n}\n\n// Variable length encoding for larger values (WOFF2 spec 6.1.2)\nexport function readBase128(buf: Buffer): number | null {\n let result = 0;\n\n for (let i = 0; i < 5; i++) {\n const code = buf.readU8();\n if (code === null) return null;\n\n // Leading zeros are invalid\n if (i === 0 && code === 0x80) {\n return null;\n }\n\n // Check for overflow - if any of the top 7 bits are set, we'll overflow\n if ((result & 0xfe000000) !== 0) {\n return null;\n }\n\n result = (result << 7) | (code & 0x7f);\n\n // If high bit is not set, we're done\n if ((code & 0x80) === 0) {\n return result;\n }\n }\n\n // Too many bytes\n return null;\n}\n\nexport function write255UShort(value: number): Uint8Array {\n if (value < 253) {\n return new Uint8Array([value]);\n } else if (value < 506) {\n return new Uint8Array([255, value - 253]);\n } else if (value < 762) {\n return new Uint8Array([254, value - 506]);\n } else {\n return new Uint8Array([253, (value >> 8) & 0xff, value & 0xff]);\n }\n}\n\nexport function size255UShort(value: number): number {\n if (value < 253) return 1;\n if (value < 762) return 2;\n return 3;\n}\n","import { decompress as brotliDecompress, decompressPure as brotliDecompressPure } from './brotli';\nimport { Buffer } from './buffer';\nimport {\n KNOWN_TAGS,\n TAG_GLYF,\n TAG_LOCA,\n TAG_HMTX,\n TAG_HHEA,\n TAG_HEAD,\n TTC_FLAVOR,\n WOFF2_SIGNATURE,\n WOFF2_FLAGS_TRANSFORM,\n tagToString,\n} from './known-tags';\nimport { readBase128, read255UShort } from './variable-length';\n\n// SFNT constants\nconst SFNT_HEADER_SIZE = 12;\nconst SFNT_ENTRY_SIZE = 16;\n\n// TrueType glyph point encoding flags\nconst FLAG_ON_CURVE = 1;\nconst FLAG_X_SHORT = 1 << 1;\nconst FLAG_Y_SHORT = 1 << 2;\nconst FLAG_REPEAT = 1 << 3;\nconst FLAG_X_SAME = 1 << 4;\nconst FLAG_Y_SAME = 1 << 5;\nconst FLAG_OVERLAP_SIMPLE = 1 << 6;\n\ninterface Table {\n tag: number;\n flags: number;\n origLength: number;\n transformLength: number;\n srcOffset: number;\n srcLength: number;\n dstOffset: number;\n dstLength: number;\n key: string;\n}\n\ninterface FontInfo {\n numGlyphs: number;\n indexFormat: number;\n numHMetrics: number;\n xMins: Int16Array;\n tableEntryByTag: Map<number, number>;\n}\n\ninterface TtcFont {\n flavor: number;\n dstOffset: number;\n headerChecksum: number;\n tableIndices: number[];\n}\n\ninterface Woff2Header {\n flavor: number;\n headerVersion: number;\n numTables: number;\n compressedOffset: number;\n compressedLength: number;\n uncompressedSize: number;\n tables: Table[];\n ttcFonts: TtcFont[];\n}\n\nexport interface DecodeOptions {\n forcePureBrotli?: boolean;\n}\n\n// Decode a WOFF2 font to TTF/OTF format\nexport function decode(data: ArrayBuffer | Uint8Array, options?: DecodeOptions): Uint8Array {\n const input = data instanceof Uint8Array ? data : new Uint8Array(data);\n const buf = new Buffer(input);\n\n // Read and validate header\n const header = readHeader(buf, input.byteLength);\n if (!header) {\n throw new Error('Failed to read WOFF2 header');\n }\n\n // Decompress table data\n const compressedData = input.subarray(\n header.compressedOffset,\n header.compressedOffset + header.compressedLength\n );\n\n const decompressFn = options?.forcePureBrotli ? brotliDecompressPure : brotliDecompress;\n const decompressed = decompressFn(compressedData);\n if (!decompressed || decompressed.byteLength !== header.uncompressedSize) {\n throw new Error(\n `Brotli decompression failed: expected ${header.uncompressedSize} bytes, got ${decompressed?.byteLength ?? 0}`\n );\n }\n\n // Calculate output size\n const firstTableOffset = computeOffsetToFirstTable(header);\n let outputSize = firstTableOffset;\n for (const table of header.tables) {\n outputSize += table.origLength;\n outputSize += (4 - (table.origLength % 4)) % 4; // padding\n }\n\n // Allocate output buffer\n const output = new Uint8Array(outputSize);\n const outView = new DataView(output.buffer);\n\n // Write headers\n const fontInfos = writeHeaders(header, output, outView);\n\n // Track written tables by tag/srcOffset for TTC table sharing\n const writtenTables = new Map<string, { dstOffset: number; dstLength: number; checksum: number }>();\n let nextTableOffset = computeOffsetToFirstTable(header);\n\n // Reconstruct font(s)\n if (header.ttcFonts.length > 0) {\n // TTC - multiple fonts\n for (let i = 0; i < header.ttcFonts.length; i++) {\n nextTableOffset = reconstructFont(\n decompressed, header, i, fontInfos[i], output, outView,\n writtenTables, nextTableOffset\n );\n }\n } else {\n // Single font\n reconstructFont(\n decompressed, header, 0, fontInfos[0], output, outView,\n writtenTables, nextTableOffset\n );\n }\n\n return output;\n}\n\nfunction readHeader(buf: Buffer, totalLength: number): Woff2Header | null {\n const signature = buf.readU32();\n if (signature !== WOFF2_SIGNATURE) {\n return null;\n }\n\n const flavor = buf.readU32();\n if (flavor === null) return null;\n\n const length = buf.readU32();\n if (length === null || length !== totalLength) return null;\n\n const numTables = buf.readU16();\n if (numTables === null || numTables === 0) return null;\n\n // Skip reserved\n if (!buf.skip(2)) return null;\n\n // Skip totalSfntSize (we compute it ourselves)\n if (!buf.skip(4)) return null;\n\n const compressedLength = buf.readU32();\n if (compressedLength === null) return null;\n\n // Skip majorVersion, minorVersion\n if (!buf.skip(4)) return null;\n\n const metaOffset = buf.readU32();\n const metaLength = buf.readU32();\n const metaOrigLength = buf.readU32();\n if (metaOffset === null || metaLength === null || metaOrigLength === null) return null;\n\n if (metaOffset !== 0) {\n if (metaOffset >= totalLength || totalLength - metaOffset < metaLength) {\n return null;\n }\n }\n\n const privOffset = buf.readU32();\n const privLength = buf.readU32();\n if (privOffset === null || privLength === null) return null;\n\n if (privOffset !== 0) {\n if (privOffset >= totalLength || totalLength - privOffset < privLength) {\n return null;\n }\n }\n\n // Read table directory\n const tables = readTableDirectory(buf, numTables);\n if (!tables) return null;\n\n // Calculate uncompressed size from last table\n const lastTable = tables[tables.length - 1];\n const uncompressedSize = lastTable.srcOffset + lastTable.srcLength;\n\n let headerVersion = 0;\n const ttcFonts: TtcFont[] = [];\n\n // Handle TTC (font collection)\n if (flavor === TTC_FLAVOR) {\n headerVersion = buf.readU32() ?? 0;\n if (headerVersion !== 0x00010000 && headerVersion !== 0x00020000) {\n return null;\n }\n\n const numFonts = read255UShort(buf);\n if (numFonts === null || numFonts === 0) return null;\n\n for (let i = 0; i < numFonts; i++) {\n const fontNumTables = read255UShort(buf);\n if (fontNumTables === null || fontNumTables === 0) return null;\n\n const fontFlavor = buf.readU32();\n if (fontFlavor === null) return null;\n\n const tableIndices: number[] = [];\n for (let j = 0; j < fontNumTables; j++) {\n const idx = read255UShort(buf);\n if (idx === null || idx >= tables.length) return null;\n tableIndices.push(idx);\n }\n\n ttcFonts.push({\n flavor: fontFlavor,\n dstOffset: 0,\n headerChecksum: 0,\n tableIndices,\n });\n }\n }\n\n return {\n flavor,\n headerVersion,\n numTables,\n compressedOffset: buf.offset,\n compressedLength,\n uncompressedSize,\n tables,\n ttcFonts,\n };\n}\n\nfunction readTableDirectory(buf: Buffer, numTables: number): Table[] | null {\n const tables: Table[] = [];\n let srcOffset = 0;\n\n for (let i = 0; i < numTables; i++) {\n const flagByte = buf.readU8();\n if (flagByte === null) return null;\n\n let tag: number;\n if ((flagByte & 0x3f) === 0x3f) {\n // Arbitrary tag follows\n tag = buf.readU32() ?? 0;\n if (tag === 0) return null;\n } else {\n tag = KNOWN_TAGS[flagByte & 0x3f];\n }\n\n const xformVersion = (flagByte >> 6) & 0x03;\n let flags = 0;\n\n // glyf/loca: xform version 0 means transform applied\n // others: xform version != 0 means transform applied\n if (tag === TAG_GLYF || tag === TAG_LOCA) {\n if (xformVersion === 0) {\n flags |= WOFF2_FLAGS_TRANSFORM;\n }\n } else if (xformVersion !== 0) {\n flags |= WOFF2_FLAGS_TRANSFORM;\n }\n flags |= xformVersion;\n\n const origLength = readBase128(buf);\n if (origLength === null) return null;\n\n let transformLength = origLength;\n if ((flags & WOFF2_FLAGS_TRANSFORM) !== 0) {\n transformLength = readBase128(buf) ?? 0;\n if (transformLength === 0 && tag !== TAG_LOCA) return null;\n if (tag === TAG_LOCA && transformLength !== 0) return null;\n }\n\n tables.push({\n tag,\n flags,\n origLength,\n transformLength,\n srcOffset,\n srcLength: transformLength,\n dstOffset: 0,\n dstLength: origLength,\n key: `${tag}:${srcOffset}`,\n });\n\n srcOffset += transformLength;\n }\n\n return tables;\n}\n\nfunction computeOffsetToFirstTable(header: Woff2Header): number {\n if (header.ttcFonts.length === 0) {\n return SFNT_HEADER_SIZE + SFNT_ENTRY_SIZE * header.numTables;\n }\n\n // TTC header size\n let offset = 12; // ttcTag, version, numFonts\n offset += 4 * header.ttcFonts.length; // offset table\n if (header.headerVersion === 0x00020000) {\n offset += 12; // DSIG fields\n }\n\n // Offset tables for each font\n for (const ttcFont of header.ttcFonts) {\n offset += SFNT_HEADER_SIZE;\n offset += SFNT_ENTRY_SIZE * ttcFont.tableIndices.length;\n }\n\n return offset;\n}\n\nfunction writeHeaders(\n header: Woff2Header,\n output: Uint8Array,\n outView: DataView\n): FontInfo[] {\n const fontInfos: FontInfo[] = [];\n let offset = 0;\n\n if (header.ttcFonts.length > 0) {\n // TTC header\n outView.setUint32(offset, header.flavor); // ttcTag\n offset += 4;\n outView.setUint32(offset, header.headerVersion);\n offset += 4;\n outView.setUint32(offset, header.ttcFonts.length);\n offset += 4;\n\n const offsetTableStart = offset;\n offset += 4 * header.ttcFonts.length; // Space for offset table\n\n if (header.headerVersion === 0x00020000) {\n // DSIG fields (zeroed)\n offset += 12;\n }\n\n // Write each font's offset table\n for (let i = 0; i < header.ttcFonts.length; i++) {\n const ttcFont = header.ttcFonts[i];\n outView.setUint32(offsetTableStart + i * 4, offset);\n ttcFont.dstOffset = offset;\n\n const numTables = ttcFont.tableIndices.length;\n offset = writeOffsetTable(outView, offset, ttcFont.flavor, numTables);\n\n // Sort table indices by tag for this font\n const sortedIndices = [...ttcFont.tableIndices].sort(\n (a, b) => header.tables[a].tag - header.tables[b].tag\n );\n\n const tableEntryByTag = new Map<number, number>();\n for (const tableIdx of sortedIndices) {\n const table = header.tables[tableIdx];\n tableEntryByTag.set(table.tag, offset);\n offset = writeTableEntry(outView, offset, table.tag);\n }\n\n // Update tableIndices to sorted order for later reconstruction\n ttcFont.tableIndices = sortedIndices;\n\n ttcFont.headerChecksum = computeChecksum(\n output,\n ttcFont.dstOffset,\n offset - ttcFont.dstOffset\n );\n\n fontInfos.push({\n numGlyphs: 0,\n indexFormat: 0,\n numHMetrics: 0,\n xMins: new Int16Array(0),\n tableEntryByTag,\n });\n }\n } else {\n // Single font\n offset = writeOffsetTable(outView, offset, header.flavor, header.numTables);\n\n // Sort tables by tag for output\n const sortedTables = [...header.tables].sort((a, b) => a.tag - b.tag);\n const tableEntryByTag = new Map<number, number>();\n\n for (const table of sortedTables) {\n tableEntryByTag.set(table.tag, offset);\n offset = writeTableEntry(outView, offset, table.tag);\n }\n\n fontInfos.push({\n numGlyphs: 0,\n indexFormat: 0,\n numHMetrics: 0,\n xMins: new Int16Array(0),\n tableEntryByTag,\n });\n }\n\n return fontInfos;\n}\n\nfunction writeOffsetTable(\n view: DataView,\n offset: number,\n flavor: number,\n numTables: number\n): number {\n view.setUint32(offset, flavor);\n view.setUint16(offset + 4, numTables);\n\n let maxPow2 = 0;\n while ((1 << (maxPow2 + 1)) <= numTables) {\n maxPow2++;\n }\n const searchRange = (1 << maxPow2) * 16;\n\n view.setUint16(offset + 6, searchRange);\n view.setUint16(offset + 8, maxPow2);\n view.setUint16(offset + 10, numTables * 16 - searchRange);\n\n return offset + SFNT_HEADER_SIZE;\n}\n\nfunction writeTableEntry(view: DataView, offset: number, tag: number): number {\n view.setUint32(offset, tag);\n view.setUint32(offset + 4, 0); // checksum placeholder\n view.setUint32(offset + 8, 0); // offset placeholder\n view.setUint32(offset + 12, 0); // length placeholder\n return offset + SFNT_ENTRY_SIZE;\n}\n\nfunction reconstructFont(\n decompressed: Uint8Array,\n header: Woff2Header,\n fontIndex: number,\n fontInfo: FontInfo,\n output: Uint8Array,\n outView: DataView,\n writtenTables: Map<string, { dstOffset: number; dstLength: number; checksum: number }>,\n dstOffset: number\n): number {\n const tables =\n header.ttcFonts.length > 0\n ? header.ttcFonts[fontIndex].tableIndices.map((i) => header.tables[i])\n : header.tables;\n\n // Sort tables for processing\n const sortedTables = [...tables].sort((a, b) => a.tag - b.tag);\n\n // First pass: find glyf/loca and hhea for metadata\n const glyfTable = sortedTables.find((t) => t.tag === TAG_GLYF);\n const locaTable = sortedTables.find((t) => t.tag === TAG_LOCA);\n const hheaTable = sortedTables.find((t) => t.tag === TAG_HHEA);\n\n if (hheaTable) {\n const hheaData = decompressed.subarray(\n hheaTable.srcOffset,\n hheaTable.srcOffset + hheaTable.srcLength\n );\n if (hheaData.byteLength >= 36) {\n const hheaView = new DataView(hheaData.buffer, hheaData.byteOffset);\n fontInfo.numHMetrics = hheaView.getUint16(34);\n }\n }\n\n // Initialize font checksum for TTC (for single fonts, we compute at the end)\n let fontChecksum = header.ttcFonts.length > 0\n ? header.ttcFonts[fontIndex].headerChecksum\n : 0;\n const isTTC = header.ttcFonts.length > 0;\n\n // Write each table\n for (const table of sortedTables) {\n const entryOffset = fontInfo.tableEntryByTag.get(table.tag);\n if (entryOffset === undefined) continue;\n\n // Check if this table was already written (TTC table sharing)\n const tKey = table.key;\n const existing = writtenTables.get(tKey);\n if (existing) {\n // Reuse the existing table\n updateTableEntry(outView, entryOffset, existing.checksum, existing.dstOffset, existing.dstLength);\n if (isTTC) {\n // Add its checksum to font checksum\n fontChecksum = (fontChecksum + existing.checksum) >>> 0;\n // Add checksum of the 12-byte table entry update\n fontChecksum = (fontChecksum + computeTableEntryChecksum(existing.checksum, existing.dstOffset, existing.dstLength)) >>> 0;\n }\n continue;\n }\n\n table.dstOffset = dstOffset;\n\n let tableData: Uint8Array;\n let checksum: number;\n\n if ((table.flags & WOFF2_FLAGS_TRANSFORM) !== 0) {\n if (table.tag === TAG_GLYF && glyfTable && locaTable) {\n // Reconstruct glyf/loca\n const result = reconstructGlyf(\n decompressed,\n glyfTable,\n locaTable,\n fontInfo\n );\n tableData = result.glyfData;\n glyfTable.dstLength = result.glyfData.byteLength;\n locaTable.dstOffset = dstOffset + pad4(result.glyfData.byteLength);\n locaTable.dstLength = result.locaData.byteLength;\n\n // Write glyf\n output.set(tableData, dstOffset);\n checksum = computeChecksum(output, dstOffset, tableData.byteLength);\n updateTableEntry(outView, entryOffset, checksum, dstOffset, tableData.byteLength);\n if (isTTC) {\n fontChecksum = (fontChecksum + checksum) >>> 0;\n fontChecksum = (fontChecksum + computeTableEntryChecksum(checksum, dstOffset, tableData.byteLength)) >>> 0;\n }\n writtenTables.set(tKey, {\n dstOffset,\n dstLength: tableData.byteLength,\n checksum,\n });\n dstOffset += pad4(tableData.byteLength);\n\n // Write loca\n const locaEntryOffset = fontInfo.tableEntryByTag.get(TAG_LOCA);\n if (locaEntryOffset !== undefined) {\n output.set(result.locaData, dstOffset);\n const locaChecksum = computeChecksum(output, dstOffset, result.locaData.byteLength);\n updateTableEntry(outView, locaEntryOffset, locaChecksum, dstOffset, result.locaData.byteLength);\n if (isTTC) {\n fontChecksum = (fontChecksum + locaChecksum) >>> 0;\n fontChecksum = (fontChecksum + computeTableEntryChecksum(locaChecksum, dstOffset, result.locaData.byteLength)) >>> 0;\n }\n writtenTables.set(locaTable.key, {\n dstOffset,\n dstLength: result.locaData.byteLength,\n checksum: locaChecksum,\n });\n dstOffset += pad4(result.locaData.byteLength);\n }\n continue;\n } else if (table.tag === TAG_LOCA) {\n // Already handled with glyf\n continue;\n } else if (table.tag === TAG_HMTX) {\n // Reconstruct hmtx\n tableData = reconstructHmtx(\n decompressed,\n table,\n fontInfo.numGlyphs,\n fontInfo.numHMetrics,\n fontInfo.xMins\n );\n } else {\n throw new Error(`Unknown transform for table ${tagToString(table.tag)}`);\n }\n } else {\n // No transform, copy directly\n tableData = decompressed.subarray(\n table.srcOffset,\n table.srcOffset + table.srcLength\n );\n\n // Zero out checkSumAdjustment in head table\n if (table.tag === TAG_HEAD && tableData.byteLength >= 12) {\n tableData = new Uint8Array(tableData); // Copy to avoid modifying decompressed\n const headView = new DataView(tableData.buffer, tableData.byteOffset);\n headView.setUint32(8, 0);\n }\n }\n\n output.set(tableData, dstOffset);\n checksum = computeChecksum(output, dstOffset, tableData.byteLength);\n table.dstLength = tableData.byteLength;\n\n updateTableEntry(outView, entryOffset, checksum, dstOffset, tableData.byteLength);\n if (isTTC) {\n fontChecksum = (fontChecksum + checksum) >>> 0;\n fontChecksum = (fontChecksum + computeTableEntryChecksum(checksum, dstOffset, tableData.byteLength)) >>> 0;\n }\n writtenTables.set(tKey, {\n dstOffset,\n dstLength: tableData.byteLength,\n checksum,\n });\n dstOffset += pad4(tableData.byteLength);\n }\n\n // Update head checkSumAdjustment\n const headTable = sortedTables.find((t) => t.tag === TAG_HEAD);\n if (headTable) {\n const headEntry = writtenTables.get(headTable.key);\n if (headEntry && headEntry.dstLength >= 12) {\n // For single fonts, compute checksum over entire output\n // For TTC, use accumulated fontChecksum\n const finalChecksum = isTTC\n ? fontChecksum\n : computeChecksum(output, 0, dstOffset);\n outView.setUint32(headEntry.dstOffset + 8, (0xb1b0afba - finalChecksum) >>> 0);\n }\n }\n\n return dstOffset;\n}\n\nfunction computeTableEntryChecksum(checksum: number, offset: number, length: number): number {\n return (checksum + offset + length) >>> 0;\n}\n\n// Lightweight byte reader to avoid Buffer class overhead in hot paths\ninterface ByteStream {\n data: Uint8Array;\n pos: number;\n end: number;\n}\n\nfunction makeByteStream(data: Uint8Array, start: number, length: number): ByteStream {\n return { data, pos: start, end: start + length };\n}\n\nfunction bsReadU8(stream: ByteStream): number {\n if (stream.pos >= stream.end) throw new Error('Stream overflow');\n return stream.data[stream.pos++];\n}\n\nfunction bsReadU16(stream: ByteStream): number {\n if (stream.pos + 2 > stream.end) throw new Error('Stream overflow');\n const idx = stream.pos;\n stream.pos = idx + 2;\n return (stream.data[idx] << 8) | stream.data[idx + 1];\n}\n\nfunction bsReadS16(stream: ByteStream): number {\n if (stream.pos + 2 > stream.end) throw new Error('Stream overflow');\n const idx = stream.pos;\n stream.pos = idx + 2;\n const val = (stream.data[idx] << 8) | stream.data[idx + 1];\n return (val & 0x8000) !== 0 ? val - 0x10000 : val;\n}\n\nfunction fsReadU32(stream: ByteStream): number {\n if (stream.pos + 4 > stream.end) throw new Error('Stream overflow');\n const idx = stream.pos;\n stream.pos = idx + 4;\n return (\n (stream.data[idx] * 0x1000000 +\n ((stream.data[idx + 1] << 16) | (stream.data[idx + 2] << 8) | stream.data[idx + 3])) >>>\n 0\n );\n}\n\nfunction bsSkip(stream: ByteStream, n: number): void {\n if (stream.pos + n > stream.end || n < 0) throw new Error('Stream overflow');\n stream.pos += n;\n}\n\nfunction fsReadBytes(stream: ByteStream, n: number): Uint8Array {\n if (stream.pos + n > stream.end || n < 0) throw new Error('Stream overflow');\n const start = stream.pos;\n stream.pos += n;\n return stream.data.subarray(start, start + n);\n}\n\nfunction bsRead255UShort(stream: ByteStream): number {\n const code = bsReadU8(stream);\n if (code === 253) {\n return bsReadU16(stream);\n } else if (code === 255) {\n return 253 + bsReadU8(stream);\n } else if (code === 254) {\n return 253 * 2 + bsReadU8(stream);\n }\n return code;\n}\n\n// WOFF2 transforms glyf/loca tables for better compression by separating\n// glyph data into streams (contours, points, flags, coordinates, composites,\n// bboxes, instructions) and using variable-length encodings. This function\n// reconstructs the original TrueType glyf and loca tables from the streams\nfunction reconstructGlyf(\n data: Uint8Array,\n glyfTable: Table,\n locaTable: Table,\n fontInfo: FontInfo\n): { glyfData: Uint8Array; locaData: Uint8Array } {\n const headerStream = makeByteStream(\n data,\n glyfTable.srcOffset,\n glyfTable.transformLength\n );\n\n // Read glyf header\n const version = bsReadU16(headerStream);\n const optionFlags = bsReadU16(headerStream);\n const numGlyphs = bsReadU16(headerStream);\n const indexFormat = bsReadU16(headerStream);\n\n fontInfo.numGlyphs = numGlyphs;\n fontInfo.indexFormat = indexFormat;\n\n // Read substream sizes\n const nContourStreamSize = fsReadU32(headerStream);\n const nPointsStreamSize = fsReadU32(headerStream);\n const flagStreamSize = fsReadU32(headerStream);\n const glyphStreamSize = fsReadU32(headerStream);\n const compositeStreamSize = fsReadU32(headerStream);\n const bboxStreamSize = fsReadU32(headerStream);\n const instructionStreamSize = fsReadU32(headerStream);\n\n // Calculate substream offsets\n let offset = headerStream.pos;\n const nContourStream = makeByteStream(data, offset, nContourStreamSize);\n offset += nContourStreamSize;\n const nPointsStream = makeByteStream(data, offset, nPointsStreamSize);\n offset += nPointsStreamSize;\n const flagStream = makeByteStream(data, offset, flagStreamSize);\n offset += flagStreamSize;\n const glyphStream = makeByteStream(data, offset, glyphStreamSize);\n offset += glyphStreamSize;\n const compositeStream = makeByteStream(data, offset, compositeStreamSize);\n offset += compositeStreamSize;\n const bboxStream = makeByteStream(data, offset, bboxStreamSize);\n offset += bboxStreamSize;\n const instructionStream = makeByteStream(data, offset, instructionStreamSize);\n\n // Overlap bitmap\n const hasOverlapBitmap = (optionFlags & 1) !== 0;\n let overlapBitmap: Uint8Array | null = null;\n if (hasOverlapBitmap) {\n const overlapBitmapLength = (numGlyphs + 7) >> 3;\n overlapBitmap = data.subarray(\n offset + instructionStreamSize,\n offset + instructionStreamSize + overlapBitmapLength\n );\n }\n\n // Read bbox bitmap\n const bboxBitmapLength = ((numGlyphs + 31) >> 5) << 2;\n const bboxBitmap = fsReadBytes(bboxStream, bboxBitmapLength);\n\n // Estimate output size (will be resized if needed)\n let glyfOutput = new Uint8Array(glyfTable.origLength * 2);\n let glyfOffset = 0;\n\n const locaValues = new Uint32Array(numGlyphs + 1);\n fontInfo.xMins = new Int16Array(numGlyphs);\n\n let contourEndsScratch = new Uint16Array(128);\n let flagsScratch = new Uint8Array(512);\n let xScratch = new Uint8Array(512);\n let yScratch = new Uint8Array(512);\n\n // Process each glyph\n for (let glyphId = 0; glyphId < numGlyphs; glyphId++) {\n locaValues[glyphId] = glyfOffset;\n\n const nContours = bsReadS16(nContourStream);\n\n const haveBbox = (bboxBitmap[glyphId >> 3] & (0x80 >> (glyphId & 7))) !== 0;\n\n if (nContours === 0) {\n // Empty glyph\n if (haveBbox) {\n throw new Error(`Empty glyph ${glyphId} has bbox`);\n }\n continue;\n }\n\n if (nContours === -1) {\n // Composite glyph\n if (!haveBbox) {\n throw new Error(`Composite glyph ${glyphId} missing bbox`);\n }\n\n const { compositeData, haveInstructions } = readCompositeGlyph(compositeStream);\n\n let instructionSize = 0;\n if (haveInstructions) {\n instructionSize = bsRead255UShort(glyphStream);\n }\n\n const glyphSize = 10 + compositeData.byteLength + (haveInstructions ? 2 + instructionSize : 0);\n ensureCapacity(glyphSize);\n\n // Write glyph header\n writeInt16BE(glyfOutput, glyfOffset, -1); // nContours\n \n // Write bbox\n const bbox = fsReadBytes(bboxStream, 8);\n glyfOutput.set(bbox, glyfOffset + 2);\n\n // Store xMin\n fontInfo.xMins[glyphId] = readInt16BE(bbox, 0);\n\n // Write composite data\n glyfOutput.set(compositeData, glyfOffset + 10);\n\n if (haveInstructions) {\n const instrOffset = glyfOffset + 10 + compositeData.byteLength;\n writeUint16BE(glyfOutput, instrOffset, instructionSize);\n const instructions = fsReadBytes(instructionStream, instructionSize);\n glyfOutput.set(instructions, instrOffset + 2);\n }\n\n glyfOffset += glyphSize;\n glyfOffset = pad4(glyfOffset);\n } else {\n // Simple glyph: write directly into output to avoid allocations\n if (nContours > contourEndsScratch.length) {\n contourEndsScratch = new Uint16Array(nContours * 2);\n }\n\n let totalPoints = 0;\n let endPoint = -1;\n for (let i = 0; i < nContours; i++) {\n const n = bsRead255UShort(nPointsStream);\n totalPoints += n;\n endPoint += n;\n contourEndsScratch[i] = endPoint;\n }\n\n const scratchSize = totalPoints * 2;\n if (scratchSize > flagsScratch.length) {\n flagsScratch = new Uint8Array(scratchSize);\n }\n if (scratchSize > xScratch.length) {\n xScratch = new Uint8Array(scratchSize);\n }\n if (scratchSize > yScratch.length) {\n yScratch = new Uint8Array(scratchSize);\n }\n\n const encoded = encodeTripletsToScratch(\n flagStream,\n glyphStream,\n totalPoints,\n ((overlapBitmap?.[glyphId >> 3] ?? 0) & (0x80 >> (glyphId & 7))) !== 0,\n flagsScratch,\n xScratch,\n yScratch\n );\n\n const instructionSize = bsRead255UShort(glyphStream);\n const glyphSize =\n 10 +\n 2 * nContours +\n 2 +\n instructionSize +\n encoded.flagsLen +\n encoded.xLen +\n encoded.yLen;\n\n ensureCapacity(glyphSize);\n\n // nContours\n writeInt16BE(glyfOutput, glyfOffset, nContours);\n\n // Bbox\n let xMin = 0;\n if (haveBbox) {\n const bbox = fsReadBytes(bboxStream, 8);\n glyfOutput.set(bbox, glyfOffset + 2);\n xMin = readInt16BE(bbox, 0);\n } else {\n writeInt16BE(glyfOutput, glyfOffset + 2, encoded.xMin);\n writeInt16BE(glyfOutput, glyfOffset + 4, encoded.yMin);\n writeInt16BE(glyfOutput, glyfOffset + 6, encoded.xMax);\n writeInt16BE(glyfOutput, glyfOffset + 8, encoded.yMax);\n xMin = encoded.xMin;\n }\n\n let writeOffset = glyfOffset + 10;\n\n // End points of contours\n for (let i = 0; i < nContours; i++) {\n writeUint16BE(glyfOutput, writeOffset, contourEndsScratch[i]);\n writeOffset += 2;\n }\n\n // Instructions\n writeUint16BE(glyfOutput, writeOffset, instructionSize);\n writeOffset += 2;\n if (instructionSize > 0) {\n const instructions = fsReadBytes(instructionStream, instructionSize);\n glyfOutput.set(instructions, writeOffset);\n writeOffset += instructionSize;\n }\n\n // Flags and coordinates\n glyfOutput.set(flagsScratch.subarray(0, encoded.flagsLen), writeOffset);\n writeOffset += encoded.flagsLen;\n glyfOutput.set(xScratch.subarray(0, encoded.xLen), writeOffset);\n writeOffset += encoded.xLen;\n glyfOutput.set(yScratch.subarray(0, encoded.yLen), writeOffset);\n\n fontInfo.xMins[glyphId] = xMin;\n glyfOffset += glyphSize;\n glyfOffset = pad4(glyfOffset);\n }\n }\n\n // Final loca entry\n locaValues[numGlyphs] = glyfOffset;\n\n // Build loca table\n const locaSize = indexFormat ? (numGlyphs + 1) * 4 : (numGlyphs + 1) * 2;\n const locaData = new Uint8Array(locaSize);\n const locaView = new DataView(locaData.buffer);\n\n for (let i = 0; i <= numGlyphs; i++) {\n if (indexFormat) {\n locaView.setUint32(i * 4, locaValues[i]);\n } else {\n locaView.setUint16(i * 2, locaValues[i] >> 1);\n }\n }\n\n return {\n glyfData: glyfOutput.subarray(0, glyfOffset),\n locaData,\n };\n\n function ensureCapacity(needed: number): void {\n if (glyfOffset + needed > glyfOutput.byteLength) {\n const newOutput = new Uint8Array((glyfOffset + needed) * 2);\n newOutput.set(glyfOutput);\n glyfOutput = newOutput;\n }\n }\n}\n\nfunction readCompositeGlyph(stream: ByteStream): {\n compositeData: Uint8Array;\n haveInstructions: boolean;\n} {\n const FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0;\n const FLAG_WE_HAVE_A_SCALE = 1 << 3;\n const FLAG_MORE_COMPONENTS = 1 << 5;\n const FLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6;\n const FLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7;\n const FLAG_WE_HAVE_INSTRUCTIONS = 1 << 8;\n\n const startOffset = stream.pos;\n let haveInstructions = false;\n let flags = FLAG_MORE_COMPONENTS;\n\n while (flags & FLAG_MORE_COMPONENTS) {\n flags = bsReadU16(stream);\n haveInstructions = haveInstructions || (flags & FLAG_WE_HAVE_INSTRUCTIONS) !== 0;\n\n let argSize = 2; // glyph index\n if (flags & FLAG_ARG_1_AND_2_ARE_WORDS) {\n argSize += 4;\n } else {\n argSize += 2;\n }\n if (flags & FLAG_WE_HAVE_A_SCALE) {\n argSize += 2;\n } else if (flags & FLAG_WE_HAVE_AN_X_AND_Y_SCALE) {\n argSize += 4;\n } else if (flags & FLAG_WE_HAVE_A_TWO_BY_TWO) {\n argSize += 8;\n }\n\n bsSkip(stream, argSize);\n }\n\n const compositeData = stream.data.subarray(startOffset, stream.pos);\n\n return { compositeData, haveInstructions };\n}\n\ninterface EncodedTriplets {\n flagsLen: number;\n xLen: number;\n yLen: number;\n xMin: number;\n yMin: number;\n xMax: number;\n yMax: number;\n}\n\n// WOFF2 encodes glyph points as \"triplets\" where a single flag byte determines\n// how dx/dy deltas are packed (see WOFF2 spec table 2). Low 7 bits select the\n// encoding format (0-9: dx=0, 10-19: dy=0, 20-83: 1-byte packed, etc), bit 7\n// indicates on-curve. This decodes triplets and re-encodes to TrueType format\nfunction encodeTripletsToScratch(\n flagStream: ByteStream,\n glyphStream: ByteStream,\n nPoints: number,\n hasOverlapBit: boolean,\n flagsOut: Uint8Array,\n xOut: Uint8Array,\n yOut: Uint8Array\n): EncodedTriplets {\n if (nPoints === 0) {\n return {\n flagsLen: 0,\n xLen: 0,\n yLen: 0,\n xMin: 0,\n yMin: 0,\n xMax: 0,\n yMax: 0,\n };\n }\n\n let flagsLen = 0;\n let xLen = 0;\n let yLen = 0;\n\n let x = 0;\n let y = 0;\n let xMin = 0;\n let yMin = 0;\n let xMax = 0;\n let yMax = 0;\n\n let lastFlag = -1;\n let repeatCount = 0;\n\n const flagData = flagStream.data;\n let flagPos = flagStream.pos;\n const flagEnd = flagStream.end;\n const glyphData = glyphStream.data;\n let glyphPos = glyphStream.pos;\n const glyphEnd = glyphStream.end;\n\n for (let i = 0; i < nPoints; i++) {\n if (flagPos >= flagEnd) throw new Error('Stream overflow');\n const flag = flagData[flagPos++];\n\n const onCurve = (flag & 0x80) === 0;\n const flagLow = flag & 0x7f;\n\n let dx: number;\n let dy: number;\n\n if (flagLow < 10) {\n // dx = 0\n dx = 0;\n if (glyphPos >= glyphEnd) throw new Error('Stream overflow');\n const b = glyphData[glyphPos++];\n dy = ((flagLow & 14) << 7) + b;\n if ((flagLow & 1) === 0) dy = -dy;\n } else if (flagLow < 20) {\n // dy = 0\n if (glyphPos >= glyphEnd) throw new Error('Stream overflow');\n const b = glyphData[glyphPos++];\n dx = (((flagLow - 10) & 14) << 7) + b;\n if ((flagLow & 1) === 0) dx = -dx;\n dy = 0;\n } else if (flagLow < 84) {\n // 1 byte packed\n if (glyphPos >= glyphEnd) throw new Error('Stream overflow');\n const b = glyphData[glyphPos++];\n const b0 = flagLow - 20;\n dx = 1 + (b0 & 0x30) + (b >> 4);\n dy = 1 + ((b0 & 0x0c) << 2) + (b & 0x0f);\n if ((flagLow & 1) === 0) dx = -dx;\n if ((flagLow & 2) === 0) dy = -dy;\n } else if (flagLow < 120) {\n // 2 bytes\n if (glyphPos + 1 >= glyphEnd) throw new Error('Stream overflow');\n const b0 = glyphData[glyphPos++];\n const b1 = glyphData[glyphPos++];\n const idx = flagLow - 84;\n dx = 1 + (((idx / 12) | 0) << 8) + b0;\n dy = 1 + (((idx % 12) >> 2) << 8) + b1;\n if ((flagLow & 1) === 0) dx = -dx;\n if ((flagLow & 2) === 0) dy = -dy;\n } else if (flagLow < 124) {\n // 3 bytes\n if (glyphPos + 2 >= glyphEnd) throw new Error('Stream overflow');\n const b0 = glyphData[glyphPos++];\n const b1 = glyphData[glyphPos++];\n const b2 = glyphData[glyphPos++];\n dx = (b0 << 4) + (b1 >> 4);\n dy = ((b1 & 0x0f) << 8) + b2;\n if ((flagLow & 1) === 0) dx = -dx;\n if ((flagLow & 2) === 0) dy = -dy;\n } else {\n // 4 bytes\n if (glyphPos + 3 >= glyphEnd) throw new Error('Stream overflow');\n const b0 = glyphData[glyphPos++];\n const b1 = glyphData[glyphPos++];\n const b2 = glyphData[glyphPos++];\n const b3 = glyphData[glyphPos++];\n dx = (b0 << 8) + b1;\n dy = (b2 << 8) + b3;\n if ((flagLow & 1) === 0) dx = -dx;\n if ((flagLow & 2) === 0) dy = -dy;\n }\n\n x += dx;\n y += dy;\n\n if (i === 0) {\n xMin = xMax = x;\n yMin = yMax = y;\n } else {\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n\n let outFlag = onCurve ? FLAG_ON_CURVE : 0;\n if (hasOverlapBit && i === 0) outFlag |= FLAG_OVERLAP_SIMPLE;\n\n if (dx === 0) {\n outFlag |= FLAG_X_SAME;\n } else if (dx >= -255 && dx <= 255) {\n outFlag |= FLAG_X_SHORT;\n if (dx > 0) outFlag |= FLAG_X_SAME;\n xOut[xLen++] = dx > 0 ? dx : -dx;\n } else {\n xOut[xLen++] = (dx >> 8) & 0xff;\n xOut[xLen++] = dx & 0xff;\n }\n\n if (dy === 0) {\n outFlag |= FLAG_Y_SAME;\n } else if (dy >= -255 && dy <= 255) {\n outFlag |= FLAG_Y_SHORT;\n if (dy > 0) outFlag |= FLAG_Y_SAME;\n yOut[yLen++] = dy > 0 ? dy : -dy;\n } else {\n yOut[yLen++] = (dy >> 8) & 0xff;\n yOut[yLen++] = dy & 0xff;\n }\n\n if (outFlag === lastFlag && repeatCount < 255) {\n flagsOut[flagsLen - 1] |= FLAG_REPEAT;\n repeatCount++;\n } else {\n if (repeatCount > 0) {\n flagsOut[flagsLen++] = repeatCount;\n repeatCount = 0;\n }\n flagsOut[flagsLen++] = outFlag;\n lastFlag = outFlag;\n }\n }\n\n if (repeatCount > 0) {\n flagsOut[flagsLen++] = repeatCount;\n }\n\n flagStream.pos = flagPos;\n glyphStream.pos = glyphPos;\n\n return {\n flagsLen,\n xLen,\n yLen,\n xMin,\n yMin,\n xMax,\n yMax,\n };\n}\n\nfunction reconstructHmtx(\n data: Uint8Array,\n table: Table,\n numGlyphs: number,\n numHMetrics: number,\n xMins: Int16Array\n): Uint8Array {\n const hmtxStream = makeByteStream(data, table.srcOffset, table.srcLength);\n\n const hmtxFlags = bsReadU8(hmtxStream);\n\n const hasProportionalLsbs = (hmtxFlags & 1) === 0;\n const hasMonospaceLsbs = (hmtxFlags & 2) === 0;\n\n // Read advance widths\n const advanceWidths = new Uint16Array(numHMetrics);\n for (let i = 0; i < numHMetrics; i++) {\n advanceWidths[i] = bsReadU16(hmtxStream);\n }\n\n // Read LSBs\n const lsbs = new Int16Array(numGlyphs);\n\n for (let i = 0; i < numHMetrics; i++) {\n if (hasProportionalLsbs) {\n lsbs[i] = bsReadS16(hmtxStream);\n } else {\n lsbs[i] = xMins[i];\n }\n }\n\n for (let i = numHMetrics; i < numGlyphs; i++) {\n if (hasMonospaceLsbs) {\n lsbs[i] = bsReadS16(hmtxStream);\n } else {\n lsbs[i] = xMins[i];\n }\n }\n\n // Build output\n const outputSize = numHMetrics * 4 + (numGlyphs - numHMetrics) * 2;\n const output = new Uint8Array(outputSize);\n let offset = 0;\n\n for (let i = 0; i < numGlyphs; i++) {\n if (i < numHMetrics) {\n writeUint16BE(output, offset, advanceWidths[i]);\n offset += 2;\n }\n writeInt16BE(output, offset, lsbs[i]);\n offset += 2;\n }\n\n return output;\n}\n\nfunction updateTableEntry(\n view: DataView,\n entryOffset: number,\n checksum: number,\n offset: number,\n length: number\n): void {\n view.setUint32(entryOffset + 4, checksum);\n view.setUint32(entryOffset + 8, offset);\n view.setUint32(entryOffset + 12, length);\n}\n\nfunction readInt16BE(data: Uint8Array, offset: number): number {\n const val = (data[offset] << 8) | data[offset + 1];\n return (val & 0x8000) !== 0 ? val - 0x10000 : val;\n}\n\nfunction writeInt16BE(data: Uint8Array, offset: number, value: number): void {\n data[offset] = (value >> 8) & 0xff;\n data[offset + 1] = value & 0xff;\n}\n\nfunction writeUint16BE(data: Uint8Array, offset: number, value: number): void {\n data[offset] = (value >> 8) & 0xff;\n data[offset + 1] = value & 0xff;\n}\n\nfunction computeChecksum(data: Uint8Array, offset: number, length: number): number {\n let sum = 0;\n const end = offset + length;\n const dataView = new DataView(data.buffer, data.byteOffset);\n\n // Process 4-byte aligned words\n const alignedEnd = offset + (length & ~3);\n for (let i = offset; i < alignedEnd; i += 4) {\n sum = (sum + dataView.getUint32(i)) >>> 0;\n }\n\n // Handle remaining bytes\n if (end > alignedEnd) {\n let last = 0;\n for (let i = alignedEnd; i < end; i++) {\n last = (last << 8) | data[i];\n }\n last <<= (4 - (end - alignedEnd)) * 8;\n sum = (sum + last) >>> 0;\n }\n\n return sum;\n}\n\nfunction pad4(n: number): number {\n return (n + 3) & ~3;\n}\n"],"mappings":"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"}
|