text-shaper 0.0.1

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 (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -0
  3. package/dist/aat/state-machine.d.ts +34 -0
  4. package/dist/buffer/glyph-buffer.d.ts +55 -0
  5. package/dist/buffer/unicode-buffer.d.ts +51 -0
  6. package/dist/font/binary/reader.d.ts +72 -0
  7. package/dist/font/face.d.ts +65 -0
  8. package/dist/font/font.d.ts +189 -0
  9. package/dist/font/tables/avar.d.ts +36 -0
  10. package/dist/font/tables/base.d.ts +79 -0
  11. package/dist/font/tables/cbdt.d.ts +120 -0
  12. package/dist/font/tables/cff-charstring.d.ts +16 -0
  13. package/dist/font/tables/cff.d.ts +93 -0
  14. package/dist/font/tables/cff2.d.ts +85 -0
  15. package/dist/font/tables/cmap.d.ts +81 -0
  16. package/dist/font/tables/colr.d.ts +278 -0
  17. package/dist/font/tables/cpal.d.ts +46 -0
  18. package/dist/font/tables/feat.d.ts +359 -0
  19. package/dist/font/tables/fvar.d.ts +77 -0
  20. package/dist/font/tables/gdef.d.ts +45 -0
  21. package/dist/font/tables/glyf.d.ts +118 -0
  22. package/dist/font/tables/gpos-contextual.d.ts +88 -0
  23. package/dist/font/tables/gpos-mark.d.ts +95 -0
  24. package/dist/font/tables/gpos.d.ts +137 -0
  25. package/dist/font/tables/gsub-contextual.d.ts +88 -0
  26. package/dist/font/tables/gsub.d.ts +107 -0
  27. package/dist/font/tables/gvar.d.ts +56 -0
  28. package/dist/font/tables/head.d.ts +47 -0
  29. package/dist/font/tables/hhea.d.ts +24 -0
  30. package/dist/font/tables/hmtx.d.ts +23 -0
  31. package/dist/font/tables/hvar.d.ts +77 -0
  32. package/dist/font/tables/jstf.d.ts +97 -0
  33. package/dist/font/tables/kern.d.ts +44 -0
  34. package/dist/font/tables/kerx.d.ts +108 -0
  35. package/dist/font/tables/loca.d.ts +31 -0
  36. package/dist/font/tables/math.d.ts +168 -0
  37. package/dist/font/tables/maxp.d.ts +27 -0
  38. package/dist/font/tables/morx.d.ts +142 -0
  39. package/dist/font/tables/mvar.d.ts +99 -0
  40. package/dist/font/tables/name.d.ts +75 -0
  41. package/dist/font/tables/os2.d.ts +102 -0
  42. package/dist/font/tables/post.d.ts +25 -0
  43. package/dist/font/tables/sbix.d.ts +65 -0
  44. package/dist/font/tables/sfnt.d.ts +20 -0
  45. package/dist/font/tables/stat.d.ts +115 -0
  46. package/dist/font/tables/svg.d.ts +40 -0
  47. package/dist/font/tables/trak.d.ts +43 -0
  48. package/dist/font/tables/vhea.d.ts +41 -0
  49. package/dist/font/tables/vmtx.d.ts +35 -0
  50. package/dist/font/tables/vorg.d.ts +33 -0
  51. package/dist/font/tables/vvar.d.ts +36 -0
  52. package/dist/index.d.ts +80 -0
  53. package/dist/index.js +9 -0
  54. package/dist/index.js.map +92 -0
  55. package/dist/index.test.d.ts +1 -0
  56. package/dist/layout/justify.d.ts +88 -0
  57. package/dist/layout/structures/class-def.d.ts +15 -0
  58. package/dist/layout/structures/coverage.d.ts +17 -0
  59. package/dist/layout/structures/device.d.ts +58 -0
  60. package/dist/layout/structures/feature-variations.d.ts +82 -0
  61. package/dist/layout/structures/layout-common.d.ts +77 -0
  62. package/dist/render/path.d.ts +136 -0
  63. package/dist/shaper/complex/arabic.d.ts +60 -0
  64. package/dist/shaper/complex/ethiopic.d.ts +70 -0
  65. package/dist/shaper/complex/georgian.d.ts +69 -0
  66. package/dist/shaper/complex/hangul.d.ts +64 -0
  67. package/dist/shaper/complex/hebrew.d.ts +28 -0
  68. package/dist/shaper/complex/indic.d.ts +117 -0
  69. package/dist/shaper/complex/khmer.d.ts +48 -0
  70. package/dist/shaper/complex/mongolian.d.ts +89 -0
  71. package/dist/shaper/complex/myanmar.d.ts +47 -0
  72. package/dist/shaper/complex/syriac.d.ts +80 -0
  73. package/dist/shaper/complex/thai-lao.d.ts +42 -0
  74. package/dist/shaper/complex/tibetan.d.ts +57 -0
  75. package/dist/shaper/complex/use.d.ts +80 -0
  76. package/dist/shaper/fallback.d.ts +16 -0
  77. package/dist/shaper/features.d.ts +189 -0
  78. package/dist/shaper/shape-plan.d.ts +29 -0
  79. package/dist/shaper/shaper.d.ts +18 -0
  80. package/dist/types.d.ts +153 -0
  81. package/dist/typeshaper.js +7 -0
  82. package/dist/unicode/bidi/brackets.d.ts +7 -0
  83. package/dist/unicode/bidi/brackets.data.d.ts +5 -0
  84. package/dist/unicode/bidi/char-types.d.ts +19 -0
  85. package/dist/unicode/bidi/char-types.data.d.ts +25 -0
  86. package/dist/unicode/bidi/embedding-levels.d.ts +18 -0
  87. package/dist/unicode/bidi/index.d.ts +9 -0
  88. package/dist/unicode/bidi/mirroring.d.ts +10 -0
  89. package/dist/unicode/bidi/mirroring.data.d.ts +2 -0
  90. package/dist/unicode/bidi/parse-character-map.d.ts +8 -0
  91. package/dist/unicode/bidi/reordering.d.ts +18 -0
  92. package/dist/unicode/bidi.d.ts +93 -0
  93. package/dist/unicode/line-break.d.ts +113 -0
  94. package/dist/unicode/normalize.d.ts +36 -0
  95. package/dist/unicode/script.d.ts +215 -0
  96. package/dist/unicode/segmentation.d.ts +104 -0
  97. package/package.json +33 -0
@@ -0,0 +1,92 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/aat/state-machine.ts", "../src/types.ts", "../src/buffer/glyph-buffer.ts", "../src/buffer/unicode-buffer.ts", "../src/font/binary/reader.ts", "../src/font/tables/avar.ts", "../src/font/tables/fvar.ts", "../src/font/tables/hvar.ts", "../src/font/face.ts", "../src/font/tables/base.ts", "../src/font/tables/cbdt.ts", "../src/font/tables/cff.ts", "../src/font/tables/cff2.ts", "../src/font/tables/cmap.ts", "../src/font/tables/colr.ts", "../src/font/tables/cpal.ts", "../src/layout/structures/class-def.ts", "../src/font/tables/gdef.ts", "../src/font/tables/gvar.ts", "../src/font/tables/loca.ts", "../src/font/tables/glyf.ts", "../src/layout/structures/coverage.ts", "../src/layout/structures/device.ts", "../src/layout/structures/layout-common.ts", "../src/font/tables/gpos-contextual.ts", "../src/font/tables/gpos-mark.ts", "../src/font/tables/gpos.ts", "../src/font/tables/gsub-contextual.ts", "../src/font/tables/gsub.ts", "../src/font/tables/head.ts", "../src/font/tables/hhea.ts", "../src/font/tables/hmtx.ts", "../src/font/tables/jstf.ts", "../src/font/tables/kern.ts", "../src/font/tables/kerx.ts", "../src/font/tables/math.ts", "../src/font/tables/maxp.ts", "../src/font/tables/morx.ts", "../src/font/tables/mvar.ts", "../src/font/tables/name.ts", "../src/font/tables/os2.ts", "../src/font/tables/post.ts", "../src/font/tables/sbix.ts", "../src/font/tables/sfnt.ts", "../src/font/tables/feat.ts", "../src/font/tables/stat.ts", "../src/font/tables/svg.ts", "../src/font/tables/trak.ts", "../src/font/tables/vhea.ts", "../src/font/tables/vmtx.ts", "../src/font/tables/vorg.ts", "../src/font/tables/vvar.ts", "../src/font/font.ts", "../src/font/tables/cff-charstring.ts", "../src/layout/justify.ts", "../src/layout/structures/feature-variations.ts", "../src/render/path.ts", "../src/unicode/normalize.ts", "../src/shaper/fallback.ts", "../src/shaper/features.ts", "../src/shaper/shape-plan.ts", "../src/shaper/complex/arabic.ts", "../src/shaper/complex/hangul.ts", "../src/shaper/complex/hebrew.ts", "../src/shaper/complex/indic.ts", "../src/shaper/complex/khmer.ts", "../src/shaper/complex/myanmar.ts", "../src/shaper/complex/thai-lao.ts", "../src/shaper/complex/use.ts", "../src/shaper/shaper.ts", "../src/unicode/bidi/brackets.data.ts", "../src/unicode/bidi/parse-character-map.ts", "../src/unicode/bidi/brackets.ts", "../src/unicode/bidi/char-types.data.ts", "../src/unicode/bidi/char-types.ts", "../src/unicode/bidi/embedding-levels.ts", "../src/unicode/bidi/mirroring.data.ts", "../src/unicode/bidi/mirroring.ts", "../src/unicode/bidi/reordering.ts", "../src/unicode/bidi.ts", "../src/unicode/line-break.ts", "../src/unicode/segmentation.ts", "../src/unicode/script.ts"],
4
+ "sourcesContent": [
5
+ "import type {\n\tClassTable,\n\tContextualEntry,\n\tInsertionEntry,\n\tLigatureEntry,\n\tMorxContextualSubtable,\n\tMorxInsertionSubtable,\n\tMorxLigatureSubtable,\n\tMorxRearrangementSubtable,\n} from \"../font/tables/morx.ts\";\nimport type { GlyphId, GlyphInfo } from \"../types.ts\";\n\n/**\n * State machine driver for AAT processing\n */\nexport interface StateMachineContext {\n\t/** Current position in buffer */\n\tpos: number;\n\t/** Mark position (for some operations) */\n\tmark: number;\n\t/** Glyph stack for ligatures */\n\tstack: number[];\n}\n\n/**\n * Special class values\n */\nconst CLASS_END_OF_TEXT = 0;\nconst CLASS_OUT_OF_BOUNDS = 1;\nconst _CLASS_DELETED_GLYPH = 2;\nconst _CLASS_END_OF_LINE = 3;\n\n/**\n * Get class for a glyph\n */\nexport function getGlyphClass(\n\tclassTable: ClassTable,\n\tglyphId: GlyphId,\n): number {\n\tif (glyphId < 0 || glyphId >= classTable.classArray.length) {\n\t\treturn CLASS_OUT_OF_BOUNDS;\n\t}\n\treturn classTable.classArray[glyphId] ?? CLASS_OUT_OF_BOUNDS;\n}\n\n/**\n * Process rearrangement subtable\n * Reorders glyphs based on state machine\n */\nexport function processRearrangement(\n\tsubtable: MorxRearrangementSubtable,\n\tinfos: GlyphInfo[],\n): void {\n\tconst { stateTable } = subtable;\n\tlet state = 0;\n\tlet markFirst = 0;\n\tlet markLast = 0;\n\n\tfor (let i = 0; i <= infos.length; i++) {\n\t\tconst isEnd = i >= infos.length;\n\t\tconst glyphClass = isEnd\n\t\t\t? CLASS_END_OF_TEXT\n\t\t\t: getGlyphClass(stateTable.classTable, infos[i]?.glyphId);\n\n\t\tconst stateRow = stateTable.stateArray[state];\n\t\tif (!stateRow) break;\n\n\t\tconst entry = stateRow[glyphClass];\n\t\tif (!entry) break;\n\n\t\tconst flags = entry.flags;\n\n\t\t// Set mark first\n\t\tif (flags & 0x8000) {\n\t\t\tmarkFirst = i;\n\t\t}\n\n\t\t// Set mark last\n\t\tif (flags & 0x2000) {\n\t\t\tmarkLast = i;\n\t\t}\n\n\t\t// Perform rearrangement\n\t\tconst verb = flags & 0x000f;\n\t\tif (verb !== 0 && markFirst <= markLast && markLast < infos.length) {\n\t\t\trearrangeGlyphs(infos, markFirst, markLast, verb);\n\t\t}\n\n\t\t// Don't advance if flag set\n\t\tif (!(flags & 0x4000)) {\n\t\t\t// Stay at current position\n\t\t}\n\n\t\tstate = entry.newState;\n\t}\n}\n\n/**\n * Rearrangement verbs\n */\nfunction rearrangeGlyphs(\n\tinfos: GlyphInfo[],\n\tfirst: number,\n\tlast: number,\n\tverb: number,\n): void {\n\tif (first >= last || first >= infos.length || last >= infos.length) return;\n\n\tconst a = infos[first];\n\tconst b = infos[first + 1];\n\tconst c = infos[last - 1];\n\tconst d = infos[last];\n\n\tif (!a || !d) return;\n\n\tswitch (verb) {\n\t\tcase 1: // Ax => xA\n\t\t\tif (b) {\n\t\t\t\tinfos[first] = b;\n\t\t\t\tinfos[first + 1] = a;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 2: // xD => Dx\n\t\t\tif (c) {\n\t\t\t\tinfos[last] = c;\n\t\t\t\tinfos[last - 1] = d;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 3: // AxD => DxA\n\t\t\tinfos[first] = d;\n\t\t\tinfos[last] = a;\n\t\t\tbreak;\n\t\tcase 4: // ABx => xAB\n\t\t\tif (b && c) {\n\t\t\t\tconst temp = infos.slice(first, first + 2);\n\t\t\t\tconst [tempFirst, tempSecond] = temp;\n\t\t\t\tconst thirdItem = infos[first + 2];\n\t\t\t\tif (tempFirst && tempSecond && thirdItem) {\n\t\t\t\t\tinfos[first] = thirdItem;\n\t\t\t\t\tinfos[first + 1] = tempFirst;\n\t\t\t\t\tinfos[first + 2] = tempSecond;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 5: // ABx => xBA\n\t\t\tif (b && c) {\n\t\t\t\tconst temp = infos.slice(first, first + 2);\n\t\t\t\tconst [tempFirst, tempSecond] = temp;\n\t\t\t\tconst thirdItem = infos[first + 2];\n\t\t\t\tif (tempFirst && tempSecond && thirdItem) {\n\t\t\t\t\tinfos[first] = thirdItem;\n\t\t\t\t\tinfos[first + 1] = tempSecond;\n\t\t\t\t\tinfos[first + 2] = tempFirst;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 6: // xCD => CDx\n\t\t\tif (c && b) {\n\t\t\t\tconst temp = infos.slice(last - 1, last + 1);\n\t\t\t\tconst [tempFirst, tempSecond] = temp;\n\t\t\t\tconst prevItem = infos[last - 2];\n\t\t\t\tif (tempFirst && tempSecond && prevItem) {\n\t\t\t\t\tinfos[last] = prevItem;\n\t\t\t\t\tinfos[last - 1] = tempSecond;\n\t\t\t\t\tinfos[last - 2] = tempFirst;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 7: // xCD => DCx\n\t\t\tif (c && b) {\n\t\t\t\tconst temp = infos.slice(last - 1, last + 1);\n\t\t\t\tconst [tempFirst, tempSecond] = temp;\n\t\t\t\tconst prevItem = infos[last - 2];\n\t\t\t\tif (tempFirst && tempSecond && prevItem) {\n\t\t\t\t\tinfos[last] = prevItem;\n\t\t\t\t\tinfos[last - 1] = tempFirst;\n\t\t\t\t\tinfos[last - 2] = tempSecond;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 8: // AxCD => CDxA\n\t\t\tif (c) {\n\t\t\t\tconst tempA = a;\n\t\t\t\tinfos[first] = c;\n\t\t\t\tinfos[last - 1] = d;\n\t\t\t\tinfos[last] = tempA;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 9: // AxCD => DCxA\n\t\t\tif (c) {\n\t\t\t\tconst tempA = a;\n\t\t\t\tinfos[first] = d;\n\t\t\t\tinfos[last - 1] = c;\n\t\t\t\tinfos[last] = tempA;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 10: // ABxD => DxAB\n\t\t\tif (b) {\n\t\t\t\tconst tempD = d;\n\t\t\t\tinfos[last] = b;\n\t\t\t\tinfos[first + 1] = a;\n\t\t\t\tinfos[first] = tempD;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 11: // ABxD => DxBA\n\t\t\tif (b) {\n\t\t\t\tconst tempD = d;\n\t\t\t\tinfos[last] = a;\n\t\t\t\tinfos[first + 1] = b;\n\t\t\t\tinfos[first] = tempD;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 12: // ABxCD => CDxAB\n\t\t\tif (b && c) {\n\t\t\t\tconst tempAB = [a, b];\n\t\t\t\tinfos[first] = c;\n\t\t\t\tinfos[first + 1] = d;\n\t\t\t\tinfos[last - 1] = tempAB[0];\n\t\t\t\tinfos[last] = tempAB[1];\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 13: // ABxCD => CDxBA\n\t\t\tif (b && c) {\n\t\t\t\tconst tempAB = [a, b];\n\t\t\t\tinfos[first] = c;\n\t\t\t\tinfos[first + 1] = d;\n\t\t\t\tinfos[last - 1] = tempAB[1];\n\t\t\t\tinfos[last] = tempAB[0];\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 14: // ABxCD => DCxAB\n\t\t\tif (b && c) {\n\t\t\t\tconst tempAB = [a, b];\n\t\t\t\tinfos[first] = d;\n\t\t\t\tinfos[first + 1] = c;\n\t\t\t\tinfos[last - 1] = tempAB[0];\n\t\t\t\tinfos[last] = tempAB[1];\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 15: // ABxCD => DCxBA\n\t\t\tif (b && c) {\n\t\t\t\tconst tempAB = [a, b];\n\t\t\t\tinfos[first] = d;\n\t\t\t\tinfos[first + 1] = c;\n\t\t\t\tinfos[last - 1] = tempAB[1];\n\t\t\t\tinfos[last] = tempAB[0];\n\t\t\t}\n\t\t\tbreak;\n\t}\n}\n\n/**\n * Process contextual substitution subtable\n */\nexport function processContextual(\n\tsubtable: MorxContextualSubtable,\n\tinfos: GlyphInfo[],\n): void {\n\tconst { stateTable, substitutionTable } = subtable;\n\tlet state = 0;\n\tlet markIndex = -1;\n\n\tfor (let i = 0; i <= infos.length; i++) {\n\t\tconst isEnd = i >= infos.length;\n\t\tconst glyphClass = isEnd\n\t\t\t? CLASS_END_OF_TEXT\n\t\t\t: getGlyphClass(stateTable.classTable, infos[i]?.glyphId);\n\n\t\tconst stateRow = stateTable.stateArray[state];\n\t\tif (!stateRow) break;\n\n\t\tconst entry = stateRow[glyphClass] as ContextualEntry | undefined;\n\t\tif (!entry) break;\n\n\t\t// Set mark\n\t\tif (entry.flags & 0x8000) {\n\t\t\tmarkIndex = i;\n\t\t}\n\n\t\t// Apply substitution at mark\n\t\tif (\n\t\t\tentry.markIndex !== 0xffff &&\n\t\t\tmarkIndex >= 0 &&\n\t\t\tmarkIndex < infos.length\n\t\t) {\n\t\t\tconst substTable = substitutionTable[entry.markIndex];\n\t\t\tif (substTable) {\n\t\t\t\tconst markedInfo = infos[markIndex];\n\t\t\t\tif (markedInfo) {\n\t\t\t\t\tconst replacement = substTable.get(markedInfo.glyphId);\n\t\t\t\t\tif (replacement !== undefined) {\n\t\t\t\t\t\tmarkedInfo.glyphId = replacement;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Apply substitution at current\n\t\tif (!isEnd && entry.currentIndex !== 0xffff) {\n\t\t\tconst substTable = substitutionTable[entry.currentIndex];\n\t\t\tif (substTable) {\n\t\t\t\tconst currentInfo = infos[i];\n\t\t\t\tif (currentInfo) {\n\t\t\t\t\tconst replacement = substTable.get(currentInfo.glyphId);\n\t\t\t\t\tif (replacement !== undefined) {\n\t\t\t\t\t\tcurrentInfo.glyphId = replacement;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Don't advance\n\t\tif (!(entry.flags & 0x4000)) {\n\t\t\t// Stay\n\t\t}\n\n\t\tstate = entry.newState;\n\t}\n}\n\n/**\n * Process ligature subtable\n */\nexport function processLigature(\n\tsubtable: MorxLigatureSubtable,\n\tinfos: GlyphInfo[],\n): GlyphInfo[] {\n\tconst { stateTable, ligatureActions, components, ligatures } = subtable;\n\tlet state = 0;\n\tconst stack: number[] = [];\n\tconst result: GlyphInfo[] = [];\n\tconst deleted = new Set<number>();\n\n\tfor (let i = 0; i <= infos.length; i++) {\n\t\tconst isEnd = i >= infos.length;\n\t\tconst glyphClass = isEnd\n\t\t\t? CLASS_END_OF_TEXT\n\t\t\t: getGlyphClass(stateTable.classTable, infos[i]?.glyphId);\n\n\t\tconst stateRow = stateTable.stateArray[state];\n\t\tif (!stateRow) break;\n\n\t\tconst entry = stateRow[glyphClass] as LigatureEntry | undefined;\n\t\tif (!entry) break;\n\n\t\t// Push to stack\n\t\tif (entry.flags & 0x8000) {\n\t\t\tstack.push(i);\n\t\t}\n\n\t\t// Perform ligature action\n\t\tif (entry.flags & 0x2000 && entry.ligActionIndex < ligatureActions.length) {\n\t\t\tlet actionIndex = entry.ligActionIndex;\n\t\t\tlet ligatureGlyph: GlyphId = 0;\n\t\t\tconst componentIndices: number[] = [];\n\n\t\t\t// Process action chain\n\t\t\twhile (actionIndex < ligatureActions.length) {\n\t\t\t\tconst action = ligatureActions[actionIndex];\n\t\t\t\tif (action === undefined) break;\n\n\t\t\t\tconst last = (action & 0x80000000) !== 0;\n\t\t\t\tconst store = (action & 0x40000000) !== 0;\n\t\t\t\tconst componentOffset = ((action & 0x3fffffff) << 2) >> 2; // Sign extend\n\n\t\t\t\tconst stackIdx = stack.pop();\n\t\t\t\tif (stackIdx !== undefined && stackIdx < infos.length) {\n\t\t\t\t\tcomponentIndices.push(stackIdx);\n\t\t\t\t\tconst info = infos[stackIdx];\n\t\t\t\t\tif (info) {\n\t\t\t\t\t\tconst glyphId = info.glyphId;\n\t\t\t\t\t\tconst componentIdx = glyphId + componentOffset;\n\n\t\t\t\t\t\tif (componentIdx >= 0 && componentIdx < components.length) {\n\t\t\t\t\t\t\tconst component = components[componentIdx];\n\t\t\t\t\t\t\tif (component !== undefined) {\n\t\t\t\t\t\t\t\tligatureGlyph = component + ligatureGlyph;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (store && ligatureGlyph < ligatures.length) {\n\t\t\t\t\t// Replace first component with ligature\n\t\t\t\t\tconst firstIdx = componentIndices[componentIndices.length - 1];\n\t\t\t\t\tif (firstIdx !== undefined && firstIdx < infos.length) {\n\t\t\t\t\t\tconst firstInfo = infos[firstIdx];\n\t\t\t\t\t\tconst ligature = ligatures[ligatureGlyph];\n\t\t\t\t\t\tif (firstInfo && ligature !== undefined) {\n\t\t\t\t\t\t\tfirstInfo.glyphId = ligature;\n\t\t\t\t\t\t\t// Mark other components for deletion\n\t\t\t\t\t\t\tfor (const [j, idx] of componentIndices.entries()) {\n\t\t\t\t\t\t\t\tif (j < componentIndices.length - 1) {\n\t\t\t\t\t\t\t\t\tdeleted.add(idx);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tligatureGlyph = 0;\n\t\t\t\t}\n\n\t\t\t\tif (last) break;\n\t\t\t\tactionIndex++;\n\t\t\t}\n\t\t}\n\n\t\t// Don't advance\n\t\tif (!(entry.flags & 0x4000)) {\n\t\t\t// Stay\n\t\t}\n\n\t\tstate = entry.newState;\n\t}\n\n\t// Build result without deleted glyphs\n\tfor (const [i, info] of infos.entries()) {\n\t\tif (!deleted.has(i)) {\n\t\t\tresult.push(info);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Process insertion subtable\n */\nexport function processInsertion(\n\tsubtable: MorxInsertionSubtable,\n\tinfos: GlyphInfo[],\n): GlyphInfo[] {\n\tconst { stateTable, insertionGlyphs } = subtable;\n\tlet state = 0;\n\tlet markIndex = -1;\n\tconst result: GlyphInfo[] = [];\n\tconst insertions: Map<number, { before: GlyphId[]; after: GlyphId[] }> =\n\t\tnew Map();\n\n\tfor (let i = 0; i <= infos.length; i++) {\n\t\tconst isEnd = i >= infos.length;\n\t\tconst glyphClass = isEnd\n\t\t\t? CLASS_END_OF_TEXT\n\t\t\t: getGlyphClass(stateTable.classTable, infos[i]?.glyphId);\n\n\t\tconst stateRow = stateTable.stateArray[state];\n\t\tif (!stateRow) break;\n\n\t\tconst entry = stateRow[glyphClass] as InsertionEntry | undefined;\n\t\tif (!entry) break;\n\n\t\t// Set mark\n\t\tif (entry.flags & 0x8000) {\n\t\t\tmarkIndex = i;\n\t\t}\n\n\t\t// Insert at marked position\n\t\tif (entry.markedInsertIndex !== 0xffff && markIndex >= 0) {\n\t\t\tconst count = (entry.flags >> 5) & 0x1f;\n\t\t\tconst insertBefore = (entry.flags & 0x0800) !== 0;\n\t\t\tconst glyphs = insertionGlyphs.slice(\n\t\t\t\tentry.markedInsertIndex,\n\t\t\t\tentry.markedInsertIndex + count,\n\t\t\t);\n\n\t\t\tlet ins = insertions.get(markIndex);\n\t\t\tif (!ins) {\n\t\t\t\tins = { before: [], after: [] };\n\t\t\t\tinsertions.set(markIndex, ins);\n\t\t\t}\n\t\t\tif (insertBefore) {\n\t\t\t\tins.before.push(...glyphs);\n\t\t\t} else {\n\t\t\t\tins.after.push(...glyphs);\n\t\t\t}\n\t\t}\n\n\t\t// Insert at current position\n\t\tif (!isEnd && entry.currentInsertIndex !== 0xffff) {\n\t\t\tconst count = entry.flags & 0x1f;\n\t\t\tconst insertBefore = (entry.flags & 0x0020) !== 0;\n\t\t\tconst glyphs = insertionGlyphs.slice(\n\t\t\t\tentry.currentInsertIndex,\n\t\t\t\tentry.currentInsertIndex + count,\n\t\t\t);\n\n\t\t\tlet ins = insertions.get(i);\n\t\t\tif (!ins) {\n\t\t\t\tins = { before: [], after: [] };\n\t\t\t\tinsertions.set(i, ins);\n\t\t\t}\n\t\t\tif (insertBefore) {\n\t\t\t\tins.before.push(...glyphs);\n\t\t\t} else {\n\t\t\t\tins.after.push(...glyphs);\n\t\t\t}\n\t\t}\n\n\t\t// Don't advance\n\t\tif (!(entry.flags & 0x4000)) {\n\t\t\t// Stay\n\t\t}\n\n\t\tstate = entry.newState;\n\t}\n\n\t// Build result with insertions\n\tfor (const [i, info] of infos.entries()) {\n\t\tconst ins = insertions.get(i);\n\n\t\tif (ins) {\n\t\t\t// Insert before\n\t\t\tfor (const glyph of ins.before) {\n\t\t\t\tresult.push({\n\t\t\t\t\tglyphId: glyph,\n\t\t\t\t\tcluster: info.cluster,\n\t\t\t\t\tmask: info.mask,\n\t\t\t\t\tcodepoint: 0,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tresult.push(info);\n\n\t\tif (ins) {\n\t\t\t// Insert after\n\t\t\tfor (const glyph of ins.after) {\n\t\t\t\tresult.push({\n\t\t\t\t\tglyphId: glyph,\n\t\t\t\t\tcluster: info.cluster,\n\t\t\t\t\tmask: info.mask,\n\t\t\t\t\tcodepoint: 0,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n",
6
+ "// OpenType primitive types\nexport type uint8 = number;\nexport type int8 = number;\nexport type uint16 = number;\nexport type int16 = number;\nexport type uint32 = number;\nexport type int32 = number;\nexport type Fixed = number; // 16.16 fixed-point\nexport type F2Dot14 = number; // 2.14 fixed-point\nexport type FWord = number; // int16 in font units\nexport type UFWord = number; // uint16 in font units\nexport type Offset16 = number;\nexport type Offset32 = number;\nexport type GlyphId = number;\n\n/** 4-character ASCII tag (packed as uint32 for efficiency) */\nexport type Tag = number;\n\n/** Text direction */\nexport enum Direction {\n\tInvalid = 0,\n\tLTR = 4,\n\tRTL = 5,\n\tTTB = 6,\n\tBTT = 7,\n}\n\n/** Cluster level for glyph-character mapping */\nexport enum ClusterLevel {\n\tMonotoneGraphemes = 0,\n\tMonotoneCharacters = 1,\n\tCharacters = 2,\n}\n\n/** Buffer flags */\nexport enum BufferFlags {\n\tDefault = 0x0,\n\tBeginningOfText = 0x1,\n\tEndOfText = 0x2,\n\tPreserveDefaultIgnorables = 0x4,\n\tRemoveDefaultIgnorables = 0x8,\n\tDoNotInsertDottedCircle = 0x10,\n}\n\n/** Glyph classification from GDEF */\nexport enum GlyphClass {\n\tBase = 1,\n\tLigature = 2,\n\tMark = 3,\n\tComponent = 4,\n}\n\n/** Feature specification for shaping */\nexport interface Feature {\n\ttag: Tag;\n\tvalue: number;\n\tstart: number;\n\tend: number;\n}\n\n/** Variation axis value */\nexport interface Variation {\n\ttag: Tag;\n\tvalue: number;\n}\n\n/** Glyph info during shaping */\nexport interface GlyphInfo {\n\tglyphId: GlyphId;\n\tcluster: number;\n\tmask: number;\n\t/** Unicode codepoint (before shaping) */\n\tcodepoint: number;\n}\n\n/** Glyph position after shaping */\nexport interface GlyphPosition {\n\txAdvance: number;\n\tyAdvance: number;\n\txOffset: number;\n\tyOffset: number;\n}\n\n/** Table record from font directory */\nexport interface TableRecord {\n\ttag: Tag;\n\tchecksum: uint32;\n\toffset: Offset32;\n\tlength: uint32;\n}\n\n/** Lookup flags for controlling glyph matching */\nexport interface LookupFlags {\n\trightToLeft: boolean;\n\tignoreBaseGlyphs: boolean;\n\tignoreLigatures: boolean;\n\tignoreMarks: boolean;\n\tuseMarkFilteringSet: boolean;\n\tmarkAttachmentType: number;\n\tmarkFilteringSet?: number;\n}\n\n// Tag utilities\nexport function tag(str: string): Tag {\n\tif (str.length !== 4) {\n\t\tthrow new Error(`Tag must be exactly 4 characters: \"${str}\"`);\n\t}\n\treturn (\n\t\t(str.charCodeAt(0) << 24) |\n\t\t(str.charCodeAt(1) << 16) |\n\t\t(str.charCodeAt(2) << 8) |\n\t\tstr.charCodeAt(3)\n\t);\n}\n\nexport function tagToString(t: Tag): string {\n\treturn String.fromCharCode(\n\t\t(t >> 24) & 0xff,\n\t\t(t >> 16) & 0xff,\n\t\t(t >> 8) & 0xff,\n\t\tt & 0xff,\n\t);\n}\n\n// Common tags\nexport const Tags = {\n\t// Required tables\n\thead: tag(\"head\"),\n\thhea: tag(\"hhea\"),\n\thmtx: tag(\"hmtx\"),\n\tmaxp: tag(\"maxp\"),\n\tcmap: tag(\"cmap\"),\n\tloca: tag(\"loca\"),\n\tglyf: tag(\"glyf\"),\n\tname: tag(\"name\"),\n\tOS2: tag(\"OS/2\"),\n\tpost: tag(\"post\"),\n\n\t// OpenType layout\n\tGDEF: tag(\"GDEF\"),\n\tGSUB: tag(\"GSUB\"),\n\tGPOS: tag(\"GPOS\"),\n\tBASE: tag(\"BASE\"),\n\tJSTF: tag(\"JSTF\"),\n\tMATH: tag(\"MATH\"),\n\n\t// CFF\n\tCFF: tag(\"CFF \"),\n\tCFF2: tag(\"CFF2\"),\n\n\t// Variable fonts\n\tfvar: tag(\"fvar\"),\n\tgvar: tag(\"gvar\"),\n\tavar: tag(\"avar\"),\n\tHVAR: tag(\"HVAR\"),\n\tVVAR: tag(\"VVAR\"),\n\tMVAR: tag(\"MVAR\"),\n\n\t// AAT\n\tmorx: tag(\"morx\"),\n\tkerx: tag(\"kerx\"),\n\tkern: tag(\"kern\"),\n\ttrak: tag(\"trak\"),\n\tfeat: tag(\"feat\"),\n\n\t// Color\n\tCOLR: tag(\"COLR\"),\n\tCPAL: tag(\"CPAL\"),\n\tSVG: tag(\"SVG \"),\n\tsbix: tag(\"sbix\"),\n\tCBDT: tag(\"CBDT\"),\n\tCBLC: tag(\"CBLC\"),\n\n\t// Style Attributes\n\tSTAT: tag(\"STAT\"),\n\n\t// Vertical\n\tvhea: tag(\"vhea\"),\n\tvmtx: tag(\"vmtx\"),\n\tVORG: tag(\"VORG\"),\n} as const;\n\n// Feature tags\nexport const FeatureTags = {\n\t// GSUB\n\tccmp: tag(\"ccmp\"),\n\tlocl: tag(\"locl\"),\n\trlig: tag(\"rlig\"),\n\tliga: tag(\"liga\"),\n\tclig: tag(\"clig\"),\n\tcalt: tag(\"calt\"),\n\trclt: tag(\"rclt\"),\n\tdlig: tag(\"dlig\"),\n\tsmcp: tag(\"smcp\"),\n\tc2sc: tag(\"c2sc\"),\n\n\t// Arabic\n\tisol: tag(\"isol\"),\n\tinit: tag(\"init\"),\n\tmedi: tag(\"medi\"),\n\tfina: tag(\"fina\"),\n\n\t// GPOS\n\tkern: tag(\"kern\"),\n\tmark: tag(\"mark\"),\n\tmkmk: tag(\"mkmk\"),\n\tcurs: tag(\"curs\"),\n\tdist: tag(\"dist\"),\n} as const;\n",
7
+ "import {\n\tDirection,\n\ttype GlyphId,\n\ttype GlyphInfo,\n\ttype GlyphPosition,\n} from \"../types.ts\";\n\n/**\n * Output buffer containing shaped glyphs.\n * Result of the shaping process.\n */\nexport class GlyphBuffer {\n\t/** Direction used during shaping */\n\tdirection: Direction = Direction.LTR;\n\n\t/** Script used during shaping */\n\tscript: string = \"Zyyy\";\n\n\t/** Language used during shaping */\n\tlanguage: string | null = null;\n\n\t/** Glyph information array */\n\tinfos: GlyphInfo[] = [];\n\n\t/** Glyph position array */\n\tpositions: GlyphPosition[] = [];\n\n\t/** Create buffer with pre-allocated capacity */\n\tstatic withCapacity(capacity: number): GlyphBuffer {\n\t\tconst buffer = new GlyphBuffer();\n\t\tbuffer.infos = new Array(capacity);\n\t\tbuffer.positions = new Array(capacity);\n\t\treturn buffer;\n\t}\n\n\t/** Number of glyphs */\n\tget length(): number {\n\t\treturn this.infos.length;\n\t}\n\n\t/** Initialize from glyph infos (positions zeroed) */\n\tinitFromInfos(infos: GlyphInfo[]): void {\n\t\tthis.infos = infos;\n\t\tthis.positions = infos.map(() => ({\n\t\t\txAdvance: 0,\n\t\t\tyAdvance: 0,\n\t\t\txOffset: 0,\n\t\t\tyOffset: 0,\n\t\t}));\n\t}\n\n\t/** Set advance width for a glyph */\n\tsetAdvance(index: number, xAdvance: number, yAdvance = 0): void {\n\t\tconst pos = this.positions[index];\n\t\tif (pos) {\n\t\t\tpos.xAdvance = xAdvance;\n\t\t\tpos.yAdvance = yAdvance;\n\t\t}\n\t}\n\n\t/** Add offset to a glyph position */\n\taddOffset(index: number, xOffset: number, yOffset: number): void {\n\t\tconst pos = this.positions[index];\n\t\tif (pos) {\n\t\t\tpos.xOffset += xOffset;\n\t\t\tpos.yOffset += yOffset;\n\t\t}\n\t}\n\n\t/** Replace glyph at index */\n\treplaceGlyph(index: number, glyphId: GlyphId): void {\n\t\tconst info = this.infos[index];\n\t\tif (info) {\n\t\t\tinfo.glyphId = glyphId;\n\t\t}\n\t}\n\n\t/** Insert glyph at index */\n\tinsertGlyph(index: number, info: GlyphInfo, position: GlyphPosition): void {\n\t\tthis.infos.splice(index, 0, info);\n\t\tthis.positions.splice(index, 0, position);\n\t}\n\n\t/** Remove glyphs in range [start, end) */\n\tremoveRange(start: number, end: number): void {\n\t\tconst count = end - start;\n\t\tthis.infos.splice(start, count);\n\t\tthis.positions.splice(start, count);\n\t}\n\n\t/** Merge clusters from start to end (inclusive) */\n\tmergeClusters(start: number, end: number): void {\n\t\tif (start >= end || start < 0 || end >= this.infos.length) return;\n\n\t\tconst cluster = this.infos[start]?.cluster;\n\t\tfor (let i = start + 1; i <= end; i++) {\n\t\t\tconst info = this.infos[i];\n\t\t\tif (info) {\n\t\t\t\tinfo.cluster = cluster;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Reverse glyph order (for RTL) */\n\treverse(): void {\n\t\tthis.infos.reverse();\n\t\tthis.positions.reverse();\n\t}\n\n\t/** Reverse range [start, end) */\n\treverseRange(start: number, end: number): void {\n\t\tlet i = start;\n\t\tlet j = end - 1;\n\t\twhile (i < j) {\n\t\t\t// Swap infos\n\t\t\tconst tmpInfo = this.infos[i];\n\t\t\tconst tmpInfoJ = this.infos[j];\n\t\t\tif (!tmpInfo || !tmpInfoJ) break;\n\t\t\tthis.infos[i] = tmpInfoJ;\n\t\t\tthis.infos[j] = tmpInfo;\n\n\t\t\t// Swap positions\n\t\t\tconst tmpPos = this.positions[i];\n\t\t\tconst tmpPosJ = this.positions[j];\n\t\t\tif (!tmpPos || !tmpPosJ) break;\n\t\t\tthis.positions[i] = tmpPosJ;\n\t\t\tthis.positions[j] = tmpPos;\n\n\t\t\ti++;\n\t\t\tj--;\n\t\t}\n\t}\n\n\t/** Get total advance width */\n\tgetTotalAdvance(): { x: number; y: number } {\n\t\tlet x = 0;\n\t\tlet y = 0;\n\t\tfor (const pos of this.positions) {\n\t\t\tx += pos.xAdvance;\n\t\t\ty += pos.yAdvance;\n\t\t}\n\t\treturn { x, y };\n\t}\n\n\t/** Serialize to HarfBuzz-compatible format */\n\tserialize(): string {\n\t\tconst parts: string[] = [];\n\n\t\tfor (const [i, info] of this.infos.entries()) {\n\t\t\tconst pos = this.positions[i];\n\t\t\tif (!pos) continue;\n\n\t\t\tlet str = `${info.glyphId}`;\n\n\t\t\t// Add cluster if not sequential\n\t\t\tif (i === 0 || info.cluster !== this.infos[i - 1]?.cluster) {\n\t\t\t\tstr += `=${info.cluster}`;\n\t\t\t}\n\n\t\t\t// Add positioning\n\t\t\tif (pos.xOffset !== 0 || pos.yOffset !== 0) {\n\t\t\t\tstr += `@${pos.xOffset},${pos.yOffset}`;\n\t\t\t}\n\t\t\tif (pos.xAdvance !== 0) {\n\t\t\t\tstr += `+${pos.xAdvance}`;\n\t\t\t}\n\n\t\t\tparts.push(str);\n\t\t}\n\n\t\treturn `[${parts.join(\"|\")}]`;\n\t}\n\n\t/** Get glyph IDs as array */\n\tglyphIds(): GlyphId[] {\n\t\treturn this.infos.map((info) => info.glyphId);\n\t}\n\n\t/** Get clusters as array */\n\tclusters(): number[] {\n\t\treturn this.infos.map((info) => info.cluster);\n\t}\n\n\t/** Iterator for glyph info/position pairs */\n\t*[Symbol.iterator](): Iterator<{ info: GlyphInfo; position: GlyphPosition }> {\n\t\tfor (const [i, info] of this.infos.entries()) {\n\t\t\tconst position = this.positions[i];\n\t\t\tif (!position) continue;\n\t\t\tyield { info, position };\n\t\t}\n\t}\n}\n",
8
+ "import {\n\tBufferFlags,\n\tClusterLevel,\n\tDirection,\n\ttype GlyphInfo,\n} from \"../types.ts\";\n\n/**\n * Input buffer for text to be shaped.\n * Holds Unicode codepoints with associated properties.\n */\nexport class UnicodeBuffer {\n\tprivate _direction: Direction = Direction.LTR;\n\tprivate _script: string = \"Zyyy\"; // Common/Unknown\n\tprivate _language: string | null = null;\n\tprivate _clusterLevel: ClusterLevel = ClusterLevel.MonotoneGraphemes;\n\tprivate _flags: BufferFlags = BufferFlags.Default;\n\n\t/** Codepoints to shape */\n\treadonly codepoints: number[] = [];\n\t/** Cluster indices (maps each codepoint to its cluster) */\n\treadonly clusters: number[] = [];\n\n\t/** Pre-context (text before the buffer for contextual shaping) */\n\tpreContext: number[] = [];\n\t/** Post-context (text after the buffer for contextual shaping) */\n\tpostContext: number[] = [];\n\n\t/** Add a string to the buffer */\n\taddStr(text: string, startCluster = 0): this {\n\t\tlet cluster = startCluster;\n\t\tfor (const char of text) {\n\t\t\tconst codepoint = char.codePointAt(0);\n\t\t\tif (codepoint === undefined) continue;\n\t\t\tthis.codepoints.push(codepoint);\n\t\t\tthis.clusters.push(cluster);\n\t\t\tcluster++;\n\t\t}\n\t\treturn this;\n\t}\n\n\t/** Add codepoints directly */\n\taddCodepoints(codepoints: number[], startCluster = 0): this {\n\t\tlet cluster = startCluster;\n\t\tfor (const cp of codepoints) {\n\t\t\tthis.codepoints.push(cp);\n\t\t\tthis.clusters.push(cluster);\n\t\t\tcluster++;\n\t\t}\n\t\treturn this;\n\t}\n\n\t/** Add a single codepoint */\n\taddCodepoint(codepoint: number, cluster?: number): this {\n\t\tthis.codepoints.push(codepoint);\n\t\tthis.clusters.push(cluster ?? this.codepoints.length - 1);\n\t\treturn this;\n\t}\n\n\t/** Set text direction */\n\tsetDirection(direction: Direction): this {\n\t\tthis._direction = direction;\n\t\treturn this;\n\t}\n\n\t/** Set script (ISO 15924 tag, e.g., 'Latn', 'Arab') */\n\tsetScript(script: string): this {\n\t\tthis._script = script;\n\t\treturn this;\n\t}\n\n\t/** Set language (BCP 47 tag, e.g., 'en', 'ar') */\n\tsetLanguage(language: string | null): this {\n\t\tthis._language = language;\n\t\treturn this;\n\t}\n\n\t/** Set cluster level */\n\tsetClusterLevel(level: ClusterLevel): this {\n\t\tthis._clusterLevel = level;\n\t\treturn this;\n\t}\n\n\t/** Set buffer flags */\n\tsetFlags(flags: BufferFlags): this {\n\t\tthis._flags = flags;\n\t\treturn this;\n\t}\n\n\t/** Set pre-context string */\n\tsetPreContext(text: string): this {\n\t\tthis.preContext = [];\n\t\tfor (const char of text) {\n\t\t\tconst codepoint = char.codePointAt(0);\n\t\t\tif (codepoint !== undefined) {\n\t\t\t\tthis.preContext.push(codepoint);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/** Set post-context string */\n\tsetPostContext(text: string): this {\n\t\tthis.postContext = [];\n\t\tfor (const char of text) {\n\t\t\tconst codepoint = char.codePointAt(0);\n\t\t\tif (codepoint !== undefined) {\n\t\t\t\tthis.postContext.push(codepoint);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/** Clear the buffer */\n\tclear(): this {\n\t\tthis.codepoints.length = 0;\n\t\tthis.clusters.length = 0;\n\t\tthis.preContext.length = 0;\n\t\tthis.postContext.length = 0;\n\t\treturn this;\n\t}\n\n\t/** Number of codepoints */\n\tget length(): number {\n\t\treturn this.codepoints.length;\n\t}\n\n\tget direction(): Direction {\n\t\treturn this._direction;\n\t}\n\n\tget script(): string {\n\t\treturn this._script;\n\t}\n\n\tget language(): string | null {\n\t\treturn this._language;\n\t}\n\n\tget clusterLevel(): ClusterLevel {\n\t\treturn this._clusterLevel;\n\t}\n\n\tget flags(): BufferFlags {\n\t\treturn this._flags;\n\t}\n\n\t/** Convert to initial glyph infos (codepoint = glyphId initially) */\n\ttoGlyphInfos(): GlyphInfo[] {\n\t\treturn this.codepoints.map((codepoint, i) => ({\n\t\t\tglyphId: 0, // Will be set during shaping\n\t\t\tcluster: this.clusters[i] ?? 0,\n\t\t\tmask: 0,\n\t\t\tcodepoint,\n\t\t}));\n\t}\n}\n",
9
+ "import type {\n\tF2Dot14,\n\tFixed,\n\tint16,\n\tint32,\n\tOffset16,\n\tOffset32,\n\tTag,\n\tuint8,\n\tuint16,\n\tuint32,\n} from \"../../types.ts\";\n\n/**\n * Zero-copy binary reader for OpenType font data.\n * All multi-byte values are big-endian per OpenType spec.\n */\nexport class Reader {\n\tprivate readonly data: DataView;\n\tprivate readonly start: number;\n\tprivate readonly end: number;\n\tprivate pos: number;\n\n\tconstructor(buffer: ArrayBuffer | DataView, offset = 0, length?: number) {\n\t\tif (buffer instanceof ArrayBuffer) {\n\t\t\tthis.data = new DataView(buffer);\n\t\t\tthis.start = offset;\n\t\t\tthis.end = length !== undefined ? offset + length : buffer.byteLength;\n\t\t} else {\n\t\t\tthis.data = buffer;\n\t\t\tthis.start = buffer.byteOffset + offset;\n\t\t\tthis.end =\n\t\t\t\tlength !== undefined\n\t\t\t\t\t? this.start + length\n\t\t\t\t\t: buffer.byteOffset + buffer.byteLength;\n\t\t}\n\t\tthis.pos = this.start;\n\t}\n\n\t/** Current read position relative to start */\n\tget offset(): number {\n\t\treturn this.pos - this.start;\n\t}\n\n\t/** Bytes remaining to read */\n\tget remaining(): number {\n\t\treturn this.end - this.pos;\n\t}\n\n\t/** Total length of this reader's view */\n\tget length(): number {\n\t\treturn this.end - this.start;\n\t}\n\n\t/** Seek to absolute offset (relative to this reader's start) */\n\tseek(offset: number): void {\n\t\tthis.pos = this.start + offset;\n\t}\n\n\t/** Skip bytes */\n\tskip(bytes: number): void {\n\t\tthis.pos += bytes;\n\t}\n\n\t/** Create a sub-reader (zero-copy slice) */\n\tslice(offset: number, length: number): Reader {\n\t\treturn new Reader(this.data, this.start + offset, length);\n\t}\n\n\t/** Create a sub-reader from current position */\n\tsliceFrom(offset: number): Reader {\n\t\treturn new Reader(\n\t\t\tthis.data,\n\t\t\tthis.start + offset,\n\t\t\tthis.end - this.start - offset,\n\t\t);\n\t}\n\n\t/** Peek at a value without advancing position */\n\tpeek<T>(fn: () => T): T {\n\t\tconst savedPos = this.pos;\n\t\tconst result = fn();\n\t\tthis.pos = savedPos;\n\t\treturn result;\n\t}\n\n\t// Primitive readers (big-endian)\n\n\tuint8(): uint8 {\n\t\tconst value = this.data.getUint8(this.pos);\n\t\tthis.pos += 1;\n\t\treturn value;\n\t}\n\n\tint8(): number {\n\t\tconst value = this.data.getInt8(this.pos);\n\t\tthis.pos += 1;\n\t\treturn value;\n\t}\n\n\tuint16(): uint16 {\n\t\tconst value = this.data.getUint16(this.pos, false);\n\t\tthis.pos += 2;\n\t\treturn value;\n\t}\n\n\tint16(): int16 {\n\t\tconst value = this.data.getInt16(this.pos, false);\n\t\tthis.pos += 2;\n\t\treturn value;\n\t}\n\n\tuint32(): uint32 {\n\t\tconst value = this.data.getUint32(this.pos, false);\n\t\tthis.pos += 4;\n\t\treturn value;\n\t}\n\n\tint32(): int32 {\n\t\tconst value = this.data.getInt32(this.pos, false);\n\t\tthis.pos += 4;\n\t\treturn value;\n\t}\n\n\t// OpenType-specific types\n\n\t/** 16.16 fixed-point number */\n\tfixed(): Fixed {\n\t\treturn this.int32() / 65536;\n\t}\n\n\t/** 2.14 fixed-point number */\n\tf2dot14(): F2Dot14 {\n\t\treturn this.int16() / 16384;\n\t}\n\n\t/** Signed 16-bit integer in font design units */\n\tfword(): int16 {\n\t\treturn this.int16();\n\t}\n\n\t/** Unsigned 16-bit integer in font design units */\n\tufword(): uint16 {\n\t\treturn this.uint16();\n\t}\n\n\t/** 64-bit signed integer (seconds since 1904-01-01) */\n\tlongDateTime(): bigint {\n\t\tconst high = this.uint32();\n\t\tconst low = this.uint32();\n\t\treturn (BigInt(high) << 32n) | BigInt(low);\n\t}\n\n\t/** 4-byte ASCII tag as packed uint32 */\n\ttag(): Tag {\n\t\treturn this.uint32();\n\t}\n\n\t/** 4-byte ASCII tag as string */\n\ttagString(): string {\n\t\tconst t = this.uint32();\n\t\treturn String.fromCharCode(\n\t\t\t(t >> 24) & 0xff,\n\t\t\t(t >> 16) & 0xff,\n\t\t\t(t >> 8) & 0xff,\n\t\t\tt & 0xff,\n\t\t);\n\t}\n\n\t/** 16-bit offset */\n\toffset16(): Offset16 {\n\t\treturn this.uint16();\n\t}\n\n\t/** 32-bit offset */\n\toffset32(): Offset32 {\n\t\treturn this.uint32();\n\t}\n\n\t/** 24-bit unsigned integer */\n\tuint24(): number {\n\t\tconst b0 = this.data.getUint8(this.pos);\n\t\tconst b1 = this.data.getUint8(this.pos + 1);\n\t\tconst b2 = this.data.getUint8(this.pos + 2);\n\t\tthis.pos += 3;\n\t\treturn (b0 << 16) | (b1 << 8) | b2;\n\t}\n\n\t// Array readers\n\n\tuint8Array(count: number): Uint8Array {\n\t\tconst result = new Uint8Array(count);\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tresult[i] = this.uint8();\n\t\t}\n\t\treturn result;\n\t}\n\n\tuint16Array(count: number): Uint16Array {\n\t\tconst result = new Uint16Array(count);\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tresult[i] = this.uint16();\n\t\t}\n\t\treturn result;\n\t}\n\n\tint16Array(count: number): Int16Array {\n\t\tconst result = new Int16Array(count);\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tresult[i] = this.int16();\n\t\t}\n\t\treturn result;\n\t}\n\n\tuint32Array(count: number): Uint32Array {\n\t\tconst result = new Uint32Array(count);\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tresult[i] = this.uint32();\n\t\t}\n\t\treturn result;\n\t}\n\n\t/** Read array using custom reader function */\n\tarray<T>(count: number, readFn: (reader: Reader) => T): T[] {\n\t\tconst result: T[] = new Array(count);\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tresult[i] = readFn(this);\n\t\t}\n\t\treturn result;\n\t}\n\n\t// String readers\n\n\t/** Read ASCII string of given length */\n\tascii(length: number): string {\n\t\tlet result = \"\";\n\t\tfor (let i = 0; i < length; i++) {\n\t\t\tresult += String.fromCharCode(this.uint8());\n\t\t}\n\t\treturn result;\n\t}\n\n\t/** Read UTF-16BE string (used in 'name' table) */\n\tutf16be(length: number): string {\n\t\tconst chars: number[] = [];\n\t\tconst charCount = length / 2;\n\t\tfor (let i = 0; i < charCount; i++) {\n\t\t\tchars.push(this.uint16());\n\t\t}\n\t\treturn String.fromCharCode(...chars);\n\t}\n\n\t// Utility methods\n\n\t/** Check if there are enough bytes remaining */\n\thasRemaining(bytes: number): boolean {\n\t\treturn this.remaining >= bytes;\n\t}\n\n\t/** Throw if not enough bytes remaining */\n\tensureRemaining(bytes: number): void {\n\t\tif (this.remaining < bytes) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unexpected end of data: need ${bytes} bytes, have ${this.remaining}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/** Get raw bytes as Uint8Array (zero-copy view) */\n\tbytes(length: number): Uint8Array {\n\t\tconst result = new Uint8Array(\n\t\t\tthis.data.buffer,\n\t\t\tthis.data.byteOffset + this.pos,\n\t\t\tlength,\n\t\t);\n\t\tthis.pos += length;\n\t\treturn result;\n\t}\n\n\t/** Read value at specific offset without moving position */\n\treadAt<T>(offset: number, fn: (reader: Reader) => T): T {\n\t\tconst savedPos = this.pos;\n\t\tthis.pos = this.start + offset;\n\t\tconst result = fn(this);\n\t\tthis.pos = savedPos;\n\t\treturn result;\n\t}\n}\n",
10
+ "import type { uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Axis Variations table (avar)\n * Maps user-facing axis values to normalized coordinates\n */\nexport interface AvarTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\taxisSegmentMaps: AxisSegmentMap[];\n}\n\n/**\n * Segment map for an axis\n */\nexport interface AxisSegmentMap {\n\taxisValueMaps: AxisValueMap[];\n}\n\n/**\n * Single value mapping\n */\nexport interface AxisValueMap {\n\tfromCoordinate: number; // F2DOT14\n\ttoCoordinate: number; // F2DOT14\n}\n\n/**\n * Parse avar table\n */\nexport function parseAvar(reader: Reader, axisCount: number): AvarTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\treader.skip(2); // reserved\n\n\tconst axisSegmentMaps: AxisSegmentMap[] = [];\n\n\tfor (let i = 0; i < axisCount; i++) {\n\t\tconst positionMapCount = reader.uint16();\n\t\tconst axisValueMaps: AxisValueMap[] = [];\n\n\t\tfor (let j = 0; j < positionMapCount; j++) {\n\t\t\taxisValueMaps.push({\n\t\t\t\tfromCoordinate: reader.f2dot14(),\n\t\t\t\ttoCoordinate: reader.f2dot14(),\n\t\t\t});\n\t\t}\n\n\t\taxisSegmentMaps.push({ axisValueMaps });\n\t}\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\taxisSegmentMaps,\n\t};\n}\n\n/**\n * Apply avar mapping to a normalized coordinate\n */\nexport function applyAvarMapping(\n\tsegmentMap: AxisSegmentMap,\n\tcoord: number,\n): number {\n\tconst maps = segmentMap.axisValueMaps;\n\n\tif (maps.length === 0) return coord;\n\n\t// Find the segment containing coord\n\tfor (let i = 0; i < maps.length - 1; i++) {\n\t\tconst map1 = maps[i];\n\t\tconst map2 = maps[i + 1];\n\t\tif (!map1 || !map2) continue;\n\n\t\tif (coord >= map1.fromCoordinate && coord <= map2.fromCoordinate) {\n\t\t\t// Linear interpolation\n\t\t\tconst t =\n\t\t\t\t(coord - map1.fromCoordinate) /\n\t\t\t\t(map2.fromCoordinate - map1.fromCoordinate);\n\t\t\treturn map1.toCoordinate + t * (map2.toCoordinate - map1.toCoordinate);\n\t\t}\n\t}\n\n\t// Clamp to range\n\tconst firstMap = maps[0];\n\tconst lastMap = maps[maps.length - 1];\n\tif (firstMap && coord <= firstMap.fromCoordinate) {\n\t\treturn firstMap.toCoordinate;\n\t}\n\treturn lastMap?.toCoordinate ?? coord;\n}\n\n/**\n * Apply avar mappings to all axis coordinates\n */\nexport function applyAvar(avar: AvarTable, coords: number[]): number[] {\n\tconst result: number[] = [];\n\n\tfor (const [i, coord] of coords.entries()) {\n\t\tconst segmentMap = avar.axisSegmentMaps[i];\n\t\tif (segmentMap) {\n\t\t\tresult.push(applyAvarMapping(segmentMap, coord));\n\t\t} else {\n\t\t\tresult.push(coord);\n\t\t}\n\t}\n\n\treturn result;\n}\n",
11
+ "import type { Fixed, Tag } from \"../../types.ts\";\nimport { tagToString } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Font Variations table (fvar)\n * Defines axes of variation in a variable font\n */\nexport interface FvarTable {\n\tmajorVersion: number;\n\tminorVersion: number;\n\taxes: VariationAxis[];\n\tinstances: NamedInstance[];\n}\n\n/**\n * Variation axis definition\n */\nexport interface VariationAxis {\n\t/** 4-byte axis tag (e.g., 'wght', 'wdth', 'ital') */\n\ttag: Tag;\n\t/** Minimum coordinate value */\n\tminValue: Fixed;\n\t/** Default coordinate value */\n\tdefaultValue: Fixed;\n\t/** Maximum coordinate value */\n\tmaxValue: Fixed;\n\t/** Axis qualifiers (flags) */\n\tflags: number;\n\t/** Name ID for this axis */\n\taxisNameId: number;\n}\n\n/**\n * Named instance (predefined variation)\n */\nexport interface NamedInstance {\n\t/** Name ID for this instance */\n\tsubfamilyNameId: number;\n\t/** Flags */\n\tflags: number;\n\t/** Coordinate values for each axis */\n\tcoordinates: Fixed[];\n\t/** PostScript name ID (optional) */\n\tpostScriptNameId?: number;\n}\n\n/**\n * Common axis tags\n */\nexport const AxisTags = {\n\t/** Weight (100-900, default 400) */\n\twght: 0x77676874,\n\t/** Width (50-200%, default 100) */\n\twdth: 0x77647468,\n\t/** Italic (0-1) */\n\tital: 0x6974616c,\n\t/** Slant (-90 to 90 degrees) */\n\tslnt: 0x736c6e74,\n\t/** Optical size (in points) */\n\topsz: 0x6f70737a,\n} as const;\n\n/**\n * Parse fvar table\n */\nexport function parseFvar(reader: Reader): FvarTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst axesArrayOffset = reader.offset16();\n\treader.skip(2); // reserved\n\tconst axisCount = reader.uint16();\n\tconst axisSize = reader.uint16();\n\tconst instanceCount = reader.uint16();\n\tconst instanceSize = reader.uint16();\n\n\t// Parse axes\n\tconst axes: VariationAxis[] = [];\n\treader.seek(axesArrayOffset);\n\n\tfor (let i = 0; i < axisCount; i++) {\n\t\tconst axisStart = reader.offset;\n\t\tconst tag = reader.uint32();\n\t\tconst minValue = reader.fixed();\n\t\tconst defaultValue = reader.fixed();\n\t\tconst maxValue = reader.fixed();\n\t\tconst flags = reader.uint16();\n\t\tconst axisNameId = reader.uint16();\n\n\t\taxes.push({\n\t\t\ttag,\n\t\t\tminValue,\n\t\t\tdefaultValue,\n\t\t\tmaxValue,\n\t\t\tflags,\n\t\t\taxisNameId,\n\t\t});\n\n\t\t// Move to next axis (in case axisSize is larger than expected)\n\t\treader.seek(axisStart + axisSize);\n\t}\n\n\t// Parse instances\n\tconst instances: NamedInstance[] = [];\n\tconst hasPostScriptNameId = instanceSize >= 4 + axisCount * 4 + 2;\n\n\tfor (let i = 0; i < instanceCount; i++) {\n\t\tconst instanceStart = reader.offset;\n\t\tconst subfamilyNameId = reader.uint16();\n\t\tconst flags = reader.uint16();\n\n\t\tconst coordinates: Fixed[] = [];\n\t\tfor (let j = 0; j < axisCount; j++) {\n\t\t\tcoordinates.push(reader.fixed());\n\t\t}\n\n\t\tconst instance: NamedInstance = {\n\t\t\tsubfamilyNameId,\n\t\t\tflags,\n\t\t\tcoordinates,\n\t\t};\n\n\t\tif (hasPostScriptNameId) {\n\t\t\tinstance.postScriptNameId = reader.uint16();\n\t\t}\n\n\t\tinstances.push(instance);\n\n\t\t// Move to next instance\n\t\treader.seek(instanceStart + instanceSize);\n\t}\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\taxes,\n\t\tinstances,\n\t};\n}\n\n/**\n * Normalize axis value to range [-1, 1]\n */\nexport function normalizeAxisValue(axis: VariationAxis, value: number): number {\n\tif (value < axis.defaultValue) {\n\t\tif (value < axis.minValue) value = axis.minValue;\n\t\tif (axis.defaultValue === axis.minValue) return 0;\n\t\treturn (value - axis.defaultValue) / (axis.defaultValue - axis.minValue);\n\t} else if (value > axis.defaultValue) {\n\t\tif (value > axis.maxValue) value = axis.maxValue;\n\t\tif (axis.defaultValue === axis.maxValue) return 0;\n\t\treturn (value - axis.defaultValue) / (axis.maxValue - axis.defaultValue);\n\t}\n\treturn 0;\n}\n\n/**\n * Get axis by tag\n */\nexport function getAxis(fvar: FvarTable, axisTag: Tag): VariationAxis | null {\n\treturn fvar.axes.find((a) => a.tag === axisTag) ?? null;\n}\n\n/**\n * Get axis index by tag\n */\nexport function getAxisIndex(fvar: FvarTable, axisTag: Tag): number {\n\treturn fvar.axes.findIndex((a) => a.tag === axisTag);\n}\n\n/**\n * Debug: Print axis info\n */\nexport function formatAxis(axis: VariationAxis): string {\n\treturn `${tagToString(axis.tag)}: ${axis.minValue.toFixed(1)}..${axis.defaultValue.toFixed(1)}..${axis.maxValue.toFixed(1)}`;\n}\n",
12
+ "import type { GlyphId, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Horizontal Metrics Variations table (HVAR)\n * Provides variations for horizontal advance widths and LSB\n */\nexport interface HvarTable {\n\tmajorVersion: number;\n\tminorVersion: number;\n\titemVariationStore: ItemVariationStore;\n\tadvanceWidthMapping: DeltaSetIndexMap | null;\n\tlsbMapping: DeltaSetIndexMap | null;\n\trsbMapping: DeltaSetIndexMap | null;\n}\n\n/**\n * Item Variation Store - stores delta values for variations\n */\nexport interface ItemVariationStore {\n\tformat: number;\n\tvariationRegions: VariationRegion[];\n\titemVariationData: ItemVariationData[];\n}\n\n/**\n * Variation region defines the space where deltas apply\n */\nexport interface VariationRegion {\n\tregionAxes: RegionAxisCoordinates[];\n}\n\n/**\n * Axis coordinates for a region\n */\nexport interface RegionAxisCoordinates {\n\tstartCoord: number; // F2DOT14\n\tpeakCoord: number;\n\tendCoord: number;\n}\n\n/**\n * Item variation data subtable\n */\nexport interface ItemVariationData {\n\titemCount: uint16;\n\tregionIndexes: uint16[];\n\tdeltaSets: number[][];\n}\n\n/**\n * Delta set index map for mapping glyphs to variation data\n */\nexport interface DeltaSetIndexMap {\n\tformat: number;\n\tmapCount: uint32;\n\tentryFormat: number;\n\tinnerIndexBitCount: number;\n\tmapData: { outer: number; inner: number }[];\n}\n\n/**\n * Parse HVAR table\n */\nexport function parseHvar(reader: Reader): HvarTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst itemVariationStoreOffset = reader.offset32();\n\tconst advanceWidthMappingOffset = reader.offset32();\n\tconst lsbMappingOffset = reader.offset32();\n\tconst rsbMappingOffset = reader.offset32();\n\n\t// Parse item variation store\n\tconst itemVariationStore = parseItemVariationStore(\n\t\treader.sliceFrom(itemVariationStoreOffset),\n\t);\n\n\t// Parse mappings\n\tconst advanceWidthMapping =\n\t\tadvanceWidthMappingOffset !== 0\n\t\t\t? parseDeltaSetIndexMap(reader.sliceFrom(advanceWidthMappingOffset))\n\t\t\t: null;\n\n\tconst lsbMapping =\n\t\tlsbMappingOffset !== 0\n\t\t\t? parseDeltaSetIndexMap(reader.sliceFrom(lsbMappingOffset))\n\t\t\t: null;\n\n\tconst rsbMapping =\n\t\trsbMappingOffset !== 0\n\t\t\t? parseDeltaSetIndexMap(reader.sliceFrom(rsbMappingOffset))\n\t\t\t: null;\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\titemVariationStore,\n\t\tadvanceWidthMapping,\n\t\tlsbMapping,\n\t\trsbMapping,\n\t};\n}\n\nfunction parseItemVariationStore(reader: Reader): ItemVariationStore {\n\tconst format = reader.uint16();\n\tconst variationRegionListOffset = reader.offset32();\n\tconst itemVariationDataCount = reader.uint16();\n\n\tconst itemVariationDataOffsets: uint32[] = [];\n\tfor (let i = 0; i < itemVariationDataCount; i++) {\n\t\titemVariationDataOffsets.push(reader.offset32());\n\t}\n\n\t// Parse variation regions\n\tconst regionReader = reader.sliceFrom(variationRegionListOffset);\n\tconst axisCount = regionReader.uint16();\n\tconst regionCount = regionReader.uint16();\n\n\tconst variationRegions: VariationRegion[] = [];\n\tfor (let i = 0; i < regionCount; i++) {\n\t\tconst regionAxes: RegionAxisCoordinates[] = [];\n\t\tfor (let j = 0; j < axisCount; j++) {\n\t\t\tregionAxes.push({\n\t\t\t\tstartCoord: regionReader.f2dot14(),\n\t\t\t\tpeakCoord: regionReader.f2dot14(),\n\t\t\t\tendCoord: regionReader.f2dot14(),\n\t\t\t});\n\t\t}\n\t\tvariationRegions.push({ regionAxes });\n\t}\n\n\t// Parse item variation data\n\tconst itemVariationData: ItemVariationData[] = [];\n\tfor (const offset of itemVariationDataOffsets) {\n\t\tconst dataReader = reader.sliceFrom(offset);\n\t\tconst itemCount = dataReader.uint16();\n\t\tconst wordDeltaCount = dataReader.uint16();\n\t\tconst regionIndexCount = dataReader.uint16();\n\n\t\tconst regionIndexes: uint16[] = [];\n\t\tfor (let i = 0; i < regionIndexCount; i++) {\n\t\t\tregionIndexes.push(dataReader.uint16());\n\t\t}\n\n\t\t// Parse delta sets\n\t\tconst longWords = (wordDeltaCount & 0x8000) !== 0;\n\t\tconst wordCount = wordDeltaCount & 0x7fff;\n\t\tconst shortCount = regionIndexCount - wordCount;\n\n\t\tconst deltaSets: number[][] = [];\n\t\tfor (let i = 0; i < itemCount; i++) {\n\t\t\tconst deltas: number[] = [];\n\t\t\t// Read word-sized deltas\n\t\t\tfor (let j = 0; j < wordCount; j++) {\n\t\t\t\tif (longWords) {\n\t\t\t\t\tdeltas.push(dataReader.int32());\n\t\t\t\t} else {\n\t\t\t\t\tdeltas.push(dataReader.int16());\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Read short-sized deltas\n\t\t\tfor (let j = 0; j < shortCount; j++) {\n\t\t\t\tif (longWords) {\n\t\t\t\t\tdeltas.push(dataReader.int16());\n\t\t\t\t} else {\n\t\t\t\t\tdeltas.push(dataReader.int8());\n\t\t\t\t}\n\t\t\t}\n\t\t\tdeltaSets.push(deltas);\n\t\t}\n\n\t\titemVariationData.push({ itemCount, regionIndexes, deltaSets });\n\t}\n\n\treturn { format, variationRegions, itemVariationData };\n}\n\nfunction parseDeltaSetIndexMap(reader: Reader): DeltaSetIndexMap {\n\tconst format = reader.uint8();\n\tconst entryFormat = reader.uint8();\n\tconst mapCount = format === 0 ? reader.uint16() : reader.uint32();\n\n\tconst innerIndexBitCount = (entryFormat & 0x0f) + 1;\n\tconst mapEntrySize = ((entryFormat >> 4) & 0x03) + 1;\n\n\tconst mapData: { outer: number; inner: number }[] = [];\n\tfor (let i = 0; i < mapCount; i++) {\n\t\tlet entry = 0;\n\t\tfor (let j = 0; j < mapEntrySize; j++) {\n\t\t\tentry = (entry << 8) | reader.uint8();\n\t\t}\n\n\t\tconst inner = entry & ((1 << innerIndexBitCount) - 1);\n\t\tconst outer = entry >> innerIndexBitCount;\n\t\tmapData.push({ outer, inner });\n\t}\n\n\treturn { format, mapCount, entryFormat, innerIndexBitCount, mapData };\n}\n\n/**\n * Calculate scalar for a variation region given axis coordinates\n */\nexport function calculateRegionScalar(\n\tregion: VariationRegion,\n\tcoords: number[], // Normalized axis coordinates [-1, 1]\n): number {\n\tlet scalar = 1.0;\n\n\tfor (let i = 0; i < region.regionAxes.length && i < coords.length; i++) {\n\t\tconst axis = region.regionAxes[i];\n\t\tconst coord = coords[i];\n\t\tif (axis === undefined || coord === undefined) continue;\n\n\t\t// Outside the region\n\t\tif (coord < axis.startCoord || coord > axis.endCoord) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t// At peak\n\t\tif (coord === axis.peakCoord) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Interpolate\n\t\tif (coord < axis.peakCoord) {\n\t\t\tif (axis.peakCoord === axis.startCoord) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tscalar *= (coord - axis.startCoord) / (axis.peakCoord - axis.startCoord);\n\t\t} else {\n\t\t\tif (axis.peakCoord === axis.endCoord) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tscalar *= (axis.endCoord - coord) / (axis.endCoord - axis.peakCoord);\n\t\t}\n\t}\n\n\treturn scalar;\n}\n\n/**\n * Get delta for a glyph from HVAR using a specific mapping\n */\nfunction getDeltaFromMapping(\n\thvar: HvarTable,\n\tglyphId: GlyphId,\n\tcoords: number[],\n\tmapping: DeltaSetIndexMap | null,\n): number {\n\t// Get outer/inner index\n\tlet outer: number;\n\tlet inner: number;\n\n\tif (mapping && glyphId < mapping.mapData.length) {\n\t\tconst entry = mapping.mapData[glyphId];\n\t\tif (!entry) {\n\t\t\touter = 0;\n\t\t\tinner = glyphId;\n\t\t} else {\n\t\t\touter = entry.outer;\n\t\t\tinner = entry.inner;\n\t\t}\n\t} else {\n\t\t// Direct mapping: outer = 0, inner = glyphId\n\t\touter = 0;\n\t\tinner = glyphId;\n\t}\n\n\t// Get variation data\n\tconst varData = hvar.itemVariationStore.itemVariationData[outer];\n\tif (!varData || inner >= varData.itemCount) {\n\t\treturn 0;\n\t}\n\n\tconst deltaSet = varData.deltaSets[inner];\n\tif (!deltaSet) {\n\t\treturn 0;\n\t}\n\n\t// Calculate total delta\n\tlet delta = 0;\n\tfor (const [i, regionIndex] of varData.regionIndexes.entries()) {\n\t\tconst region = hvar.itemVariationStore.variationRegions[regionIndex];\n\t\tif (!region) continue;\n\n\t\tconst scalar = calculateRegionScalar(region, coords);\n\t\tconst regionDelta = deltaSet[i] ?? 0;\n\t\tdelta += scalar * regionDelta;\n\t}\n\n\treturn Math.round(delta);\n}\n\n/**\n * Get advance width delta for a glyph at given variation coordinates\n */\nexport function getAdvanceWidthDelta(\n\thvar: HvarTable,\n\tglyphId: GlyphId,\n\tcoords: number[],\n): number {\n\treturn getDeltaFromMapping(hvar, glyphId, coords, hvar.advanceWidthMapping);\n}\n\n/**\n * Get left side bearing delta for a glyph at given variation coordinates\n */\nexport function getLsbDelta(\n\thvar: HvarTable,\n\tglyphId: GlyphId,\n\tcoords: number[],\n): number {\n\tif (!hvar.lsbMapping) {\n\t\treturn 0; // No LSB variations in this font\n\t}\n\treturn getDeltaFromMapping(hvar, glyphId, coords, hvar.lsbMapping);\n}\n\n/**\n * Get right side bearing delta for a glyph at given variation coordinates\n */\nexport function getRsbDelta(\n\thvar: HvarTable,\n\tglyphId: GlyphId,\n\tcoords: number[],\n): number {\n\tif (!hvar.rsbMapping) {\n\t\treturn 0; // No RSB variations in this font\n\t}\n\treturn getDeltaFromMapping(hvar, glyphId, coords, hvar.rsbMapping);\n}\n",
13
+ "import type { GlyphId, Tag, Variation } from \"../types.ts\";\nimport { tag } from \"../types.ts\";\nimport type { Font } from \"./font.ts\";\nimport { applyAvar } from \"./tables/avar.ts\";\nimport { normalizeAxisValue, type VariationAxis } from \"./tables/fvar.ts\";\nimport { getAdvanceWidthDelta, getLsbDelta } from \"./tables/hvar.ts\";\n\n/**\n * A Face represents a specific instance of a variable font.\n * For non-variable fonts, it simply wraps the Font.\n */\nexport class Face {\n\treadonly font: Font;\n\n\t/** Normalized axis coordinates [-1, 1] */\n\tprivate _coords: number[];\n\n\t/** User-space axis values */\n\tprivate _variations: Map<Tag, number>;\n\n\tconstructor(font: Font, variations?: Record<string, number> | Variation[]) {\n\t\tthis.font = font;\n\t\tthis._coords = [];\n\t\tthis._variations = new Map();\n\n\t\t// Initialize to default axis values\n\t\tconst fvar = font.fvar;\n\t\tif (fvar) {\n\t\t\tthis._coords = new Array(fvar.axes.length).fill(0);\n\n\t\t\t// Apply user variations\n\t\t\tif (variations) {\n\t\t\t\tthis.setVariations(variations);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Set variation axis values\n\t * @param variations Object with axis tags as keys (e.g., { wght: 700, wdth: 100 })\n\t * or array of Variation objects\n\t */\n\tsetVariations(variations: Record<string, number> | Variation[]): void {\n\t\tconst fvar = this.font.fvar;\n\t\tif (!fvar) return;\n\n\t\t// Convert to map\n\t\tif (Array.isArray(variations)) {\n\t\t\tfor (const v of variations) {\n\t\t\t\tthis._variations.set(v.tag, v.value);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const [tagStr, value] of Object.entries(variations)) {\n\t\t\t\tconst t = tag(tagStr.padEnd(4, \" \"));\n\t\t\t\tthis._variations.set(t, value);\n\t\t\t}\n\t\t}\n\n\t\t// Normalize coordinates\n\t\tfor (const [i, axis] of fvar.axes.entries()) {\n\t\t\tconst userValue = this._variations.get(axis.tag) ?? axis.defaultValue;\n\t\t\tthis._coords[i] = normalizeAxisValue(axis, userValue);\n\t\t}\n\n\t\t// Apply avar mapping if present\n\t\tconst avar = this.font.avar;\n\t\tif (avar) {\n\t\t\tthis._coords = applyAvar(avar, this._coords);\n\t\t}\n\t}\n\n\t/**\n\t * Get normalized coordinates for variation processing\n\t */\n\tget normalizedCoords(): number[] {\n\t\treturn this._coords;\n\t}\n\n\t/**\n\t * Check if this is a variable font instance\n\t */\n\tget isVariable(): boolean {\n\t\treturn this.font.isVariable;\n\t}\n\n\t/**\n\t * Get variation axes\n\t */\n\tget axes(): VariationAxis[] {\n\t\treturn this.font.fvar?.axes ?? [];\n\t}\n\n\t/**\n\t * Get current value for an axis\n\t */\n\tgetAxisValue(axisTag: Tag | string): number | null {\n\t\tconst t =\n\t\t\ttypeof axisTag === \"string\" ? tag(axisTag.padEnd(4, \" \")) : axisTag;\n\t\tconst fvar = this.font.fvar;\n\t\tif (!fvar) return null;\n\n\t\tconst value = this._variations.get(t);\n\t\tif (value !== undefined) return value;\n\n\t\tconst axis = fvar.axes.find((a) => a.tag === t);\n\t\treturn axis?.defaultValue ?? null;\n\t}\n\n\t/**\n\t * Get advance width for a glyph, including variation deltas\n\t */\n\tadvanceWidth(glyphId: GlyphId): number {\n\t\tlet advance = this.font.advanceWidth(glyphId);\n\n\t\t// Apply HVAR delta if variable\n\t\tif (this._coords.length > 0 && this.font.hvar) {\n\t\t\tconst delta = getAdvanceWidthDelta(this.font.hvar, glyphId, this._coords);\n\t\t\tadvance += delta;\n\t\t}\n\n\t\treturn advance;\n\t}\n\n\t/**\n\t * Get left side bearing for a glyph, including variation deltas\n\t */\n\tleftSideBearing(glyphId: GlyphId): number {\n\t\tlet lsb = this.font.leftSideBearing(glyphId);\n\n\t\t// Apply HVAR LSB delta if variable\n\t\tif (this._coords.length > 0 && this.font.hvar) {\n\t\t\tconst delta = getLsbDelta(this.font.hvar, glyphId, this._coords);\n\t\t\tlsb += delta;\n\t\t}\n\n\t\treturn lsb;\n\t}\n\n\t// Delegate common properties to font\n\n\tget numGlyphs(): number {\n\t\treturn this.font.numGlyphs;\n\t}\n\n\tget unitsPerEm(): number {\n\t\treturn this.font.unitsPerEm;\n\t}\n\n\tget ascender(): number {\n\t\treturn this.font.ascender;\n\t}\n\n\tget descender(): number {\n\t\treturn this.font.descender;\n\t}\n\n\tget lineGap(): number {\n\t\treturn this.font.lineGap;\n\t}\n\n\tglyphId(codepoint: number): GlyphId {\n\t\treturn this.font.glyphId(codepoint);\n\t}\n\n\tglyphIdForChar(char: string): GlyphId {\n\t\treturn this.font.glyphIdForChar(char);\n\t}\n\n\thasTable(t: Tag): boolean {\n\t\treturn this.font.hasTable(t);\n\t}\n\n\t// Expose tables\n\tget gdef() {\n\t\treturn this.font.gdef;\n\t}\n\tget gsub() {\n\t\treturn this.font.gsub;\n\t}\n\tget gpos() {\n\t\treturn this.font.gpos;\n\t}\n\tget kern() {\n\t\treturn this.font.kern;\n\t}\n\tget morx() {\n\t\treturn this.font.morx;\n\t}\n\tget cmap() {\n\t\treturn this.font.cmap;\n\t}\n\tget hmtx() {\n\t\treturn this.font.hmtx;\n\t}\n\tget hhea() {\n\t\treturn this.font.hhea;\n\t}\n}\n\n/**\n * Create a face from a font with optional variations\n */\nexport function createFace(\n\tfont: Font,\n\tvariations?: Record<string, number> | Variation[],\n): Face {\n\treturn new Face(font, variations);\n}\n",
14
+ "import type { int16, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * BASE table - Baseline alignment data\n * Provides baseline offsets for scripts to align mixed-script text\n */\n\n/** Baseline tags */\nexport const BaselineTag = {\n\t/** Hanging baseline (Devanagari, Tibetan) */\n\thang: 0x68616e67,\n\t/** Ideographic character face bottom edge (CJK) */\n\ticfb: 0x69636662,\n\t/** Ideographic character face top edge (CJK) */\n\ticft: 0x69636674,\n\t/** Ideographic em-box bottom edge (CJK) */\n\tideo: 0x6964656f,\n\t/** Ideographic em-box top edge */\n\tidtp: 0x69647470,\n\t/** Mathematical baseline (math layout) */\n\tmath: 0x6d617468,\n\t/** Roman baseline (Latin, Greek, Cyrillic) */\n\tromn: 0x726f6d6e,\n} as const;\n\n/** A single baseline value */\nexport interface BaselineValue {\n\tbaselineTag: number;\n\tcoordinate: int16;\n}\n\n/** Min/max extent values */\nexport interface MinMaxRecord {\n\tminCoord: int16 | null;\n\tmaxCoord: int16 | null;\n}\n\n/** Feature-specific min/max values */\nexport interface FeatMinMaxRecord {\n\tfeatureTag: number;\n\tminCoord: int16 | null;\n\tmaxCoord: int16 | null;\n}\n\n/** Base values for a script */\nexport interface BaseValues {\n\tdefaultBaselineIndex: uint16;\n\tbaseCoords: int16[];\n}\n\n/** MinMax values for a language system */\nexport interface MinMax {\n\tminCoord: int16 | null;\n\tmaxCoord: int16 | null;\n\tfeatMinMaxRecords: FeatMinMaxRecord[];\n}\n\n/** Base script record */\nexport interface BaseScriptRecord {\n\tscriptTag: number;\n\tbaseValues: BaseValues | null;\n\tdefaultMinMax: MinMax | null;\n\tbaseLangSysRecords: Map<number, MinMax>;\n}\n\n/** Axis table (horizontal or vertical) */\nexport interface AxisTable {\n\tbaseTagList: number[];\n\tbaseScriptList: BaseScriptRecord[];\n}\n\n/** BASE table */\nexport interface BaseTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\thorizAxis: AxisTable | null;\n\tvertAxis: AxisTable | null;\n}\n\n/** Coordinate format */\ninterface BaseCoord {\n\tformat: uint16;\n\tcoordinate: int16;\n\treferenceGlyph?: uint16;\n\tbaseCoordPoint?: uint16;\n\tdeviceOffset?: uint16;\n}\n\nfunction parseBaseCoord(reader: Reader): BaseCoord {\n\tconst format = reader.uint16();\n\tconst coordinate = reader.int16();\n\n\tconst result: BaseCoord = { format, coordinate };\n\n\tif (format === 2) {\n\t\tresult.referenceGlyph = reader.uint16();\n\t\tresult.baseCoordPoint = reader.uint16();\n\t} else if (format === 3) {\n\t\tresult.deviceOffset = reader.uint16();\n\t}\n\n\treturn result;\n}\n\nfunction parseMinMax(reader: Reader, minMaxOffset: number): MinMax | null {\n\tif (minMaxOffset === 0) return null;\n\n\tconst minMaxReader = reader.sliceFrom(minMaxOffset);\n\tconst minCoordOffset = minMaxReader.uint16();\n\tconst maxCoordOffset = minMaxReader.uint16();\n\tconst featMinMaxCount = minMaxReader.uint16();\n\n\tlet minCoord: int16 | null = null;\n\tlet maxCoord: int16 | null = null;\n\n\tif (minCoordOffset !== 0) {\n\t\tconst coordReader = reader.sliceFrom(minMaxOffset + minCoordOffset);\n\t\tminCoord = parseBaseCoord(coordReader).coordinate;\n\t}\n\n\tif (maxCoordOffset !== 0) {\n\t\tconst coordReader = reader.sliceFrom(minMaxOffset + maxCoordOffset);\n\t\tmaxCoord = parseBaseCoord(coordReader).coordinate;\n\t}\n\n\tconst featMinMaxRecords: FeatMinMaxRecord[] = [];\n\tfor (let i = 0; i < featMinMaxCount; i++) {\n\t\tconst featureTag = minMaxReader.uint32();\n\t\tconst minOffset = minMaxReader.uint16();\n\t\tconst maxOffset = minMaxReader.uint16();\n\n\t\tlet featMin: int16 | null = null;\n\t\tlet featMax: int16 | null = null;\n\n\t\tif (minOffset !== 0) {\n\t\t\tconst coordReader = reader.sliceFrom(minMaxOffset + minOffset);\n\t\t\tfeatMin = parseBaseCoord(coordReader).coordinate;\n\t\t}\n\n\t\tif (maxOffset !== 0) {\n\t\t\tconst coordReader = reader.sliceFrom(minMaxOffset + maxOffset);\n\t\t\tfeatMax = parseBaseCoord(coordReader).coordinate;\n\t\t}\n\n\t\tfeatMinMaxRecords.push({\n\t\t\tfeatureTag,\n\t\t\tminCoord: featMin,\n\t\t\tmaxCoord: featMax,\n\t\t});\n\t}\n\n\treturn { minCoord, maxCoord, featMinMaxRecords };\n}\n\nfunction parseBaseValues(\n\treader: Reader,\n\tbaseValuesOffset: number,\n\t_baseTagList: number[],\n): BaseValues | null {\n\tif (baseValuesOffset === 0) return null;\n\n\tconst bvReader = reader.sliceFrom(baseValuesOffset);\n\tconst defaultBaselineIndex = bvReader.uint16();\n\tconst baseCoordCount = bvReader.uint16();\n\n\tconst coordOffsets: uint16[] = [];\n\tfor (let i = 0; i < baseCoordCount; i++) {\n\t\tcoordOffsets.push(bvReader.uint16());\n\t}\n\n\tconst baseCoords: int16[] = [];\n\tfor (const offset of coordOffsets) {\n\t\tif (offset !== 0) {\n\t\t\tconst coordReader = reader.sliceFrom(baseValuesOffset + offset);\n\t\t\tbaseCoords.push(parseBaseCoord(coordReader).coordinate);\n\t\t} else {\n\t\t\tbaseCoords.push(0);\n\t\t}\n\t}\n\n\treturn { defaultBaselineIndex, baseCoords };\n}\n\nfunction parseBaseScriptRecord(\n\treader: Reader,\n\tscriptOffset: number,\n\tbaseTagList: number[],\n): Omit<BaseScriptRecord, \"scriptTag\"> {\n\tconst scriptReader = reader.sliceFrom(scriptOffset);\n\tconst baseValuesOffset = scriptReader.uint16();\n\tconst defaultMinMaxOffset = scriptReader.uint16();\n\tconst baseLangSysCount = scriptReader.uint16();\n\n\tconst baseLangSysRecords = new Map<number, MinMax>();\n\tconst langSysData: Array<{ tag: number; offset: number }> = [];\n\n\tfor (let i = 0; i < baseLangSysCount; i++) {\n\t\tconst tag = scriptReader.uint32();\n\t\tconst offset = scriptReader.uint16();\n\t\tlangSysData.push({ tag, offset });\n\t}\n\n\tconst baseValues = parseBaseValues(\n\t\treader,\n\t\tscriptOffset + baseValuesOffset,\n\t\tbaseTagList,\n\t);\n\tconst defaultMinMax = parseMinMax(reader, scriptOffset + defaultMinMaxOffset);\n\n\tfor (const { tag, offset } of langSysData) {\n\t\tconst minMax = parseMinMax(reader, scriptOffset + offset);\n\t\tif (minMax) {\n\t\t\tbaseLangSysRecords.set(tag, minMax);\n\t\t}\n\t}\n\n\treturn { baseValues, defaultMinMax, baseLangSysRecords };\n}\n\nfunction parseAxisTable(reader: Reader, axisOffset: number): AxisTable | null {\n\tif (axisOffset === 0) return null;\n\n\tconst axisReader = reader.sliceFrom(axisOffset);\n\tconst baseTagListOffset = axisReader.uint16();\n\tconst baseScriptListOffset = axisReader.uint16();\n\n\t// Parse base tag list\n\tconst baseTagList: number[] = [];\n\tif (baseTagListOffset !== 0) {\n\t\tconst tagReader = reader.sliceFrom(axisOffset + baseTagListOffset);\n\t\tconst baseTagCount = tagReader.uint16();\n\t\tfor (let i = 0; i < baseTagCount; i++) {\n\t\t\tbaseTagList.push(tagReader.uint32());\n\t\t}\n\t}\n\n\t// Parse base script list\n\tconst baseScriptList: BaseScriptRecord[] = [];\n\tif (baseScriptListOffset !== 0) {\n\t\tconst scriptListReader = reader.sliceFrom(\n\t\t\taxisOffset + baseScriptListOffset,\n\t\t);\n\t\tconst baseScriptCount = scriptListReader.uint16();\n\n\t\tconst scriptData: Array<{ tag: number; offset: number }> = [];\n\t\tfor (let i = 0; i < baseScriptCount; i++) {\n\t\t\tconst tag = scriptListReader.uint32();\n\t\t\tconst offset = scriptListReader.uint16();\n\t\t\tscriptData.push({ tag, offset });\n\t\t}\n\n\t\tfor (const { tag, offset } of scriptData) {\n\t\t\tconst record = parseBaseScriptRecord(\n\t\t\t\treader,\n\t\t\t\taxisOffset + baseScriptListOffset + offset,\n\t\t\t\tbaseTagList,\n\t\t\t);\n\t\t\tbaseScriptList.push({ scriptTag: tag, ...record });\n\t\t}\n\t}\n\n\treturn { baseTagList, baseScriptList };\n}\n\nexport function parseBase(reader: Reader): BaseTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst horizAxisOffset = reader.uint16();\n\tconst vertAxisOffset = reader.uint16();\n\n\tconst horizAxis = parseAxisTable(reader, horizAxisOffset);\n\tconst vertAxis = parseAxisTable(reader, vertAxisOffset);\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\thorizAxis,\n\t\tvertAxis,\n\t};\n}\n\n/** Get baseline value for a script */\nexport function getBaselineForScript(\n\tbase: BaseTable,\n\tscriptTag: number,\n\tbaselineTag: number,\n\thorizontal: boolean = true,\n): int16 | null {\n\tconst axis = horizontal ? base.horizAxis : base.vertAxis;\n\tif (!axis) return null;\n\n\t// Find script record\n\tconst scriptRecord = axis.baseScriptList.find(\n\t\t(r) => r.scriptTag === scriptTag,\n\t);\n\tif (!scriptRecord?.baseValues) return null;\n\n\t// Find baseline tag index\n\tconst tagIndex = axis.baseTagList.indexOf(baselineTag);\n\tif (tagIndex === -1) return null;\n\n\treturn scriptRecord.baseValues.baseCoords[tagIndex] ?? null;\n}\n\n/** Get default baseline for a script */\nexport function getDefaultBaseline(\n\tbase: BaseTable,\n\tscriptTag: number,\n\thorizontal: boolean = true,\n): { tag: number; coordinate: int16 } | null {\n\tconst axis = horizontal ? base.horizAxis : base.vertAxis;\n\tif (!axis) return null;\n\n\tconst scriptRecord = axis.baseScriptList.find(\n\t\t(r) => r.scriptTag === scriptTag,\n\t);\n\tif (!scriptRecord?.baseValues) return null;\n\n\tconst index = scriptRecord.baseValues.defaultBaselineIndex;\n\tconst tag = axis.baseTagList[index];\n\tconst coordinate = scriptRecord.baseValues.baseCoords[index];\n\n\tif (tag === undefined || coordinate === undefined) return null;\n\n\treturn { tag, coordinate };\n}\n\n/** Get min/max extent for a script/language */\nexport function getMinMaxExtent(\n\tbase: BaseTable,\n\tscriptTag: number,\n\tlanguageTag?: number,\n\thorizontal: boolean = true,\n): MinMaxRecord | null {\n\tconst axis = horizontal ? base.horizAxis : base.vertAxis;\n\tif (!axis) return null;\n\n\tconst scriptRecord = axis.baseScriptList.find(\n\t\t(r) => r.scriptTag === scriptTag,\n\t);\n\tif (!scriptRecord) return null;\n\n\t// Try language-specific first\n\tif (languageTag !== undefined) {\n\t\tconst langMinMax = scriptRecord.baseLangSysRecords.get(languageTag);\n\t\tif (langMinMax) {\n\t\t\treturn { minCoord: langMinMax.minCoord, maxCoord: langMinMax.maxCoord };\n\t\t}\n\t}\n\n\t// Fall back to default\n\tif (scriptRecord.defaultMinMax) {\n\t\treturn {\n\t\t\tminCoord: scriptRecord.defaultMinMax.minCoord,\n\t\t\tmaxCoord: scriptRecord.defaultMinMax.maxCoord,\n\t\t};\n\t}\n\n\treturn null;\n}\n",
15
+ "import type { GlyphId, int8, uint8, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Color Bitmap Data Table (CBDT)\n * Google's color bitmap table for emoji fonts\n * Used together with CBLC (Color Bitmap Location Table)\n */\nexport interface CbdtTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\t/** Raw data for bitmap lookup */\n\tdata: Uint8Array;\n}\n\n/**\n * Color Bitmap Location Table (CBLC)\n * Index for looking up bitmaps in CBDT\n */\nexport interface CblcTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\tbitmapSizes: BitmapSize[];\n}\n\n/**\n * Bitmap size record\n */\nexport interface BitmapSize {\n\tindexSubTableArrayOffset: uint32;\n\tindexTablesSize: uint32;\n\tnumberOfIndexSubTables: uint32;\n\tcolorRef: uint32;\n\thori: SbitLineMetrics;\n\tvert: SbitLineMetrics;\n\tstartGlyphIndex: GlyphId;\n\tendGlyphIndex: GlyphId;\n\tppemX: uint8;\n\tppemY: uint8;\n\tbitDepth: uint8;\n\tflags: int8;\n\tindexSubTables: IndexSubTable[];\n}\n\n/**\n * Line metrics for bitmap glyphs\n */\nexport interface SbitLineMetrics {\n\tascender: int8;\n\tdescender: int8;\n\twidthMax: uint8;\n\tcaretSlopeNumerator: int8;\n\tcaretSlopeDenominator: int8;\n\tcaretOffset: int8;\n\tminOriginSB: int8;\n\tminAdvanceSB: int8;\n\tmaxBeforeBL: int8;\n\tminAfterBL: int8;\n\tpad1: int8;\n\tpad2: int8;\n}\n\n/**\n * Index sub-table for glyph lookup\n */\nexport interface IndexSubTable {\n\tfirstGlyphIndex: GlyphId;\n\tlastGlyphIndex: GlyphId;\n\tindexFormat: uint16;\n\timageFormat: uint16;\n\timageDataOffset: uint32;\n\t/** Glyph offsets (format-dependent) */\n\tglyphOffsets: Map<GlyphId, { offset: uint32; length: uint32 }>;\n}\n\n/**\n * Bitmap glyph metrics\n */\nexport interface GlyphBitmapMetrics {\n\theight: uint8;\n\twidth: uint8;\n\tbearingX: int8;\n\tbearingY: int8;\n\tadvance: uint8;\n}\n\n/**\n * Bitmap glyph data\n */\nexport interface BitmapGlyph {\n\tmetrics: GlyphBitmapMetrics;\n\timageFormat: uint16;\n\tdata: Uint8Array;\n}\n\n/**\n * Image formats in CBDT\n */\nexport const CbdtImageFormat = {\n\tSmallMetrics: 1, // Small metrics, byte-aligned\n\tSmallMetricsPng: 17, // Small metrics + PNG\n\tBigMetrics: 2, // Big metrics, byte-aligned\n\tBigMetricsPng: 18, // Big metrics + PNG\n\tCompressedPng: 19, // Metrics in CBLC + PNG\n} as const;\n\n/**\n * Parse CBLC table\n */\nexport function parseCblc(reader: Reader): CblcTable {\n\tconst tableStart = reader.offset;\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst numSizes = reader.uint32();\n\n\tconst bitmapSizes: BitmapSize[] = [];\n\n\t// Read BitmapSize records\n\tfor (let i = 0; i < numSizes; i++) {\n\t\tconst indexSubTableArrayOffset = reader.uint32();\n\t\tconst indexTablesSize = reader.uint32();\n\t\tconst numberOfIndexSubTables = reader.uint32();\n\t\tconst colorRef = reader.uint32();\n\n\t\tconst hori = parseSbitLineMetrics(reader);\n\t\tconst vert = parseSbitLineMetrics(reader);\n\n\t\tconst startGlyphIndex = reader.uint16();\n\t\tconst endGlyphIndex = reader.uint16();\n\t\tconst ppemX = reader.uint8();\n\t\tconst ppemY = reader.uint8();\n\t\tconst bitDepth = reader.uint8();\n\t\tconst flags = reader.int8();\n\n\t\tbitmapSizes.push({\n\t\t\tindexSubTableArrayOffset,\n\t\t\tindexTablesSize,\n\t\t\tnumberOfIndexSubTables,\n\t\t\tcolorRef,\n\t\t\thori,\n\t\t\tvert,\n\t\t\tstartGlyphIndex,\n\t\t\tendGlyphIndex,\n\t\t\tppemX,\n\t\t\tppemY,\n\t\t\tbitDepth,\n\t\t\tflags,\n\t\t\tindexSubTables: [],\n\t\t});\n\t}\n\n\t// Parse index sub-tables for each bitmap size\n\tfor (const size of bitmapSizes) {\n\t\tconst subTableReader = reader.sliceFrom(\n\t\t\ttableStart + size.indexSubTableArrayOffset,\n\t\t);\n\n\t\t// Read IndexSubTableArray\n\t\tconst subTableHeaders: {\n\t\t\tfirstGlyphIndex: uint16;\n\t\t\tlastGlyphIndex: uint16;\n\t\t\tadditionalOffsetToIndexSubtable: uint32;\n\t\t}[] = [];\n\n\t\tfor (let i = 0; i < size.numberOfIndexSubTables; i++) {\n\t\t\tsubTableHeaders.push({\n\t\t\t\tfirstGlyphIndex: subTableReader.uint16(),\n\t\t\t\tlastGlyphIndex: subTableReader.uint16(),\n\t\t\t\tadditionalOffsetToIndexSubtable: subTableReader.uint32(),\n\t\t\t});\n\t\t}\n\n\t\t// Parse each index sub-table\n\t\tfor (const header of subTableHeaders) {\n\t\t\tconst indexSubTable = parseIndexSubTable(\n\t\t\t\treader,\n\t\t\t\ttableStart +\n\t\t\t\t\tsize.indexSubTableArrayOffset +\n\t\t\t\t\theader.additionalOffsetToIndexSubtable,\n\t\t\t\theader.firstGlyphIndex,\n\t\t\t\theader.lastGlyphIndex,\n\t\t\t);\n\t\t\tsize.indexSubTables.push(indexSubTable);\n\t\t}\n\t}\n\n\treturn { majorVersion, minorVersion, bitmapSizes };\n}\n\nfunction parseSbitLineMetrics(reader: Reader): SbitLineMetrics {\n\treturn {\n\t\tascender: reader.int8(),\n\t\tdescender: reader.int8(),\n\t\twidthMax: reader.uint8(),\n\t\tcaretSlopeNumerator: reader.int8(),\n\t\tcaretSlopeDenominator: reader.int8(),\n\t\tcaretOffset: reader.int8(),\n\t\tminOriginSB: reader.int8(),\n\t\tminAdvanceSB: reader.int8(),\n\t\tmaxBeforeBL: reader.int8(),\n\t\tminAfterBL: reader.int8(),\n\t\tpad1: reader.int8(),\n\t\tpad2: reader.int8(),\n\t};\n}\n\nfunction parseIndexSubTable(\n\treader: Reader,\n\toffset: number,\n\tfirstGlyph: GlyphId,\n\tlastGlyph: GlyphId,\n): IndexSubTable {\n\tconst subReader = reader.sliceFrom(offset);\n\tconst indexFormat = subReader.uint16();\n\tconst imageFormat = subReader.uint16();\n\tconst imageDataOffset = subReader.uint32();\n\n\tconst glyphOffsets = new Map<GlyphId, { offset: uint32; length: uint32 }>();\n\tconst numGlyphs = lastGlyph - firstGlyph + 1;\n\n\tswitch (indexFormat) {\n\t\tcase 1: {\n\t\t\t// Variable metrics, 4-byte offsets\n\t\t\tconst offsets: uint32[] = [];\n\t\t\tfor (let i = 0; i <= numGlyphs; i++) {\n\t\t\t\toffsets.push(subReader.uint32());\n\t\t\t}\n\t\t\tfor (let i = 0; i < numGlyphs; i++) {\n\t\t\t\tconst glyphOffset = offsets[i]!;\n\t\t\t\tconst nextOffset = offsets[i + 1]!;\n\t\t\t\tif (nextOffset > glyphOffset) {\n\t\t\t\t\tglyphOffsets.set(firstGlyph + i, {\n\t\t\t\t\t\toffset: imageDataOffset + glyphOffset,\n\t\t\t\t\t\tlength: nextOffset - glyphOffset,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 2: {\n\t\t\t// Constant image size\n\t\t\tconst imageSize = subReader.uint32();\n\t\t\t// Big metrics follow\n\t\t\tconst _bigMetrics = {\n\t\t\t\theight: subReader.uint8(),\n\t\t\t\twidth: subReader.uint8(),\n\t\t\t\thoriBearingX: subReader.int8(),\n\t\t\t\thoriBearingY: subReader.int8(),\n\t\t\t\thoriAdvance: subReader.uint8(),\n\t\t\t\tvertBearingX: subReader.int8(),\n\t\t\t\tvertBearingY: subReader.int8(),\n\t\t\t\tvertAdvance: subReader.uint8(),\n\t\t\t};\n\t\t\tfor (let i = 0; i < numGlyphs; i++) {\n\t\t\t\tglyphOffsets.set(firstGlyph + i, {\n\t\t\t\t\toffset: imageDataOffset + i * imageSize,\n\t\t\t\t\tlength: imageSize,\n\t\t\t\t});\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 3: {\n\t\t\t// Variable metrics, 2-byte offsets\n\t\t\tconst offsets: uint16[] = [];\n\t\t\tfor (let i = 0; i <= numGlyphs; i++) {\n\t\t\t\toffsets.push(subReader.uint16());\n\t\t\t}\n\t\t\tfor (let i = 0; i < numGlyphs; i++) {\n\t\t\t\tconst glyphOffset = offsets[i]!;\n\t\t\t\tconst nextOffset = offsets[i + 1]!;\n\t\t\t\tif (nextOffset > glyphOffset) {\n\t\t\t\t\tglyphOffsets.set(firstGlyph + i, {\n\t\t\t\t\t\toffset: imageDataOffset + glyphOffset,\n\t\t\t\t\t\tlength: nextOffset - glyphOffset,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 4: {\n\t\t\t// Sparse glyph array\n\t\t\tconst numGlyphsActual = subReader.uint32();\n\t\t\tconst glyphArray: { glyphId: uint16; offset: uint16 }[] = [];\n\t\t\tfor (let i = 0; i <= numGlyphsActual; i++) {\n\t\t\t\tglyphArray.push({\n\t\t\t\t\tglyphId: subReader.uint16(),\n\t\t\t\t\toffset: subReader.uint16(),\n\t\t\t\t});\n\t\t\t}\n\t\t\tfor (let i = 0; i < numGlyphsActual; i++) {\n\t\t\t\tconst entry = glyphArray[i]!;\n\t\t\t\tconst nextEntry = glyphArray[i + 1]!;\n\t\t\t\tglyphOffsets.set(entry.glyphId, {\n\t\t\t\t\toffset: imageDataOffset + entry.offset,\n\t\t\t\t\tlength: nextEntry.offset - entry.offset,\n\t\t\t\t});\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 5: {\n\t\t\t// Constant metrics, sparse glyph array\n\t\t\tconst imageSize = subReader.uint32();\n\t\t\t// Big metrics\n\t\t\tsubReader.skip(8);\n\t\t\tconst numGlyphsActual = subReader.uint32();\n\t\t\tfor (let i = 0; i < numGlyphsActual; i++) {\n\t\t\t\tconst glyphId = subReader.uint16();\n\t\t\t\tglyphOffsets.set(glyphId, {\n\t\t\t\t\toffset: imageDataOffset + i * imageSize,\n\t\t\t\t\tlength: imageSize,\n\t\t\t\t});\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn {\n\t\tfirstGlyphIndex: firstGlyph,\n\t\tlastGlyphIndex: lastGlyph,\n\t\tindexFormat,\n\t\timageFormat,\n\t\timageDataOffset,\n\t\tglyphOffsets,\n\t};\n}\n\n/**\n * Parse CBDT table\n */\nexport function parseCbdt(reader: Reader): CbdtTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\n\t// Store raw data for later lookup\n\tconst data = reader.bytes(reader.remaining);\n\n\treturn { majorVersion, minorVersion, data };\n}\n\n/**\n * Get bitmap glyph from CBDT using CBLC index\n */\nexport function getBitmapGlyph(\n\tcblc: CblcTable,\n\tcbdt: CbdtTable,\n\tglyphId: GlyphId,\n\tppem: number,\n): BitmapGlyph | null {\n\t// Find matching bitmap size\n\tlet bestSize: BitmapSize | null = null;\n\tlet bestDiff = Infinity;\n\n\tfor (const size of cblc.bitmapSizes) {\n\t\tif (glyphId < size.startGlyphIndex || glyphId > size.endGlyphIndex) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst diff = Math.abs(size.ppemX - ppem);\n\t\tif (diff < bestDiff) {\n\t\t\tbestDiff = diff;\n\t\t\tbestSize = size;\n\t\t}\n\t}\n\n\tif (!bestSize) return null;\n\n\t// Find glyph in index sub-tables\n\tfor (const subTable of bestSize.indexSubTables) {\n\t\tconst glyphInfo = subTable.glyphOffsets.get(glyphId);\n\t\tif (!glyphInfo) continue;\n\n\t\t// Read glyph data from CBDT\n\t\tconst glyphData = cbdt.data.slice(\n\t\t\tglyphInfo.offset - 4, // Adjust for CBDT header\n\t\t\tglyphInfo.offset - 4 + glyphInfo.length,\n\t\t);\n\n\t\treturn parseGlyphData(glyphData, subTable.imageFormat);\n\t}\n\n\treturn null;\n}\n\nfunction parseGlyphData(\n\tdata: Uint8Array,\n\timageFormat: uint16,\n): BitmapGlyph | null {\n\tif (data.length === 0) return null;\n\n\tlet offset = 0;\n\tlet metrics: GlyphBitmapMetrics;\n\n\tswitch (imageFormat) {\n\t\tcase 1:\n\t\tcase 2:\n\t\tcase 17:\n\t\tcase 18: {\n\t\t\t// Small or big metrics embedded\n\t\t\tif (imageFormat === 1 || imageFormat === 17) {\n\t\t\t\t// Small metrics (5 bytes)\n\t\t\t\tmetrics = {\n\t\t\t\t\theight: data[offset++]!,\n\t\t\t\t\twidth: data[offset++]!,\n\t\t\t\t\tbearingX: (data[offset++]! << 24) >> 24, // Sign extend\n\t\t\t\t\tbearingY: (data[offset++]! << 24) >> 24,\n\t\t\t\t\tadvance: data[offset++]!,\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\t// Big metrics (8 bytes)\n\t\t\t\tmetrics = {\n\t\t\t\t\theight: data[offset++]!,\n\t\t\t\t\twidth: data[offset++]!,\n\t\t\t\t\tbearingX: (data[offset++]! << 24) >> 24,\n\t\t\t\t\tbearingY: (data[offset++]! << 24) >> 24,\n\t\t\t\t\tadvance: data[offset++]!,\n\t\t\t\t};\n\t\t\t\toffset += 3; // Skip vertical metrics\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 19: {\n\t\t\t// Metrics in CBLC, just PNG data\n\t\t\tmetrics = { height: 0, width: 0, bearingX: 0, bearingY: 0, advance: 0 };\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\treturn null;\n\t}\n\n\treturn {\n\t\tmetrics,\n\t\timageFormat,\n\t\tdata: data.slice(offset),\n\t};\n}\n\n/**\n * Check if glyph has color bitmap\n */\nexport function hasColorBitmap(\n\tcblc: CblcTable,\n\tglyphId: GlyphId,\n\tppem?: number,\n): boolean {\n\tfor (const size of cblc.bitmapSizes) {\n\t\tif (ppem !== undefined && size.ppemX !== ppem) continue;\n\t\tif (glyphId < size.startGlyphIndex || glyphId > size.endGlyphIndex) {\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const subTable of size.indexSubTables) {\n\t\t\tif (subTable.glyphOffsets.has(glyphId)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Get available ppem sizes for color bitmaps\n */\nexport function getColorBitmapSizes(cblc: CblcTable): number[] {\n\tconst sizes = new Set<number>();\n\tfor (const size of cblc.bitmapSizes) {\n\t\tsizes.add(size.ppemX);\n\t}\n\treturn Array.from(sizes).sort((a, b) => a - b);\n}\n",
16
+ "import { Reader } from \"../binary/reader.ts\";\n\n/**\n * CFF (Compact Font Format) table parser\n * Used by OpenType fonts with PostScript outlines\n */\n\nexport interface CffTable {\n\tversion: { major: number; minor: number };\n\tnames: string[];\n\ttopDicts: TopDict[];\n\tstrings: string[];\n\tglobalSubrs: Uint8Array[];\n\tcharStrings: Uint8Array[][];\n\tlocalSubrs: Uint8Array[][];\n\tfdArrays: FDDict[][];\n\tfdSelects: FDSelect[];\n}\n\nexport interface TopDict {\n\tversion?: string;\n\tnotice?: string;\n\tcopyright?: string;\n\tfullName?: string;\n\tfamilyName?: string;\n\tweight?: string;\n\tisFixedPitch?: boolean;\n\titalicAngle?: number;\n\tunderlinePosition?: number;\n\tunderlineThickness?: number;\n\tpaintType?: number;\n\tcharstringType?: number;\n\tfontMatrix?: number[];\n\tuniqueID?: number;\n\tfontBBox?: number[];\n\tstrokeWidth?: number;\n\tcharset?: number;\n\tencoding?: number;\n\tcharStrings?: number;\n\tprivate?: [number, number]; // [size, offset]\n\tsyntheticBase?: number;\n\tpostScript?: string;\n\tbaseFontName?: string;\n\tbaseFontBlend?: number[];\n\t// CIDFont-specific\n\tros?: { registry: string; ordering: string; supplement: number };\n\tcidFontVersion?: number;\n\tcidFontRevision?: number;\n\tcidFontType?: number;\n\tcidCount?: number;\n\tuidBase?: number;\n\tfdArray?: number;\n\tfdSelect?: number;\n\tfontName?: string;\n}\n\nexport interface PrivateDict {\n\tblueValues?: number[];\n\totherBlues?: number[];\n\tfamilyBlues?: number[];\n\tfamilyOtherBlues?: number[];\n\tblueScale?: number;\n\tblueShift?: number;\n\tblueFuzz?: number;\n\tstdHW?: number;\n\tstdVW?: number;\n\tstemSnapH?: number[];\n\tstemSnapV?: number[];\n\tforceBold?: boolean;\n\tlanguageGroup?: number;\n\texpansionFactor?: number;\n\tinitialRandomSeed?: number;\n\tsubrs?: number;\n\tdefaultWidthX?: number;\n\tnominalWidthX?: number;\n}\n\nexport interface FDDict extends PrivateDict {\n\tfontName?: string;\n}\n\nexport interface FDSelect {\n\tformat: number;\n\tselect: (glyphId: number) => number;\n}\n\n// Standard strings defined in CFF spec\nconst STANDARD_STRINGS = [\n\t\".notdef\",\n\t\"space\",\n\t\"exclam\",\n\t\"quotedbl\",\n\t\"numbersign\",\n\t\"dollar\",\n\t\"percent\",\n\t\"ampersand\",\n\t\"quoteright\",\n\t\"parenleft\",\n\t\"parenright\",\n\t\"asterisk\",\n\t\"plus\",\n\t\"comma\",\n\t\"hyphen\",\n\t\"period\",\n\t\"slash\",\n\t\"zero\",\n\t\"one\",\n\t\"two\",\n\t\"three\",\n\t\"four\",\n\t\"five\",\n\t\"six\",\n\t\"seven\",\n\t\"eight\",\n\t\"nine\",\n\t\"colon\",\n\t\"semicolon\",\n\t\"less\",\n\t\"equal\",\n\t\"greater\",\n\t\"question\",\n\t\"at\",\n\t\"A\",\n\t\"B\",\n\t\"C\",\n\t\"D\",\n\t\"E\",\n\t\"F\",\n\t\"G\",\n\t\"H\",\n\t\"I\",\n\t\"J\",\n\t\"K\",\n\t\"L\",\n\t\"M\",\n\t\"N\",\n\t\"O\",\n\t\"P\",\n\t\"Q\",\n\t\"R\",\n\t\"S\",\n\t\"T\",\n\t\"U\",\n\t\"V\",\n\t\"W\",\n\t\"X\",\n\t\"Y\",\n\t\"Z\",\n\t\"bracketleft\",\n\t\"backslash\",\n\t\"bracketright\",\n\t\"asciicircum\",\n\t\"underscore\",\n\t\"quoteleft\",\n\t\"a\",\n\t\"b\",\n\t\"c\",\n\t\"d\",\n\t\"e\",\n\t\"f\",\n\t\"g\",\n\t\"h\",\n\t\"i\",\n\t\"j\",\n\t\"k\",\n\t\"l\",\n\t\"m\",\n\t\"n\",\n\t\"o\",\n\t\"p\",\n\t\"q\",\n\t\"r\",\n\t\"s\",\n\t\"t\",\n\t\"u\",\n\t\"v\",\n\t\"w\",\n\t\"x\",\n\t\"y\",\n\t\"z\",\n\t\"braceleft\",\n\t\"bar\",\n\t\"braceright\",\n\t\"asciitilde\",\n\t\"exclamdown\",\n\t\"cent\",\n\t\"sterling\",\n\t\"fraction\",\n\t\"yen\",\n\t\"florin\",\n\t\"section\",\n\t\"currency\",\n\t\"quotesingle\",\n\t\"quotedblleft\",\n\t\"guillemotleft\",\n\t\"guilsinglleft\",\n\t\"guilsinglright\",\n\t\"fi\",\n\t\"fl\",\n\t\"endash\",\n\t\"dagger\",\n\t\"daggerdbl\",\n\t\"periodcentered\",\n\t\"paragraph\",\n\t\"bullet\",\n\t\"quotesinglbase\",\n\t\"quotedblbase\",\n\t\"quotedblright\",\n\t\"guillemotright\",\n\t\"ellipsis\",\n\t\"perthousand\",\n\t\"questiondown\",\n\t\"grave\",\n\t\"acute\",\n\t\"circumflex\",\n\t\"tilde\",\n\t\"macron\",\n\t\"breve\",\n\t\"dotaccent\",\n\t\"dieresis\",\n\t\"ring\",\n\t\"cedilla\",\n\t\"hungarumlaut\",\n\t\"ogonek\",\n\t\"caron\",\n\t\"emdash\",\n\t\"AE\",\n\t\"ordfeminine\",\n\t\"Lslash\",\n\t\"Oslash\",\n\t\"OE\",\n\t\"ordmasculine\",\n\t\"ae\",\n\t\"dotlessi\",\n\t\"lslash\",\n\t\"oslash\",\n\t\"oe\",\n\t\"germandbls\",\n\t\"onesuperior\",\n\t\"logicalnot\",\n\t\"mu\",\n\t\"trademark\",\n\t\"Eth\",\n\t\"onehalf\",\n\t\"plusminus\",\n\t\"Thorn\",\n\t\"onequarter\",\n\t\"divide\",\n\t\"brokenbar\",\n\t\"degree\",\n\t\"thorn\",\n\t\"threequarters\",\n\t\"twosuperior\",\n\t\"registered\",\n\t\"minus\",\n\t\"eth\",\n\t\"multiply\",\n\t\"threesuperior\",\n\t\"copyright\",\n\t\"Aacute\",\n\t\"Acircumflex\",\n\t\"Adieresis\",\n\t\"Agrave\",\n\t\"Aring\",\n\t\"Atilde\",\n\t\"Ccedilla\",\n\t\"Eacute\",\n\t\"Ecircumflex\",\n\t\"Edieresis\",\n\t\"Egrave\",\n\t\"Iacute\",\n\t\"Icircumflex\",\n\t\"Idieresis\",\n\t\"Igrave\",\n\t\"Ntilde\",\n\t\"Oacute\",\n\t\"Ocircumflex\",\n\t\"Odieresis\",\n\t\"Ograve\",\n\t\"Otilde\",\n\t\"Scaron\",\n\t\"Uacute\",\n\t\"Ucircumflex\",\n\t\"Udieresis\",\n\t\"Ugrave\",\n\t\"Yacute\",\n\t\"Ydieresis\",\n\t\"Zcaron\",\n\t\"aacute\",\n\t\"acircumflex\",\n\t\"adieresis\",\n\t\"agrave\",\n\t\"aring\",\n\t\"atilde\",\n\t\"ccedilla\",\n\t\"eacute\",\n\t\"ecircumflex\",\n\t\"edieresis\",\n\t\"egrave\",\n\t\"iacute\",\n\t\"icircumflex\",\n\t\"idieresis\",\n\t\"igrave\",\n\t\"ntilde\",\n\t\"oacute\",\n\t\"ocircumflex\",\n\t\"odieresis\",\n\t\"ograve\",\n\t\"otilde\",\n\t\"scaron\",\n\t\"uacute\",\n\t\"ucircumflex\",\n\t\"udieresis\",\n\t\"ugrave\",\n\t\"yacute\",\n\t\"ydieresis\",\n\t\"zcaron\",\n\t\"exclamsmall\",\n\t\"Hungarumlautsmall\",\n\t\"dollaroldstyle\",\n\t\"dollarsuperior\",\n\t\"ampersandsmall\",\n\t\"Acutesmall\",\n\t\"parenleftsuperior\",\n\t\"parenrightsuperior\",\n\t\"twodotenleader\",\n\t\"onedotenleader\",\n\t\"zerooldstyle\",\n\t\"oneoldstyle\",\n\t\"twooldstyle\",\n\t\"threeoldstyle\",\n\t\"fouroldstyle\",\n\t\"fiveoldstyle\",\n\t\"sixoldstyle\",\n\t\"sevenoldstyle\",\n\t\"eightoldstyle\",\n\t\"nineoldstyle\",\n\t\"commasuperior\",\n\t\"threequartersemdash\",\n\t\"periodsuperior\",\n\t\"questionsmall\",\n\t\"asuperior\",\n\t\"bsuperior\",\n\t\"centsuperior\",\n\t\"dsuperior\",\n\t\"esuperior\",\n\t\"isuperior\",\n\t\"lsuperior\",\n\t\"msuperior\",\n\t\"nsuperior\",\n\t\"osuperior\",\n\t\"rsuperior\",\n\t\"ssuperior\",\n\t\"tsuperior\",\n\t\"ff\",\n\t\"ffi\",\n\t\"ffl\",\n\t\"parenleftinferior\",\n\t\"parenrightinferior\",\n\t\"Circumflexsmall\",\n\t\"hyphensuperior\",\n\t\"Gravesmall\",\n\t\"Asmall\",\n\t\"Bsmall\",\n\t\"Csmall\",\n\t\"Dsmall\",\n\t\"Esmall\",\n\t\"Fsmall\",\n\t\"Gsmall\",\n\t\"Hsmall\",\n\t\"Ismall\",\n\t\"Jsmall\",\n\t\"Ksmall\",\n\t\"Lsmall\",\n\t\"Msmall\",\n\t\"Nsmall\",\n\t\"Osmall\",\n\t\"Psmall\",\n\t\"Qsmall\",\n\t\"Rsmall\",\n\t\"Ssmall\",\n\t\"Tsmall\",\n\t\"Usmall\",\n\t\"Vsmall\",\n\t\"Wsmall\",\n\t\"Xsmall\",\n\t\"Ysmall\",\n\t\"Zsmall\",\n\t\"colonmonetary\",\n\t\"onefitted\",\n\t\"rupiah\",\n\t\"Tildesmall\",\n\t\"exclamdownsmall\",\n\t\"centoldstyle\",\n\t\"Lslashsmall\",\n\t\"Scaronsmall\",\n\t\"Zcaronsmall\",\n\t\"Dieresissmall\",\n\t\"Brevesmall\",\n\t\"Caronsmall\",\n\t\"Dotaccentsmall\",\n\t\"Macronsmall\",\n\t\"figuredash\",\n\t\"hypheninferior\",\n\t\"Ogoneksmall\",\n\t\"Ringsmall\",\n\t\"Cedillasmall\",\n\t\"questiondownsmall\",\n\t\"oneeighth\",\n\t\"threeeighths\",\n\t\"fiveeighths\",\n\t\"seveneighths\",\n\t\"onethird\",\n\t\"twothirds\",\n\t\"zerosuperior\",\n\t\"foursuperior\",\n\t\"fivesuperior\",\n\t\"sixsuperior\",\n\t\"sevensuperior\",\n\t\"eightsuperior\",\n\t\"ninesuperior\",\n\t\"zeroinferior\",\n\t\"oneinferior\",\n\t\"twoinferior\",\n\t\"threeinferior\",\n\t\"fourinferior\",\n\t\"fiveinferior\",\n\t\"sixinferior\",\n\t\"seveninferior\",\n\t\"eightinferior\",\n\t\"nineinferior\",\n\t\"centinferior\",\n\t\"dollarinferior\",\n\t\"periodinferior\",\n\t\"commainferior\",\n\t\"Agravesmall\",\n\t\"Aacutesmall\",\n\t\"Acircumflexsmall\",\n\t\"Atildesmall\",\n\t\"Adieresissmall\",\n\t\"Aringsmall\",\n\t\"AEsmall\",\n\t\"Ccedillasmall\",\n\t\"Egravesmall\",\n\t\"Eacutesmall\",\n\t\"Ecircumflexsmall\",\n\t\"Edieresissmall\",\n\t\"Igravesmall\",\n\t\"Iacutesmall\",\n\t\"Icircumflexsmall\",\n\t\"Idieresissmall\",\n\t\"Ethsmall\",\n\t\"Ntildesmall\",\n\t\"Ogravesmall\",\n\t\"Oacutesmall\",\n\t\"Ocircumflexsmall\",\n\t\"Otildesmall\",\n\t\"Odieresissmall\",\n\t\"OEsmall\",\n\t\"Oslashsmall\",\n\t\"Ugravesmall\",\n\t\"Uacutesmall\",\n\t\"Ucircumflexsmall\",\n\t\"Udieresissmall\",\n\t\"Yacutesmall\",\n\t\"Thornsmall\",\n\t\"Ydieresissmall\",\n\t\"001.000\",\n\t\"001.001\",\n\t\"001.002\",\n\t\"001.003\",\n\t\"Black\",\n\t\"Bold\",\n\t\"Book\",\n\t\"Light\",\n\t\"Medium\",\n\t\"Regular\",\n\t\"Roman\",\n\t\"Semibold\",\n];\n\n// Top DICT operators\nenum TopDictOp {\n\tversion = 0,\n\tNotice = 1,\n\tFullName = 2,\n\tFamilyName = 3,\n\tWeight = 4,\n\tFontBBox = 5,\n\tUniqueID = 13,\n\tXUID = 14,\n\tcharset = 15,\n\tEncoding = 16,\n\tCharStrings = 17,\n\tPrivate = 18,\n\tCopyright = 0x0c00,\n\tisFixedPitch = 0x0c01,\n\tItalicAngle = 0x0c02,\n\tUnderlinePosition = 0x0c03,\n\tUnderlineThickness = 0x0c04,\n\tPaintType = 0x0c05,\n\tCharstringType = 0x0c06,\n\tFontMatrix = 0x0c07,\n\tStrokeWidth = 0x0c08,\n\tSyntheticBase = 0x0c14,\n\tPostScript = 0x0c15,\n\tBaseFontName = 0x0c16,\n\tBaseFontBlend = 0x0c17,\n\t// CID-specific\n\tROS = 0x0c1e,\n\tCIDFontVersion = 0x0c1f,\n\tCIDFontRevision = 0x0c20,\n\tCIDFontType = 0x0c21,\n\tCIDCount = 0x0c22,\n\tUIDBase = 0x0c23,\n\tFDArray = 0x0c24,\n\tFDSelect = 0x0c25,\n\tFontName = 0x0c26,\n}\n\n// Private DICT operators\nenum PrivateDictOp {\n\tBlueValues = 6,\n\tOtherBlues = 7,\n\tFamilyBlues = 8,\n\tFamilyOtherBlues = 9,\n\tStdHW = 10,\n\tStdVW = 11,\n\tSubrs = 19,\n\tdefaultWidthX = 20,\n\tnominalWidthX = 21,\n\tBlueScale = 0x0c09,\n\tBlueShift = 0x0c0a,\n\tBlueFuzz = 0x0c0b,\n\tStemSnapH = 0x0c0c,\n\tStemSnapV = 0x0c0d,\n\tForceBold = 0x0c0e,\n\tLanguageGroup = 0x0c11,\n\tExpansionFactor = 0x0c12,\n\tinitialRandomSeed = 0x0c13,\n}\n\n/**\n * Parse CFF table\n */\nexport function parseCff(reader: Reader): CffTable {\n\tconst startOffset = reader.offset;\n\n\t// Header\n\tconst major = reader.uint8();\n\tconst minor = reader.uint8();\n\tconst hdrSize = reader.uint8();\n\tconst _offSize = reader.uint8();\n\n\treader.seek(startOffset + hdrSize);\n\n\t// Name INDEX\n\tconst names = parseIndex(reader).map((data) =>\n\t\tnew TextDecoder().decode(data),\n\t);\n\n\t// Top DICT INDEX\n\tconst topDictData = parseIndex(reader);\n\tconst topDicts: TopDict[] = [];\n\n\t// String INDEX\n\tconst stringData = parseIndex(reader);\n\tconst strings = stringData.map((data) => new TextDecoder().decode(data));\n\n\t// Global Subr INDEX\n\tconst globalSubrs = parseIndex(reader);\n\n\t// Parse Top DICTs\n\tfor (const data of topDictData) {\n\t\ttopDicts.push(\n\t\t\tparseTopDict(\n\t\t\t\tnew Reader(\n\t\t\t\t\tdata.buffer as ArrayBuffer,\n\t\t\t\t\tdata.byteOffset,\n\t\t\t\t\tdata.byteLength,\n\t\t\t\t),\n\t\t\t\tstrings,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Parse CharStrings and local subrs for each font\n\tconst charStrings: Uint8Array[][] = [];\n\tconst localSubrs: Uint8Array[][] = [];\n\tconst fdArrays: FDDict[][] = [];\n\tconst fdSelects: FDSelect[] = [];\n\n\tfor (const topDict of topDicts) {\n\t\t// CharStrings\n\t\tif (topDict.charStrings !== undefined) {\n\t\t\treader.seek(startOffset + topDict.charStrings);\n\t\t\tcharStrings.push(parseIndex(reader));\n\t\t} else {\n\t\t\tcharStrings.push([]);\n\t\t}\n\n\t\t// Private DICT and local subrs\n\t\tif (topDict.private) {\n\t\t\tconst [privateSize, privateOffset] = topDict.private;\n\t\t\treader.seek(startOffset + privateOffset);\n\t\t\tconst privateDict = parsePrivateDict(\n\t\t\t\treader.slice(0, privateSize),\n\t\t\t\tstrings,\n\t\t\t);\n\n\t\t\tif (privateDict.subrs !== undefined) {\n\t\t\t\treader.seek(startOffset + privateOffset + privateDict.subrs);\n\t\t\t\tlocalSubrs.push(parseIndex(reader));\n\t\t\t} else {\n\t\t\t\tlocalSubrs.push([]);\n\t\t\t}\n\t\t} else {\n\t\t\tlocalSubrs.push([]);\n\t\t}\n\n\t\t// FDArray (for CID fonts)\n\t\tif (topDict.fdArray !== undefined) {\n\t\t\treader.seek(startOffset + topDict.fdArray);\n\t\t\tconst fdData = parseIndex(reader);\n\t\t\tconst fds: FDDict[] = [];\n\t\t\tfor (const data of fdData) {\n\t\t\t\tconst fdDict = parseTopDict(\n\t\t\t\t\tnew Reader(\n\t\t\t\t\t\tdata.buffer as ArrayBuffer,\n\t\t\t\t\t\tdata.byteOffset,\n\t\t\t\t\t\tdata.byteLength,\n\t\t\t\t\t),\n\t\t\t\t\tstrings,\n\t\t\t\t) as FDDict;\n\t\t\t\tfds.push(fdDict);\n\t\t\t}\n\t\t\tfdArrays.push(fds);\n\t\t} else {\n\t\t\tfdArrays.push([]);\n\t\t}\n\n\t\t// FDSelect (for CID fonts)\n\t\tif (topDict.fdSelect !== undefined) {\n\t\t\treader.seek(startOffset + topDict.fdSelect);\n\t\t\tconst lastCharStrings = charStrings[charStrings.length - 1];\n\t\t\tfdSelects.push(parseFDSelect(reader, lastCharStrings?.length ?? 0));\n\t\t} else {\n\t\t\tfdSelects.push({ format: 0, select: () => 0 });\n\t\t}\n\t}\n\n\treturn {\n\t\tversion: { major, minor },\n\t\tnames,\n\t\ttopDicts,\n\t\tstrings,\n\t\tglobalSubrs,\n\t\tcharStrings,\n\t\tlocalSubrs,\n\t\tfdArrays,\n\t\tfdSelects,\n\t};\n}\n\n/**\n * Parse an INDEX structure\n */\nfunction parseIndex(reader: Reader): Uint8Array[] {\n\tconst count = reader.uint16();\n\tif (count === 0) return [];\n\n\tconst offSize = reader.uint8();\n\tconst offsets: number[] = [];\n\n\tfor (let i = 0; i <= count; i++) {\n\t\toffsets.push(readOffset(reader, offSize));\n\t}\n\n\tconst result: Uint8Array[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tconst start = offsets[i];\n\t\tconst end = offsets[i + 1];\n\t\tif (start === undefined || end === undefined) continue;\n\t\tconst length = end - start;\n\t\tresult.push(reader.bytes(length));\n\t}\n\n\treturn result;\n}\n\n/**\n * Read offset of given size\n */\nfunction readOffset(reader: Reader, offSize: number): number {\n\tswitch (offSize) {\n\t\tcase 1:\n\t\t\treturn reader.uint8();\n\t\tcase 2:\n\t\t\treturn reader.uint16();\n\t\tcase 3:\n\t\t\treturn reader.uint24();\n\t\tcase 4:\n\t\t\treturn reader.uint32();\n\t\tdefault:\n\t\t\tthrow new Error(`Invalid offset size: ${offSize}`);\n\t}\n}\n\n/**\n * Parse a DICT structure\n */\nfunction parseDict(reader: Reader): Map<number, number[]> {\n\tconst result = new Map<number, number[]>();\n\tconst operands: number[] = [];\n\n\twhile (reader.remaining > 0) {\n\t\tconst b0 = reader.uint8();\n\n\t\tif (b0 <= 21) {\n\t\t\t// Operator\n\t\t\tlet op = b0;\n\t\t\tif (b0 === 12) {\n\t\t\t\top = 0x0c00 | reader.uint8();\n\t\t\t}\n\t\t\tresult.set(op, [...operands]);\n\t\t\toperands.length = 0;\n\t\t} else if (b0 === 28) {\n\t\t\t// 16-bit signed integer\n\t\t\toperands.push(reader.int16());\n\t\t} else if (b0 === 29) {\n\t\t\t// 32-bit signed integer\n\t\t\toperands.push(reader.int32());\n\t\t} else if (b0 === 30) {\n\t\t\t// Real number\n\t\t\toperands.push(parseReal(reader));\n\t\t} else if (b0 >= 32 && b0 <= 246) {\n\t\t\toperands.push(b0 - 139);\n\t\t} else if (b0 >= 247 && b0 <= 250) {\n\t\t\tconst b1 = reader.uint8();\n\t\t\toperands.push((b0 - 247) * 256 + b1 + 108);\n\t\t} else if (b0 >= 251 && b0 <= 254) {\n\t\t\tconst b1 = reader.uint8();\n\t\t\toperands.push(-(b0 - 251) * 256 - b1 - 108);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Parse real number from DICT\n */\nfunction parseReal(reader: Reader): number {\n\tlet str = \"\";\n\tconst nibbleChars = \"0123456789.EE -\";\n\tlet done = false;\n\n\twhile (!done) {\n\t\tconst byte = reader.uint8();\n\t\tfor (let i = 0; i < 2; i++) {\n\t\t\tconst nibble = i === 0 ? byte >> 4 : byte & 0x0f;\n\t\t\tif (nibble === 0x0f) {\n\t\t\t\tdone = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (nibble === 0x0c) {\n\t\t\t\tstr += \"E-\";\n\t\t\t} else {\n\t\t\t\tstr += nibbleChars[nibble];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parseFloat(str);\n}\n\n/**\n * Parse Top DICT\n */\nfunction parseTopDict(reader: Reader, strings: string[]): TopDict {\n\tconst dict = parseDict(reader);\n\tconst result: TopDict = {};\n\n\tconst getString = (sid: number): string => {\n\t\tif (sid < STANDARD_STRINGS.length) {\n\t\t\tconst str = STANDARD_STRINGS[sid];\n\t\t\treturn str ?? \"\";\n\t\t}\n\t\treturn strings[sid - STANDARD_STRINGS.length] ?? \"\";\n\t};\n\n\tfor (const [op, operands] of dict) {\n\t\tconst op0 = operands[0];\n\t\tconst op1 = operands[1];\n\t\tconst op2 = operands[2];\n\n\t\tswitch (op) {\n\t\t\tcase TopDictOp.version:\n\t\t\t\tif (op0 !== undefined) result.version = getString(op0);\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.Notice:\n\t\t\t\tif (op0 !== undefined) result.notice = getString(op0);\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.Copyright:\n\t\t\t\tif (op0 !== undefined) result.copyright = getString(op0);\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.FullName:\n\t\t\t\tif (op0 !== undefined) result.fullName = getString(op0);\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.FamilyName:\n\t\t\t\tif (op0 !== undefined) result.familyName = getString(op0);\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.Weight:\n\t\t\t\tif (op0 !== undefined) result.weight = getString(op0);\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.isFixedPitch:\n\t\t\t\tresult.isFixedPitch = op0 !== 0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.ItalicAngle:\n\t\t\t\tresult.italicAngle = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.UnderlinePosition:\n\t\t\t\tresult.underlinePosition = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.UnderlineThickness:\n\t\t\t\tresult.underlineThickness = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.PaintType:\n\t\t\t\tresult.paintType = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.CharstringType:\n\t\t\t\tresult.charstringType = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.FontMatrix:\n\t\t\t\tresult.fontMatrix = operands;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.UniqueID:\n\t\t\t\tresult.uniqueID = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.FontBBox:\n\t\t\t\tresult.fontBBox = operands;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.StrokeWidth:\n\t\t\t\tresult.strokeWidth = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.charset:\n\t\t\t\tresult.charset = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.Encoding:\n\t\t\t\tresult.encoding = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.CharStrings:\n\t\t\t\tresult.charStrings = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.Private:\n\t\t\t\tif (op0 !== undefined && op1 !== undefined) {\n\t\t\t\t\tresult.private = [op0, op1];\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.SyntheticBase:\n\t\t\t\tresult.syntheticBase = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.PostScript:\n\t\t\t\tif (op0 !== undefined) result.postScript = getString(op0);\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.BaseFontName:\n\t\t\t\tif (op0 !== undefined) result.baseFontName = getString(op0);\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.BaseFontBlend:\n\t\t\t\tresult.baseFontBlend = operands;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.ROS:\n\t\t\t\tif (op0 !== undefined && op1 !== undefined && op2 !== undefined) {\n\t\t\t\t\tresult.ros = {\n\t\t\t\t\t\tregistry: getString(op0),\n\t\t\t\t\t\tordering: getString(op1),\n\t\t\t\t\t\tsupplement: op2,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.CIDFontVersion:\n\t\t\t\tresult.cidFontVersion = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.CIDFontRevision:\n\t\t\t\tresult.cidFontRevision = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.CIDFontType:\n\t\t\t\tresult.cidFontType = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.CIDCount:\n\t\t\t\tresult.cidCount = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.UIDBase:\n\t\t\t\tresult.uidBase = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.FDArray:\n\t\t\t\tresult.fdArray = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.FDSelect:\n\t\t\t\tresult.fdSelect = op0;\n\t\t\t\tbreak;\n\t\t\tcase TopDictOp.FontName:\n\t\t\t\tif (op0 !== undefined) result.fontName = getString(op0);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Parse Private DICT\n */\nfunction parsePrivateDict(reader: Reader, _strings: string[]): PrivateDict {\n\tconst dict = parseDict(reader);\n\tconst result: PrivateDict = {};\n\n\tfor (const [op, operands] of dict) {\n\t\tconst op0 = operands[0];\n\n\t\tswitch (op) {\n\t\t\tcase PrivateDictOp.BlueValues:\n\t\t\t\tresult.blueValues = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.OtherBlues:\n\t\t\t\tresult.otherBlues = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.FamilyBlues:\n\t\t\t\tresult.familyBlues = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.FamilyOtherBlues:\n\t\t\t\tresult.familyOtherBlues = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.BlueScale:\n\t\t\t\tresult.blueScale = op0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.BlueShift:\n\t\t\t\tresult.blueShift = op0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.BlueFuzz:\n\t\t\t\tresult.blueFuzz = op0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.StdHW:\n\t\t\t\tresult.stdHW = op0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.StdVW:\n\t\t\t\tresult.stdVW = op0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.StemSnapH:\n\t\t\t\tresult.stemSnapH = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.StemSnapV:\n\t\t\t\tresult.stemSnapV = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.ForceBold:\n\t\t\t\tresult.forceBold = op0 !== 0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.LanguageGroup:\n\t\t\t\tresult.languageGroup = op0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.ExpansionFactor:\n\t\t\t\tresult.expansionFactor = op0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.initialRandomSeed:\n\t\t\t\tresult.initialRandomSeed = op0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.Subrs:\n\t\t\t\tresult.subrs = op0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.defaultWidthX:\n\t\t\t\tresult.defaultWidthX = op0;\n\t\t\t\tbreak;\n\t\t\tcase PrivateDictOp.nominalWidthX:\n\t\t\t\tresult.nominalWidthX = op0;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Convert delta-encoded values to absolute\n */\nfunction deltaToAbsolute(deltas: number[]): number[] {\n\tconst result: number[] = [];\n\tlet value = 0;\n\tfor (const delta of deltas) {\n\t\tvalue += delta;\n\t\tresult.push(value);\n\t}\n\treturn result;\n}\n\n/**\n * Parse FDSelect structure\n */\nfunction parseFDSelect(reader: Reader, numGlyphs: number): FDSelect {\n\tconst format = reader.uint8();\n\n\tif (format === 0) {\n\t\tconst fds = reader.uint8Array(numGlyphs);\n\t\treturn {\n\t\t\tformat,\n\t\t\tselect: (glyphId: number) => fds[glyphId] ?? 0,\n\t\t};\n\t} else if (format === 3) {\n\t\tconst nRanges = reader.uint16();\n\t\tconst ranges: Array<{ first: number; fd: number }> = [];\n\n\t\tfor (let i = 0; i < nRanges; i++) {\n\t\t\tranges.push({\n\t\t\t\tfirst: reader.uint16(),\n\t\t\t\tfd: reader.uint8(),\n\t\t\t});\n\t\t}\n\t\tconst _sentinel = reader.uint16();\n\n\t\treturn {\n\t\t\tformat,\n\t\t\tselect: (glyphId: number) => {\n\t\t\t\t// Binary search through ranges\n\t\t\t\tlet lo = 0;\n\t\t\t\tlet hi = ranges.length - 1;\n\t\t\t\twhile (lo < hi) {\n\t\t\t\t\tconst mid = Math.ceil((lo + hi) / 2);\n\t\t\t\t\tconst range = ranges[mid];\n\t\t\t\t\tif (range && range.first <= glyphId) {\n\t\t\t\t\t\tlo = mid;\n\t\t\t\t\t} else {\n\t\t\t\t\t\thi = mid - 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst foundRange = ranges[lo];\n\t\t\t\treturn foundRange?.fd ?? 0;\n\t\t\t},\n\t\t};\n\t}\n\n\treturn { format, select: () => 0 };\n}\n\n/**\n * Get string by SID\n */\nexport function getCffString(cff: CffTable, sid: number): string {\n\tif (sid < STANDARD_STRINGS.length) {\n\t\tconst str = STANDARD_STRINGS[sid];\n\t\treturn str ?? \"\";\n\t}\n\treturn cff.strings[sid - STANDARD_STRINGS.length] ?? \"\";\n}\n",
17
+ "import { Reader } from \"../binary/reader.ts\";\n\n/**\n * CFF2 (Compact Font Format 2) table parser\n * Used by variable fonts with PostScript outlines\n */\n\nexport interface Cff2Table {\n\tversion: { major: number; minor: number };\n\ttopDict: Cff2TopDict;\n\tglobalSubrs: Uint8Array[];\n\tcharStrings: Uint8Array[];\n\tfdArray: Cff2FDDict[];\n\tfdSelect: Cff2FDSelect | null;\n\tvstore: ItemVariationStore | null;\n}\n\nexport interface Cff2TopDict {\n\tcharStrings?: number;\n\tfdArray?: number;\n\tfdSelect?: number;\n\tvstore?: number;\n\tfontMatrix?: number[];\n}\n\nexport interface Cff2PrivateDict {\n\tblueValues?: number[];\n\totherBlues?: number[];\n\tfamilyBlues?: number[];\n\tfamilyOtherBlues?: number[];\n\tblueScale?: number;\n\tblueShift?: number;\n\tblueFuzz?: number;\n\tstdHW?: number;\n\tstdVW?: number;\n\tstemSnapH?: number[];\n\tstemSnapV?: number[];\n\tlanguageGroup?: number;\n\texpansionFactor?: number;\n\tsubrs?: number;\n\tvsindex?: number;\n\tblend?: number[];\n}\n\nexport interface Cff2FDDict {\n\tfontName?: string;\n\tprivate?: Cff2PrivateDict;\n\tprivateOffset?: number;\n\tprivateSize?: number;\n\tlocalSubrs?: Uint8Array[];\n}\n\nexport interface Cff2FDSelect {\n\tformat: number;\n\tselect: (glyphId: number) => number;\n}\n\nexport interface ItemVariationStore {\n\tformat: number;\n\tvariationRegionList: VariationRegionList;\n\titemVariationData: ItemVariationData[];\n}\n\nexport interface VariationRegionList {\n\taxisCount: number;\n\tregionCount: number;\n\tregions: VariationRegion[];\n}\n\nexport interface VariationRegion {\n\taxes: RegionAxisCoordinates[];\n}\n\nexport interface RegionAxisCoordinates {\n\tstartCoord: number;\n\tpeakCoord: number;\n\tendCoord: number;\n}\n\nexport interface ItemVariationData {\n\titemCount: number;\n\tregionIndexCount: number;\n\tregionIndexes: number[];\n\tdeltaSets: number[][];\n}\n\n// CFF2 Top DICT operators\nenum Cff2TopDictOp {\n\tFontMatrix = 0x0c07,\n\tCharStrings = 17,\n\tFDArray = 0x0c24,\n\tFDSelect = 0x0c25,\n\tvstore = 24,\n}\n\n// CFF2 Private DICT operators\nenum Cff2PrivateDictOp {\n\tBlueValues = 6,\n\tOtherBlues = 7,\n\tFamilyBlues = 8,\n\tFamilyOtherBlues = 9,\n\tStdHW = 10,\n\tStdVW = 11,\n\tSubrs = 19,\n\tvsindex = 22,\n\tblend = 23,\n\tBlueScale = 0x0c09,\n\tBlueShift = 0x0c0a,\n\tBlueFuzz = 0x0c0b,\n\tStemSnapH = 0x0c0c,\n\tStemSnapV = 0x0c0d,\n\tLanguageGroup = 0x0c11,\n\tExpansionFactor = 0x0c12,\n}\n\n/**\n * Parse CFF2 table\n */\nexport function parseCff2(reader: Reader): Cff2Table {\n\tconst startOffset = reader.offset;\n\n\t// Header\n\tconst major = reader.uint8();\n\tconst minor = reader.uint8();\n\tconst headerSize = reader.uint8();\n\tconst topDictLength = reader.uint16();\n\n\t// Skip to after header\n\treader.seek(startOffset + headerSize);\n\n\t// Top DICT (not an INDEX in CFF2, just raw data)\n\tconst topDictReader = reader.slice(\n\t\treader.offset - startOffset,\n\t\ttopDictLength,\n\t);\n\treader.skip(topDictLength);\n\tconst topDict = parseCff2TopDict(topDictReader);\n\n\t// Global Subr INDEX\n\tconst globalSubrs = parseIndex(reader);\n\n\t// CharStrings INDEX\n\tlet charStrings: Uint8Array[] = [];\n\tif (topDict.charStrings !== undefined) {\n\t\treader.seek(startOffset + topDict.charStrings);\n\t\tcharStrings = parseIndex(reader);\n\t}\n\n\t// FDArray INDEX\n\tconst fdArray: Cff2FDDict[] = [];\n\tif (topDict.fdArray !== undefined) {\n\t\treader.seek(startOffset + topDict.fdArray);\n\t\tconst fdDictData = parseIndex(reader);\n\n\t\tfor (const data of fdDictData) {\n\t\t\tconst fd = parseCff2FDDict(\n\t\t\t\tnew Reader(\n\t\t\t\t\tdata.buffer as ArrayBuffer,\n\t\t\t\t\tdata.byteOffset,\n\t\t\t\t\tdata.byteLength,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\t// Parse local subrs if Private DICT has them\n\t\t\tif (fd.privateOffset !== undefined && fd.privateSize !== undefined) {\n\t\t\t\treader.seek(startOffset + fd.privateOffset);\n\t\t\t\tconst privateReader = reader.slice(0, fd.privateSize);\n\t\t\t\tfd.private = parseCff2PrivateDict(privateReader);\n\n\t\t\t\tif (fd.private.subrs !== undefined) {\n\t\t\t\t\treader.seek(startOffset + fd.privateOffset + fd.private.subrs);\n\t\t\t\t\tfd.localSubrs = parseIndex(reader);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfdArray.push(fd);\n\t\t}\n\t}\n\n\t// FDSelect\n\tlet fdSelect: Cff2FDSelect | null = null;\n\tif (topDict.fdSelect !== undefined) {\n\t\treader.seek(startOffset + topDict.fdSelect);\n\t\tfdSelect = parseFDSelect(reader, charStrings.length);\n\t}\n\n\t// Variation Store\n\tlet vstore: ItemVariationStore | null = null;\n\tif (topDict.vstore !== undefined) {\n\t\treader.seek(startOffset + topDict.vstore);\n\t\tvstore = parseItemVariationStore(reader);\n\t}\n\n\treturn {\n\t\tversion: { major, minor },\n\t\ttopDict,\n\t\tglobalSubrs,\n\t\tcharStrings,\n\t\tfdArray,\n\t\tfdSelect,\n\t\tvstore,\n\t};\n}\n\n/**\n * Parse CFF2 INDEX structure (uses 32-bit count)\n */\nfunction parseIndex(reader: Reader): Uint8Array[] {\n\tconst count = reader.uint32();\n\tif (count === 0) return [];\n\n\tconst offSize = reader.uint8();\n\tconst offsets: number[] = [];\n\n\tfor (let i = 0; i <= count; i++) {\n\t\toffsets.push(readOffset(reader, offSize));\n\t}\n\n\tconst result: Uint8Array[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tconst start = offsets[i];\n\t\tconst end = offsets[i + 1];\n\t\tif (start === undefined || end === undefined) continue;\n\t\tconst length = end - start;\n\t\tresult.push(reader.bytes(length));\n\t}\n\n\treturn result;\n}\n\n/**\n * Read offset of given size\n */\nfunction readOffset(reader: Reader, offSize: number): number {\n\tswitch (offSize) {\n\t\tcase 1:\n\t\t\treturn reader.uint8();\n\t\tcase 2:\n\t\t\treturn reader.uint16();\n\t\tcase 3:\n\t\t\treturn reader.uint24();\n\t\tcase 4:\n\t\t\treturn reader.uint32();\n\t\tdefault:\n\t\t\tthrow new Error(`Invalid offset size: ${offSize}`);\n\t}\n}\n\n/**\n * Parse a CFF2 DICT structure\n */\nfunction parseDict(reader: Reader): Map<number, number[]> {\n\tconst result = new Map<number, number[]>();\n\tconst operands: number[] = [];\n\n\twhile (reader.remaining > 0) {\n\t\tconst b0 = reader.uint8();\n\n\t\tif (b0 <= 21) {\n\t\t\t// Operator\n\t\t\tlet op = b0;\n\t\t\tif (b0 === 12) {\n\t\t\t\top = 0x0c00 | reader.uint8();\n\t\t\t}\n\t\t\tresult.set(op, [...operands]);\n\t\t\toperands.length = 0;\n\t\t} else if (b0 === 22) {\n\t\t\t// vsindex operator\n\t\t\tresult.set(22, [...operands]);\n\t\t\toperands.length = 0;\n\t\t} else if (b0 === 23) {\n\t\t\t// blend operator\n\t\t\tresult.set(23, [...operands]);\n\t\t\toperands.length = 0;\n\t\t} else if (b0 === 24) {\n\t\t\t// vstore operator\n\t\t\tresult.set(24, [...operands]);\n\t\t\toperands.length = 0;\n\t\t} else if (b0 === 28) {\n\t\t\t// 16-bit signed integer\n\t\t\toperands.push(reader.int16());\n\t\t} else if (b0 === 29) {\n\t\t\t// 32-bit signed integer\n\t\t\toperands.push(reader.int32());\n\t\t} else if (b0 === 30) {\n\t\t\t// Real number\n\t\t\toperands.push(parseReal(reader));\n\t\t} else if (b0 >= 32 && b0 <= 246) {\n\t\t\toperands.push(b0 - 139);\n\t\t} else if (b0 >= 247 && b0 <= 250) {\n\t\t\tconst b1 = reader.uint8();\n\t\t\toperands.push((b0 - 247) * 256 + b1 + 108);\n\t\t} else if (b0 >= 251 && b0 <= 254) {\n\t\t\tconst b1 = reader.uint8();\n\t\t\toperands.push(-(b0 - 251) * 256 - b1 - 108);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Parse real number\n */\nfunction parseReal(reader: Reader): number {\n\tlet str = \"\";\n\tconst nibbleChars = \"0123456789.EE -\";\n\tlet done = false;\n\n\twhile (!done) {\n\t\tconst byte = reader.uint8();\n\t\tfor (let i = 0; i < 2; i++) {\n\t\t\tconst nibble = i === 0 ? byte >> 4 : byte & 0x0f;\n\t\t\tif (nibble === 0x0f) {\n\t\t\t\tdone = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (nibble === 0x0c) {\n\t\t\t\tstr += \"E-\";\n\t\t\t} else {\n\t\t\t\tconst char = nibbleChars[nibble];\n\t\t\t\tif (char !== undefined) str += char;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parseFloat(str);\n}\n\n/**\n * Parse CFF2 Top DICT\n */\nfunction parseCff2TopDict(reader: Reader): Cff2TopDict {\n\tconst dict = parseDict(reader);\n\tconst result: Cff2TopDict = {};\n\n\tfor (const [op, operands] of dict) {\n\t\tswitch (op) {\n\t\t\tcase Cff2TopDictOp.FontMatrix:\n\t\t\t\tresult.fontMatrix = operands;\n\t\t\t\tbreak;\n\t\t\tcase Cff2TopDictOp.CharStrings:\n\t\t\t\tresult.charStrings = operands[0];\n\t\t\t\tbreak;\n\t\t\tcase Cff2TopDictOp.FDArray:\n\t\t\t\tresult.fdArray = operands[0];\n\t\t\t\tbreak;\n\t\t\tcase Cff2TopDictOp.FDSelect:\n\t\t\t\tresult.fdSelect = operands[0];\n\t\t\t\tbreak;\n\t\t\tcase Cff2TopDictOp.vstore:\n\t\t\t\tresult.vstore = operands[0];\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Parse CFF2 FD DICT\n */\nfunction parseCff2FDDict(reader: Reader): Cff2FDDict {\n\tconst dict = parseDict(reader);\n\tconst result: Cff2FDDict = {};\n\n\t// Private DICT pointer (operator 18)\n\tconst privateOp = dict.get(18);\n\tif (privateOp && privateOp.length >= 2) {\n\t\tresult.privateSize = privateOp[0];\n\t\tresult.privateOffset = privateOp[1];\n\t}\n\n\treturn result;\n}\n\n/**\n * Parse CFF2 Private DICT\n */\nfunction parseCff2PrivateDict(reader: Reader): Cff2PrivateDict {\n\tconst dict = parseDict(reader);\n\tconst result: Cff2PrivateDict = {};\n\n\tfor (const [op, operands] of dict) {\n\t\tconst op0 = operands[0];\n\n\t\tswitch (op) {\n\t\t\tcase Cff2PrivateDictOp.BlueValues:\n\t\t\t\tresult.blueValues = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.OtherBlues:\n\t\t\t\tresult.otherBlues = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.FamilyBlues:\n\t\t\t\tresult.familyBlues = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.FamilyOtherBlues:\n\t\t\t\tresult.familyOtherBlues = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.BlueScale:\n\t\t\t\tresult.blueScale = op0;\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.BlueShift:\n\t\t\t\tresult.blueShift = op0;\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.BlueFuzz:\n\t\t\t\tresult.blueFuzz = op0;\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.StdHW:\n\t\t\t\tresult.stdHW = op0;\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.StdVW:\n\t\t\t\tresult.stdVW = op0;\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.StemSnapH:\n\t\t\t\tresult.stemSnapH = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.StemSnapV:\n\t\t\t\tresult.stemSnapV = deltaToAbsolute(operands);\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.LanguageGroup:\n\t\t\t\tresult.languageGroup = op0;\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.ExpansionFactor:\n\t\t\t\tresult.expansionFactor = op0;\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.Subrs:\n\t\t\t\tresult.subrs = op0;\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.vsindex:\n\t\t\t\tresult.vsindex = op0;\n\t\t\t\tbreak;\n\t\t\tcase Cff2PrivateDictOp.blend:\n\t\t\t\tresult.blend = operands;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Convert delta-encoded values to absolute\n */\nfunction deltaToAbsolute(deltas: number[]): number[] {\n\tconst result: number[] = [];\n\tlet value = 0;\n\tfor (const delta of deltas) {\n\t\tvalue += delta;\n\t\tresult.push(value);\n\t}\n\treturn result;\n}\n\n/**\n * Parse FDSelect structure\n */\nfunction parseFDSelect(reader: Reader, numGlyphs: number): Cff2FDSelect {\n\tconst format = reader.uint8();\n\n\tif (format === 0) {\n\t\tconst fds = reader.uint8Array(numGlyphs);\n\t\treturn {\n\t\t\tformat,\n\t\t\tselect: (glyphId: number) => fds[glyphId] ?? 0,\n\t\t};\n\t} else if (format === 3) {\n\t\tconst nRanges = reader.uint16();\n\t\tconst ranges: Array<{ first: number; fd: number }> = [];\n\n\t\tfor (let i = 0; i < nRanges; i++) {\n\t\t\tranges.push({\n\t\t\t\tfirst: reader.uint16(),\n\t\t\t\tfd: reader.uint8(),\n\t\t\t});\n\t\t}\n\t\treader.uint16(); // sentinel\n\n\t\treturn {\n\t\t\tformat,\n\t\t\tselect: (glyphId: number) => {\n\t\t\t\tlet lo = 0;\n\t\t\t\tlet hi = ranges.length - 1;\n\t\t\t\twhile (lo < hi) {\n\t\t\t\t\tconst mid = Math.ceil((lo + hi) / 2);\n\t\t\t\t\tconst range = ranges[mid];\n\t\t\t\t\tif (range && range.first <= glyphId) {\n\t\t\t\t\t\tlo = mid;\n\t\t\t\t\t} else {\n\t\t\t\t\t\thi = mid - 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst foundRange = ranges[lo];\n\t\t\t\treturn foundRange?.fd ?? 0;\n\t\t\t},\n\t\t};\n\t} else if (format === 4) {\n\t\t// CFF2 format 4: 32-bit range records\n\t\tconst nRanges = reader.uint32();\n\t\tconst ranges: Array<{ first: number; fd: number }> = [];\n\n\t\tfor (let i = 0; i < nRanges; i++) {\n\t\t\tranges.push({\n\t\t\t\tfirst: reader.uint32(),\n\t\t\t\tfd: reader.uint16(),\n\t\t\t});\n\t\t}\n\t\treader.uint32(); // sentinel\n\n\t\treturn {\n\t\t\tformat,\n\t\t\tselect: (glyphId: number) => {\n\t\t\t\tlet lo = 0;\n\t\t\t\tlet hi = ranges.length - 1;\n\t\t\t\twhile (lo < hi) {\n\t\t\t\t\tconst mid = Math.ceil((lo + hi) / 2);\n\t\t\t\t\tconst range = ranges[mid];\n\t\t\t\t\tif (range && range.first <= glyphId) {\n\t\t\t\t\t\tlo = mid;\n\t\t\t\t\t} else {\n\t\t\t\t\t\thi = mid - 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst foundRange = ranges[lo];\n\t\t\t\treturn foundRange?.fd ?? 0;\n\t\t\t},\n\t\t};\n\t}\n\n\treturn { format, select: () => 0 };\n}\n\n/**\n * Parse ItemVariationStore\n */\nfunction parseItemVariationStore(reader: Reader): ItemVariationStore {\n\tconst startOffset = reader.offset;\n\n\tconst _length = reader.uint16();\n\tconst format = reader.uint16();\n\tconst variationRegionListOffset = reader.uint32();\n\tconst itemVariationDataCount = reader.uint16();\n\tconst itemVariationDataOffsets: number[] = [];\n\n\tfor (let i = 0; i < itemVariationDataCount; i++) {\n\t\titemVariationDataOffsets.push(reader.uint32());\n\t}\n\n\t// Parse VariationRegionList\n\treader.seek(startOffset + variationRegionListOffset);\n\tconst variationRegionList = parseVariationRegionList(reader);\n\n\t// Parse ItemVariationData\n\tconst itemVariationData: ItemVariationData[] = [];\n\tfor (const offset of itemVariationDataOffsets) {\n\t\treader.seek(startOffset + offset);\n\t\titemVariationData.push(parseItemVariationData(reader));\n\t}\n\n\treturn {\n\t\tformat,\n\t\tvariationRegionList,\n\t\titemVariationData,\n\t};\n}\n\n/**\n * Parse VariationRegionList\n */\nfunction parseVariationRegionList(reader: Reader): VariationRegionList {\n\tconst axisCount = reader.uint16();\n\tconst regionCount = reader.uint16();\n\tconst regions: VariationRegion[] = [];\n\n\tfor (let i = 0; i < regionCount; i++) {\n\t\tconst axes: RegionAxisCoordinates[] = [];\n\t\tfor (let j = 0; j < axisCount; j++) {\n\t\t\taxes.push({\n\t\t\t\tstartCoord: reader.f2dot14(),\n\t\t\t\tpeakCoord: reader.f2dot14(),\n\t\t\t\tendCoord: reader.f2dot14(),\n\t\t\t});\n\t\t}\n\t\tregions.push({ axes });\n\t}\n\n\treturn { axisCount, regionCount, regions };\n}\n\n/**\n * Parse ItemVariationData\n */\nfunction parseItemVariationData(reader: Reader): ItemVariationData {\n\tconst itemCount = reader.uint16();\n\tconst wordDeltaCount = reader.uint16();\n\tconst regionIndexCount = wordDeltaCount & 0x7fff;\n\tconst longWords = (wordDeltaCount & 0x8000) !== 0;\n\n\tconst regionIndexes: number[] = [];\n\tfor (let i = 0; i < regionIndexCount; i++) {\n\t\tregionIndexes.push(reader.uint16());\n\t}\n\n\tconst deltaSets: number[][] = [];\n\tfor (let i = 0; i < itemCount; i++) {\n\t\tconst deltas: number[] = [];\n\t\tfor (let j = 0; j < regionIndexCount; j++) {\n\t\t\tif (longWords) {\n\t\t\t\tdeltas.push(reader.int32());\n\t\t\t} else {\n\t\t\t\tdeltas.push(reader.int16());\n\t\t\t}\n\t\t}\n\t\tdeltaSets.push(deltas);\n\t}\n\n\treturn {\n\t\titemCount,\n\t\tregionIndexCount,\n\t\tregionIndexes,\n\t\tdeltaSets,\n\t};\n}\n\n/**\n * Calculate variation delta for given coordinates\n */\nexport function calculateVariationDelta(\n\tvstore: ItemVariationStore,\n\touterIndex: number,\n\tinnerIndex: number,\n\tnormalizedCoords: number[],\n): number {\n\tconst itemData = vstore.itemVariationData[outerIndex];\n\tif (!itemData) return 0;\n\n\tconst deltaSet = itemData.deltaSets[innerIndex];\n\tif (!deltaSet) return 0;\n\n\tlet delta = 0;\n\tfor (let i = 0; i < itemData.regionIndexCount; i++) {\n\t\tconst regionIndex = itemData.regionIndexes[i];\n\t\tif (regionIndex === undefined) continue;\n\t\tconst region = vstore.variationRegionList.regions[regionIndex];\n\t\tif (!region) continue;\n\n\t\t// Calculate scalar for this region\n\t\tlet scalar = 1.0;\n\t\tfor (const [axis, coords] of region.axes.entries()) {\n\t\t\tconst coord = normalizedCoords[axis] ?? 0;\n\n\t\t\tif (coords.peakCoord === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (coord < coords.startCoord || coord > coords.endCoord) {\n\t\t\t\tscalar = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (coord === coords.peakCoord) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (coord < coords.peakCoord) {\n\t\t\t\tscalar *=\n\t\t\t\t\t(coord - coords.startCoord) / (coords.peakCoord - coords.startCoord);\n\t\t\t} else {\n\t\t\t\tscalar *=\n\t\t\t\t\t(coords.endCoord - coord) / (coords.endCoord - coords.peakCoord);\n\t\t\t}\n\t\t}\n\n\t\tdelta += scalar * (deltaSet[i] ?? 0);\n\t}\n\n\treturn Math.round(delta);\n}\n",
18
+ "import type { GlyphId, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/** Platform IDs */\nexport enum PlatformId {\n\tUnicode = 0,\n\tMacintosh = 1,\n\tISO = 2, // deprecated\n\tWindows = 3,\n\tCustom = 4,\n}\n\n/** Encoding record in cmap header */\nexport interface EncodingRecord {\n\tplatformId: uint16;\n\tencodingId: uint16;\n\toffset: uint32;\n}\n\n/** Base interface for cmap subtables */\ninterface CmapSubtableBase {\n\tformat: number;\n\tlookup(codepoint: number): GlyphId | undefined;\n}\n\n/** Format 0: Byte encoding table (legacy, 256 entries) */\ninterface CmapFormat0 extends CmapSubtableBase {\n\tformat: 0;\n\tglyphIdArray: Uint8Array;\n}\n\n/** Format 4: Segment mapping to delta values (BMP characters) */\ninterface CmapFormat4 extends CmapSubtableBase {\n\tformat: 4;\n\tsegCount: number;\n\tendCodes: Uint16Array;\n\tstartCodes: Uint16Array;\n\tidDeltas: Int16Array;\n\tidRangeOffsets: Uint16Array;\n\tglyphIdArray: Uint16Array;\n}\n\n/** Format 12: Segmented coverage (full Unicode) */\ninterface CmapFormat12 extends CmapSubtableBase {\n\tformat: 12;\n\tgroups: Array<{\n\t\tstartCharCode: uint32;\n\t\tendCharCode: uint32;\n\t\tstartGlyphId: uint32;\n\t}>;\n}\n\n/** Variation selector record */\ninterface VariationSelectorRecord {\n\tvarSelector: number;\n\tdefaultUVS: Array<{\n\t\tstartUnicodeValue: number;\n\t\tadditionalCount: number;\n\t}> | null;\n\tnonDefaultUVS: Array<{ unicodeValue: number; glyphId: GlyphId }> | null;\n}\n\n/** Format 14: Unicode Variation Sequences */\ninterface CmapFormat14 extends CmapSubtableBase {\n\tformat: 14;\n\tvarSelectorRecords: VariationSelectorRecord[];\n\tlookupVariation(\n\t\tcodepoint: number,\n\t\tvariationSelector: number,\n\t): GlyphId | undefined | \"default\";\n}\n\nexport type CmapSubtable =\n\t| CmapFormat0\n\t| CmapFormat4\n\t| CmapFormat12\n\t| CmapFormat14;\n\n/** Character to glyph index mapping table */\nexport interface CmapTable {\n\tversion: uint16;\n\tnumTables: uint16;\n\tencodingRecords: EncodingRecord[];\n\tsubtables: Map<string, CmapSubtable>;\n\t/** Best subtable for Unicode lookup */\n\tbestSubtable: CmapSubtable | null;\n}\n\nexport function parseCmap(reader: Reader, tableLength: number): CmapTable {\n\tconst _tableStart = reader.offset;\n\tconst version = reader.uint16();\n\tconst numTables = reader.uint16();\n\n\tconst encodingRecords: EncodingRecord[] = [];\n\tfor (let i = 0; i < numTables; i++) {\n\t\tencodingRecords.push({\n\t\t\tplatformId: reader.uint16(),\n\t\t\tencodingId: reader.uint16(),\n\t\t\toffset: reader.uint32(),\n\t\t});\n\t}\n\n\t// Parse subtables\n\tconst subtables = new Map<string, CmapSubtable>();\n\tconst parsedOffsets = new Set<number>();\n\n\tfor (const record of encodingRecords) {\n\t\t// Skip duplicates (multiple records can point to same subtable)\n\t\tif (parsedOffsets.has(record.offset)) {\n\t\t\tconst key = `${record.platformId}-${record.encodingId}`;\n\t\t\t// Find existing subtable\n\t\t\tfor (const [existingKey, subtable] of subtables) {\n\t\t\t\tconst parts = existingKey.split(\"@\");\n\t\t\t\tconst existingOffset = parts[0];\n\t\t\t\tif (\n\t\t\t\t\texistingOffset &&\n\t\t\t\t\tNumber.parseInt(existingOffset, 10) === record.offset\n\t\t\t\t) {\n\t\t\t\t\tsubtables.set(key, subtable);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tparsedOffsets.add(record.offset);\n\n\t\tconst subtableReader = reader.slice(\n\t\t\trecord.offset,\n\t\t\ttableLength - record.offset,\n\t\t);\n\t\tconst subtable = parseCmapSubtable(subtableReader);\n\n\t\tif (subtable) {\n\t\t\tconst key = `${record.platformId}-${record.encodingId}`;\n\t\t\tsubtables.set(key, subtable);\n\t\t}\n\t}\n\n\t// Find best subtable for Unicode lookup\n\t// Prefer: Windows Unicode full (3-10), Unicode full (0-4), Windows BMP (3-1), Unicode BMP (0-3)\n\tconst preferredKeys = [\"3-10\", \"0-4\", \"3-1\", \"0-3\", \"0-6\", \"1-0\"];\n\tlet bestSubtable: CmapSubtable | null = null;\n\n\tfor (const key of preferredKeys) {\n\t\tconst subtable = subtables.get(key);\n\t\tif (subtable && subtable.format !== 14) {\n\t\t\tbestSubtable = subtable;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Fallback to first non-format-14 subtable\n\tif (!bestSubtable) {\n\t\tfor (const subtable of subtables.values()) {\n\t\t\tif (subtable.format !== 14) {\n\t\t\t\tbestSubtable = subtable;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tversion,\n\t\tnumTables,\n\t\tencodingRecords,\n\t\tsubtables,\n\t\tbestSubtable,\n\t};\n}\n\nfunction parseCmapSubtable(reader: Reader): CmapSubtable | null {\n\tconst format = reader.uint16();\n\n\tswitch (format) {\n\t\tcase 0:\n\t\t\treturn parseCmapFormat0(reader);\n\t\tcase 4:\n\t\t\treturn parseCmapFormat4(reader);\n\t\tcase 12:\n\t\t\treturn parseCmapFormat12(reader);\n\t\tcase 14:\n\t\t\treturn parseCmapFormat14(reader);\n\t\tdefault:\n\t\t\t// Unsupported format - skip\n\t\t\treturn null;\n\t}\n}\n\nfunction parseCmapFormat0(reader: Reader): CmapFormat0 {\n\tconst _length = reader.uint16();\n\tconst _language = reader.uint16();\n\tconst glyphIdArray = reader.uint8Array(256);\n\n\treturn {\n\t\tformat: 0,\n\t\tglyphIdArray,\n\t\tlookup(codepoint: number): GlyphId | undefined {\n\t\t\tif (codepoint >= 0 && codepoint < 256) {\n\t\t\t\treturn glyphIdArray[codepoint];\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\nfunction parseCmapFormat4(reader: Reader): CmapFormat4 {\n\tconst _length = reader.uint16();\n\tconst _language = reader.uint16();\n\tconst segCountX2 = reader.uint16();\n\tconst segCount = segCountX2 / 2;\n\n\treader.skip(6); // searchRange, entrySelector, rangeShift\n\n\tconst endCodes = reader.uint16Array(segCount);\n\treader.skip(2); // reservedPad\n\tconst startCodes = reader.uint16Array(segCount);\n\tconst idDeltas = reader.int16Array(segCount);\n\n\t// Save position before idRangeOffsets for glyph ID calculation\n\tconst _idRangeOffsetPos = reader.offset;\n\tconst idRangeOffsets = reader.uint16Array(segCount);\n\n\t// Read remaining glyph IDs\n\tconst remainingBytes = reader.remaining;\n\tconst glyphIdCount = remainingBytes / 2;\n\tconst glyphIdArray = reader.uint16Array(glyphIdCount);\n\n\treturn {\n\t\tformat: 4,\n\t\tsegCount,\n\t\tendCodes,\n\t\tstartCodes,\n\t\tidDeltas,\n\t\tidRangeOffsets,\n\t\tglyphIdArray,\n\t\tlookup(codepoint: number): GlyphId | undefined {\n\t\t\tif (codepoint > 0xffff) return undefined;\n\n\t\t\t// Binary search for segment\n\t\t\tlet low = 0;\n\t\t\tlet high = segCount - 1;\n\n\t\t\twhile (low <= high) {\n\t\t\t\tconst mid = (low + high) >>> 1;\n\t\t\t\tconst endCode = endCodes[mid];\n\t\t\t\tif (endCode === undefined) break;\n\n\t\t\t\tif (codepoint > endCode) {\n\t\t\t\t\tlow = mid + 1;\n\t\t\t\t} else {\n\t\t\t\t\tconst startCode = startCodes[mid];\n\t\t\t\t\tif (startCode === undefined) break;\n\t\t\t\t\tif (codepoint < startCode) {\n\t\t\t\t\t\thigh = mid - 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Found segment\n\t\t\t\t\t\tconst idRangeOffset = idRangeOffsets[mid];\n\t\t\t\t\t\tconst idDelta = idDeltas[mid];\n\t\t\t\t\t\tif (idRangeOffset === undefined || idDelta === undefined) break;\n\n\t\t\t\t\t\tif (idRangeOffset === 0) {\n\t\t\t\t\t\t\treturn (codepoint + idDelta) & 0xffff;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Calculate index into glyphIdArray\n\t\t\t\t\t\t// idRangeOffset is relative to its own position in the array\n\t\t\t\t\t\tconst glyphIdIndex =\n\t\t\t\t\t\t\tidRangeOffset / 2 - (segCount - mid) + (codepoint - startCode);\n\n\t\t\t\t\t\tconst glyphId = glyphIdArray[glyphIdIndex];\n\t\t\t\t\t\tif (glyphId === undefined || glyphId === 0) {\n\t\t\t\t\t\t\treturn 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn (glyphId + idDelta) & 0xffff;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\nfunction parseCmapFormat12(reader: Reader): CmapFormat12 {\n\treader.skip(2); // reserved\n\tconst _length = reader.uint32();\n\tconst _language = reader.uint32();\n\tconst numGroups = reader.uint32();\n\n\tconst groups: CmapFormat12[\"groups\"] = new Array(numGroups);\n\tfor (let i = 0; i < numGroups; i++) {\n\t\tgroups[i] = {\n\t\t\tstartCharCode: reader.uint32(),\n\t\t\tendCharCode: reader.uint32(),\n\t\t\tstartGlyphId: reader.uint32(),\n\t\t};\n\t}\n\n\treturn {\n\t\tformat: 12,\n\t\tgroups,\n\t\tlookup(codepoint: number): GlyphId | undefined {\n\t\t\t// Binary search for group\n\t\t\tlet low = 0;\n\t\t\tlet high = groups.length - 1;\n\n\t\t\twhile (low <= high) {\n\t\t\t\tconst mid = (low + high) >>> 1;\n\t\t\t\tconst group = groups[mid];\n\t\t\t\tif (!group) break;\n\n\t\t\t\tif (codepoint > group.endCharCode) {\n\t\t\t\t\tlow = mid + 1;\n\t\t\t\t} else if (codepoint < group.startCharCode) {\n\t\t\t\t\thigh = mid - 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Found group\n\t\t\t\t\treturn group.startGlyphId + (codepoint - group.startCharCode);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\nfunction parseCmapFormat14(reader: Reader): CmapFormat14 {\n\tconst subtableStart = reader.offset - 2; // Account for format already read\n\tconst _length = reader.uint32();\n\tconst numVarSelectorRecords = reader.uint32();\n\n\t// First pass: read all variation selector records\n\tconst rawRecords: Array<{\n\t\tvarSelector: number;\n\t\tdefaultUVSOffset: number;\n\t\tnonDefaultUVSOffset: number;\n\t}> = [];\n\n\tfor (let i = 0; i < numVarSelectorRecords; i++) {\n\t\trawRecords.push({\n\t\t\tvarSelector: reader.uint24(),\n\t\t\tdefaultUVSOffset: reader.uint32(),\n\t\t\tnonDefaultUVSOffset: reader.uint32(),\n\t\t});\n\t}\n\n\t// Second pass: parse the UVS tables\n\tconst varSelectorRecords: VariationSelectorRecord[] = [];\n\n\tfor (const raw of rawRecords) {\n\t\tlet defaultUVS: VariationSelectorRecord[\"defaultUVS\"] = null;\n\t\tlet nonDefaultUVS: VariationSelectorRecord[\"nonDefaultUVS\"] = null;\n\n\t\t// Parse default UVS table (ranges where default glyph is used)\n\t\tif (raw.defaultUVSOffset !== 0) {\n\t\t\tconst uvsReader = reader.sliceFrom(subtableStart + raw.defaultUVSOffset);\n\t\t\tconst numUnicodeValueRanges = uvsReader.uint32();\n\t\t\tdefaultUVS = [];\n\n\t\t\tfor (let j = 0; j < numUnicodeValueRanges; j++) {\n\t\t\t\tdefaultUVS.push({\n\t\t\t\t\tstartUnicodeValue: uvsReader.uint24(),\n\t\t\t\t\tadditionalCount: uvsReader.uint8(),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Parse non-default UVS table (specific glyph mappings)\n\t\tif (raw.nonDefaultUVSOffset !== 0) {\n\t\t\tconst uvsReader = reader.sliceFrom(\n\t\t\t\tsubtableStart + raw.nonDefaultUVSOffset,\n\t\t\t);\n\t\t\tconst numUVSMappings = uvsReader.uint32();\n\t\t\tnonDefaultUVS = [];\n\n\t\t\tfor (let j = 0; j < numUVSMappings; j++) {\n\t\t\t\tnonDefaultUVS.push({\n\t\t\t\t\tunicodeValue: uvsReader.uint24(),\n\t\t\t\t\tglyphId: uvsReader.uint16(),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvarSelectorRecords.push({\n\t\t\tvarSelector: raw.varSelector,\n\t\t\tdefaultUVS,\n\t\t\tnonDefaultUVS,\n\t\t});\n\t}\n\n\treturn {\n\t\tformat: 14,\n\t\tvarSelectorRecords,\n\t\tlookup(_codepoint: number): GlyphId | undefined {\n\t\t\t// Format 14 is only for variation selectors\n\t\t\treturn undefined;\n\t\t},\n\t\tlookupVariation(\n\t\t\tcodepoint: number,\n\t\t\tvariationSelector: number,\n\t\t): GlyphId | undefined | \"default\" {\n\t\t\t// Binary search for the variation selector\n\t\t\tlet low = 0;\n\t\t\tlet high = varSelectorRecords.length - 1;\n\t\t\tlet record: VariationSelectorRecord | null = null;\n\n\t\t\twhile (low <= high) {\n\t\t\t\tconst mid = (low + high) >>> 1;\n\t\t\t\tconst rec = varSelectorRecords[mid];\n\t\t\t\tif (!rec) break;\n\n\t\t\t\tif (variationSelector > rec.varSelector) {\n\t\t\t\t\tlow = mid + 1;\n\t\t\t\t} else if (variationSelector < rec.varSelector) {\n\t\t\t\t\thigh = mid - 1;\n\t\t\t\t} else {\n\t\t\t\t\trecord = rec;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!record) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\t// Check non-default UVS first (specific glyph mappings)\n\t\t\tif (record.nonDefaultUVS) {\n\t\t\t\tlet lo = 0;\n\t\t\t\tlet hi = record.nonDefaultUVS.length - 1;\n\n\t\t\t\twhile (lo <= hi) {\n\t\t\t\t\tconst mid = (lo + hi) >>> 1;\n\t\t\t\t\tconst mapping = record.nonDefaultUVS[mid];\n\t\t\t\t\tif (!mapping) break;\n\n\t\t\t\t\tif (codepoint > mapping.unicodeValue) {\n\t\t\t\t\t\tlo = mid + 1;\n\t\t\t\t\t} else if (codepoint < mapping.unicodeValue) {\n\t\t\t\t\t\thi = mid - 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn mapping.glyphId;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check default UVS (use default glyph for base codepoint)\n\t\t\tif (record.defaultUVS) {\n\t\t\t\tfor (const range of record.defaultUVS) {\n\t\t\t\t\tconst end = range.startUnicodeValue + range.additionalCount;\n\t\t\t\t\tif (codepoint >= range.startUnicodeValue && codepoint <= end) {\n\t\t\t\t\t\treturn \"default\"; // Signal to use the default glyph\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\n/** Get glyph ID for a codepoint using the best subtable */\nexport function getGlyphId(cmap: CmapTable, codepoint: number): GlyphId {\n\treturn cmap.bestSubtable?.lookup(codepoint) ?? 0;\n}\n\n/** Get glyph ID for a variation sequence (base + variation selector) */\nexport function getVariationGlyphId(\n\tcmap: CmapTable,\n\tcodepoint: number,\n\tvariationSelector: number,\n): GlyphId | undefined {\n\t// Find Format 14 subtable\n\tconst format14 = Array.from(cmap.subtables.values()).find(\n\t\t(s): s is CmapFormat14 => s.format === 14,\n\t);\n\n\tif (!format14) {\n\t\treturn undefined;\n\t}\n\n\tconst result = format14.lookupVariation(codepoint, variationSelector);\n\n\tif (result === \"default\") {\n\t\t// Use the default glyph for this codepoint\n\t\treturn getGlyphId(cmap, codepoint);\n\t}\n\n\treturn result;\n}\n\n/** Check if a codepoint is a variation selector */\nexport function isVariationSelector(codepoint: number): boolean {\n\t// Variation Selectors block (VS1-VS16)\n\tif (codepoint >= 0xfe00 && codepoint <= 0xfe0f) {\n\t\treturn true;\n\t}\n\t// Variation Selectors Supplement (VS17-VS256)\n\tif (codepoint >= 0xe0100 && codepoint <= 0xe01ef) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n",
19
+ "import type { GlyphId } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * COLR (Color) table parser\n * Defines color glyph layers\n */\n\nexport interface ColrTable {\n\tversion: number;\n\t// v0 data\n\tbaseGlyphRecords: BaseGlyphRecord[];\n\tlayerRecords: LayerRecord[];\n\t// v1 data\n\tbaseGlyphPaintRecords?: BaseGlyphPaintRecord[];\n\tlayerList?: Paint[];\n\tclipList?: ClipRecord[];\n\tvarIdxMap?: number[];\n\titemVariationStore?: ItemVariationStore;\n}\n\n// v0 structures\nexport interface BaseGlyphRecord {\n\tglyphId: GlyphId;\n\tfirstLayerIndex: number;\n\tnumLayers: number;\n}\n\nexport interface LayerRecord {\n\tglyphId: GlyphId;\n\tpaletteIndex: number;\n}\n\n// v1 structures\nexport interface BaseGlyphPaintRecord {\n\tglyphId: GlyphId;\n\tpaint: Paint;\n}\n\n// Paint types for COLR v1\nexport enum PaintFormat {\n\tColrLayers = 1,\n\tSolid = 2,\n\tVarSolid = 3,\n\tLinearGradient = 4,\n\tVarLinearGradient = 5,\n\tRadialGradient = 6,\n\tVarRadialGradient = 7,\n\tSweepGradient = 8,\n\tVarSweepGradient = 9,\n\tGlyph = 10,\n\tColrGlyph = 11,\n\tTransform = 12,\n\tVarTransform = 13,\n\tTranslate = 14,\n\tVarTranslate = 15,\n\tScale = 16,\n\tVarScale = 17,\n\tScaleAroundCenter = 18,\n\tVarScaleAroundCenter = 19,\n\tScaleUniform = 20,\n\tVarScaleUniform = 21,\n\tScaleUniformAroundCenter = 22,\n\tVarScaleUniformAroundCenter = 23,\n\tRotate = 24,\n\tVarRotate = 25,\n\tRotateAroundCenter = 26,\n\tVarRotateAroundCenter = 27,\n\tSkew = 28,\n\tVarSkew = 29,\n\tSkewAroundCenter = 30,\n\tVarSkewAroundCenter = 31,\n\tComposite = 32,\n}\n\nexport type Paint =\n\t| PaintColrLayers\n\t| PaintSolid\n\t| PaintLinearGradient\n\t| PaintRadialGradient\n\t| PaintSweepGradient\n\t| PaintGlyph\n\t| PaintColrGlyph\n\t| PaintTransform\n\t| PaintTranslate\n\t| PaintScale\n\t| PaintRotate\n\t| PaintSkew\n\t| PaintComposite;\n\nexport interface PaintColrLayers {\n\tformat: PaintFormat.ColrLayers;\n\tnumLayers: number;\n\tfirstLayerIndex: number;\n}\n\nexport interface PaintSolid {\n\tformat: PaintFormat.Solid | PaintFormat.VarSolid;\n\tpaletteIndex: number;\n\talpha: number;\n\tvarIndexBase?: number;\n}\n\nexport interface PaintLinearGradient {\n\tformat: PaintFormat.LinearGradient | PaintFormat.VarLinearGradient;\n\tcolorLine: ColorLine;\n\tx0: number;\n\ty0: number;\n\tx1: number;\n\ty1: number;\n\tx2: number;\n\ty2: number;\n}\n\nexport interface PaintRadialGradient {\n\tformat: PaintFormat.RadialGradient | PaintFormat.VarRadialGradient;\n\tcolorLine: ColorLine;\n\tx0: number;\n\ty0: number;\n\tradius0: number;\n\tx1: number;\n\ty1: number;\n\tradius1: number;\n}\n\nexport interface PaintSweepGradient {\n\tformat: PaintFormat.SweepGradient | PaintFormat.VarSweepGradient;\n\tcolorLine: ColorLine;\n\tcenterX: number;\n\tcenterY: number;\n\tstartAngle: number;\n\tendAngle: number;\n}\n\nexport interface PaintGlyph {\n\tformat: PaintFormat.Glyph;\n\tpaint: Paint;\n\tglyphId: GlyphId;\n}\n\nexport interface PaintColrGlyph {\n\tformat: PaintFormat.ColrGlyph;\n\tglyphId: GlyphId;\n}\n\nexport interface PaintTransform {\n\tformat: PaintFormat.Transform | PaintFormat.VarTransform;\n\tpaint: Paint;\n\ttransform: Affine2x3;\n}\n\nexport interface PaintTranslate {\n\tformat: PaintFormat.Translate | PaintFormat.VarTranslate;\n\tpaint: Paint;\n\tdx: number;\n\tdy: number;\n}\n\nexport interface PaintScale {\n\tformat:\n\t\t| PaintFormat.Scale\n\t\t| PaintFormat.VarScale\n\t\t| PaintFormat.ScaleAroundCenter\n\t\t| PaintFormat.VarScaleAroundCenter\n\t\t| PaintFormat.ScaleUniform\n\t\t| PaintFormat.VarScaleUniform\n\t\t| PaintFormat.ScaleUniformAroundCenter\n\t\t| PaintFormat.VarScaleUniformAroundCenter;\n\tpaint: Paint;\n\tscaleX: number;\n\tscaleY: number;\n\tcenterX?: number;\n\tcenterY?: number;\n}\n\nexport interface PaintRotate {\n\tformat:\n\t\t| PaintFormat.Rotate\n\t\t| PaintFormat.VarRotate\n\t\t| PaintFormat.RotateAroundCenter\n\t\t| PaintFormat.VarRotateAroundCenter;\n\tpaint: Paint;\n\tangle: number;\n\tcenterX?: number;\n\tcenterY?: number;\n}\n\nexport interface PaintSkew {\n\tformat:\n\t\t| PaintFormat.Skew\n\t\t| PaintFormat.VarSkew\n\t\t| PaintFormat.SkewAroundCenter\n\t\t| PaintFormat.VarSkewAroundCenter;\n\tpaint: Paint;\n\txSkewAngle: number;\n\tySkewAngle: number;\n\tcenterX?: number;\n\tcenterY?: number;\n}\n\nexport interface PaintComposite {\n\tformat: PaintFormat.Composite;\n\tsourcePaint: Paint;\n\tcompositeMode: CompositeMode;\n\tbackdropPaint: Paint;\n}\n\nexport interface ColorLine {\n\textend: Extend;\n\tcolorStops: ColorStop[];\n}\n\nexport interface ColorStop {\n\tstopOffset: number;\n\tpaletteIndex: number;\n\talpha: number;\n}\n\nexport enum Extend {\n\tPad = 0,\n\tRepeat = 1,\n\tReflect = 2,\n}\n\nexport enum CompositeMode {\n\tClear = 0,\n\tSrc = 1,\n\tDest = 2,\n\tSrcOver = 3,\n\tDestOver = 4,\n\tSrcIn = 5,\n\tDestIn = 6,\n\tSrcOut = 7,\n\tDestOut = 8,\n\tSrcAtop = 9,\n\tDestAtop = 10,\n\tXor = 11,\n\tPlus = 12,\n\tScreen = 13,\n\tOverlay = 14,\n\tDarken = 15,\n\tLighten = 16,\n\tColorDodge = 17,\n\tColorBurn = 18,\n\tHardLight = 19,\n\tSoftLight = 20,\n\tDifference = 21,\n\tExclusion = 22,\n\tMultiply = 23,\n\tHue = 24,\n\tSaturation = 25,\n\tColor = 26,\n\tLuminosity = 27,\n}\n\nexport interface Affine2x3 {\n\txx: number;\n\tyx: number;\n\txy: number;\n\tyy: number;\n\tdx: number;\n\tdy: number;\n}\n\nexport interface ClipRecord {\n\tstartGlyphId: GlyphId;\n\tendGlyphId: GlyphId;\n\tclipBox: ClipBox;\n}\n\nexport interface ClipBox {\n\tformat: number;\n\txMin: number;\n\tyMin: number;\n\txMax: number;\n\tyMax: number;\n\tvarIndexBase?: number;\n}\n\nexport interface ItemVariationStore {\n\tformat: number;\n\tvariationRegionListOffset: number;\n\titemVariationDataCount: number;\n\titemVariationDataOffsets: number[];\n\tvariationRegions: VariationRegion[];\n\titemVariationData: ItemVariationData[];\n}\n\nexport interface VariationRegion {\n\tregionAxes: RegionAxisCoordinates[];\n}\n\nexport interface RegionAxisCoordinates {\n\tstartCoord: number;\n\tpeakCoord: number;\n\tendCoord: number;\n}\n\nexport interface ItemVariationData {\n\titemCount: number;\n\twordDeltaCount: number;\n\tregionIndexCount: number;\n\tregionIndexes: number[];\n\tdeltaSets: number[][];\n}\n\nexport interface VarColorLine extends ColorLine {\n\tvarIndexBase?: number;\n}\n\nexport interface VarColorStop extends ColorStop {\n\tvarIndexBase?: number;\n}\n\n/**\n * Parse COLR table\n */\nexport function parseColr(reader: Reader): ColrTable {\n\tconst startOffset = reader.offset;\n\n\tconst version = reader.uint16();\n\tconst numBaseGlyphRecords = reader.uint16();\n\tconst baseGlyphRecordsOffset = reader.uint32();\n\tconst layerRecordsOffset = reader.uint32();\n\tconst numLayerRecords = reader.uint16();\n\n\t// Parse v0 base glyph records\n\tconst baseGlyphRecords: BaseGlyphRecord[] = [];\n\tif (baseGlyphRecordsOffset !== 0 && numBaseGlyphRecords > 0) {\n\t\treader.seek(startOffset + baseGlyphRecordsOffset);\n\t\tfor (let i = 0; i < numBaseGlyphRecords; i++) {\n\t\t\tbaseGlyphRecords.push({\n\t\t\t\tglyphId: reader.uint16(),\n\t\t\t\tfirstLayerIndex: reader.uint16(),\n\t\t\t\tnumLayers: reader.uint16(),\n\t\t\t});\n\t\t}\n\t}\n\n\t// Parse v0 layer records\n\tconst layerRecords: LayerRecord[] = [];\n\tif (layerRecordsOffset !== 0 && numLayerRecords > 0) {\n\t\treader.seek(startOffset + layerRecordsOffset);\n\t\tfor (let i = 0; i < numLayerRecords; i++) {\n\t\t\tlayerRecords.push({\n\t\t\t\tglyphId: reader.uint16(),\n\t\t\t\tpaletteIndex: reader.uint16(),\n\t\t\t});\n\t\t}\n\t}\n\n\tconst result: ColrTable = {\n\t\tversion,\n\t\tbaseGlyphRecords,\n\t\tlayerRecords,\n\t};\n\n\t// Parse v1 extensions\n\tif (version >= 1) {\n\t\treader.seek(startOffset + 14); // After v0 header\n\n\t\tconst baseGlyphListOffset = reader.uint32();\n\t\tconst layerListOffset = reader.uint32();\n\t\tconst clipListOffset = reader.uint32();\n\t\tconst varIdxMapOffset = reader.uint32();\n\t\tconst itemVariationStoreOffset = reader.uint32();\n\n\t\t// Parse base glyph paint records\n\t\tif (baseGlyphListOffset !== 0) {\n\t\t\treader.seek(startOffset + baseGlyphListOffset);\n\t\t\tconst numRecords = reader.uint32();\n\t\t\tresult.baseGlyphPaintRecords = [];\n\n\t\t\tfor (let i = 0; i < numRecords; i++) {\n\t\t\t\tconst glyphId = reader.uint16();\n\t\t\t\tconst paintOffset = reader.uint32();\n\n\t\t\t\t// Parse paint at offset\n\t\t\t\tconst savedPos = reader.offset;\n\t\t\t\treader.seek(\n\t\t\t\t\tstartOffset + baseGlyphListOffset + 4 + i * 6 + 2 + paintOffset - 4,\n\t\t\t\t);\n\t\t\t\tconst paint = parsePaint(reader, startOffset);\n\t\t\t\treader.seek(savedPos);\n\n\t\t\t\tresult.baseGlyphPaintRecords.push({ glyphId, paint });\n\t\t\t}\n\t\t}\n\n\t\t// Parse layer list\n\t\tif (layerListOffset !== 0) {\n\t\t\treader.seek(startOffset + layerListOffset);\n\t\t\tconst numLayers = reader.uint32();\n\t\t\tconst paintOffsets: number[] = [];\n\n\t\t\tfor (let i = 0; i < numLayers; i++) {\n\t\t\t\tpaintOffsets.push(reader.uint32());\n\t\t\t}\n\n\t\t\tresult.layerList = [];\n\t\t\tfor (const offset of paintOffsets) {\n\t\t\t\treader.seek(startOffset + layerListOffset + offset);\n\t\t\t\tresult.layerList.push(parsePaint(reader, startOffset));\n\t\t\t}\n\t\t}\n\n\t\t// Parse clip list\n\t\tif (clipListOffset !== 0) {\n\t\t\treader.seek(startOffset + clipListOffset);\n\t\t\tresult.clipList = parseClipList(reader, startOffset);\n\t\t}\n\n\t\t// Parse DeltaSetIndexMap (for variable fonts)\n\t\tif (varIdxMapOffset !== 0) {\n\t\t\treader.seek(startOffset + varIdxMapOffset);\n\t\t\tresult.varIdxMap = parseDeltaSetIndexMap(reader);\n\t\t}\n\n\t\t// Parse ItemVariationStore (for variable fonts)\n\t\tif (itemVariationStoreOffset !== 0) {\n\t\t\treader.seek(startOffset + itemVariationStoreOffset);\n\t\t\tresult.itemVariationStore = parseItemVariationStore(reader);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Parse a Paint structure\n */\nfunction parsePaint(reader: Reader, tableOffset: number): Paint {\n\tconst format = reader.uint8();\n\n\tswitch (format) {\n\t\tcase PaintFormat.ColrLayers:\n\t\t\treturn {\n\t\t\t\tformat,\n\t\t\t\tnumLayers: reader.uint8(),\n\t\t\t\tfirstLayerIndex: reader.uint32(),\n\t\t\t};\n\n\t\tcase PaintFormat.Solid:\n\t\t\treturn {\n\t\t\t\tformat,\n\t\t\t\tpaletteIndex: reader.uint16(),\n\t\t\t\talpha: reader.f2dot14(),\n\t\t\t};\n\n\t\tcase PaintFormat.VarSolid:\n\t\t\treturn {\n\t\t\t\tformat,\n\t\t\t\tpaletteIndex: reader.uint16(),\n\t\t\t\talpha: reader.f2dot14(),\n\t\t\t\tvarIndexBase: reader.uint32(),\n\t\t\t};\n\n\t\tcase PaintFormat.LinearGradient:\n\t\tcase PaintFormat.VarLinearGradient: {\n\t\t\tconst colorLineOffset = reader.uint24();\n\t\t\tconst x0 = reader.fword();\n\t\t\tconst y0 = reader.fword();\n\t\t\tconst x1 = reader.fword();\n\t\t\tconst y1 = reader.fword();\n\t\t\tconst x2 = reader.fword();\n\t\t\tconst y2 = reader.fword();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 18 + colorLineOffset);\n\t\t\tconst colorLine = parseColorLine(reader);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, colorLine, x0, y0, x1, y1, x2, y2 };\n\t\t}\n\n\t\tcase PaintFormat.RadialGradient:\n\t\tcase PaintFormat.VarRadialGradient: {\n\t\t\tconst colorLineOffset = reader.uint24();\n\t\t\tconst x0 = reader.fword();\n\t\t\tconst y0 = reader.fword();\n\t\t\tconst radius0 = reader.ufword();\n\t\t\tconst x1 = reader.fword();\n\t\t\tconst y1 = reader.fword();\n\t\t\tconst radius1 = reader.ufword();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 18 + colorLineOffset);\n\t\t\tconst colorLine = parseColorLine(reader);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, colorLine, x0, y0, radius0, x1, y1, radius1 };\n\t\t}\n\n\t\tcase PaintFormat.SweepGradient:\n\t\tcase PaintFormat.VarSweepGradient: {\n\t\t\tconst colorLineOffset = reader.uint24();\n\t\t\tconst centerX = reader.fword();\n\t\t\tconst centerY = reader.fword();\n\t\t\tconst startAngle = reader.f2dot14();\n\t\t\tconst endAngle = reader.f2dot14();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 12 + colorLineOffset);\n\t\t\tconst colorLine = parseColorLine(reader);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, colorLine, centerX, centerY, startAngle, endAngle };\n\t\t}\n\n\t\tcase PaintFormat.Glyph: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst glyphId = reader.uint16();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 5 + paintOffset);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, paint, glyphId };\n\t\t}\n\n\t\tcase PaintFormat.ColrGlyph:\n\t\t\treturn {\n\t\t\t\tformat,\n\t\t\t\tglyphId: reader.uint16(),\n\t\t\t};\n\n\t\tcase PaintFormat.Transform:\n\t\tcase PaintFormat.VarTransform: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst transformOffset = reader.uint24();\n\n\t\t\tconst paintPos = reader.offset - 6 + paintOffset;\n\t\t\tconst transformPos = reader.offset - 3 + transformOffset;\n\n\t\t\treader.seek(transformPos);\n\t\t\tconst transform: Affine2x3 = {\n\t\t\t\txx: reader.fixed(),\n\t\t\t\tyx: reader.fixed(),\n\t\t\t\txy: reader.fixed(),\n\t\t\t\tyy: reader.fixed(),\n\t\t\t\tdx: reader.fixed(),\n\t\t\t\tdy: reader.fixed(),\n\t\t\t};\n\n\t\t\treader.seek(paintPos);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\n\t\t\treturn { format, paint, transform };\n\t\t}\n\n\t\tcase PaintFormat.Translate:\n\t\tcase PaintFormat.VarTranslate: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst dx = reader.fword();\n\t\t\tconst dy = reader.fword();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 7 + paintOffset);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, paint, dx, dy };\n\t\t}\n\n\t\tcase PaintFormat.Scale:\n\t\tcase PaintFormat.VarScale: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst scaleX = reader.f2dot14();\n\t\t\tconst scaleY = reader.f2dot14();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 7 + paintOffset);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, paint, scaleX, scaleY };\n\t\t}\n\n\t\tcase PaintFormat.ScaleAroundCenter:\n\t\tcase PaintFormat.VarScaleAroundCenter: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst scaleX = reader.f2dot14();\n\t\t\tconst scaleY = reader.f2dot14();\n\t\t\tconst centerX = reader.fword();\n\t\t\tconst centerY = reader.fword();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 11 + paintOffset);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, paint, scaleX, scaleY, centerX, centerY };\n\t\t}\n\n\t\tcase PaintFormat.ScaleUniform:\n\t\tcase PaintFormat.VarScaleUniform: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst scale = reader.f2dot14();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 5 + paintOffset);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, paint, scaleX: scale, scaleY: scale };\n\t\t}\n\n\t\tcase PaintFormat.ScaleUniformAroundCenter:\n\t\tcase PaintFormat.VarScaleUniformAroundCenter: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst scale = reader.f2dot14();\n\t\t\tconst centerX = reader.fword();\n\t\t\tconst centerY = reader.fword();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 9 + paintOffset);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, paint, scaleX: scale, scaleY: scale, centerX, centerY };\n\t\t}\n\n\t\tcase PaintFormat.Rotate:\n\t\tcase PaintFormat.VarRotate: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst angle = reader.f2dot14();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 5 + paintOffset);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, paint, angle };\n\t\t}\n\n\t\tcase PaintFormat.RotateAroundCenter:\n\t\tcase PaintFormat.VarRotateAroundCenter: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst angle = reader.f2dot14();\n\t\t\tconst centerX = reader.fword();\n\t\t\tconst centerY = reader.fword();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 9 + paintOffset);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, paint, angle, centerX, centerY };\n\t\t}\n\n\t\tcase PaintFormat.Skew:\n\t\tcase PaintFormat.VarSkew: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst xSkewAngle = reader.f2dot14();\n\t\t\tconst ySkewAngle = reader.f2dot14();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 7 + paintOffset);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, paint, xSkewAngle, ySkewAngle };\n\t\t}\n\n\t\tcase PaintFormat.SkewAroundCenter:\n\t\tcase PaintFormat.VarSkewAroundCenter: {\n\t\t\tconst paintOffset = reader.uint24();\n\t\t\tconst xSkewAngle = reader.f2dot14();\n\t\t\tconst ySkewAngle = reader.f2dot14();\n\t\t\tconst centerX = reader.fword();\n\t\t\tconst centerY = reader.fword();\n\n\t\t\tconst savedPos = reader.offset;\n\t\t\treader.seek(reader.offset - 11 + paintOffset);\n\t\t\tconst paint = parsePaint(reader, tableOffset);\n\t\t\treader.seek(savedPos);\n\n\t\t\treturn { format, paint, xSkewAngle, ySkewAngle, centerX, centerY };\n\t\t}\n\n\t\tcase PaintFormat.Composite: {\n\t\t\tconst sourcePaintOffset = reader.uint24();\n\t\t\tconst compositeMode = reader.uint8() as CompositeMode;\n\t\t\tconst backdropPaintOffset = reader.uint24();\n\n\t\t\tconst sourcePos = reader.offset - 7 + sourcePaintOffset;\n\t\t\tconst backdropPos = reader.offset - 3 + backdropPaintOffset;\n\n\t\t\treader.seek(sourcePos);\n\t\t\tconst sourcePaint = parsePaint(reader, tableOffset);\n\n\t\t\treader.seek(backdropPos);\n\t\t\tconst backdropPaint = parsePaint(reader, tableOffset);\n\n\t\t\treturn { format, sourcePaint, compositeMode, backdropPaint };\n\t\t}\n\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown paint format: ${format}`);\n\t}\n}\n\n/**\n * Parse ColorLine structure\n */\nfunction parseColorLine(reader: Reader): ColorLine {\n\tconst extend = reader.uint8() as Extend;\n\tconst numStops = reader.uint16();\n\tconst colorStops: ColorStop[] = [];\n\n\tfor (let i = 0; i < numStops; i++) {\n\t\tcolorStops.push({\n\t\t\tstopOffset: reader.f2dot14(),\n\t\t\tpaletteIndex: reader.uint16(),\n\t\t\talpha: reader.f2dot14(),\n\t\t});\n\t}\n\n\treturn { extend, colorStops };\n}\n\n/**\n * Parse ClipList structure\n */\nfunction parseClipList(reader: Reader, _tableOffset: number): ClipRecord[] {\n\tconst _format = reader.uint8();\n\tconst numClips = reader.uint32();\n\tconst records: ClipRecord[] = [];\n\n\tfor (let i = 0; i < numClips; i++) {\n\t\tconst startGlyphId = reader.uint16();\n\t\tconst endGlyphId = reader.uint16();\n\t\tconst clipBoxOffset = reader.uint24();\n\n\t\tconst savedPos = reader.offset;\n\t\treader.seek(reader.offset - 7 + clipBoxOffset);\n\n\t\tconst boxFormat = reader.uint8();\n\t\tconst clipBox: ClipBox = {\n\t\t\tformat: boxFormat,\n\t\t\txMin: reader.fword(),\n\t\t\tyMin: reader.fword(),\n\t\t\txMax: reader.fword(),\n\t\t\tyMax: reader.fword(),\n\t\t};\n\n\t\tif (boxFormat === 2) {\n\t\t\tclipBox.varIndexBase = reader.uint32();\n\t\t}\n\n\t\treader.seek(savedPos);\n\n\t\trecords.push({ startGlyphId, endGlyphId, clipBox });\n\t}\n\n\treturn records;\n}\n\n/**\n * Get color layers for a glyph (v0)\n */\nexport function getColorLayers(\n\tcolr: ColrTable,\n\tglyphId: GlyphId,\n): LayerRecord[] | null {\n\t// Binary search for base glyph record\n\tconst records = colr.baseGlyphRecords;\n\tlet lo = 0;\n\tlet hi = records.length - 1;\n\n\twhile (lo <= hi) {\n\t\tconst mid = (lo + hi) >>> 1;\n\t\tconst record = records[mid];\n\t\tif (!record) break;\n\n\t\tif (record.glyphId === glyphId) {\n\t\t\tconst layers: LayerRecord[] = [];\n\t\t\tfor (let i = 0; i < record.numLayers; i++) {\n\t\t\t\tconst layer = colr.layerRecords[record.firstLayerIndex + i];\n\t\t\t\tif (layer) layers.push(layer);\n\t\t\t}\n\t\t\treturn layers;\n\t\t} else if (record.glyphId < glyphId) {\n\t\t\tlo = mid + 1;\n\t\t} else {\n\t\t\thi = mid - 1;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Get paint for a glyph (v1)\n */\nexport function getColorPaint(colr: ColrTable, glyphId: GlyphId): Paint | null {\n\tif (!colr.baseGlyphPaintRecords) return null;\n\n\t// Binary search\n\tconst records = colr.baseGlyphPaintRecords;\n\tlet lo = 0;\n\tlet hi = records.length - 1;\n\n\twhile (lo <= hi) {\n\t\tconst mid = (lo + hi) >>> 1;\n\t\tconst record = records[mid];\n\t\tif (!record) break;\n\n\t\tif (record.glyphId === glyphId) {\n\t\t\treturn record.paint;\n\t\t} else if (record.glyphId < glyphId) {\n\t\t\tlo = mid + 1;\n\t\t} else {\n\t\t\thi = mid - 1;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Check if glyph has color data\n */\nexport function hasColorGlyph(colr: ColrTable, glyphId: GlyphId): boolean {\n\treturn (\n\t\tgetColorLayers(colr, glyphId) !== null ||\n\t\tgetColorPaint(colr, glyphId) !== null\n\t);\n}\n\n/**\n * Parse DeltaSetIndexMap (used by variable fonts)\n */\nfunction parseDeltaSetIndexMap(reader: Reader): number[] {\n\tconst format = reader.uint8();\n\tconst entryFormat = reader.uint8();\n\tconst mapCount = format === 0 ? reader.uint16() : reader.uint32();\n\n\tconst innerBits = (entryFormat & 0x0f) + 1;\n\tconst outerBits = ((entryFormat >> 4) & 0x0f) + 1;\n\tconst entrySize = Math.ceil((innerBits + outerBits) / 8);\n\n\tconst result: number[] = [];\n\tfor (let i = 0; i < mapCount; i++) {\n\t\tlet entry = 0;\n\t\tfor (let b = 0; b < entrySize; b++) {\n\t\t\tentry = (entry << 8) | reader.uint8();\n\t\t}\n\t\t// Pack outer and inner indices into a single number\n\t\t// Format: (outer << 16) | inner\n\t\tconst innerMask = (1 << innerBits) - 1;\n\t\tconst inner = entry & innerMask;\n\t\tconst outer = entry >> innerBits;\n\t\tresult.push((outer << 16) | inner);\n\t}\n\n\treturn result;\n}\n\n/**\n * Parse ItemVariationStore (used by variable fonts)\n */\nfunction parseItemVariationStore(reader: Reader): ItemVariationStore {\n\tconst storeOffset = reader.offset;\n\tconst format = reader.uint16();\n\tconst variationRegionListOffset = reader.uint32();\n\tconst itemVariationDataCount = reader.uint16();\n\n\tconst itemVariationDataOffsets: number[] = [];\n\tfor (let i = 0; i < itemVariationDataCount; i++) {\n\t\titemVariationDataOffsets.push(reader.uint32());\n\t}\n\n\t// Parse variation region list\n\treader.seek(storeOffset + variationRegionListOffset);\n\tconst axisCount = reader.uint16();\n\tconst regionCount = reader.uint16();\n\n\tconst variationRegions: VariationRegion[] = [];\n\tfor (let i = 0; i < regionCount; i++) {\n\t\tconst regionAxes: RegionAxisCoordinates[] = [];\n\t\tfor (let j = 0; j < axisCount; j++) {\n\t\t\tregionAxes.push({\n\t\t\t\tstartCoord: reader.f2dot14(),\n\t\t\t\tpeakCoord: reader.f2dot14(),\n\t\t\t\tendCoord: reader.f2dot14(),\n\t\t\t});\n\t\t}\n\t\tvariationRegions.push({ regionAxes });\n\t}\n\n\t// Parse item variation data subtables\n\tconst itemVariationData: ItemVariationData[] = [];\n\tfor (const offset of itemVariationDataOffsets) {\n\t\treader.seek(storeOffset + offset);\n\t\tconst itemCount = reader.uint16();\n\t\tconst wordDeltaCount = reader.uint16();\n\t\tconst regionIndexCount = reader.uint16();\n\n\t\tconst regionIndexes: number[] = [];\n\t\tfor (let i = 0; i < regionIndexCount; i++) {\n\t\t\tregionIndexes.push(reader.uint16());\n\t\t}\n\n\t\t// Parse delta sets\n\t\tconst longWords = (wordDeltaCount & 0x8000) !== 0;\n\t\tconst wordCount = wordDeltaCount & 0x7fff;\n\n\t\tconst deltaSets: number[][] = [];\n\t\tfor (let i = 0; i < itemCount; i++) {\n\t\t\tconst deltas: number[] = [];\n\t\t\tfor (let j = 0; j < regionIndexCount; j++) {\n\t\t\t\tif (j < wordCount) {\n\t\t\t\t\tdeltas.push(longWords ? reader.int32() : reader.int16());\n\t\t\t\t} else {\n\t\t\t\t\tdeltas.push(longWords ? reader.int16() : reader.int8());\n\t\t\t\t}\n\t\t\t}\n\t\t\tdeltaSets.push(deltas);\n\t\t}\n\n\t\titemVariationData.push({\n\t\t\titemCount,\n\t\t\twordDeltaCount,\n\t\t\tregionIndexCount,\n\t\t\tregionIndexes,\n\t\t\tdeltaSets,\n\t\t});\n\t}\n\n\treturn {\n\t\tformat,\n\t\tvariationRegionListOffset,\n\t\titemVariationDataCount,\n\t\titemVariationDataOffsets,\n\t\tvariationRegions,\n\t\titemVariationData,\n\t};\n}\n\n/**\n * Get clip box for a glyph\n */\nexport function getClipBox(\n\tcolr: ColrTable,\n\tglyphId: GlyphId,\n): ClipBox | null {\n\tif (!colr.clipList) return null;\n\n\tfor (const record of colr.clipList) {\n\t\tif (glyphId >= record.startGlyphId && glyphId <= record.endGlyphId) {\n\t\t\treturn record.clipBox;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Calculate variation delta for a paint value\n */\nexport function getColorVariationDelta(\n\tcolr: ColrTable,\n\tvarIndex: number,\n\tcoords: number[],\n): number {\n\tif (!colr.itemVariationStore || !colr.varIdxMap) return 0;\n\n\t// Get outer/inner indices from varIdxMap\n\tconst mappedIndex = colr.varIdxMap[varIndex];\n\tif (mappedIndex === undefined) return 0;\n\n\tconst outer = mappedIndex >> 16;\n\tconst inner = mappedIndex & 0xffff;\n\n\tconst store = colr.itemVariationStore;\n\tconst data = store.itemVariationData[outer];\n\tif (!data) return 0;\n\n\tconst deltas = data.deltaSets[inner];\n\tif (!deltas) return 0;\n\n\t// Calculate scalar for each region and sum deltas\n\tlet result = 0;\n\tfor (let i = 0; i < data.regionIndexCount; i++) {\n\t\tconst regionIndex = data.regionIndexes[i]!;\n\t\tconst region = store.variationRegions[regionIndex];\n\t\tif (!region) continue;\n\n\t\t// Calculate scalar for this region\n\t\tlet scalar = 1.0;\n\t\tfor (let j = 0; j < region.regionAxes.length && j < coords.length; j++) {\n\t\t\tconst axis = region.regionAxes[j]!;\n\t\t\tconst coord = coords[j]!;\n\t\t\tscalar *= calculateAxisScalar(coord, axis.startCoord, axis.peakCoord, axis.endCoord);\n\t\t\tif (scalar === 0) break;\n\t\t}\n\n\t\tresult += deltas[i]! * scalar;\n\t}\n\n\treturn result;\n}\n\n/**\n * Calculate scalar contribution for a single axis\n */\nfunction calculateAxisScalar(\n\tcoord: number,\n\tstart: number,\n\tpeak: number,\n\tend: number,\n): number {\n\t// If peak is 0, no contribution\n\tif (peak === 0) return 1.0;\n\n\t// If coord exactly at peak, full contribution\n\tif (coord === peak) return 1.0;\n\n\t// If coord outside range, no contribution\n\tif (coord < start || coord > end) return 0.0;\n\n\t// Interpolate\n\tif (coord < peak) {\n\t\tif (start === peak) return 1.0;\n\t\treturn (coord - start) / (peak - start);\n\t} else {\n\t\tif (peak === end) return 1.0;\n\t\treturn (end - coord) / (end - peak);\n\t}\n}\n\n/**\n * Check if COLR table is version 1\n */\nexport function isColrV1(colr: ColrTable): boolean {\n\treturn colr.version >= 1 && colr.baseGlyphPaintRecords !== undefined;\n}\n\n/**\n * Get the paint layer at a specific index from the layer list\n */\nexport function getLayerPaint(colr: ColrTable, index: number): Paint | null {\n\treturn colr.layerList?.[index] ?? null;\n}\n",
20
+ "import type { Reader } from \"../binary/reader.ts\";\n\n/**\n * CPAL (Color Palette) table parser\n * Provides color palettes for color fonts\n */\n\nexport interface CpalTable {\n\tversion: number;\n\tnumPalettes: number;\n\tnumPaletteEntries: number;\n\tpalettes: ColorPalette[];\n\tpaletteTypes?: number[];\n\tpaletteLabels?: number[];\n\tpaletteEntryLabels?: number[];\n}\n\nexport interface ColorPalette {\n\tcolors: Color[];\n}\n\nexport interface Color {\n\tblue: number; // 0-255\n\tgreen: number; // 0-255\n\tred: number; // 0-255\n\talpha: number; // 0-255\n}\n\n/**\n * Palette type flags\n */\nexport enum PaletteType {\n\tUsableWithLightBackground = 0x0001,\n\tUsableWithDarkBackground = 0x0002,\n}\n\n/**\n * Parse CPAL table\n */\nexport function parseCpal(reader: Reader): CpalTable {\n\tconst startOffset = reader.offset;\n\n\tconst version = reader.uint16();\n\tconst numPaletteEntries = reader.uint16();\n\tconst numPalettes = reader.uint16();\n\tconst numColorRecords = reader.uint16();\n\tconst colorRecordsArrayOffset = reader.uint32();\n\n\t// Read color record indices for each palette\n\tconst colorRecordIndices: number[] = [];\n\tfor (let i = 0; i < numPalettes; i++) {\n\t\tcolorRecordIndices.push(reader.uint16());\n\t}\n\n\t// Read all color records\n\treader.seek(startOffset + colorRecordsArrayOffset);\n\tconst colorRecords: Color[] = [];\n\tfor (let i = 0; i < numColorRecords; i++) {\n\t\tcolorRecords.push({\n\t\t\tblue: reader.uint8(),\n\t\t\tgreen: reader.uint8(),\n\t\t\tred: reader.uint8(),\n\t\t\talpha: reader.uint8(),\n\t\t});\n\t}\n\n\t// Build palettes\n\tconst palettes: ColorPalette[] = [];\n\tfor (let i = 0; i < numPalettes; i++) {\n\t\tconst startIndex = colorRecordIndices[i];\n\t\tif (startIndex === undefined) continue;\n\t\tconst colors: Color[] = [];\n\t\tfor (let j = 0; j < numPaletteEntries; j++) {\n\t\t\tconst color = colorRecords[startIndex + j];\n\t\t\tif (color) colors.push(color);\n\t\t}\n\t\tpalettes.push({ colors });\n\t}\n\n\t// Version 1 extensions\n\tlet paletteTypes: number[] | undefined;\n\tlet paletteLabels: number[] | undefined;\n\tlet paletteEntryLabels: number[] | undefined;\n\n\tif (version >= 1) {\n\t\t// After color record indices\n\t\treader.seek(startOffset + 12 + numPalettes * 2);\n\n\t\tconst paletteTypesArrayOffset = reader.uint32();\n\t\tconst paletteLabelsArrayOffset = reader.uint32();\n\t\tconst paletteEntryLabelsArrayOffset = reader.uint32();\n\n\t\tif (paletteTypesArrayOffset !== 0) {\n\t\t\treader.seek(startOffset + paletteTypesArrayOffset);\n\t\t\tpaletteTypes = [];\n\t\t\tfor (let i = 0; i < numPalettes; i++) {\n\t\t\t\tpaletteTypes.push(reader.uint32());\n\t\t\t}\n\t\t}\n\n\t\tif (paletteLabelsArrayOffset !== 0) {\n\t\t\treader.seek(startOffset + paletteLabelsArrayOffset);\n\t\t\tpaletteLabels = [];\n\t\t\tfor (let i = 0; i < numPalettes; i++) {\n\t\t\t\tpaletteLabels.push(reader.uint16());\n\t\t\t}\n\t\t}\n\n\t\tif (paletteEntryLabelsArrayOffset !== 0) {\n\t\t\treader.seek(startOffset + paletteEntryLabelsArrayOffset);\n\t\t\tpaletteEntryLabels = [];\n\t\t\tfor (let i = 0; i < numPaletteEntries; i++) {\n\t\t\t\tpaletteEntryLabels.push(reader.uint16());\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tversion,\n\t\tnumPalettes,\n\t\tnumPaletteEntries,\n\t\tpalettes,\n\t\tpaletteTypes,\n\t\tpaletteLabels,\n\t\tpaletteEntryLabels,\n\t};\n}\n\n/**\n * Get color from palette\n */\nexport function getColor(\n\tcpal: CpalTable,\n\tpaletteIndex: number,\n\tcolorIndex: number,\n): Color | null {\n\tconst palette = cpal.palettes[paletteIndex];\n\tif (!palette) return null;\n\treturn palette.colors[colorIndex] ?? null;\n}\n\n/**\n * Convert color to CSS rgba string\n */\nexport function colorToRgba(color: Color): string {\n\treturn `rgba(${color.red}, ${color.green}, ${color.blue}, ${(color.alpha / 255).toFixed(3)})`;\n}\n\n/**\n * Convert color to CSS hex string\n */\nexport function colorToHex(color: Color): string {\n\tconst r = color.red.toString(16).padStart(2, \"0\");\n\tconst g = color.green.toString(16).padStart(2, \"0\");\n\tconst b = color.blue.toString(16).padStart(2, \"0\");\n\tif (color.alpha === 255) {\n\t\treturn `#${r}${g}${b}`;\n\t}\n\tconst a = color.alpha.toString(16).padStart(2, \"0\");\n\treturn `#${r}${g}${b}${a}`;\n}\n",
21
+ "import type { Reader } from \"../../font/binary/reader.ts\";\nimport type { GlyphId, uint16 } from \"../../types.ts\";\n\n/** Class Definition table - maps glyph IDs to class values */\nexport interface ClassDef {\n\t/** Get class for a glyph ID (returns 0 if not defined) */\n\tget(glyphId: GlyphId): number;\n\n\t/** Get all glyphs in a specific class */\n\tglyphsInClass(classValue: number): GlyphId[];\n}\n\n/** Format 1: Array of class values for a range of glyph IDs */\nclass ClassDefFormat1 implements ClassDef {\n\tprivate readonly startGlyphId: GlyphId;\n\tprivate readonly classValueArray: Uint16Array;\n\n\tconstructor(startGlyphId: GlyphId, classValueArray: Uint16Array) {\n\t\tthis.startGlyphId = startGlyphId;\n\t\tthis.classValueArray = classValueArray;\n\t}\n\n\tget(glyphId: GlyphId): number {\n\t\tconst index = glyphId - this.startGlyphId;\n\t\tif (index >= 0 && index < this.classValueArray.length) {\n\t\t\tconst value = this.classValueArray[index];\n\t\t\treturn value ?? 0;\n\t\t}\n\t\treturn 0; // Default class\n\t}\n\n\tglyphsInClass(classValue: number): GlyphId[] {\n\t\tconst result: GlyphId[] = [];\n\t\tfor (let i = 0; i < this.classValueArray.length; i++) {\n\t\t\tif (this.classValueArray[i] === classValue) {\n\t\t\t\tresult.push(this.startGlyphId + i);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n}\n\n/** Class range record for Format 2 */\ninterface ClassRangeRecord {\n\tstartGlyphId: GlyphId;\n\tendGlyphId: GlyphId;\n\tclassValue: uint16;\n}\n\n/** Format 2: Ranges of glyph IDs with class values */\nclass ClassDefFormat2 implements ClassDef {\n\tprivate readonly ranges: ClassRangeRecord[];\n\n\tconstructor(ranges: ClassRangeRecord[]) {\n\t\tthis.ranges = ranges;\n\t}\n\n\tget(glyphId: GlyphId): number {\n\t\t// Binary search through ranges\n\t\tlet low = 0;\n\t\tlet high = this.ranges.length - 1;\n\n\t\twhile (low <= high) {\n\t\t\tconst mid = (low + high) >>> 1;\n\t\t\tconst range = this.ranges[mid];\n\t\t\tif (!range) continue;\n\n\t\t\tif (glyphId > range.endGlyphId) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else if (glyphId < range.startGlyphId) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else {\n\t\t\t\treturn range.classValue;\n\t\t\t}\n\t\t}\n\n\t\treturn 0; // Default class\n\t}\n\n\tglyphsInClass(classValue: number): GlyphId[] {\n\t\tconst result: GlyphId[] = [];\n\t\tfor (const range of this.ranges) {\n\t\t\tif (range.classValue === classValue) {\n\t\t\t\tfor (let g = range.startGlyphId; g <= range.endGlyphId; g++) {\n\t\t\t\t\tresult.push(g);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n}\n\n/** Empty class definition (all glyphs are class 0) */\nclass ClassDefEmpty implements ClassDef {\n\tget(_glyphId: GlyphId): number {\n\t\treturn 0;\n\t}\n\n\tglyphsInClass(_classValue: number): GlyphId[] {\n\t\treturn [];\n\t}\n}\n\n/** Singleton empty ClassDef */\nexport const EMPTY_CLASS_DEF: ClassDef = new ClassDefEmpty();\n\n/** Parse a Class Definition table */\nexport function parseClassDef(reader: Reader): ClassDef {\n\tconst format = reader.uint16();\n\n\tif (format === 1) {\n\t\tconst startGlyphId = reader.uint16();\n\t\tconst glyphCount = reader.uint16();\n\t\tconst classValueArray = reader.uint16Array(glyphCount);\n\t\treturn new ClassDefFormat1(startGlyphId, classValueArray);\n\t}\n\n\tif (format === 2) {\n\t\tconst classRangeCount = reader.uint16();\n\t\tconst ranges: ClassRangeRecord[] = new Array(classRangeCount);\n\n\t\tfor (let i = 0; i < classRangeCount; i++) {\n\t\t\tranges[i] = {\n\t\t\t\tstartGlyphId: reader.uint16(),\n\t\t\t\tendGlyphId: reader.uint16(),\n\t\t\t\tclassValue: reader.uint16(),\n\t\t\t};\n\t\t}\n\n\t\treturn new ClassDefFormat2(ranges);\n\t}\n\n\tthrow new Error(`Unknown ClassDef format: ${format}`);\n}\n\n/** Parse ClassDef from offset, or return empty if offset is 0 */\nexport function parseClassDefAt(reader: Reader, offset: number): ClassDef {\n\tif (offset === 0) {\n\t\treturn EMPTY_CLASS_DEF;\n\t}\n\treturn parseClassDef(reader.sliceFrom(offset));\n}\n",
22
+ "import {\n\ttype ClassDef,\n\tparseClassDefAt,\n} from \"../../layout/structures/class-def.ts\";\nimport type { GlyphId, uint16 } from \"../../types.ts\";\nimport { GlyphClass } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/** Attach point for a glyph */\nexport interface AttachPoint {\n\tpointIndices: uint16[];\n}\n\n/** Ligature caret for a ligature glyph */\nexport interface LigatureCaret {\n\tcaretValues: number[];\n}\n\n/** Mark glyph sets */\nexport interface MarkGlyphSets {\n\t/** Check if glyph is in mark set */\n\thas(setIndex: number, glyphId: GlyphId): boolean;\n}\n\n/** Glyph Definition table */\nexport interface GdefTable {\n\tversion: { major: number; minor: number };\n\n\t/** Glyph class definitions (Base=1, Ligature=2, Mark=3, Component=4) */\n\tglyphClassDef: ClassDef;\n\n\t/** Attachment point list (optional) */\n\tattachList: Map<GlyphId, AttachPoint> | null;\n\n\t/** Ligature caret list (optional) */\n\tligCaretList: Map<GlyphId, LigatureCaret> | null;\n\n\t/** Mark attachment class definitions */\n\tmarkAttachClassDef: ClassDef;\n\n\t/** Mark glyph sets (version 1.2+) */\n\tmarkGlyphSets: MarkGlyphSets | null;\n}\n\nexport function parseGdef(reader: Reader): GdefTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\n\tconst glyphClassDefOffset = reader.offset16();\n\tconst attachListOffset = reader.offset16();\n\tconst ligCaretListOffset = reader.offset16();\n\tconst markAttachClassDefOffset = reader.offset16();\n\n\tlet markGlyphSetsDefOffset = 0;\n\tif (majorVersion === 1 && minorVersion >= 2) {\n\t\tmarkGlyphSetsDefOffset = reader.offset16();\n\t}\n\n\t// Parse glyph class definitions\n\tconst glyphClassDef = parseClassDefAt(reader, glyphClassDefOffset);\n\n\t// Parse attachment list (optional)\n\tlet attachList: Map<GlyphId, AttachPoint> | null = null;\n\tif (attachListOffset !== 0) {\n\t\tattachList = parseAttachList(reader.sliceFrom(attachListOffset));\n\t}\n\n\t// Parse ligature caret list (optional)\n\tlet ligCaretList: Map<GlyphId, LigatureCaret> | null = null;\n\tif (ligCaretListOffset !== 0) {\n\t\tligCaretList = parseLigCaretList(reader.sliceFrom(ligCaretListOffset));\n\t}\n\n\t// Parse mark attachment class definitions\n\tconst markAttachClassDef = parseClassDefAt(reader, markAttachClassDefOffset);\n\n\t// Parse mark glyph sets (version 1.2+)\n\tlet markGlyphSets: MarkGlyphSets | null = null;\n\tif (markGlyphSetsDefOffset !== 0) {\n\t\tmarkGlyphSets = parseMarkGlyphSets(\n\t\t\treader.sliceFrom(markGlyphSetsDefOffset),\n\t\t);\n\t}\n\n\treturn {\n\t\tversion: { major: majorVersion, minor: minorVersion },\n\t\tglyphClassDef,\n\t\tattachList,\n\t\tligCaretList,\n\t\tmarkAttachClassDef,\n\t\tmarkGlyphSets,\n\t};\n}\n\nfunction parseAttachList(reader: Reader): Map<GlyphId, AttachPoint> {\n\tconst coverageOffset = reader.offset16();\n\tconst glyphCount = reader.uint16();\n\n\t// Read attach point offsets\n\tconst attachPointOffsets = reader.uint16Array(glyphCount);\n\n\t// Parse coverage to get glyph IDs\n\tconst coverageReader = reader.sliceFrom(coverageOffset);\n\tconst format = coverageReader.uint16();\n\n\tconst glyphIds: GlyphId[] = [];\n\tif (format === 1) {\n\t\tconst count = coverageReader.uint16();\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tglyphIds.push(coverageReader.uint16());\n\t\t}\n\t} else if (format === 2) {\n\t\tconst rangeCount = coverageReader.uint16();\n\t\tfor (let i = 0; i < rangeCount; i++) {\n\t\t\tconst start = coverageReader.uint16();\n\t\t\tconst end = coverageReader.uint16();\n\t\t\tcoverageReader.skip(2); // startCoverageIndex\n\t\t\tfor (let g = start; g <= end; g++) {\n\t\t\t\tglyphIds.push(g);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Parse attach points\n\tconst result = new Map<GlyphId, AttachPoint>();\n\tfor (const [i, offset] of attachPointOffsets.entries()) {\n\t\tconst glyphId = glyphIds[i];\n\t\tif (glyphId === undefined) continue;\n\n\t\tconst pointReader = reader.sliceFrom(offset);\n\t\tconst pointCount = pointReader.uint16();\n\t\tconst pointIndices = Array.from(pointReader.uint16Array(pointCount));\n\n\t\tresult.set(glyphId, { pointIndices });\n\t}\n\n\treturn result;\n}\n\nfunction parseLigCaretList(reader: Reader): Map<GlyphId, LigatureCaret> {\n\tconst coverageOffset = reader.offset16();\n\tconst ligGlyphCount = reader.uint16();\n\n\t// Read ligature glyph offsets\n\tconst ligGlyphOffsets = reader.uint16Array(ligGlyphCount);\n\n\t// Parse coverage to get glyph IDs\n\tconst coverageReader = reader.sliceFrom(coverageOffset);\n\tconst format = coverageReader.uint16();\n\n\tconst glyphIds: GlyphId[] = [];\n\tif (format === 1) {\n\t\tconst count = coverageReader.uint16();\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tglyphIds.push(coverageReader.uint16());\n\t\t}\n\t} else if (format === 2) {\n\t\tconst rangeCount = coverageReader.uint16();\n\t\tfor (let i = 0; i < rangeCount; i++) {\n\t\t\tconst start = coverageReader.uint16();\n\t\t\tconst end = coverageReader.uint16();\n\t\t\tcoverageReader.skip(2);\n\t\t\tfor (let g = start; g <= end; g++) {\n\t\t\t\tglyphIds.push(g);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Parse ligature glyphs\n\tconst result = new Map<GlyphId, LigatureCaret>();\n\tfor (const [i, offset] of ligGlyphOffsets.entries()) {\n\t\tconst glyphId = glyphIds[i];\n\t\tif (glyphId === undefined) continue;\n\n\t\tconst ligReader = reader.sliceFrom(offset);\n\t\tconst caretCount = ligReader.uint16();\n\t\tconst caretValueOffsets = ligReader.uint16Array(caretCount);\n\n\t\tconst caretValues: number[] = [];\n\t\tfor (const caretOffset of caretValueOffsets) {\n\t\t\tconst caretReader = reader.sliceFrom(offset + caretOffset);\n\t\t\tconst caretFormat = caretReader.uint16();\n\n\t\t\tif (caretFormat === 1) {\n\t\t\t\t// Design units\n\t\t\t\tcaretValues.push(caretReader.int16());\n\t\t\t} else if (caretFormat === 2) {\n\t\t\t\t// Contour point\n\t\t\t\tcaretValues.push(caretReader.uint16()); // point index\n\t\t\t} else if (caretFormat === 3) {\n\t\t\t\t// Design units + device table\n\t\t\t\tcaretValues.push(caretReader.int16());\n\t\t\t}\n\t\t}\n\n\t\tresult.set(glyphId, { caretValues });\n\t}\n\n\treturn result;\n}\n\nfunction parseMarkGlyphSets(reader: Reader): MarkGlyphSets {\n\tconst _format = reader.uint16();\n\tconst markSetCount = reader.uint16();\n\n\t// Read coverage offsets\n\tconst coverageOffsets = reader.uint32Array(markSetCount);\n\n\t// Parse each mark set coverage\n\tconst markSets: Set<GlyphId>[] = [];\n\tfor (const offset of coverageOffsets) {\n\t\tconst coverageReader = reader.sliceFrom(offset);\n\t\tconst coverageFormat = coverageReader.uint16();\n\n\t\tconst glyphSet = new Set<GlyphId>();\n\t\tif (coverageFormat === 1) {\n\t\t\tconst count = coverageReader.uint16();\n\t\t\tfor (let i = 0; i < count; i++) {\n\t\t\t\tglyphSet.add(coverageReader.uint16());\n\t\t\t}\n\t\t} else if (coverageFormat === 2) {\n\t\t\tconst rangeCount = coverageReader.uint16();\n\t\t\tfor (let i = 0; i < rangeCount; i++) {\n\t\t\t\tconst start = coverageReader.uint16();\n\t\t\t\tconst end = coverageReader.uint16();\n\t\t\t\tcoverageReader.skip(2);\n\t\t\t\tfor (let g = start; g <= end; g++) {\n\t\t\t\t\tglyphSet.add(g);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tmarkSets.push(glyphSet);\n\t}\n\n\treturn {\n\t\thas(setIndex: number, glyphId: GlyphId): boolean {\n\t\t\tconst set = markSets[setIndex];\n\t\t\treturn set ? set.has(glyphId) : false;\n\t\t},\n\t};\n}\n\n/** Get glyph class from GDEF */\nexport function getGlyphClass(\n\tgdef: GdefTable | null,\n\tglyphId: GlyphId,\n): GlyphClass | 0 {\n\tif (!gdef) return 0;\n\tconst cls = gdef.glyphClassDef.get(glyphId);\n\treturn cls as GlyphClass | 0;\n}\n\n/** Check if glyph is a base glyph */\nexport function isBaseGlyph(gdef: GdefTable | null, glyphId: GlyphId): boolean {\n\treturn getGlyphClass(gdef, glyphId) === GlyphClass.Base;\n}\n\n/** Check if glyph is a ligature */\nexport function isLigature(gdef: GdefTable | null, glyphId: GlyphId): boolean {\n\treturn getGlyphClass(gdef, glyphId) === GlyphClass.Ligature;\n}\n\n/** Check if glyph is a mark */\nexport function isMark(gdef: GdefTable | null, glyphId: GlyphId): boolean {\n\treturn getGlyphClass(gdef, glyphId) === GlyphClass.Mark;\n}\n\n/** Check if glyph is a component */\nexport function isComponent(gdef: GdefTable | null, glyphId: GlyphId): boolean {\n\treturn getGlyphClass(gdef, glyphId) === GlyphClass.Component;\n}\n",
23
+ "import type { GlyphId, int16, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Glyph Variations table (gvar)\n * Contains variation data for TrueType glyph outlines\n */\nexport interface GvarTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\taxisCount: uint16;\n\tsharedTupleCount: uint16;\n\tsharedTuples: number[][]; // [tupleIndex][axisIndex]\n\tglyphVariationData: GlyphVariationData[];\n}\n\n/**\n * Variation data for a single glyph\n */\nexport interface GlyphVariationData {\n\ttupleVariationHeaders: TupleVariationHeader[];\n}\n\n/**\n * Tuple variation header\n */\nexport interface TupleVariationHeader {\n\tvariationDataSize: uint16;\n\ttupleIndex: uint16;\n\tpeakTuple: number[] | null; // null if embedded in shared tuples\n\tintermediateStartTuple: number[] | null;\n\tintermediateEndTuple: number[] | null;\n\tserializedData: Uint8Array;\n\tpointNumbers: number[] | null; // null means all points\n\tdeltas: PointDelta[];\n}\n\n/**\n * Delta values for a point\n */\nexport interface PointDelta {\n\tx: int16;\n\ty: int16;\n}\n\n// Tuple flags\nconst EMBEDDED_PEAK_TUPLE = 0x8000;\nconst INTERMEDIATE_REGION = 0x4000;\nconst PRIVATE_POINT_NUMBERS = 0x2000;\nconst TUPLE_INDEX_MASK = 0x0fff;\n\n/**\n * Parse gvar table\n */\nexport function parseGvar(reader: Reader, _numGlyphs: number): GvarTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst axisCount = reader.uint16();\n\tconst sharedTupleCount = reader.uint16();\n\tconst sharedTuplesOffset = reader.offset32();\n\tconst glyphCount = reader.uint16();\n\tconst flags = reader.uint16();\n\tconst glyphVariationDataArrayOffset = reader.offset32();\n\n\tconst offsetSize = flags & 1 ? 4 : 2;\n\n\t// Read glyph offsets\n\tconst offsets: number[] = [];\n\tfor (let i = 0; i <= glyphCount; i++) {\n\t\tconst offset = offsetSize === 4 ? reader.uint32() : reader.uint16() * 2;\n\t\toffsets.push(offset);\n\t}\n\n\t// Parse shared tuples\n\tconst sharedTuples: number[][] = [];\n\tif (sharedTupleCount > 0) {\n\t\tconst tupleReader = reader.sliceFrom(sharedTuplesOffset);\n\t\tfor (let i = 0; i < sharedTupleCount; i++) {\n\t\t\tconst tuple: number[] = [];\n\t\t\tfor (let a = 0; a < axisCount; a++) {\n\t\t\t\ttuple.push(tupleReader.f2dot14());\n\t\t\t}\n\t\t\tsharedTuples.push(tuple);\n\t\t}\n\t}\n\n\t// Parse glyph variation data\n\tconst glyphVariationData: GlyphVariationData[] = [];\n\tfor (let g = 0; g < glyphCount; g++) {\n\t\tconst startOffset = offsets[g];\n\t\tconst endOffset = offsets[g + 1];\n\t\tif (startOffset === undefined || endOffset === undefined) {\n\t\t\tglyphVariationData.push({ tupleVariationHeaders: [] });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst dataStart = glyphVariationDataArrayOffset + startOffset;\n\t\tconst dataEnd = glyphVariationDataArrayOffset + endOffset;\n\n\t\tif (dataStart === dataEnd) {\n\t\t\t// No variation data for this glyph\n\t\t\tglyphVariationData.push({ tupleVariationHeaders: [] });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst dataReader = reader.sliceFrom(dataStart);\n\t\tconst variationData = parseGlyphVariationData(\n\t\t\tdataReader,\n\t\t\tdataEnd - dataStart,\n\t\t\taxisCount,\n\t\t\tsharedTuples,\n\t\t);\n\t\tglyphVariationData.push(variationData);\n\t}\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\taxisCount,\n\t\tsharedTupleCount,\n\t\tsharedTuples,\n\t\tglyphVariationData,\n\t};\n}\n\nfunction parseGlyphVariationData(\n\treader: Reader,\n\tdataLength: number,\n\taxisCount: number,\n\tsharedTuples: number[][],\n): GlyphVariationData {\n\tif (dataLength === 0) {\n\t\treturn { tupleVariationHeaders: [] };\n\t}\n\n\tconst startOffset = reader.offset;\n\tconst tupleVariationCount = reader.uint16();\n\tconst dataOffset = reader.offset16();\n\n\tconst tupleCount = tupleVariationCount & 0x0fff;\n\tconst hasSharedPointNumbers = (tupleVariationCount & 0x8000) !== 0;\n\n\t// Read tuple variation headers first\n\tconst headerData: Array<{\n\t\tvariationDataSize: uint16;\n\t\ttupleIndex: uint16;\n\t\tpeakTuple: number[] | null;\n\t\tintermediateStartTuple: number[] | null;\n\t\tintermediateEndTuple: number[] | null;\n\t}> = [];\n\n\tfor (let i = 0; i < tupleCount; i++) {\n\t\tconst variationDataSize = reader.uint16();\n\t\tconst tupleIndex = reader.uint16();\n\n\t\tlet peakTuple: number[] | null = null;\n\t\tlet intermediateStartTuple: number[] | null = null;\n\t\tlet intermediateEndTuple: number[] | null = null;\n\n\t\tif (tupleIndex & EMBEDDED_PEAK_TUPLE) {\n\t\t\tpeakTuple = [];\n\t\t\tfor (let a = 0; a < axisCount; a++) {\n\t\t\t\tpeakTuple.push(reader.f2dot14());\n\t\t\t}\n\t\t} else {\n\t\t\tconst sharedIndex = tupleIndex & TUPLE_INDEX_MASK;\n\t\t\tpeakTuple = sharedTuples[sharedIndex] || null;\n\t\t}\n\n\t\tif (tupleIndex & INTERMEDIATE_REGION) {\n\t\t\tintermediateStartTuple = [];\n\t\t\tintermediateEndTuple = [];\n\t\t\tfor (let a = 0; a < axisCount; a++) {\n\t\t\t\tintermediateStartTuple.push(reader.f2dot14());\n\t\t\t}\n\t\t\tfor (let a = 0; a < axisCount; a++) {\n\t\t\t\tintermediateEndTuple.push(reader.f2dot14());\n\t\t\t}\n\t\t}\n\n\t\theaderData.push({\n\t\t\tvariationDataSize,\n\t\t\ttupleIndex,\n\t\t\tpeakTuple,\n\t\t\tintermediateStartTuple,\n\t\t\tintermediateEndTuple,\n\t\t});\n\t}\n\n\t// Now parse serialized data starting at dataOffset\n\tconst dataReader = reader.sliceFrom(startOffset + dataOffset);\n\n\t// Parse shared point numbers if present\n\tlet sharedPoints: number[] | null = null;\n\tif (hasSharedPointNumbers) {\n\t\tsharedPoints = parsePackedPoints(dataReader);\n\t}\n\n\t// Parse each tuple's deltas\n\tconst headers: TupleVariationHeader[] = [];\n\tfor (const hd of headerData) {\n\t\tconst hasPrivatePoints = (hd.tupleIndex & PRIVATE_POINT_NUMBERS) !== 0;\n\n\t\tlet pointNumbers: number[] | null;\n\t\tif (hasPrivatePoints) {\n\t\t\tpointNumbers = parsePackedPoints(dataReader);\n\t\t} else {\n\t\t\tpointNumbers = sharedPoints;\n\t\t}\n\n\t\t// Calculate number of points to read deltas for\n\t\tconst numPoints = pointNumbers ? pointNumbers.length : 0;\n\n\t\t// Parse x deltas then y deltas\n\t\tconst xDeltas =\n\t\t\tnumPoints > 0 ? parsePackedDeltas(dataReader, numPoints) : [];\n\t\tconst yDeltas =\n\t\t\tnumPoints > 0 ? parsePackedDeltas(dataReader, numPoints) : [];\n\n\t\tconst deltas: PointDelta[] = [];\n\t\tfor (const [p, xDelta] of xDeltas.entries()) {\n\t\t\tconst yDelta = yDeltas[p];\n\t\t\tdeltas.push({\n\t\t\t\tx: xDelta ?? 0,\n\t\t\t\ty: yDelta ?? 0,\n\t\t\t});\n\t\t}\n\n\t\theaders.push({\n\t\t\tvariationDataSize: hd.variationDataSize,\n\t\t\ttupleIndex: hd.tupleIndex,\n\t\t\tpeakTuple: hd.peakTuple,\n\t\t\tintermediateStartTuple: hd.intermediateStartTuple,\n\t\t\tintermediateEndTuple: hd.intermediateEndTuple,\n\t\t\tserializedData: new Uint8Array(0),\n\t\t\tpointNumbers,\n\t\t\tdeltas,\n\t\t});\n\t}\n\n\treturn { tupleVariationHeaders: headers };\n}\n\n/**\n * Parse packed point numbers\n */\nfunction parsePackedPoints(reader: Reader): number[] {\n\tconst count = reader.uint8();\n\tconst totalPoints =\n\t\tcount === 0\n\t\t\t? 0\n\t\t\t: count & 0x80\n\t\t\t\t? ((count & 0x7f) << 8) | reader.uint8()\n\t\t\t\t: count;\n\n\tif (totalPoints === 0) {\n\t\treturn []; // All points\n\t}\n\n\tconst points: number[] = [];\n\tlet pointIdx = 0;\n\n\twhile (points.length < totalPoints) {\n\t\tconst runHeader = reader.uint8();\n\t\tconst runCount = (runHeader & 0x7f) + 1;\n\t\tconst pointsAreWords = (runHeader & 0x80) !== 0;\n\n\t\tfor (let i = 0; i < runCount && points.length < totalPoints; i++) {\n\t\t\tconst delta = pointsAreWords ? reader.uint16() : reader.uint8();\n\t\t\tpointIdx += delta;\n\t\t\tpoints.push(pointIdx);\n\t\t}\n\t}\n\n\treturn points;\n}\n\n/**\n * Parse packed deltas\n */\nexport function parsePackedDeltas(reader: Reader, count: number): number[] {\n\tconst deltas: number[] = [];\n\n\twhile (deltas.length < count) {\n\t\tconst runHeader = reader.uint8();\n\t\tconst runCount = (runHeader & 0x3f) + 1;\n\t\tconst deltasAreZero = (runHeader & 0x80) !== 0;\n\t\tconst deltasAreWords = (runHeader & 0x40) !== 0;\n\n\t\tfor (let i = 0; i < runCount && deltas.length < count; i++) {\n\t\t\tif (deltasAreZero) {\n\t\t\t\tdeltas.push(0);\n\t\t\t} else if (deltasAreWords) {\n\t\t\t\tdeltas.push(reader.int16());\n\t\t\t} else {\n\t\t\t\tdeltas.push(reader.int8());\n\t\t\t}\n\t\t}\n\t}\n\n\treturn deltas;\n}\n\n/**\n * Calculate the scalar for a tuple given axis coordinates\n */\nexport function calculateTupleScalar(\n\tpeakTuple: number[],\n\taxisCoords: number[],\n\tintermediateStart: number[] | null,\n\tintermediateEnd: number[] | null,\n): number {\n\tlet scalar = 1.0;\n\n\tfor (const [i, peak] of peakTuple.entries()) {\n\t\tconst coord = axisCoords[i] ?? 0;\n\n\t\tif (peak === 0 || coord === 0) {\n\t\t\tif (peak !== 0) scalar = 0;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (intermediateStart && intermediateEnd) {\n\t\t\tconst start = intermediateStart[i];\n\t\t\tconst end = intermediateEnd[i];\n\t\t\tif (start === undefined || end === undefined) continue;\n\n\t\t\tif (coord < start || coord > end) {\n\t\t\t\tscalar = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (coord < peak) {\n\t\t\t\tscalar *= (coord - start) / (peak - start);\n\t\t\t} else if (coord > peak) {\n\t\t\t\tscalar *= (end - coord) / (end - peak);\n\t\t\t}\n\t\t} else {\n\t\t\t// Simple case\n\t\t\tif ((peak > 0 && coord < 0) || (peak < 0 && coord > 0)) {\n\t\t\t\tscalar = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (Math.abs(coord) < Math.abs(peak)) {\n\t\t\t\tscalar *= coord / peak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn scalar;\n}\n\n/**\n * Get delta for a glyph point at given variation coordinates\n */\nexport function getGlyphDelta(\n\tgvar: GvarTable,\n\tglyphId: GlyphId,\n\tpointIndex: number,\n\taxisCoords: number[],\n): PointDelta {\n\tconst glyphData = gvar.glyphVariationData[glyphId];\n\tif (!glyphData) return { x: 0, y: 0 };\n\n\tlet totalX = 0;\n\tlet totalY = 0;\n\n\tfor (const header of glyphData.tupleVariationHeaders) {\n\t\tif (!header.peakTuple) continue;\n\n\t\tconst scalar = calculateTupleScalar(\n\t\t\theader.peakTuple,\n\t\t\taxisCoords,\n\t\t\theader.intermediateStartTuple,\n\t\t\theader.intermediateEndTuple,\n\t\t);\n\n\t\tif (scalar === 0) continue;\n\n\t\t// Check if point is in the variation\n\t\tif (header.pointNumbers !== null) {\n\t\t\tconst pointIdx = header.pointNumbers.indexOf(pointIndex);\n\t\t\tif (pointIdx < 0) continue;\n\n\t\t\tconst delta = header.deltas[pointIdx];\n\t\t\tif (delta) {\n\t\t\t\ttotalX += delta.x * scalar;\n\t\t\t\ttotalY += delta.y * scalar;\n\t\t\t}\n\t\t} else {\n\t\t\t// All points\n\t\t\tconst delta = header.deltas[pointIndex];\n\t\t\tif (delta) {\n\t\t\t\ttotalX += delta.x * scalar;\n\t\t\t\ttotalY += delta.y * scalar;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { x: Math.round(totalX), y: Math.round(totalY) };\n}\n",
24
+ "import type { GlyphId, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * loca table - Glyph location index\n * Maps glyph IDs to byte offsets in the glyf table\n */\n\nexport interface LocaTable {\n\t/** Glyph offsets (numGlyphs + 1 entries) */\n\toffsets: uint32[];\n\t/** Whether the font uses short (16-bit) or long (32-bit) offsets */\n\tisShort: boolean;\n}\n\n/**\n * Parse loca table\n * @param reader - Reader positioned at start of loca table\n * @param numGlyphs - Number of glyphs from maxp table\n * @param indexToLocFormat - 0 for short offsets, 1 for long (from head table)\n */\nexport function parseLoca(\n\treader: Reader,\n\tnumGlyphs: number,\n\tindexToLocFormat: number,\n): LocaTable {\n\tconst isShort = indexToLocFormat === 0;\n\tconst offsets: uint32[] = [];\n\n\t// loca has numGlyphs + 1 entries (last entry marks end of last glyph)\n\tconst count = numGlyphs + 1;\n\n\tif (isShort) {\n\t\t// Short format: offsets are uint16, multiply by 2 to get actual byte offset\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\toffsets.push(reader.uint16() * 2);\n\t\t}\n\t} else {\n\t\t// Long format: offsets are uint32\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\toffsets.push(reader.uint32());\n\t\t}\n\t}\n\n\treturn { offsets, isShort };\n}\n\n/**\n * Get byte offset and length for a glyph in the glyf table\n * Returns null if glyph has no outline (empty glyph)\n */\nexport function getGlyphLocation(\n\tloca: LocaTable,\n\tglyphId: GlyphId,\n): { offset: uint32; length: uint32 } | null {\n\tif (glyphId < 0 || glyphId >= loca.offsets.length - 1) {\n\t\treturn null;\n\t}\n\n\tconst offset = loca.offsets[glyphId];\n\tconst nextOffset = loca.offsets[glyphId + 1];\n\tif (offset === undefined || nextOffset === undefined) {\n\t\treturn null;\n\t}\n\n\tconst length = nextOffset - offset;\n\n\t// Zero-length means empty glyph (space, etc.)\n\tif (length === 0) {\n\t\treturn null;\n\t}\n\n\treturn { offset, length };\n}\n\n/**\n * Check if a glyph has outline data\n */\nexport function hasGlyphOutline(loca: LocaTable, glyphId: GlyphId): boolean {\n\treturn getGlyphLocation(loca, glyphId) !== null;\n}\n",
25
+ "import type { GlyphId, int16, uint8, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\nimport type { GvarTable, PointDelta } from \"./gvar.ts\";\nimport { calculateTupleScalar } from \"./gvar.ts\";\nimport type { LocaTable } from \"./loca.ts\";\nimport { getGlyphLocation } from \"./loca.ts\";\n\n/**\n * glyf table - Glyph outline data\n * Contains TrueType glyph contours as quadratic Bézier curves\n */\n\n/** Point flags */\nexport const PointFlag = {\n\tOnCurve: 0x01,\n\tXShortVector: 0x02,\n\tYShortVector: 0x04,\n\tRepeat: 0x08,\n\tXIsSameOrPositive: 0x10,\n\tYIsSameOrPositive: 0x20,\n\tOverlapSimple: 0x40,\n} as const;\n\n/** Composite glyph flags */\nexport const CompositeFlag = {\n\tArg1And2AreWords: 0x0001,\n\tArgsAreXYValues: 0x0002,\n\tRoundXYToGrid: 0x0004,\n\tWeHaveAScale: 0x0008,\n\tMoreComponents: 0x0020,\n\tWeHaveAnXAndYScale: 0x0040,\n\tWeHaveATwoByTwo: 0x0080,\n\tWeHaveInstructions: 0x0100,\n\tUseMyMetrics: 0x0200,\n\tOverlapCompound: 0x0400,\n\tScaledComponentOffset: 0x0800,\n\tUnscaledComponentOffset: 0x1000,\n} as const;\n\n/** A point in a glyph contour */\nexport interface GlyphPoint {\n\tx: number;\n\ty: number;\n\tonCurve: boolean;\n}\n\n/** A contour is a closed path of points */\nexport type Contour = GlyphPoint[];\n\n/** Simple glyph with contours */\nexport interface SimpleGlyph {\n\ttype: \"simple\";\n\tnumberOfContours: int16;\n\txMin: int16;\n\tyMin: int16;\n\txMax: int16;\n\tyMax: int16;\n\tcontours: Contour[];\n\tinstructions: Uint8Array<ArrayBufferLike>;\n}\n\n/** Component of a composite glyph */\nexport interface GlyphComponent {\n\tglyphId: GlyphId;\n\tflags: uint16;\n\t/** X offset or point number */\n\targ1: number;\n\t/** Y offset or point number */\n\targ2: number;\n\t/** Transformation matrix [a, b, c, d] */\n\ttransform: [number, number, number, number];\n}\n\n/** Composite glyph made of other glyphs */\nexport interface CompositeGlyph {\n\ttype: \"composite\";\n\tnumberOfContours: int16;\n\txMin: int16;\n\tyMin: int16;\n\txMax: int16;\n\tyMax: int16;\n\tcomponents: GlyphComponent[];\n\tinstructions: Uint8Array<ArrayBufferLike>;\n}\n\n/** Empty glyph (space, etc.) */\nexport interface EmptyGlyph {\n\ttype: \"empty\";\n}\n\nexport type Glyph = SimpleGlyph | CompositeGlyph | EmptyGlyph;\n\n/** glyf table stores the raw reader for on-demand glyph parsing */\nexport interface GlyfTable {\n\treader: Reader;\n}\n\nexport function parseGlyf(reader: Reader): GlyfTable {\n\t// We don't parse all glyphs upfront - store reader for lazy access\n\treturn { reader };\n}\n\n/**\n * Parse a single glyph from the glyf table\n */\nexport function parseGlyph(\n\tglyf: GlyfTable,\n\tloca: LocaTable,\n\tglyphId: GlyphId,\n): Glyph {\n\tconst location = getGlyphLocation(loca, glyphId);\n\tif (!location) {\n\t\treturn { type: \"empty\" };\n\t}\n\n\tconst reader = glyf.reader.slice(location.offset, location.length);\n\treturn parseGlyphData(reader);\n}\n\nfunction parseGlyphData(reader: Reader): Glyph {\n\tconst numberOfContours = reader.int16();\n\tconst xMin = reader.int16();\n\tconst yMin = reader.int16();\n\tconst xMax = reader.int16();\n\tconst yMax = reader.int16();\n\n\tif (numberOfContours >= 0) {\n\t\treturn parseSimpleGlyph(reader, numberOfContours, xMin, yMin, xMax, yMax);\n\t} else {\n\t\treturn parseCompositeGlyph(\n\t\t\treader,\n\t\t\tnumberOfContours,\n\t\t\txMin,\n\t\t\tyMin,\n\t\t\txMax,\n\t\t\tyMax,\n\t\t);\n\t}\n}\n\nfunction parseSimpleGlyph(\n\treader: Reader,\n\tnumberOfContours: int16,\n\txMin: int16,\n\tyMin: int16,\n\txMax: int16,\n\tyMax: int16,\n): SimpleGlyph {\n\tif (numberOfContours === 0) {\n\t\treturn {\n\t\t\ttype: \"simple\",\n\t\t\tnumberOfContours,\n\t\t\txMin,\n\t\t\tyMin,\n\t\t\txMax,\n\t\t\tyMax,\n\t\t\tcontours: [],\n\t\t\tinstructions: new Uint8Array(0),\n\t\t};\n\t}\n\n\t// Read end points of each contour\n\tconst endPtsOfContours: uint16[] = [];\n\tfor (let i = 0; i < numberOfContours; i++) {\n\t\tendPtsOfContours.push(reader.uint16());\n\t}\n\n\t// Total number of points\n\tconst lastEndPt = endPtsOfContours[numberOfContours - 1];\n\tif (lastEndPt === undefined) {\n\t\treturn {\n\t\t\ttype: \"simple\",\n\t\t\tnumberOfContours,\n\t\t\txMin,\n\t\t\tyMin,\n\t\t\txMax,\n\t\t\tyMax,\n\t\t\tcontours: [],\n\t\t\tinstructions: new Uint8Array(0),\n\t\t};\n\t}\n\tconst numPoints = lastEndPt + 1;\n\n\t// Read instructions\n\tconst instructionLength = reader.uint16();\n\tconst instructions = reader.bytes(instructionLength);\n\n\t// Read flags\n\tconst flags: uint8[] = [];\n\twhile (flags.length < numPoints) {\n\t\tconst flag = reader.uint8();\n\t\tflags.push(flag);\n\n\t\t// Handle repeat flag\n\t\tif (flag & PointFlag.Repeat) {\n\t\t\tconst repeatCount = reader.uint8();\n\t\t\tfor (let i = 0; i < repeatCount; i++) {\n\t\t\t\tflags.push(flag);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Read X coordinates\n\tconst xCoordinates: number[] = [];\n\tlet x = 0;\n\tfor (const [_i, flag] of flags.entries()) {\n\t\tif (flag & PointFlag.XShortVector) {\n\t\t\tconst dx = reader.uint8();\n\t\t\tx += flag & PointFlag.XIsSameOrPositive ? dx : -dx;\n\t\t} else if (!(flag & PointFlag.XIsSameOrPositive)) {\n\t\t\tx += reader.int16();\n\t\t}\n\t\t// else x stays the same (XIsSameOrPositive with no short vector)\n\t\txCoordinates.push(x);\n\t}\n\n\t// Read Y coordinates\n\tconst yCoordinates: number[] = [];\n\tlet y = 0;\n\tfor (const [_i, flag] of flags.entries()) {\n\t\tif (flag & PointFlag.YShortVector) {\n\t\t\tconst dy = reader.uint8();\n\t\t\ty += flag & PointFlag.YIsSameOrPositive ? dy : -dy;\n\t\t} else if (!(flag & PointFlag.YIsSameOrPositive)) {\n\t\t\ty += reader.int16();\n\t\t}\n\t\t// else y stays the same\n\t\tyCoordinates.push(y);\n\t}\n\n\t// Build contours\n\tconst contours: Contour[] = [];\n\tlet pointIndex = 0;\n\tfor (const endPt of endPtsOfContours) {\n\t\tconst contour: Contour = [];\n\n\t\twhile (pointIndex <= endPt) {\n\t\t\tconst xCoord = xCoordinates[pointIndex];\n\t\t\tconst yCoord = yCoordinates[pointIndex];\n\t\t\tconst flag = flags[pointIndex];\n\t\t\tif (xCoord === undefined || yCoord === undefined || flag === undefined) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcontour.push({\n\t\t\t\tx: xCoord,\n\t\t\t\ty: yCoord,\n\t\t\t\tonCurve: (flag & PointFlag.OnCurve) !== 0,\n\t\t\t});\n\t\t\tpointIndex++;\n\t\t}\n\n\t\tcontours.push(contour);\n\t}\n\n\treturn {\n\t\ttype: \"simple\",\n\t\tnumberOfContours,\n\t\txMin,\n\t\tyMin,\n\t\txMax,\n\t\tyMax,\n\t\tcontours,\n\t\tinstructions,\n\t};\n}\n\nfunction parseCompositeGlyph(\n\treader: Reader,\n\tnumberOfContours: int16,\n\txMin: int16,\n\tyMin: int16,\n\txMax: int16,\n\tyMax: int16,\n): CompositeGlyph {\n\tconst components: GlyphComponent[] = [];\n\tlet flags: uint16;\n\n\tdo {\n\t\tflags = reader.uint16();\n\t\tconst glyphIndex = reader.uint16();\n\n\t\tlet arg1: number;\n\t\tlet arg2: number;\n\n\t\tif (flags & CompositeFlag.Arg1And2AreWords) {\n\t\t\tif (flags & CompositeFlag.ArgsAreXYValues) {\n\t\t\t\targ1 = reader.int16();\n\t\t\t\targ2 = reader.int16();\n\t\t\t} else {\n\t\t\t\targ1 = reader.uint16();\n\t\t\t\targ2 = reader.uint16();\n\t\t\t}\n\t\t} else {\n\t\t\tif (flags & CompositeFlag.ArgsAreXYValues) {\n\t\t\t\targ1 = reader.int8();\n\t\t\t\targ2 = reader.int8();\n\t\t\t} else {\n\t\t\t\targ1 = reader.uint8();\n\t\t\t\targ2 = reader.uint8();\n\t\t\t}\n\t\t}\n\n\t\t// Transformation matrix defaults to identity\n\t\tlet a = 1,\n\t\t\tb = 0,\n\t\t\tc = 0,\n\t\t\td = 1;\n\n\t\tif (flags & CompositeFlag.WeHaveAScale) {\n\t\t\ta = d = reader.f2dot14();\n\t\t} else if (flags & CompositeFlag.WeHaveAnXAndYScale) {\n\t\t\ta = reader.f2dot14();\n\t\t\td = reader.f2dot14();\n\t\t} else if (flags & CompositeFlag.WeHaveATwoByTwo) {\n\t\t\ta = reader.f2dot14();\n\t\t\tb = reader.f2dot14();\n\t\t\tc = reader.f2dot14();\n\t\t\td = reader.f2dot14();\n\t\t}\n\n\t\tcomponents.push({\n\t\t\tglyphId: glyphIndex,\n\t\t\tflags,\n\t\t\targ1,\n\t\t\targ2,\n\t\t\ttransform: [a, b, c, d],\n\t\t});\n\t} while (flags & CompositeFlag.MoreComponents);\n\n\t// Read instructions if present\n\tlet instructions: Uint8Array<ArrayBufferLike> = new Uint8Array(0);\n\tif (flags & CompositeFlag.WeHaveInstructions) {\n\t\tconst instructionLength = reader.uint16();\n\t\tinstructions = reader.bytes(instructionLength);\n\t}\n\n\treturn {\n\t\ttype: \"composite\",\n\t\tnumberOfContours,\n\t\txMin,\n\t\tyMin,\n\t\txMax,\n\t\tyMax,\n\t\tcomponents,\n\t\tinstructions,\n\t};\n}\n\n/**\n * Flatten a composite glyph into simple contours\n * Recursively resolves all component glyphs and applies transformations\n */\nexport function flattenCompositeGlyph(\n\tglyf: GlyfTable,\n\tloca: LocaTable,\n\tglyph: CompositeGlyph,\n\tdepth: number = 0,\n): Contour[] {\n\t// Prevent infinite recursion\n\tif (depth > 32) {\n\t\treturn [];\n\t}\n\n\tconst result: Contour[] = [];\n\n\tfor (const component of glyph.components) {\n\t\tconst componentGlyph = parseGlyph(glyf, loca, component.glyphId);\n\n\t\tlet componentContours: Contour[];\n\t\tif (componentGlyph.type === \"simple\") {\n\t\t\tcomponentContours = componentGlyph.contours;\n\t\t} else if (componentGlyph.type === \"composite\") {\n\t\t\tcomponentContours = flattenCompositeGlyph(\n\t\t\t\tglyf,\n\t\t\t\tloca,\n\t\t\t\tcomponentGlyph,\n\t\t\t\tdepth + 1,\n\t\t\t);\n\t\t} else {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Apply transformation and offset\n\t\tconst [a, b, c, d] = component.transform;\n\t\tconst dx =\n\t\t\tcomponent.flags & CompositeFlag.ArgsAreXYValues ? component.arg1 : 0;\n\t\tconst dy =\n\t\t\tcomponent.flags & CompositeFlag.ArgsAreXYValues ? component.arg2 : 0;\n\n\t\tfor (const contour of componentContours) {\n\t\t\tconst transformedContour: Contour = contour.map((point) => ({\n\t\t\t\tx: Math.round(a * point.x + c * point.y + dx),\n\t\t\t\ty: Math.round(b * point.x + d * point.y + dy),\n\t\t\t\tonCurve: point.onCurve,\n\t\t\t}));\n\t\t\tresult.push(transformedContour);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Get all contours for a glyph, flattening composites\n */\nexport function getGlyphContours(\n\tglyf: GlyfTable,\n\tloca: LocaTable,\n\tglyphId: GlyphId,\n): Contour[] {\n\tconst glyph = parseGlyph(glyf, loca, glyphId);\n\n\tif (glyph.type === \"empty\") {\n\t\treturn [];\n\t} else if (glyph.type === \"simple\") {\n\t\treturn glyph.contours;\n\t} else {\n\t\treturn flattenCompositeGlyph(glyf, loca, glyph);\n\t}\n}\n\n/**\n * Get bounding box for a glyph\n */\nexport function getGlyphBounds(\n\tglyf: GlyfTable,\n\tloca: LocaTable,\n\tglyphId: GlyphId,\n): { xMin: number; yMin: number; xMax: number; yMax: number } | null {\n\tconst glyph = parseGlyph(glyf, loca, glyphId);\n\n\tif (glyph.type === \"empty\") {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\txMin: glyph.xMin,\n\t\tyMin: glyph.yMin,\n\t\txMax: glyph.xMax,\n\t\tyMax: glyph.yMax,\n\t};\n}\n\n/**\n * Get all deltas for a glyph at given variation coordinates\n */\nexport function getGlyphDeltas(\n\tgvar: GvarTable,\n\tglyphId: GlyphId,\n\tnumPoints: number,\n\taxisCoords: number[],\n): PointDelta[] {\n\tconst glyphData = gvar.glyphVariationData[glyphId];\n\tif (!glyphData) {\n\t\treturn Array(numPoints).fill({ x: 0, y: 0 });\n\t}\n\n\t// Initialize deltas array\n\tconst deltas: PointDelta[] = Array(numPoints)\n\t\t.fill(null)\n\t\t.map(() => ({ x: 0, y: 0 }));\n\n\tfor (const header of glyphData.tupleVariationHeaders) {\n\t\tif (!header.peakTuple) continue;\n\n\t\tconst scalar = calculateTupleScalar(\n\t\t\theader.peakTuple,\n\t\t\taxisCoords,\n\t\t\theader.intermediateStartTuple,\n\t\t\theader.intermediateEndTuple,\n\t\t);\n\n\t\tif (scalar === 0) continue;\n\n\t\tif (header.pointNumbers !== null) {\n\t\t\t// Sparse point deltas\n\t\t\tfor (const [i, pointIndex] of header.pointNumbers.entries()) {\n\t\t\t\tconst delta = deltas[pointIndex];\n\t\t\t\tconst headerDelta = header.deltas[i];\n\t\t\t\tif (pointIndex < numPoints && delta && headerDelta) {\n\t\t\t\t\tdelta.x += headerDelta.x * scalar;\n\t\t\t\t\tdelta.y += headerDelta.y * scalar;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// All points\n\t\t\tfor (let i = 0; i < Math.min(header.deltas.length, numPoints); i++) {\n\t\t\t\tconst delta = deltas[i];\n\t\t\t\tconst headerDelta = header.deltas[i];\n\t\t\t\tif (delta && headerDelta) {\n\t\t\t\t\tdelta.x += headerDelta.x * scalar;\n\t\t\t\t\tdelta.y += headerDelta.y * scalar;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Round final values\n\tfor (const d of deltas) {\n\t\td.x = Math.round(d.x);\n\t\td.y = Math.round(d.y);\n\t}\n\n\treturn deltas;\n}\n\n/**\n * Apply variation deltas to contours\n */\nexport function applyVariationDeltas(\n\tcontours: Contour[],\n\tdeltas: PointDelta[],\n): Contour[] {\n\tconst result: Contour[] = [];\n\tlet pointIndex = 0;\n\n\tfor (const contour of contours) {\n\t\tconst newContour: Contour = [];\n\t\tfor (const point of contour) {\n\t\t\tconst delta = deltas[pointIndex] ?? { x: 0, y: 0 };\n\t\t\tnewContour.push({\n\t\t\t\tx: point.x + delta.x,\n\t\t\t\ty: point.y + delta.y,\n\t\t\t\tonCurve: point.onCurve,\n\t\t\t});\n\t\t\tpointIndex++;\n\t\t}\n\t\tresult.push(newContour);\n\t}\n\n\treturn result;\n}\n\n/**\n * Get contours for a glyph with variation applied\n */\nexport function getGlyphContoursWithVariation(\n\tglyf: GlyfTable,\n\tloca: LocaTable,\n\tgvar: GvarTable | null,\n\tglyphId: GlyphId,\n\taxisCoords?: number[],\n): Contour[] {\n\tconst glyph = parseGlyph(glyf, loca, glyphId);\n\n\tif (glyph.type === \"empty\") {\n\t\treturn [];\n\t}\n\n\tlet contours: Contour[];\n\tif (glyph.type === \"simple\") {\n\t\tcontours = glyph.contours;\n\t} else {\n\t\tcontours = flattenCompositeGlyphWithVariation(\n\t\t\tglyf,\n\t\t\tloca,\n\t\t\tgvar,\n\t\t\tglyph,\n\t\t\taxisCoords,\n\t\t);\n\t}\n\n\t// Apply variation if we have gvar and axis coordinates\n\tif (gvar && axisCoords && axisCoords.length > 0) {\n\t\t// Count total points\n\t\tlet numPoints = 0;\n\t\tfor (const c of contours) {\n\t\t\tnumPoints += c.length;\n\t\t}\n\t\t// Add phantom points (4)\n\t\tnumPoints += 4;\n\n\t\tconst deltas = getGlyphDeltas(gvar, glyphId, numPoints, axisCoords);\n\t\tcontours = applyVariationDeltas(contours, deltas);\n\t}\n\n\treturn contours;\n}\n\n/**\n * Flatten composite glyph with variation support\n */\nfunction flattenCompositeGlyphWithVariation(\n\tglyf: GlyfTable,\n\tloca: LocaTable,\n\tgvar: GvarTable | null,\n\tglyph: CompositeGlyph,\n\taxisCoords?: number[],\n\tdepth: number = 0,\n): Contour[] {\n\tif (depth > 32) {\n\t\treturn [];\n\t}\n\n\tconst result: Contour[] = [];\n\n\tfor (const component of glyph.components) {\n\t\tconst componentGlyph = parseGlyph(glyf, loca, component.glyphId);\n\n\t\tlet componentContours: Contour[];\n\t\tif (componentGlyph.type === \"simple\") {\n\t\t\tcomponentContours = componentGlyph.contours;\n\n\t\t\t// Apply variation to component\n\t\t\tif (gvar && axisCoords && axisCoords.length > 0) {\n\t\t\t\tlet numPoints = 0;\n\t\t\t\tfor (const c of componentContours) {\n\t\t\t\t\tnumPoints += c.length;\n\t\t\t\t}\n\t\t\t\tnumPoints += 4; // phantom points\n\n\t\t\t\tconst deltas = getGlyphDeltas(\n\t\t\t\t\tgvar,\n\t\t\t\t\tcomponent.glyphId,\n\t\t\t\t\tnumPoints,\n\t\t\t\t\taxisCoords,\n\t\t\t\t);\n\t\t\t\tcomponentContours = applyVariationDeltas(componentContours, deltas);\n\t\t\t}\n\t\t} else if (componentGlyph.type === \"composite\") {\n\t\t\tcomponentContours = flattenCompositeGlyphWithVariation(\n\t\t\t\tglyf,\n\t\t\t\tloca,\n\t\t\t\tgvar,\n\t\t\t\tcomponentGlyph,\n\t\t\t\taxisCoords,\n\t\t\t\tdepth + 1,\n\t\t\t);\n\t\t} else {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Apply transformation and offset\n\t\tconst [a, b, c, d] = component.transform;\n\t\tconst dx =\n\t\t\tcomponent.flags & CompositeFlag.ArgsAreXYValues ? component.arg1 : 0;\n\t\tconst dy =\n\t\t\tcomponent.flags & CompositeFlag.ArgsAreXYValues ? component.arg2 : 0;\n\n\t\tfor (const contour of componentContours) {\n\t\t\tconst transformedContour: Contour = contour.map((point) => ({\n\t\t\t\tx: Math.round(a * point.x + c * point.y + dx),\n\t\t\t\ty: Math.round(b * point.x + d * point.y + dy),\n\t\t\t\tonCurve: point.onCurve,\n\t\t\t}));\n\t\t\tresult.push(transformedContour);\n\t\t}\n\t}\n\n\treturn result;\n}\n",
26
+ "import type { Reader } from \"../../font/binary/reader.ts\";\nimport type { GlyphId, uint16 } from \"../../types.ts\";\n\n/** Coverage table - maps glyph IDs to coverage indices */\nexport interface Coverage {\n\t/** Get coverage index for a glyph ID, or null if not covered */\n\tget(glyphId: GlyphId): number | null;\n\n\t/** Check if glyph is covered */\n\tcovers(glyphId: GlyphId): boolean;\n\n\t/** Get all covered glyph IDs */\n\tglyphs(): GlyphId[];\n\n\t/** Number of covered glyphs */\n\treadonly size: number;\n}\n\n/** Format 1: Individual glyph IDs */\nclass CoverageFormat1 implements Coverage {\n\tprivate readonly glyphArray: Uint16Array;\n\tprivate readonly glyphSet: Set<GlyphId>;\n\n\tconstructor(glyphArray: Uint16Array) {\n\t\tthis.glyphArray = glyphArray;\n\t\tthis.glyphSet = new Set(glyphArray);\n\t}\n\n\tget size(): number {\n\t\treturn this.glyphArray.length;\n\t}\n\n\tget(glyphId: GlyphId): number | null {\n\t\t// Binary search since glyphs are sorted\n\t\tlet low = 0;\n\t\tlet high = this.glyphArray.length - 1;\n\n\t\twhile (low <= high) {\n\t\t\tconst mid = (low + high) >>> 1;\n\t\t\tconst midVal = this.glyphArray[mid];\n\t\t\tif (midVal === undefined) continue;\n\n\t\t\tif (midVal < glyphId) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else if (midVal > glyphId) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else {\n\t\t\t\treturn mid; // Found - return coverage index\n\t\t\t}\n\t\t}\n\n\t\treturn null; // Not found\n\t}\n\n\tcovers(glyphId: GlyphId): boolean {\n\t\treturn this.glyphSet.has(glyphId);\n\t}\n\n\tglyphs(): GlyphId[] {\n\t\treturn Array.from(this.glyphArray);\n\t}\n}\n\n/** Range record for Format 2 */\ninterface RangeRecord {\n\tstartGlyphId: GlyphId;\n\tendGlyphId: GlyphId;\n\tstartCoverageIndex: uint16;\n}\n\n/** Format 2: Ranges of glyph IDs */\nclass CoverageFormat2 implements Coverage {\n\tprivate readonly ranges: RangeRecord[];\n\tprivate readonly _size: number;\n\n\tconstructor(ranges: RangeRecord[]) {\n\t\tthis.ranges = ranges;\n\t\t// Calculate total size\n\t\tif (ranges.length === 0) {\n\t\t\tthis._size = 0;\n\t\t} else {\n\t\t\tconst lastRange = ranges[ranges.length - 1];\n\t\t\tif (lastRange) {\n\t\t\t\tthis._size =\n\t\t\t\t\tlastRange.startCoverageIndex +\n\t\t\t\t\t(lastRange.endGlyphId - lastRange.startGlyphId + 1);\n\t\t\t} else {\n\t\t\t\tthis._size = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tget size(): number {\n\t\treturn this._size;\n\t}\n\n\tget(glyphId: GlyphId): number | null {\n\t\t// Binary search through ranges\n\t\tlet low = 0;\n\t\tlet high = this.ranges.length - 1;\n\n\t\twhile (low <= high) {\n\t\t\tconst mid = (low + high) >>> 1;\n\t\t\tconst range = this.ranges[mid];\n\t\t\tif (!range) continue;\n\n\t\t\tif (glyphId > range.endGlyphId) {\n\t\t\t\tlow = mid + 1;\n\t\t\t} else if (glyphId < range.startGlyphId) {\n\t\t\t\thigh = mid - 1;\n\t\t\t} else {\n\t\t\t\t// Found - calculate coverage index\n\t\t\t\treturn range.startCoverageIndex + (glyphId - range.startGlyphId);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tcovers(glyphId: GlyphId): boolean {\n\t\treturn this.get(glyphId) !== null;\n\t}\n\n\tglyphs(): GlyphId[] {\n\t\tconst result: GlyphId[] = [];\n\t\tfor (const range of this.ranges) {\n\t\t\tfor (let g = range.startGlyphId; g <= range.endGlyphId; g++) {\n\t\t\t\tresult.push(g);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n}\n\n/** Parse a Coverage table */\nexport function parseCoverage(reader: Reader): Coverage {\n\tconst format = reader.uint16();\n\n\tif (format === 1) {\n\t\tconst glyphCount = reader.uint16();\n\t\tconst glyphArray = reader.uint16Array(glyphCount);\n\t\treturn new CoverageFormat1(glyphArray);\n\t}\n\n\tif (format === 2) {\n\t\tconst rangeCount = reader.uint16();\n\t\tconst ranges: RangeRecord[] = new Array(rangeCount);\n\n\t\tfor (let i = 0; i < rangeCount; i++) {\n\t\t\tranges[i] = {\n\t\t\t\tstartGlyphId: reader.uint16(),\n\t\t\t\tendGlyphId: reader.uint16(),\n\t\t\t\tstartCoverageIndex: reader.uint16(),\n\t\t\t};\n\t\t}\n\n\t\treturn new CoverageFormat2(ranges);\n\t}\n\n\tthrow new Error(`Unknown Coverage format: ${format}`);\n}\n\n/** Parse Coverage from offset (creates sub-reader) */\nexport function parseCoverageAt(reader: Reader, offset: number): Coverage {\n\treturn parseCoverage(reader.sliceFrom(offset));\n}\n",
27
+ "import type { Reader } from \"../../font/binary/reader.ts\";\nimport type { int16, uint16 } from \"../../types.ts\";\n\n/**\n * Device table - pixel-level adjustments for different PPEM sizes\n * Used in GPOS for fine-tuning positioning at specific sizes\n */\n\nexport interface DeviceTable {\n\tstartSize: uint16;\n\tendSize: uint16;\n\tdeltaFormat: uint16;\n\t/** Delta values indexed by (ppem - startSize) */\n\tdeltaValues: int16[];\n}\n\n/** VariationIndex table for variable fonts (shares format with Device) */\nexport interface VariationIndexTable {\n\tdeltaSetOuterIndex: uint16;\n\tdeltaSetInnerIndex: uint16;\n}\n\n/** Combined type - can be either Device or VariationIndex */\nexport type DeviceOrVariationIndex = DeviceTable | VariationIndexTable;\n\n/** Check if this is a VariationIndex table */\nexport function isVariationIndexTable(\n\ttable: DeviceOrVariationIndex,\n): table is VariationIndexTable {\n\treturn \"deltaSetOuterIndex\" in table;\n}\n\n/** Parse Device or VariationIndex table at offset */\nexport function parseDeviceAt(\n\treader: Reader,\n\toffset: number,\n): DeviceOrVariationIndex | null {\n\tif (offset === 0) return null;\n\treturn parseDevice(reader.sliceFrom(offset));\n}\n\n/** Parse Device or VariationIndex table */\nexport function parseDevice(reader: Reader): DeviceOrVariationIndex {\n\tconst startSize = reader.uint16();\n\tconst endSize = reader.uint16();\n\tconst deltaFormat = reader.uint16();\n\n\t// Format 0x8000 indicates VariationIndex table\n\tif (deltaFormat === 0x8000) {\n\t\treturn {\n\t\t\tdeltaSetOuterIndex: startSize,\n\t\t\tdeltaSetInnerIndex: endSize,\n\t\t};\n\t}\n\n\tconst deltaValues: int16[] = [];\n\n\tif (deltaFormat >= 1 && deltaFormat <= 3) {\n\t\tconst count = endSize - startSize + 1;\n\t\tconst bitsPerValue = 1 << deltaFormat; // 2, 4, or 8 bits\n\t\tconst valuesPerWord = 16 / bitsPerValue;\n\t\tconst mask = (1 << bitsPerValue) - 1;\n\t\tconst signBit = 1 << (bitsPerValue - 1);\n\n\t\tconst wordCount = Math.ceil(count / valuesPerWord);\n\t\tlet valueIndex = 0;\n\n\t\tfor (let w = 0; w < wordCount; w++) {\n\t\t\tconst word = reader.uint16();\n\n\t\t\tfor (\n\t\t\t\tlet v = 0;\n\t\t\t\tv < valuesPerWord && valueIndex < count;\n\t\t\t\tv++, valueIndex++\n\t\t\t) {\n\t\t\t\tconst shift = 16 - bitsPerValue * (v + 1);\n\t\t\t\tlet delta = (word >> shift) & mask;\n\n\t\t\t\t// Sign extend\n\t\t\t\tif (delta & signBit) {\n\t\t\t\t\tdelta = delta - (1 << bitsPerValue);\n\t\t\t\t}\n\n\t\t\t\tdeltaValues.push(delta);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tstartSize,\n\t\tendSize,\n\t\tdeltaFormat,\n\t\tdeltaValues,\n\t};\n}\n\n/**\n * Get delta adjustment for a specific PPEM size\n * Returns 0 if the size is outside the table's range\n */\nexport function getDeviceDelta(device: DeviceTable, ppem: number): int16 {\n\tif (ppem < device.startSize || ppem > device.endSize) {\n\t\treturn 0;\n\t}\n\tconst index = ppem - device.startSize;\n\treturn device.deltaValues[index] ?? 0;\n}\n\n/**\n * Apply Device table adjustment to a value\n * For variable fonts, this would need ItemVariationStore lookup instead\n */\nexport function applyDeviceAdjustment(\n\tdevice: DeviceOrVariationIndex | null,\n\tvalue: number,\n\tppem: number,\n): number {\n\tif (!device) return value;\n\n\tif (isVariationIndexTable(device)) {\n\t\t// VariationIndex tables need ItemVariationStore to resolve\n\t\t// For now, return value unchanged (proper support requires fvar integration)\n\t\treturn value;\n\t}\n\n\treturn value + getDeviceDelta(device, ppem);\n}\n\n/**\n * Parsed value record with resolved Device tables\n */\nexport interface ResolvedValueRecord {\n\txPlacement: number;\n\tyPlacement: number;\n\txAdvance: number;\n\tyAdvance: number;\n\txPlaDevice: DeviceOrVariationIndex | null;\n\tyPlaDevice: DeviceOrVariationIndex | null;\n\txAdvDevice: DeviceOrVariationIndex | null;\n\tyAdvDevice: DeviceOrVariationIndex | null;\n}\n\n/**\n * Apply all Device adjustments to a resolved value record\n */\nexport function applyDeviceAdjustments(\n\trecord: ResolvedValueRecord,\n\tppem: number,\n): {\n\txPlacement: number;\n\tyPlacement: number;\n\txAdvance: number;\n\tyAdvance: number;\n} {\n\treturn {\n\t\txPlacement: applyDeviceAdjustment(\n\t\t\trecord.xPlaDevice,\n\t\t\trecord.xPlacement,\n\t\t\tppem,\n\t\t),\n\t\tyPlacement: applyDeviceAdjustment(\n\t\t\trecord.yPlaDevice,\n\t\t\trecord.yPlacement,\n\t\t\tppem,\n\t\t),\n\t\txAdvance: applyDeviceAdjustment(record.xAdvDevice, record.xAdvance, ppem),\n\t\tyAdvance: applyDeviceAdjustment(record.yAdvDevice, record.yAdvance, ppem),\n\t};\n}\n",
28
+ "import type { Reader } from \"../../font/binary/reader.ts\";\nimport type { Tag, uint16 } from \"../../types.ts\";\n\n/** Language system record */\nexport interface LangSysRecord {\n\tlangSysTag: Tag;\n\tlangSys: LangSys;\n}\n\n/** Language system table */\nexport interface LangSys {\n\t/** Required feature index (0xFFFF if none) */\n\trequiredFeatureIndex: uint16;\n\t/** Feature indices */\n\tfeatureIndices: uint16[];\n}\n\n/** Script record */\nexport interface ScriptRecord {\n\tscriptTag: Tag;\n\tscript: Script;\n}\n\n/** Script table */\nexport interface Script {\n\t/** Default language system (may be null) */\n\tdefaultLangSys: LangSys | null;\n\t/** Language system records */\n\tlangSysRecords: LangSysRecord[];\n}\n\n/** Script list table */\nexport interface ScriptList {\n\tscripts: ScriptRecord[];\n}\n\n/** Feature record */\nexport interface FeatureRecord {\n\tfeatureTag: Tag;\n\tfeature: Feature;\n}\n\n/** Feature table */\nexport interface Feature {\n\t/** Feature parameters offset (usually 0) */\n\tfeatureParamsOffset: uint16;\n\t/** Lookup indices */\n\tlookupListIndices: uint16[];\n}\n\n/** Feature list table */\nexport interface FeatureList {\n\tfeatures: FeatureRecord[];\n}\n\n/** Lookup table header */\nexport interface LookupHeader {\n\tlookupType: uint16;\n\tlookupFlag: uint16;\n\tsubtableOffsets: uint16[];\n\t/** Mark filtering set (if UseMarkFilteringSet flag is set) */\n\tmarkFilteringSet?: uint16;\n}\n\n/** Lookup flags */\nexport const LookupFlag = {\n\tRightToLeft: 0x0001,\n\tIgnoreBaseGlyphs: 0x0002,\n\tIgnoreLigatures: 0x0004,\n\tIgnoreMarks: 0x0008,\n\tUseMarkFilteringSet: 0x0010,\n\t// Bits 5-7 reserved\n\tMarkAttachmentTypeMask: 0xff00,\n} as const;\n\n/** Extract mark attachment type from lookup flag */\nexport function getMarkAttachmentType(lookupFlag: uint16): number {\n\treturn (lookupFlag & LookupFlag.MarkAttachmentTypeMask) >> 8;\n}\n\n/** Parse ScriptList */\nexport function parseScriptList(reader: Reader): ScriptList {\n\tconst scriptCount = reader.uint16();\n\tconst scriptRecords: Array<{ tag: Tag; offset: uint16 }> = [];\n\n\tfor (let i = 0; i < scriptCount; i++) {\n\t\tscriptRecords.push({\n\t\t\ttag: reader.tag(),\n\t\t\toffset: reader.offset16(),\n\t\t});\n\t}\n\n\tconst scripts: ScriptRecord[] = [];\n\tfor (const record of scriptRecords) {\n\t\tconst scriptReader = reader.sliceFrom(record.offset);\n\t\tconst script = parseScript(scriptReader);\n\t\tscripts.push({\n\t\t\tscriptTag: record.tag,\n\t\t\tscript,\n\t\t});\n\t}\n\n\treturn { scripts };\n}\n\nfunction parseScript(reader: Reader): Script {\n\tconst defaultLangSysOffset = reader.offset16();\n\tconst langSysCount = reader.uint16();\n\n\tconst langSysRecords: Array<{ tag: Tag; offset: uint16 }> = [];\n\tfor (let i = 0; i < langSysCount; i++) {\n\t\tlangSysRecords.push({\n\t\t\ttag: reader.tag(),\n\t\t\toffset: reader.offset16(),\n\t\t});\n\t}\n\n\t// Parse default language system\n\tlet defaultLangSys: LangSys | null = null;\n\tif (defaultLangSysOffset !== 0) {\n\t\tdefaultLangSys = parseLangSys(reader.sliceFrom(defaultLangSysOffset));\n\t}\n\n\t// Parse language system records\n\tconst parsedLangSysRecords: LangSysRecord[] = [];\n\tfor (const record of langSysRecords) {\n\t\tconst langSys = parseLangSys(reader.sliceFrom(record.offset));\n\t\tparsedLangSysRecords.push({\n\t\t\tlangSysTag: record.tag,\n\t\t\tlangSys,\n\t\t});\n\t}\n\n\treturn {\n\t\tdefaultLangSys,\n\t\tlangSysRecords: parsedLangSysRecords,\n\t};\n}\n\nfunction parseLangSys(reader: Reader): LangSys {\n\tconst _lookupOrderOffset = reader.offset16(); // Reserved, always 0\n\tconst requiredFeatureIndex = reader.uint16();\n\tconst featureIndexCount = reader.uint16();\n\tconst featureIndices = Array.from(reader.uint16Array(featureIndexCount));\n\n\treturn {\n\t\trequiredFeatureIndex,\n\t\tfeatureIndices,\n\t};\n}\n\n/** Parse FeatureList */\nexport function parseFeatureList(reader: Reader): FeatureList {\n\tconst featureCount = reader.uint16();\n\tconst featureRecords: Array<{ tag: Tag; offset: uint16 }> = [];\n\n\tfor (let i = 0; i < featureCount; i++) {\n\t\tfeatureRecords.push({\n\t\t\ttag: reader.tag(),\n\t\t\toffset: reader.offset16(),\n\t\t});\n\t}\n\n\tconst features: FeatureRecord[] = [];\n\tfor (const record of featureRecords) {\n\t\tconst featureReader = reader.sliceFrom(record.offset);\n\t\tconst feature = parseFeature(featureReader);\n\t\tfeatures.push({\n\t\t\tfeatureTag: record.tag,\n\t\t\tfeature,\n\t\t});\n\t}\n\n\treturn { features };\n}\n\nfunction parseFeature(reader: Reader): Feature {\n\tconst featureParamsOffset = reader.offset16();\n\tconst lookupIndexCount = reader.uint16();\n\tconst lookupListIndices = Array.from(reader.uint16Array(lookupIndexCount));\n\n\treturn {\n\t\tfeatureParamsOffset,\n\t\tlookupListIndices,\n\t};\n}\n\n/** Parse lookup headers (does not parse subtables) */\nexport function parseLookupHeaders(reader: Reader): LookupHeader[] {\n\tconst lookupCount = reader.uint16();\n\tconst lookupOffsets = reader.uint16Array(lookupCount);\n\n\tconst headers: LookupHeader[] = [];\n\tfor (const offset of lookupOffsets) {\n\t\tconst lookupReader = reader.sliceFrom(offset);\n\t\theaders.push(parseLookupHeader(lookupReader));\n\t}\n\n\treturn headers;\n}\n\nfunction parseLookupHeader(reader: Reader): LookupHeader {\n\tconst lookupType = reader.uint16();\n\tconst lookupFlag = reader.uint16();\n\tconst subtableCount = reader.uint16();\n\tconst subtableOffsets = Array.from(reader.uint16Array(subtableCount));\n\n\tlet markFilteringSet: uint16 | undefined;\n\tif (lookupFlag & LookupFlag.UseMarkFilteringSet) {\n\t\tmarkFilteringSet = reader.uint16();\n\t}\n\n\treturn {\n\t\tlookupType,\n\t\tlookupFlag,\n\t\tsubtableOffsets,\n\t\tmarkFilteringSet,\n\t};\n}\n\n/** Find script in script list */\nexport function findScript(\n\tscriptList: ScriptList,\n\tscriptTag: Tag,\n): Script | null {\n\tfor (const record of scriptList.scripts) {\n\t\tif (record.scriptTag === scriptTag) {\n\t\t\treturn record.script;\n\t\t}\n\t}\n\treturn null;\n}\n\n/** Find language system in script */\nexport function findLangSys(\n\tscript: Script,\n\tlangSysTag: Tag | null,\n): LangSys | null {\n\tif (langSysTag === null) {\n\t\treturn script.defaultLangSys;\n\t}\n\n\tfor (const record of script.langSysRecords) {\n\t\tif (record.langSysTag === langSysTag) {\n\t\t\treturn record.langSys;\n\t\t}\n\t}\n\n\treturn script.defaultLangSys;\n}\n\n/** Get feature by index */\nexport function getFeature(\n\tfeatureList: FeatureList,\n\tindex: number,\n): FeatureRecord | null {\n\treturn featureList.features[index] ?? null;\n}\n",
29
+ "import {\n\ttype ClassDef,\n\tparseClassDefAt,\n} from \"../../layout/structures/class-def.ts\";\nimport {\n\ttype Coverage,\n\tparseCoverageAt,\n} from \"../../layout/structures/coverage.ts\";\nimport type { GlyphId, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\nimport type { GposLookup } from \"./gpos.ts\";\n\n/** Position lookup record - applies a lookup at a position */\nexport interface PosLookupRecord {\n\tsequenceIndex: uint16; // Position in input sequence\n\tlookupListIndex: uint16; // Lookup to apply\n}\n\n/** Context positioning lookup (Type 7) */\nexport interface ContextPosLookup extends GposLookup {\n\ttype: 7;\n\tsubtables: ContextPosSubtable[];\n}\n\nexport type ContextPosSubtable =\n\t| ContextPosFormat1\n\t| ContextPosFormat2\n\t| ContextPosFormat3;\n\n/** Format 1: Simple glyph contexts */\nexport interface ContextPosFormat1 {\n\tformat: 1;\n\tcoverage: Coverage;\n\truleSets: (PosContextRule[] | null)[];\n}\n\nexport interface PosContextRule {\n\tglyphCount: uint16;\n\tinputSequence: GlyphId[]; // Excludes first glyph (in coverage)\n\tlookupRecords: PosLookupRecord[];\n}\n\n/** Format 2: Class-based contexts */\nexport interface ContextPosFormat2 {\n\tformat: 2;\n\tcoverage: Coverage;\n\tclassDef: ClassDef;\n\tclassRuleSets: (PosClassRule[] | null)[];\n}\n\nexport interface PosClassRule {\n\tglyphCount: uint16;\n\tinputClasses: uint16[]; // Excludes first class\n\tlookupRecords: PosLookupRecord[];\n}\n\n/** Format 3: Coverage-based contexts */\nexport interface ContextPosFormat3 {\n\tformat: 3;\n\tcoverages: Coverage[];\n\tlookupRecords: PosLookupRecord[];\n}\n\n/** Chaining context positioning lookup (Type 8) */\nexport interface ChainingContextPosLookup extends GposLookup {\n\ttype: 8;\n\tsubtables: ChainingContextPosSubtable[];\n}\n\nexport type ChainingContextPosSubtable =\n\t| ChainingContextPosFormat1\n\t| ChainingContextPosFormat2\n\t| ChainingContextPosFormat3;\n\n/** Format 1: Simple chaining context */\nexport interface ChainingContextPosFormat1 {\n\tformat: 1;\n\tcoverage: Coverage;\n\tchainRuleSets: (PosChainRule[] | null)[];\n}\n\nexport interface PosChainRule {\n\tbacktrackSequence: GlyphId[];\n\tinputSequence: GlyphId[]; // Excludes first glyph\n\tlookaheadSequence: GlyphId[];\n\tlookupRecords: PosLookupRecord[];\n}\n\n/** Format 2: Class-based chaining context */\nexport interface ChainingContextPosFormat2 {\n\tformat: 2;\n\tcoverage: Coverage;\n\tbacktrackClassDef: ClassDef;\n\tinputClassDef: ClassDef;\n\tlookaheadClassDef: ClassDef;\n\tchainClassRuleSets: (PosChainClassRule[] | null)[];\n}\n\nexport interface PosChainClassRule {\n\tbacktrackClasses: uint16[];\n\tinputClasses: uint16[]; // Excludes first class\n\tlookaheadClasses: uint16[];\n\tlookupRecords: PosLookupRecord[];\n}\n\n/** Format 3: Coverage-based chaining context */\nexport interface ChainingContextPosFormat3 {\n\tformat: 3;\n\tbacktrackCoverages: Coverage[];\n\tinputCoverages: Coverage[];\n\tlookaheadCoverages: Coverage[];\n\tlookupRecords: PosLookupRecord[];\n}\n\nexport function parseContextPos(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): ContextPosSubtable[] {\n\tconst subtables: ContextPosSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tswitch (format) {\n\t\t\tcase 1:\n\t\t\t\tsubtables.push(parseContextPosFormat1(r));\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tsubtables.push(parseContextPosFormat2(r));\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tsubtables.push(parseContextPosFormat3(r));\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parseContextPosFormat1(reader: Reader): ContextPosFormat1 {\n\tconst coverageOffset = reader.offset16();\n\tconst ruleSetCount = reader.uint16();\n\tconst ruleSetOffsets = reader.uint16Array(ruleSetCount);\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\tconst ruleSets: (PosContextRule[] | null)[] = [];\n\n\tfor (const ruleSetOffset of ruleSetOffsets) {\n\t\tif (ruleSetOffset === 0) {\n\t\t\truleSets.push(null);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst rsReader = reader.sliceFrom(ruleSetOffset);\n\t\tconst ruleCount = rsReader.uint16();\n\t\tconst ruleOffsets = rsReader.uint16Array(ruleCount);\n\n\t\tconst rules: PosContextRule[] = [];\n\t\tfor (const ruleOffset of ruleOffsets) {\n\t\t\tconst ruleReader = rsReader.sliceFrom(ruleOffset);\n\t\t\tconst glyphCount = ruleReader.uint16();\n\t\t\tconst lookupCount = ruleReader.uint16();\n\t\t\tconst inputSequence = Array.from(ruleReader.uint16Array(glyphCount - 1));\n\t\t\tconst lookupRecords = parsePosLookupRecords(ruleReader, lookupCount);\n\n\t\t\trules.push({ glyphCount, inputSequence, lookupRecords });\n\t\t}\n\n\t\truleSets.push(rules);\n\t}\n\n\treturn { format: 1, coverage, ruleSets };\n}\n\nfunction parseContextPosFormat2(reader: Reader): ContextPosFormat2 {\n\tconst coverageOffset = reader.offset16();\n\tconst classDefOffset = reader.offset16();\n\tconst classRuleSetCount = reader.uint16();\n\tconst classRuleSetOffsets = reader.uint16Array(classRuleSetCount);\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\tconst classDef = parseClassDefAt(reader, classDefOffset);\n\tconst classRuleSets: (PosClassRule[] | null)[] = [];\n\n\tfor (const crsOffset of classRuleSetOffsets) {\n\t\tif (crsOffset === 0) {\n\t\t\tclassRuleSets.push(null);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst crsReader = reader.sliceFrom(crsOffset);\n\t\tconst ruleCount = crsReader.uint16();\n\t\tconst ruleOffsets = crsReader.uint16Array(ruleCount);\n\n\t\tconst rules: PosClassRule[] = [];\n\t\tfor (const ruleOffset of ruleOffsets) {\n\t\t\tconst ruleReader = crsReader.sliceFrom(ruleOffset);\n\t\t\tconst glyphCount = ruleReader.uint16();\n\t\t\tconst lookupCount = ruleReader.uint16();\n\t\t\tconst inputClasses = Array.from(ruleReader.uint16Array(glyphCount - 1));\n\t\t\tconst lookupRecords = parsePosLookupRecords(ruleReader, lookupCount);\n\n\t\t\trules.push({ glyphCount, inputClasses, lookupRecords });\n\t\t}\n\n\t\tclassRuleSets.push(rules);\n\t}\n\n\treturn { format: 2, coverage, classDef, classRuleSets };\n}\n\nfunction parseContextPosFormat3(reader: Reader): ContextPosFormat3 {\n\tconst glyphCount = reader.uint16();\n\tconst lookupCount = reader.uint16();\n\tconst coverageOffsets = reader.uint16Array(glyphCount);\n\n\tconst coverages: Coverage[] = [];\n\tfor (const offset of coverageOffsets) {\n\t\tcoverages.push(parseCoverageAt(reader, offset));\n\t}\n\n\tconst lookupRecords = parsePosLookupRecords(reader, lookupCount);\n\n\treturn { format: 3, coverages, lookupRecords };\n}\n\nexport function parseChainingContextPos(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): ChainingContextPosSubtable[] {\n\tconst subtables: ChainingContextPosSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tswitch (format) {\n\t\t\tcase 1:\n\t\t\t\tsubtables.push(parseChainingPosFormat1(r));\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tsubtables.push(parseChainingPosFormat2(r));\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tsubtables.push(parseChainingPosFormat3(r));\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parseChainingPosFormat1(reader: Reader): ChainingContextPosFormat1 {\n\tconst coverageOffset = reader.offset16();\n\tconst chainRuleSetCount = reader.uint16();\n\tconst chainRuleSetOffsets = reader.uint16Array(chainRuleSetCount);\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\tconst chainRuleSets: (PosChainRule[] | null)[] = [];\n\n\tfor (const crsOffset of chainRuleSetOffsets) {\n\t\tif (crsOffset === 0) {\n\t\t\tchainRuleSets.push(null);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst crsReader = reader.sliceFrom(crsOffset);\n\t\tconst ruleCount = crsReader.uint16();\n\t\tconst ruleOffsets = crsReader.uint16Array(ruleCount);\n\n\t\tconst rules: PosChainRule[] = [];\n\t\tfor (const ruleOffset of ruleOffsets) {\n\t\t\tconst ruleReader = crsReader.sliceFrom(ruleOffset);\n\n\t\t\tconst backtrackCount = ruleReader.uint16();\n\t\t\tconst backtrackSequence = Array.from(\n\t\t\t\truleReader.uint16Array(backtrackCount),\n\t\t\t);\n\n\t\t\tconst inputCount = ruleReader.uint16();\n\t\t\tconst inputSequence = Array.from(ruleReader.uint16Array(inputCount - 1));\n\n\t\t\tconst lookaheadCount = ruleReader.uint16();\n\t\t\tconst lookaheadSequence = Array.from(\n\t\t\t\truleReader.uint16Array(lookaheadCount),\n\t\t\t);\n\n\t\t\tconst lookupCount = ruleReader.uint16();\n\t\t\tconst lookupRecords = parsePosLookupRecords(ruleReader, lookupCount);\n\n\t\t\trules.push({\n\t\t\t\tbacktrackSequence,\n\t\t\t\tinputSequence,\n\t\t\t\tlookaheadSequence,\n\t\t\t\tlookupRecords,\n\t\t\t});\n\t\t}\n\n\t\tchainRuleSets.push(rules);\n\t}\n\n\treturn { format: 1, coverage, chainRuleSets };\n}\n\nfunction parseChainingPosFormat2(reader: Reader): ChainingContextPosFormat2 {\n\tconst coverageOffset = reader.offset16();\n\tconst backtrackClassDefOffset = reader.offset16();\n\tconst inputClassDefOffset = reader.offset16();\n\tconst lookaheadClassDefOffset = reader.offset16();\n\tconst chainClassRuleSetCount = reader.uint16();\n\tconst chainClassRuleSetOffsets = reader.uint16Array(chainClassRuleSetCount);\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\tconst backtrackClassDef = parseClassDefAt(reader, backtrackClassDefOffset);\n\tconst inputClassDef = parseClassDefAt(reader, inputClassDefOffset);\n\tconst lookaheadClassDef = parseClassDefAt(reader, lookaheadClassDefOffset);\n\n\tconst chainClassRuleSets: (PosChainClassRule[] | null)[] = [];\n\n\tfor (const ccrsOffset of chainClassRuleSetOffsets) {\n\t\tif (ccrsOffset === 0) {\n\t\t\tchainClassRuleSets.push(null);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst ccrsReader = reader.sliceFrom(ccrsOffset);\n\t\tconst ruleCount = ccrsReader.uint16();\n\t\tconst ruleOffsets = ccrsReader.uint16Array(ruleCount);\n\n\t\tconst rules: PosChainClassRule[] = [];\n\t\tfor (const ruleOffset of ruleOffsets) {\n\t\t\tconst ruleReader = ccrsReader.sliceFrom(ruleOffset);\n\n\t\t\tconst backtrackCount = ruleReader.uint16();\n\t\t\tconst backtrackClasses = Array.from(\n\t\t\t\truleReader.uint16Array(backtrackCount),\n\t\t\t);\n\n\t\t\tconst inputCount = ruleReader.uint16();\n\t\t\tconst inputClasses = Array.from(ruleReader.uint16Array(inputCount - 1));\n\n\t\t\tconst lookaheadCount = ruleReader.uint16();\n\t\t\tconst lookaheadClasses = Array.from(\n\t\t\t\truleReader.uint16Array(lookaheadCount),\n\t\t\t);\n\n\t\t\tconst lookupCount = ruleReader.uint16();\n\t\t\tconst lookupRecords = parsePosLookupRecords(ruleReader, lookupCount);\n\n\t\t\trules.push({\n\t\t\t\tbacktrackClasses,\n\t\t\t\tinputClasses,\n\t\t\t\tlookaheadClasses,\n\t\t\t\tlookupRecords,\n\t\t\t});\n\t\t}\n\n\t\tchainClassRuleSets.push(rules);\n\t}\n\n\treturn {\n\t\tformat: 2,\n\t\tcoverage,\n\t\tbacktrackClassDef,\n\t\tinputClassDef,\n\t\tlookaheadClassDef,\n\t\tchainClassRuleSets,\n\t};\n}\n\nfunction parseChainingPosFormat3(reader: Reader): ChainingContextPosFormat3 {\n\tconst backtrackCount = reader.uint16();\n\tconst backtrackCoverageOffsets = reader.uint16Array(backtrackCount);\n\n\tconst inputCount = reader.uint16();\n\tconst inputCoverageOffsets = reader.uint16Array(inputCount);\n\n\tconst lookaheadCount = reader.uint16();\n\tconst lookaheadCoverageOffsets = reader.uint16Array(lookaheadCount);\n\n\tconst lookupCount = reader.uint16();\n\tconst lookupRecords = parsePosLookupRecords(reader, lookupCount);\n\n\tconst backtrackCoverages: Coverage[] = [];\n\tfor (const offset of backtrackCoverageOffsets) {\n\t\tbacktrackCoverages.push(parseCoverageAt(reader, offset));\n\t}\n\n\tconst inputCoverages: Coverage[] = [];\n\tfor (const offset of inputCoverageOffsets) {\n\t\tinputCoverages.push(parseCoverageAt(reader, offset));\n\t}\n\n\tconst lookaheadCoverages: Coverage[] = [];\n\tfor (const offset of lookaheadCoverageOffsets) {\n\t\tlookaheadCoverages.push(parseCoverageAt(reader, offset));\n\t}\n\n\treturn {\n\t\tformat: 3,\n\t\tbacktrackCoverages,\n\t\tinputCoverages,\n\t\tlookaheadCoverages,\n\t\tlookupRecords,\n\t};\n}\n\nfunction parsePosLookupRecords(\n\treader: Reader,\n\tcount: number,\n): PosLookupRecord[] {\n\tconst records: PosLookupRecord[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\trecords.push({\n\t\t\tsequenceIndex: reader.uint16(),\n\t\t\tlookupListIndex: reader.uint16(),\n\t\t});\n\t}\n\treturn records;\n}\n",
30
+ "import {\n\ttype Coverage,\n\tparseCoverageAt,\n} from \"../../layout/structures/coverage.ts\";\nimport type { int16, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\nimport type { GposLookup } from \"./gpos.ts\";\n\n/** Anchor point for attachment */\nexport interface Anchor {\n\txCoordinate: int16;\n\tyCoordinate: int16;\n\t/** Contour point index (format 2) */\n\tanchorPoint?: uint16;\n\t/** Device table offsets (format 3) */\n\txDeviceOffset?: uint16;\n\tyDeviceOffset?: uint16;\n}\n\n/** Mark record */\nexport interface MarkRecord {\n\tmarkClass: uint16;\n\tmarkAnchor: Anchor;\n}\n\n/** Mark array */\nexport interface MarkArray {\n\tmarkRecords: MarkRecord[];\n}\n\n/** Base record for mark-to-base */\nexport interface BaseRecord {\n\tbaseAnchors: (Anchor | null)[]; // One per mark class\n}\n\n/** Ligature attach record */\nexport interface LigatureAttach {\n\tcomponentRecords: ComponentRecord[];\n}\n\n/** Component record for ligature */\nexport interface ComponentRecord {\n\tligatureAnchors: (Anchor | null)[]; // One per mark class\n}\n\n/** Mark2 record for mark-to-mark */\nexport interface Mark2Record {\n\tmark2Anchors: (Anchor | null)[]; // One per mark1 class\n}\n\n/** Cursive attachment lookup (Type 3) */\nexport interface CursivePosLookup extends GposLookup {\n\ttype: 3;\n\tsubtables: CursivePosSubtable[];\n}\n\nexport interface CursivePosSubtable {\n\tcoverage: Coverage;\n\tentryExitRecords: EntryExitRecord[];\n}\n\nexport interface EntryExitRecord {\n\tentryAnchor: Anchor | null;\n\texitAnchor: Anchor | null;\n}\n\n/** Mark-to-base attachment lookup (Type 4) */\nexport interface MarkBasePosLookup extends GposLookup {\n\ttype: 4;\n\tsubtables: MarkBasePosSubtable[];\n}\n\nexport interface MarkBasePosSubtable {\n\tmarkCoverage: Coverage;\n\tbaseCoverage: Coverage;\n\tmarkClassCount: uint16;\n\tmarkArray: MarkArray;\n\tbaseArray: BaseRecord[];\n}\n\n/** Mark-to-ligature attachment lookup (Type 5) */\nexport interface MarkLigaturePosLookup extends GposLookup {\n\ttype: 5;\n\tsubtables: MarkLigaturePosSubtable[];\n}\n\nexport interface MarkLigaturePosSubtable {\n\tmarkCoverage: Coverage;\n\tligatureCoverage: Coverage;\n\tmarkClassCount: uint16;\n\tmarkArray: MarkArray;\n\tligatureArray: LigatureAttach[];\n}\n\n/** Mark-to-mark attachment lookup (Type 6) */\nexport interface MarkMarkPosLookup extends GposLookup {\n\ttype: 6;\n\tsubtables: MarkMarkPosSubtable[];\n}\n\nexport interface MarkMarkPosSubtable {\n\tmark1Coverage: Coverage;\n\tmark2Coverage: Coverage;\n\tmarkClassCount: uint16;\n\tmark1Array: MarkArray;\n\tmark2Array: Mark2Record[];\n}\n\n// Parsing functions\n\nexport function parseAnchor(reader: Reader): Anchor {\n\tconst format = reader.uint16();\n\tconst xCoordinate = reader.int16();\n\tconst yCoordinate = reader.int16();\n\n\tconst anchor: Anchor = { xCoordinate, yCoordinate };\n\n\tif (format === 2) {\n\t\tanchor.anchorPoint = reader.uint16();\n\t} else if (format === 3) {\n\t\tanchor.xDeviceOffset = reader.uint16();\n\t\tanchor.yDeviceOffset = reader.uint16();\n\t}\n\n\treturn anchor;\n}\n\nexport function parseAnchorAt(reader: Reader, offset: number): Anchor | null {\n\tif (offset === 0) return null;\n\treturn parseAnchor(reader.sliceFrom(offset));\n}\n\nexport function parseMarkArray(reader: Reader): MarkArray {\n\tconst markCount = reader.uint16();\n\tconst markRecords: MarkRecord[] = [];\n\n\tconst recordData: Array<{ markClass: uint16; anchorOffset: uint16 }> = [];\n\tfor (let i = 0; i < markCount; i++) {\n\t\trecordData.push({\n\t\t\tmarkClass: reader.uint16(),\n\t\t\tanchorOffset: reader.uint16(),\n\t\t});\n\t}\n\n\tfor (const data of recordData) {\n\t\tconst markAnchor = parseAnchor(reader.sliceFrom(data.anchorOffset));\n\t\tmarkRecords.push({\n\t\t\tmarkClass: data.markClass,\n\t\t\tmarkAnchor,\n\t\t});\n\t}\n\n\treturn { markRecords };\n}\n\nexport function parseCursivePos(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): CursivePosSubtable[] {\n\tconst subtables: CursivePosSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconst coverageOffset = r.offset16();\n\t\t\tconst entryExitCount = r.uint16();\n\n\t\t\tconst entryExitData: Array<{ entryOffset: uint16; exitOffset: uint16 }> =\n\t\t\t\t[];\n\t\t\tfor (let i = 0; i < entryExitCount; i++) {\n\t\t\t\tentryExitData.push({\n\t\t\t\t\tentryOffset: r.uint16(),\n\t\t\t\t\texitOffset: r.uint16(),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst coverage = parseCoverageAt(r, coverageOffset);\n\t\t\tconst entryExitRecords: EntryExitRecord[] = [];\n\n\t\t\tfor (const data of entryExitData) {\n\t\t\t\tentryExitRecords.push({\n\t\t\t\t\tentryAnchor: parseAnchorAt(r, data.entryOffset),\n\t\t\t\t\texitAnchor: parseAnchorAt(r, data.exitOffset),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsubtables.push({ coverage, entryExitRecords });\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nexport function parseMarkBasePos(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): MarkBasePosSubtable[] {\n\tconst subtables: MarkBasePosSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconst markCoverageOffset = r.offset16();\n\t\t\tconst baseCoverageOffset = r.offset16();\n\t\t\tconst markClassCount = r.uint16();\n\t\t\tconst markArrayOffset = r.offset16();\n\t\t\tconst baseArrayOffset = r.offset16();\n\n\t\t\tconst markCoverage = parseCoverageAt(r, markCoverageOffset);\n\t\t\tconst baseCoverage = parseCoverageAt(r, baseCoverageOffset);\n\t\t\tconst markArray = parseMarkArray(r.sliceFrom(markArrayOffset));\n\n\t\t\t// Parse base array\n\t\t\tconst baseArrayReader = r.sliceFrom(baseArrayOffset);\n\t\t\tconst baseCount = baseArrayReader.uint16();\n\t\t\tconst baseArray: BaseRecord[] = [];\n\n\t\t\t// Read anchor offsets first\n\t\t\tconst baseRecordData: Array<uint16[]> = [];\n\t\t\tfor (let i = 0; i < baseCount; i++) {\n\t\t\t\tconst anchorOffsets: uint16[] = [];\n\t\t\t\tfor (let j = 0; j < markClassCount; j++) {\n\t\t\t\t\tanchorOffsets.push(baseArrayReader.uint16());\n\t\t\t\t}\n\t\t\t\tbaseRecordData.push(anchorOffsets);\n\t\t\t}\n\n\t\t\t// Parse anchors\n\t\t\tfor (const anchorOffsets of baseRecordData) {\n\t\t\t\tconst baseAnchors: (Anchor | null)[] = [];\n\t\t\t\tfor (const anchorOffset of anchorOffsets) {\n\t\t\t\t\tbaseAnchors.push(parseAnchorAt(baseArrayReader, anchorOffset));\n\t\t\t\t}\n\t\t\t\tbaseArray.push({ baseAnchors });\n\t\t\t}\n\n\t\t\tsubtables.push({\n\t\t\t\tmarkCoverage,\n\t\t\t\tbaseCoverage,\n\t\t\t\tmarkClassCount,\n\t\t\t\tmarkArray,\n\t\t\t\tbaseArray,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nexport function parseMarkLigaturePos(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): MarkLigaturePosSubtable[] {\n\tconst subtables: MarkLigaturePosSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconst markCoverageOffset = r.offset16();\n\t\t\tconst ligatureCoverageOffset = r.offset16();\n\t\t\tconst markClassCount = r.uint16();\n\t\t\tconst markArrayOffset = r.offset16();\n\t\t\tconst ligatureArrayOffset = r.offset16();\n\n\t\t\tconst markCoverage = parseCoverageAt(r, markCoverageOffset);\n\t\t\tconst ligatureCoverage = parseCoverageAt(r, ligatureCoverageOffset);\n\t\t\tconst markArray = parseMarkArray(r.sliceFrom(markArrayOffset));\n\n\t\t\t// Parse ligature array\n\t\t\tconst ligArrayReader = r.sliceFrom(ligatureArrayOffset);\n\t\t\tconst ligatureCount = ligArrayReader.uint16();\n\t\t\tconst ligatureAttachOffsets = ligArrayReader.uint16Array(ligatureCount);\n\n\t\t\tconst ligatureArray: LigatureAttach[] = [];\n\t\t\tfor (const ligAttachOffset of ligatureAttachOffsets) {\n\t\t\t\tconst ligAttachReader = ligArrayReader.sliceFrom(ligAttachOffset);\n\t\t\t\tconst componentCount = ligAttachReader.uint16();\n\n\t\t\t\tconst componentRecords: ComponentRecord[] = [];\n\t\t\t\t// Read all anchor offsets first\n\t\t\t\tconst componentData: Array<uint16[]> = [];\n\t\t\t\tfor (let i = 0; i < componentCount; i++) {\n\t\t\t\t\tconst anchorOffsets: uint16[] = [];\n\t\t\t\t\tfor (let j = 0; j < markClassCount; j++) {\n\t\t\t\t\t\tanchorOffsets.push(ligAttachReader.uint16());\n\t\t\t\t\t}\n\t\t\t\t\tcomponentData.push(anchorOffsets);\n\t\t\t\t}\n\n\t\t\t\t// Parse anchors\n\t\t\t\tfor (const anchorOffsets of componentData) {\n\t\t\t\t\tconst ligatureAnchors: (Anchor | null)[] = [];\n\t\t\t\t\tfor (const anchorOffset of anchorOffsets) {\n\t\t\t\t\t\tligatureAnchors.push(parseAnchorAt(ligAttachReader, anchorOffset));\n\t\t\t\t\t}\n\t\t\t\t\tcomponentRecords.push({ ligatureAnchors });\n\t\t\t\t}\n\n\t\t\t\tligatureArray.push({ componentRecords });\n\t\t\t}\n\n\t\t\tsubtables.push({\n\t\t\t\tmarkCoverage,\n\t\t\t\tligatureCoverage,\n\t\t\t\tmarkClassCount,\n\t\t\t\tmarkArray,\n\t\t\t\tligatureArray,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nexport function parseMarkMarkPos(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): MarkMarkPosSubtable[] {\n\tconst subtables: MarkMarkPosSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconst mark1CoverageOffset = r.offset16();\n\t\t\tconst mark2CoverageOffset = r.offset16();\n\t\t\tconst markClassCount = r.uint16();\n\t\t\tconst mark1ArrayOffset = r.offset16();\n\t\t\tconst mark2ArrayOffset = r.offset16();\n\n\t\t\tconst mark1Coverage = parseCoverageAt(r, mark1CoverageOffset);\n\t\t\tconst mark2Coverage = parseCoverageAt(r, mark2CoverageOffset);\n\t\t\tconst mark1Array = parseMarkArray(r.sliceFrom(mark1ArrayOffset));\n\n\t\t\t// Parse mark2 array\n\t\t\tconst mark2ArrayReader = r.sliceFrom(mark2ArrayOffset);\n\t\t\tconst mark2Count = mark2ArrayReader.uint16();\n\t\t\tconst mark2Array: Mark2Record[] = [];\n\n\t\t\t// Read anchor offsets\n\t\t\tconst mark2Data: Array<uint16[]> = [];\n\t\t\tfor (let i = 0; i < mark2Count; i++) {\n\t\t\t\tconst anchorOffsets: uint16[] = [];\n\t\t\t\tfor (let j = 0; j < markClassCount; j++) {\n\t\t\t\t\tanchorOffsets.push(mark2ArrayReader.uint16());\n\t\t\t\t}\n\t\t\t\tmark2Data.push(anchorOffsets);\n\t\t\t}\n\n\t\t\t// Parse anchors\n\t\t\tfor (const anchorOffsets of mark2Data) {\n\t\t\t\tconst mark2Anchors: (Anchor | null)[] = [];\n\t\t\t\tfor (const anchorOffset of anchorOffsets) {\n\t\t\t\t\tmark2Anchors.push(parseAnchorAt(mark2ArrayReader, anchorOffset));\n\t\t\t\t}\n\t\t\t\tmark2Array.push({ mark2Anchors });\n\t\t\t}\n\n\t\t\tsubtables.push({\n\t\t\t\tmark1Coverage,\n\t\t\t\tmark2Coverage,\n\t\t\t\tmarkClassCount,\n\t\t\t\tmark1Array,\n\t\t\t\tmark2Array,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn subtables;\n}\n",
31
+ "import {\n\ttype ClassDef,\n\tparseClassDefAt,\n} from \"../../layout/structures/class-def.ts\";\nimport {\n\ttype Coverage,\n\tparseCoverageAt,\n} from \"../../layout/structures/coverage.ts\";\nimport {\n\ttype DeviceOrVariationIndex,\n\tparseDeviceAt,\n} from \"../../layout/structures/device.ts\";\nimport {\n\ttype FeatureList,\n\tLookupFlag,\n\tparseFeatureList,\n\tparseScriptList,\n\ttype ScriptList,\n} from \"../../layout/structures/layout-common.ts\";\nimport type { GlyphId, int16, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\nimport {\n\ttype ChainingContextPosLookup,\n\ttype ChainingContextPosSubtable,\n\ttype ContextPosLookup,\n\ttype ContextPosSubtable,\n\tparseChainingContextPos,\n\tparseContextPos,\n} from \"./gpos-contextual.ts\";\nimport {\n\ttype CursivePosSubtable,\n\ttype MarkBasePosSubtable,\n\ttype MarkLigaturePosSubtable,\n\ttype MarkMarkPosSubtable,\n\tparseCursivePos,\n\tparseMarkBasePos,\n\tparseMarkLigaturePos,\n\tparseMarkMarkPos,\n} from \"./gpos-mark.ts\";\n\n/** GPOS lookup types */\nexport enum GposLookupType {\n\tSingle = 1,\n\tPair = 2,\n\tCursive = 3,\n\tMarkToBase = 4,\n\tMarkToLigature = 5,\n\tMarkToMark = 6,\n\tContext = 7,\n\tChainingContext = 8,\n\tExtension = 9,\n}\n\n/** Value record - positioning adjustments */\nexport interface ValueRecord {\n\txPlacement?: int16;\n\tyPlacement?: int16;\n\txAdvance?: int16;\n\tyAdvance?: int16;\n\txPlaDevice?: DeviceOrVariationIndex;\n\tyPlaDevice?: DeviceOrVariationIndex;\n\txAdvDevice?: DeviceOrVariationIndex;\n\tyAdvDevice?: DeviceOrVariationIndex;\n}\n\n/** Value format flags */\nexport const ValueFormat = {\n\tXPlacement: 0x0001,\n\tYPlacement: 0x0002,\n\tXAdvance: 0x0004,\n\tYAdvance: 0x0008,\n\tXPlaDevice: 0x0010,\n\tYPlaDevice: 0x0020,\n\tXAdvDevice: 0x0040,\n\tYAdvDevice: 0x0080,\n} as const;\n\n/** Base interface for all GPOS lookups */\nexport interface GposLookup {\n\ttype: GposLookupType;\n\tflag: uint16;\n\tmarkFilteringSet?: uint16;\n}\n\n/** Single adjustment lookup (Type 1) */\nexport interface SinglePosLookup extends GposLookup {\n\ttype: GposLookupType.Single;\n\tsubtables: SinglePosSubtable[];\n}\n\nexport interface SinglePosSubtable {\n\tformat: 1 | 2;\n\tcoverage: Coverage;\n\tvalueFormat: uint16;\n\tvalue?: ValueRecord;\n\tvalues?: ValueRecord[];\n}\n\n/** Pair adjustment lookup (Type 2) - kerning */\nexport interface PairPosLookup extends GposLookup {\n\ttype: GposLookupType.Pair;\n\tsubtables: PairPosSubtable[];\n}\n\nexport type PairPosSubtable = PairPosFormat1 | PairPosFormat2;\n\nexport interface PairPosFormat1 {\n\tformat: 1;\n\tcoverage: Coverage;\n\tvalueFormat1: uint16;\n\tvalueFormat2: uint16;\n\tpairSets: PairSet[];\n}\n\nexport interface PairSet {\n\tpairValueRecords: PairValueRecord[];\n}\n\nexport interface PairValueRecord {\n\tsecondGlyph: GlyphId;\n\tvalue1: ValueRecord;\n\tvalue2: ValueRecord;\n}\n\nexport interface PairPosFormat2 {\n\tformat: 2;\n\tcoverage: Coverage;\n\tvalueFormat1: uint16;\n\tvalueFormat2: uint16;\n\tclassDef1: ClassDef;\n\tclassDef2: ClassDef;\n\tclass1Count: uint16;\n\tclass2Count: uint16;\n\tclass1Records: Class1Record[];\n}\n\nexport interface Class1Record {\n\tclass2Records: Class2Record[];\n}\n\nexport interface Class2Record {\n\tvalue1: ValueRecord;\n\tvalue2: ValueRecord;\n}\n\n/** Cursive attachment lookup (Type 3) */\nexport interface CursivePosLookup extends GposLookup {\n\ttype: GposLookupType.Cursive;\n\tsubtables: CursivePosSubtable[];\n}\n\n/** Mark-to-base attachment lookup (Type 4) */\nexport interface MarkBasePosLookup extends GposLookup {\n\ttype: GposLookupType.MarkToBase;\n\tsubtables: MarkBasePosSubtable[];\n}\n\n/** Mark-to-ligature attachment lookup (Type 5) */\nexport interface MarkLigaturePosLookup extends GposLookup {\n\ttype: GposLookupType.MarkToLigature;\n\tsubtables: MarkLigaturePosSubtable[];\n}\n\n/** Mark-to-mark attachment lookup (Type 6) */\nexport interface MarkMarkPosLookup extends GposLookup {\n\ttype: GposLookupType.MarkToMark;\n\tsubtables: MarkMarkPosSubtable[];\n}\n\n/** Union of all GPOS lookup types */\nexport type AnyGposLookup =\n\t| SinglePosLookup\n\t| PairPosLookup\n\t| CursivePosLookup\n\t| MarkBasePosLookup\n\t| MarkLigaturePosLookup\n\t| MarkMarkPosLookup\n\t| ContextPosLookup\n\t| ChainingContextPosLookup;\n\n/** GPOS table */\nexport interface GposTable {\n\tversion: { major: number; minor: number };\n\tscriptList: ScriptList;\n\tfeatureList: FeatureList;\n\tlookups: AnyGposLookup[];\n}\n\n// Re-export mark types\nexport type { Anchor, MarkArray } from \"./gpos-mark.ts\";\n\nexport function parseGpos(reader: Reader): GposTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\n\tconst scriptListOffset = reader.offset16();\n\tconst featureListOffset = reader.offset16();\n\tconst lookupListOffset = reader.offset16();\n\n\tif (majorVersion === 1 && minorVersion >= 1) {\n\t\treader.offset32(); // featureVariationsOffset\n\t}\n\n\tconst scriptList = parseScriptList(reader.sliceFrom(scriptListOffset));\n\tconst featureList = parseFeatureList(reader.sliceFrom(featureListOffset));\n\n\tconst lookupListReader = reader.sliceFrom(lookupListOffset);\n\tconst lookupCount = lookupListReader.uint16();\n\tconst lookupOffsets = lookupListReader.uint16Array(lookupCount);\n\n\tconst lookups: AnyGposLookup[] = [];\n\tfor (const lookupOffset of lookupOffsets) {\n\t\tconst lookupReader = lookupListReader.sliceFrom(lookupOffset);\n\t\tconst lookup = parseGposLookup(lookupReader);\n\t\tif (lookup) {\n\t\t\tlookups.push(lookup);\n\t\t}\n\t}\n\n\treturn {\n\t\tversion: { major: majorVersion, minor: minorVersion },\n\t\tscriptList,\n\t\tfeatureList,\n\t\tlookups,\n\t};\n}\n\nfunction parseGposLookup(reader: Reader): AnyGposLookup | null {\n\tconst lookupType = reader.uint16();\n\tconst lookupFlag = reader.uint16();\n\tconst subtableCount = reader.uint16();\n\tconst subtableOffsets = Array.from(reader.uint16Array(subtableCount));\n\n\tlet markFilteringSet: uint16 | undefined;\n\tif (lookupFlag & LookupFlag.UseMarkFilteringSet) {\n\t\tmarkFilteringSet = reader.uint16();\n\t}\n\n\tconst baseProps = { flag: lookupFlag, markFilteringSet };\n\n\tswitch (lookupType) {\n\t\tcase GposLookupType.Single:\n\t\t\treturn {\n\t\t\t\ttype: GposLookupType.Single,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseSinglePos(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GposLookupType.Pair:\n\t\t\treturn {\n\t\t\t\ttype: GposLookupType.Pair,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parsePairPos(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GposLookupType.Cursive:\n\t\t\treturn {\n\t\t\t\ttype: GposLookupType.Cursive,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseCursivePos(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GposLookupType.MarkToBase:\n\t\t\treturn {\n\t\t\t\ttype: GposLookupType.MarkToBase,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseMarkBasePos(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GposLookupType.MarkToLigature:\n\t\t\treturn {\n\t\t\t\ttype: GposLookupType.MarkToLigature,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseMarkLigaturePos(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GposLookupType.MarkToMark:\n\t\t\treturn {\n\t\t\t\ttype: GposLookupType.MarkToMark,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseMarkMarkPos(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GposLookupType.Context:\n\t\t\treturn {\n\t\t\t\ttype: GposLookupType.Context,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseContextPos(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GposLookupType.ChainingContext:\n\t\t\treturn {\n\t\t\t\ttype: GposLookupType.ChainingContext,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseChainingContextPos(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GposLookupType.Extension:\n\t\t\treturn parseExtensionLookup(reader, subtableOffsets, baseProps);\n\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\nfunction parseValueRecord(\n\treader: Reader,\n\tvalueFormat: uint16,\n\tsubtableReader?: Reader,\n): ValueRecord {\n\tconst record: ValueRecord = {};\n\n\tif (valueFormat & ValueFormat.XPlacement) record.xPlacement = reader.int16();\n\tif (valueFormat & ValueFormat.YPlacement) record.yPlacement = reader.int16();\n\tif (valueFormat & ValueFormat.XAdvance) record.xAdvance = reader.int16();\n\tif (valueFormat & ValueFormat.YAdvance) record.yAdvance = reader.int16();\n\n\t// Parse Device tables if we have a subtable reader to resolve offsets\n\tconst deviceReader = subtableReader ?? reader;\n\tif (valueFormat & ValueFormat.XPlaDevice) {\n\t\tconst offset = reader.uint16();\n\t\tif (offset !== 0)\n\t\t\trecord.xPlaDevice = parseDeviceAt(deviceReader, offset) ?? undefined;\n\t}\n\tif (valueFormat & ValueFormat.YPlaDevice) {\n\t\tconst offset = reader.uint16();\n\t\tif (offset !== 0)\n\t\t\trecord.yPlaDevice = parseDeviceAt(deviceReader, offset) ?? undefined;\n\t}\n\tif (valueFormat & ValueFormat.XAdvDevice) {\n\t\tconst offset = reader.uint16();\n\t\tif (offset !== 0)\n\t\t\trecord.xAdvDevice = parseDeviceAt(deviceReader, offset) ?? undefined;\n\t}\n\tif (valueFormat & ValueFormat.YAdvDevice) {\n\t\tconst offset = reader.uint16();\n\t\tif (offset !== 0)\n\t\t\trecord.yAdvDevice = parseDeviceAt(deviceReader, offset) ?? undefined;\n\t}\n\n\treturn record;\n}\n\nfunction parseSinglePos(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): SinglePosSubtable[] {\n\tconst subtables: SinglePosSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst subtableReader = reader.sliceFrom(offset);\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconst coverageOffset = r.offset16();\n\t\t\tconst valueFormat = r.uint16();\n\t\t\tconst value = parseValueRecord(r, valueFormat, subtableReader);\n\t\t\tconst coverage = parseCoverageAt(subtableReader, coverageOffset);\n\t\t\tsubtables.push({ format: 1, coverage, valueFormat, value });\n\t\t} else if (format === 2) {\n\t\t\tconst coverageOffset = r.offset16();\n\t\t\tconst valueFormat = r.uint16();\n\t\t\tconst valueCount = r.uint16();\n\t\t\tconst values: ValueRecord[] = [];\n\t\t\tfor (let i = 0; i < valueCount; i++) {\n\t\t\t\tvalues.push(parseValueRecord(r, valueFormat, subtableReader));\n\t\t\t}\n\t\t\tconst coverage = parseCoverageAt(subtableReader, coverageOffset);\n\t\t\tsubtables.push({ format: 2, coverage, valueFormat, values });\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parsePairPos(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): PairPosSubtable[] {\n\tconst subtables: PairPosSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst subtableReader = reader.sliceFrom(offset);\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tsubtables.push(parsePairPosFormat1(r, subtableReader));\n\t\t} else if (format === 2) {\n\t\t\tsubtables.push(parsePairPosFormat2(r, subtableReader));\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parsePairPosFormat1(\n\treader: Reader,\n\tsubtableReader: Reader,\n): PairPosFormat1 {\n\tconst coverageOffset = reader.offset16();\n\tconst valueFormat1 = reader.uint16();\n\tconst valueFormat2 = reader.uint16();\n\tconst pairSetCount = reader.uint16();\n\tconst pairSetOffsets = reader.uint16Array(pairSetCount);\n\n\tconst coverage = parseCoverageAt(subtableReader, coverageOffset);\n\tconst pairSets: PairSet[] = [];\n\n\tfor (const pairSetOffset of pairSetOffsets) {\n\t\tconst pairSetReader = subtableReader.sliceFrom(pairSetOffset);\n\t\tconst r = subtableReader.sliceFrom(pairSetOffset);\n\t\tconst pairValueCount = r.uint16();\n\t\tconst pairValueRecords: PairValueRecord[] = [];\n\n\t\tfor (let i = 0; i < pairValueCount; i++) {\n\t\t\tconst secondGlyph = r.uint16();\n\t\t\tconst value1 = parseValueRecord(r, valueFormat1, pairSetReader);\n\t\t\tconst value2 = parseValueRecord(r, valueFormat2, pairSetReader);\n\t\t\tpairValueRecords.push({ secondGlyph, value1, value2 });\n\t\t}\n\n\t\tpairSets.push({ pairValueRecords });\n\t}\n\n\treturn { format: 1, coverage, valueFormat1, valueFormat2, pairSets };\n}\n\nfunction parsePairPosFormat2(\n\treader: Reader,\n\tsubtableReader: Reader,\n): PairPosFormat2 {\n\tconst coverageOffset = reader.offset16();\n\tconst valueFormat1 = reader.uint16();\n\tconst valueFormat2 = reader.uint16();\n\tconst classDef1Offset = reader.offset16();\n\tconst classDef2Offset = reader.offset16();\n\tconst class1Count = reader.uint16();\n\tconst class2Count = reader.uint16();\n\n\tconst coverage = parseCoverageAt(subtableReader, coverageOffset);\n\tconst classDef1 = parseClassDefAt(subtableReader, classDef1Offset);\n\tconst classDef2 = parseClassDefAt(subtableReader, classDef2Offset);\n\n\tconst class1Records: Class1Record[] = [];\n\tfor (let i = 0; i < class1Count; i++) {\n\t\tconst class2Records: Class2Record[] = [];\n\t\tfor (let j = 0; j < class2Count; j++) {\n\t\t\tconst value1 = parseValueRecord(reader, valueFormat1, subtableReader);\n\t\t\tconst value2 = parseValueRecord(reader, valueFormat2, subtableReader);\n\t\t\tclass2Records.push({ value1, value2 });\n\t\t}\n\t\tclass1Records.push({ class2Records });\n\t}\n\n\treturn {\n\t\tformat: 2,\n\t\tcoverage,\n\t\tvalueFormat1,\n\t\tvalueFormat2,\n\t\tclassDef1,\n\t\tclassDef2,\n\t\tclass1Count,\n\t\tclass2Count,\n\t\tclass1Records,\n\t};\n}\n\nfunction parseExtensionLookup(\n\treader: Reader,\n\tsubtableOffsets: number[],\n\tbaseProps: { flag: uint16; markFilteringSet?: uint16 },\n): AnyGposLookup | null {\n\tif (subtableOffsets.length === 0) return null;\n\n\tconst extSubtables: Array<{ type: number; reader: Reader }> = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst extReader = reader.sliceFrom(offset);\n\t\tconst format = extReader.uint16();\n\t\tif (format !== 1) continue;\n\n\t\tconst extensionLookupType = extReader.uint16();\n\t\tconst extensionOffset = extReader.uint32();\n\n\t\textSubtables.push({\n\t\t\ttype: extensionLookupType,\n\t\t\treader: extReader.sliceFrom(extensionOffset - 8),\n\t\t});\n\t}\n\n\tif (extSubtables.length === 0) return null;\n\n\tconst actualType = extSubtables[0]?.type;\n\n\tswitch (actualType) {\n\t\tcase GposLookupType.Single: {\n\t\t\tconst subtables: SinglePosSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseSinglePos(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GposLookupType.Single, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GposLookupType.Pair: {\n\t\t\tconst subtables: PairPosSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parsePairPos(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GposLookupType.Pair, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GposLookupType.Cursive: {\n\t\t\tconst subtables: CursivePosSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseCursivePos(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GposLookupType.Cursive, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GposLookupType.MarkToBase: {\n\t\t\tconst subtables: MarkBasePosSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseMarkBasePos(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GposLookupType.MarkToBase, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GposLookupType.MarkToLigature: {\n\t\t\tconst subtables: MarkLigaturePosSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseMarkLigaturePos(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GposLookupType.MarkToLigature, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GposLookupType.MarkToMark: {\n\t\t\tconst subtables: MarkMarkPosSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseMarkMarkPos(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GposLookupType.MarkToMark, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GposLookupType.Context: {\n\t\t\tconst subtables: ContextPosSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseContextPos(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GposLookupType.Context, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GposLookupType.ChainingContext: {\n\t\t\tconst subtables: ChainingContextPosSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseChainingContextPos(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GposLookupType.ChainingContext, ...baseProps, subtables };\n\t\t}\n\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\n// Utility functions\n\nexport function getKerning(\n\tlookup: PairPosLookup,\n\tfirstGlyph: GlyphId,\n\tsecondGlyph: GlyphId,\n): { xAdvance1: number; xAdvance2: number } | null {\n\tfor (const subtable of lookup.subtables) {\n\t\tconst coverageIndex = subtable.coverage.get(firstGlyph);\n\t\tif (coverageIndex === null) continue;\n\n\t\tif (subtable.format === 1) {\n\t\t\tconst pairSet = subtable.pairSets[coverageIndex];\n\t\t\tif (!pairSet) continue;\n\n\t\t\tfor (const record of pairSet.pairValueRecords) {\n\t\t\t\tif (record.secondGlyph === secondGlyph) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\txAdvance1: record.value1.xAdvance ?? 0,\n\t\t\t\t\t\txAdvance2: record.value2.xAdvance ?? 0,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (subtable.format === 2) {\n\t\t\tconst class1 = subtable.classDef1.get(firstGlyph);\n\t\t\tconst class2 = subtable.classDef2.get(secondGlyph);\n\n\t\t\tconst class1Record = subtable.class1Records[class1];\n\t\t\tif (!class1Record) continue;\n\n\t\t\tconst class2Record = class1Record.class2Records[class2];\n\t\t\tif (!class2Record) continue;\n\n\t\t\treturn {\n\t\t\t\txAdvance1: class2Record.value1.xAdvance ?? 0,\n\t\t\t\txAdvance2: class2Record.value2.xAdvance ?? 0,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn null;\n}\n",
32
+ "import {\n\ttype ClassDef,\n\tparseClassDefAt,\n} from \"../../layout/structures/class-def.ts\";\nimport {\n\ttype Coverage,\n\tparseCoverageAt,\n} from \"../../layout/structures/coverage.ts\";\nimport type { GlyphId, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\nimport type { GsubLookup } from \"./gsub.ts\";\n\n/** Sequence lookup record - applies a lookup at a position */\nexport interface SequenceLookupRecord {\n\tsequenceIndex: uint16; // Position in input sequence\n\tlookupListIndex: uint16; // Lookup to apply\n}\n\n/** Context substitution lookup (Type 5) */\nexport interface ContextSubstLookup extends GsubLookup {\n\ttype: 5;\n\tsubtables: ContextSubstSubtable[];\n}\n\nexport type ContextSubstSubtable =\n\t| ContextSubstFormat1\n\t| ContextSubstFormat2\n\t| ContextSubstFormat3;\n\n/** Format 1: Simple glyph contexts */\nexport interface ContextSubstFormat1 {\n\tformat: 1;\n\tcoverage: Coverage;\n\truleSets: (ContextRule[] | null)[];\n}\n\nexport interface ContextRule {\n\tglyphCount: uint16;\n\tinputSequence: GlyphId[]; // Excludes first glyph (in coverage)\n\tlookupRecords: SequenceLookupRecord[];\n}\n\n/** Format 2: Class-based contexts */\nexport interface ContextSubstFormat2 {\n\tformat: 2;\n\tcoverage: Coverage;\n\tclassDef: ClassDef;\n\tclassRuleSets: (ClassRule[] | null)[];\n}\n\nexport interface ClassRule {\n\tglyphCount: uint16;\n\tinputClasses: uint16[]; // Excludes first class\n\tlookupRecords: SequenceLookupRecord[];\n}\n\n/** Format 3: Coverage-based contexts */\nexport interface ContextSubstFormat3 {\n\tformat: 3;\n\tcoverages: Coverage[];\n\tlookupRecords: SequenceLookupRecord[];\n}\n\n/** Chaining context substitution lookup (Type 6) */\nexport interface ChainingContextSubstLookup extends GsubLookup {\n\ttype: 6;\n\tsubtables: ChainingContextSubstSubtable[];\n}\n\nexport type ChainingContextSubstSubtable =\n\t| ChainingContextFormat1\n\t| ChainingContextFormat2\n\t| ChainingContextFormat3;\n\n/** Format 1: Simple chaining context */\nexport interface ChainingContextFormat1 {\n\tformat: 1;\n\tcoverage: Coverage;\n\tchainRuleSets: (ChainRule[] | null)[];\n}\n\nexport interface ChainRule {\n\tbacktrackSequence: GlyphId[];\n\tinputSequence: GlyphId[]; // Excludes first glyph\n\tlookaheadSequence: GlyphId[];\n\tlookupRecords: SequenceLookupRecord[];\n}\n\n/** Format 2: Class-based chaining context */\nexport interface ChainingContextFormat2 {\n\tformat: 2;\n\tcoverage: Coverage;\n\tbacktrackClassDef: ClassDef;\n\tinputClassDef: ClassDef;\n\tlookaheadClassDef: ClassDef;\n\tchainClassRuleSets: (ChainClassRule[] | null)[];\n}\n\nexport interface ChainClassRule {\n\tbacktrackClasses: uint16[];\n\tinputClasses: uint16[]; // Excludes first class\n\tlookaheadClasses: uint16[];\n\tlookupRecords: SequenceLookupRecord[];\n}\n\n/** Format 3: Coverage-based chaining context */\nexport interface ChainingContextFormat3 {\n\tformat: 3;\n\tbacktrackCoverages: Coverage[];\n\tinputCoverages: Coverage[];\n\tlookaheadCoverages: Coverage[];\n\tlookupRecords: SequenceLookupRecord[];\n}\n\nexport function parseContextSubst(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): ContextSubstSubtable[] {\n\tconst subtables: ContextSubstSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tswitch (format) {\n\t\t\tcase 1:\n\t\t\t\tsubtables.push(parseContextFormat1(r));\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tsubtables.push(parseContextFormat2(r));\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tsubtables.push(parseContextFormat3(r));\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parseContextFormat1(reader: Reader): ContextSubstFormat1 {\n\tconst coverageOffset = reader.offset16();\n\tconst ruleSetCount = reader.uint16();\n\tconst ruleSetOffsets = reader.uint16Array(ruleSetCount);\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\tconst ruleSets: (ContextRule[] | null)[] = [];\n\n\tfor (const ruleSetOffset of ruleSetOffsets) {\n\t\tif (ruleSetOffset === 0) {\n\t\t\truleSets.push(null);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst rsReader = reader.sliceFrom(ruleSetOffset);\n\t\tconst ruleCount = rsReader.uint16();\n\t\tconst ruleOffsets = rsReader.uint16Array(ruleCount);\n\n\t\tconst rules: ContextRule[] = [];\n\t\tfor (const ruleOffset of ruleOffsets) {\n\t\t\tconst ruleReader = rsReader.sliceFrom(ruleOffset);\n\t\t\tconst glyphCount = ruleReader.uint16();\n\t\t\tconst lookupCount = ruleReader.uint16();\n\t\t\tconst inputSequence = Array.from(ruleReader.uint16Array(glyphCount - 1));\n\t\t\tconst lookupRecords = parseLookupRecords(ruleReader, lookupCount);\n\n\t\t\trules.push({ glyphCount, inputSequence, lookupRecords });\n\t\t}\n\n\t\truleSets.push(rules);\n\t}\n\n\treturn { format: 1, coverage, ruleSets };\n}\n\nfunction parseContextFormat2(reader: Reader): ContextSubstFormat2 {\n\tconst coverageOffset = reader.offset16();\n\tconst classDefOffset = reader.offset16();\n\tconst classRuleSetCount = reader.uint16();\n\tconst classRuleSetOffsets = reader.uint16Array(classRuleSetCount);\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\tconst classDef = parseClassDefAt(reader, classDefOffset);\n\tconst classRuleSets: (ClassRule[] | null)[] = [];\n\n\tfor (const crsOffset of classRuleSetOffsets) {\n\t\tif (crsOffset === 0) {\n\t\t\tclassRuleSets.push(null);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst crsReader = reader.sliceFrom(crsOffset);\n\t\tconst ruleCount = crsReader.uint16();\n\t\tconst ruleOffsets = crsReader.uint16Array(ruleCount);\n\n\t\tconst rules: ClassRule[] = [];\n\t\tfor (const ruleOffset of ruleOffsets) {\n\t\t\tconst ruleReader = crsReader.sliceFrom(ruleOffset);\n\t\t\tconst glyphCount = ruleReader.uint16();\n\t\t\tconst lookupCount = ruleReader.uint16();\n\t\t\tconst inputClasses = Array.from(ruleReader.uint16Array(glyphCount - 1));\n\t\t\tconst lookupRecords = parseLookupRecords(ruleReader, lookupCount);\n\n\t\t\trules.push({ glyphCount, inputClasses, lookupRecords });\n\t\t}\n\n\t\tclassRuleSets.push(rules);\n\t}\n\n\treturn { format: 2, coverage, classDef, classRuleSets };\n}\n\nfunction parseContextFormat3(reader: Reader): ContextSubstFormat3 {\n\tconst glyphCount = reader.uint16();\n\tconst lookupCount = reader.uint16();\n\tconst coverageOffsets = reader.uint16Array(glyphCount);\n\n\tconst coverages: Coverage[] = [];\n\tfor (const offset of coverageOffsets) {\n\t\tcoverages.push(parseCoverageAt(reader, offset));\n\t}\n\n\tconst lookupRecords = parseLookupRecords(reader, lookupCount);\n\n\treturn { format: 3, coverages, lookupRecords };\n}\n\nexport function parseChainingContextSubst(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): ChainingContextSubstSubtable[] {\n\tconst subtables: ChainingContextSubstSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tswitch (format) {\n\t\t\tcase 1:\n\t\t\t\tsubtables.push(parseChainingFormat1(r));\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tsubtables.push(parseChainingFormat2(r));\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tsubtables.push(parseChainingFormat3(r));\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parseChainingFormat1(reader: Reader): ChainingContextFormat1 {\n\tconst coverageOffset = reader.offset16();\n\tconst chainRuleSetCount = reader.uint16();\n\tconst chainRuleSetOffsets = reader.uint16Array(chainRuleSetCount);\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\tconst chainRuleSets: (ChainRule[] | null)[] = [];\n\n\tfor (const crsOffset of chainRuleSetOffsets) {\n\t\tif (crsOffset === 0) {\n\t\t\tchainRuleSets.push(null);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst crsReader = reader.sliceFrom(crsOffset);\n\t\tconst ruleCount = crsReader.uint16();\n\t\tconst ruleOffsets = crsReader.uint16Array(ruleCount);\n\n\t\tconst rules: ChainRule[] = [];\n\t\tfor (const ruleOffset of ruleOffsets) {\n\t\t\tconst ruleReader = crsReader.sliceFrom(ruleOffset);\n\n\t\t\tconst backtrackCount = ruleReader.uint16();\n\t\t\tconst backtrackSequence = Array.from(\n\t\t\t\truleReader.uint16Array(backtrackCount),\n\t\t\t);\n\n\t\t\tconst inputCount = ruleReader.uint16();\n\t\t\tconst inputSequence = Array.from(ruleReader.uint16Array(inputCount - 1));\n\n\t\t\tconst lookaheadCount = ruleReader.uint16();\n\t\t\tconst lookaheadSequence = Array.from(\n\t\t\t\truleReader.uint16Array(lookaheadCount),\n\t\t\t);\n\n\t\t\tconst lookupCount = ruleReader.uint16();\n\t\t\tconst lookupRecords = parseLookupRecords(ruleReader, lookupCount);\n\n\t\t\trules.push({\n\t\t\t\tbacktrackSequence,\n\t\t\t\tinputSequence,\n\t\t\t\tlookaheadSequence,\n\t\t\t\tlookupRecords,\n\t\t\t});\n\t\t}\n\n\t\tchainRuleSets.push(rules);\n\t}\n\n\treturn { format: 1, coverage, chainRuleSets };\n}\n\nfunction parseChainingFormat2(reader: Reader): ChainingContextFormat2 {\n\tconst coverageOffset = reader.offset16();\n\tconst backtrackClassDefOffset = reader.offset16();\n\tconst inputClassDefOffset = reader.offset16();\n\tconst lookaheadClassDefOffset = reader.offset16();\n\tconst chainClassRuleSetCount = reader.uint16();\n\tconst chainClassRuleSetOffsets = reader.uint16Array(chainClassRuleSetCount);\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\tconst backtrackClassDef = parseClassDefAt(reader, backtrackClassDefOffset);\n\tconst inputClassDef = parseClassDefAt(reader, inputClassDefOffset);\n\tconst lookaheadClassDef = parseClassDefAt(reader, lookaheadClassDefOffset);\n\n\tconst chainClassRuleSets: (ChainClassRule[] | null)[] = [];\n\n\tfor (const ccrsOffset of chainClassRuleSetOffsets) {\n\t\tif (ccrsOffset === 0) {\n\t\t\tchainClassRuleSets.push(null);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst ccrsReader = reader.sliceFrom(ccrsOffset);\n\t\tconst ruleCount = ccrsReader.uint16();\n\t\tconst ruleOffsets = ccrsReader.uint16Array(ruleCount);\n\n\t\tconst rules: ChainClassRule[] = [];\n\t\tfor (const ruleOffset of ruleOffsets) {\n\t\t\tconst ruleReader = ccrsReader.sliceFrom(ruleOffset);\n\n\t\t\tconst backtrackCount = ruleReader.uint16();\n\t\t\tconst backtrackClasses = Array.from(\n\t\t\t\truleReader.uint16Array(backtrackCount),\n\t\t\t);\n\n\t\t\tconst inputCount = ruleReader.uint16();\n\t\t\tconst inputClasses = Array.from(ruleReader.uint16Array(inputCount - 1));\n\n\t\t\tconst lookaheadCount = ruleReader.uint16();\n\t\t\tconst lookaheadClasses = Array.from(\n\t\t\t\truleReader.uint16Array(lookaheadCount),\n\t\t\t);\n\n\t\t\tconst lookupCount = ruleReader.uint16();\n\t\t\tconst lookupRecords = parseLookupRecords(ruleReader, lookupCount);\n\n\t\t\trules.push({\n\t\t\t\tbacktrackClasses,\n\t\t\t\tinputClasses,\n\t\t\t\tlookaheadClasses,\n\t\t\t\tlookupRecords,\n\t\t\t});\n\t\t}\n\n\t\tchainClassRuleSets.push(rules);\n\t}\n\n\treturn {\n\t\tformat: 2,\n\t\tcoverage,\n\t\tbacktrackClassDef,\n\t\tinputClassDef,\n\t\tlookaheadClassDef,\n\t\tchainClassRuleSets,\n\t};\n}\n\nfunction parseChainingFormat3(reader: Reader): ChainingContextFormat3 {\n\tconst backtrackCount = reader.uint16();\n\tconst backtrackCoverageOffsets = reader.uint16Array(backtrackCount);\n\n\tconst inputCount = reader.uint16();\n\tconst inputCoverageOffsets = reader.uint16Array(inputCount);\n\n\tconst lookaheadCount = reader.uint16();\n\tconst lookaheadCoverageOffsets = reader.uint16Array(lookaheadCount);\n\n\tconst lookupCount = reader.uint16();\n\tconst lookupRecords = parseLookupRecords(reader, lookupCount);\n\n\tconst backtrackCoverages: Coverage[] = [];\n\tfor (const offset of backtrackCoverageOffsets) {\n\t\tbacktrackCoverages.push(parseCoverageAt(reader, offset));\n\t}\n\n\tconst inputCoverages: Coverage[] = [];\n\tfor (const offset of inputCoverageOffsets) {\n\t\tinputCoverages.push(parseCoverageAt(reader, offset));\n\t}\n\n\tconst lookaheadCoverages: Coverage[] = [];\n\tfor (const offset of lookaheadCoverageOffsets) {\n\t\tlookaheadCoverages.push(parseCoverageAt(reader, offset));\n\t}\n\n\treturn {\n\t\tformat: 3,\n\t\tbacktrackCoverages,\n\t\tinputCoverages,\n\t\tlookaheadCoverages,\n\t\tlookupRecords,\n\t};\n}\n\nfunction parseLookupRecords(\n\treader: Reader,\n\tcount: number,\n): SequenceLookupRecord[] {\n\tconst records: SequenceLookupRecord[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\trecords.push({\n\t\t\tsequenceIndex: reader.uint16(),\n\t\t\tlookupListIndex: reader.uint16(),\n\t\t});\n\t}\n\treturn records;\n}\n",
33
+ "import {\n\ttype Coverage,\n\tparseCoverageAt,\n} from \"../../layout/structures/coverage.ts\";\nimport {\n\ttype FeatureList,\n\tLookupFlag,\n\tparseFeatureList,\n\tparseScriptList,\n\ttype ScriptList,\n} from \"../../layout/structures/layout-common.ts\";\nimport type { GlyphId, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\nimport {\n\ttype ChainingContextSubstSubtable,\n\ttype ContextSubstSubtable,\n\tparseChainingContextSubst,\n\tparseContextSubst,\n} from \"./gsub-contextual.ts\";\n\n/** GSUB lookup types */\nexport enum GsubLookupType {\n\tSingle = 1,\n\tMultiple = 2,\n\tAlternate = 3,\n\tLigature = 4,\n\tContext = 5,\n\tChainingContext = 6,\n\tExtension = 7,\n\tReverseChainingSingle = 8,\n}\n\n/** Base interface for all GSUB lookups */\nexport interface GsubLookup {\n\ttype: GsubLookupType;\n\tflag: uint16;\n\tmarkFilteringSet?: uint16;\n}\n\n/** Single substitution lookup (Type 1) */\nexport interface SingleSubstLookup extends GsubLookup {\n\ttype: GsubLookupType.Single;\n\tsubtables: SingleSubstSubtable[];\n}\n\nexport interface SingleSubstSubtable {\n\tformat: 1 | 2;\n\tcoverage: Coverage;\n\tdeltaGlyphId?: number;\n\tsubstituteGlyphIds?: GlyphId[];\n}\n\n/** Multiple substitution lookup (Type 2) */\nexport interface MultipleSubstLookup extends GsubLookup {\n\ttype: GsubLookupType.Multiple;\n\tsubtables: MultipleSubstSubtable[];\n}\n\nexport interface MultipleSubstSubtable {\n\tcoverage: Coverage;\n\tsequences: GlyphId[][];\n}\n\n/** Alternate substitution lookup (Type 3) */\nexport interface AlternateSubstLookup extends GsubLookup {\n\ttype: GsubLookupType.Alternate;\n\tsubtables: AlternateSubstSubtable[];\n}\n\nexport interface AlternateSubstSubtable {\n\tcoverage: Coverage;\n\talternateSets: GlyphId[][];\n}\n\n/** Ligature substitution lookup (Type 4) */\nexport interface LigatureSubstLookup extends GsubLookup {\n\ttype: GsubLookupType.Ligature;\n\tsubtables: LigatureSubstSubtable[];\n}\n\nexport interface LigatureSubstSubtable {\n\tcoverage: Coverage;\n\tligatureSets: LigatureSet[];\n}\n\nexport interface LigatureSet {\n\tligatures: Ligature[];\n}\n\nexport interface Ligature {\n\tligatureGlyph: GlyphId;\n\tcomponentGlyphIds: GlyphId[];\n}\n\n/** Context substitution lookup (Type 5) */\nexport interface ContextSubstLookup extends GsubLookup {\n\ttype: GsubLookupType.Context;\n\tsubtables: ContextSubstSubtable[];\n}\n\n/** Chaining context substitution lookup (Type 6) */\nexport interface ChainingContextSubstLookup extends GsubLookup {\n\ttype: GsubLookupType.ChainingContext;\n\tsubtables: ChainingContextSubstSubtable[];\n}\n\n/** Reverse chaining single substitution lookup (Type 8) */\nexport interface ReverseChainingSingleSubstLookup extends GsubLookup {\n\ttype: GsubLookupType.ReverseChainingSingle;\n\tsubtables: ReverseChainingSingleSubstSubtable[];\n}\n\nexport interface ReverseChainingSingleSubstSubtable {\n\tcoverage: Coverage;\n\tbacktrackCoverages: Coverage[];\n\tlookaheadCoverages: Coverage[];\n\tsubstituteGlyphIds: GlyphId[];\n}\n\n/** Union of all GSUB lookup types */\nexport type AnyGsubLookup =\n\t| SingleSubstLookup\n\t| MultipleSubstLookup\n\t| AlternateSubstLookup\n\t| LigatureSubstLookup\n\t| ContextSubstLookup\n\t| ChainingContextSubstLookup\n\t| ReverseChainingSingleSubstLookup;\n\n/** GSUB table */\nexport interface GsubTable {\n\tversion: { major: number; minor: number };\n\tscriptList: ScriptList;\n\tfeatureList: FeatureList;\n\tlookups: AnyGsubLookup[];\n}\n\n// Re-export for use in shaper\nexport type { SequenceLookupRecord } from \"./gsub-contextual.ts\";\n\nexport function parseGsub(reader: Reader): GsubTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\n\tconst scriptListOffset = reader.offset16();\n\tconst featureListOffset = reader.offset16();\n\tconst lookupListOffset = reader.offset16();\n\n\tif (majorVersion === 1 && minorVersion >= 1) {\n\t\treader.offset32(); // featureVariationsOffset\n\t}\n\n\tconst scriptList = parseScriptList(reader.sliceFrom(scriptListOffset));\n\tconst featureList = parseFeatureList(reader.sliceFrom(featureListOffset));\n\n\tconst lookupListReader = reader.sliceFrom(lookupListOffset);\n\tconst lookupCount = lookupListReader.uint16();\n\tconst lookupOffsets = lookupListReader.uint16Array(lookupCount);\n\n\tconst lookups: AnyGsubLookup[] = [];\n\tfor (const lookupOffset of lookupOffsets) {\n\t\tconst lookupReader = lookupListReader.sliceFrom(lookupOffset);\n\t\tconst lookup = parseGsubLookup(\n\t\t\tlookupReader,\n\t\t\tlookupListReader,\n\t\t\tlookupOffset,\n\t\t);\n\t\tif (lookup) {\n\t\t\tlookups.push(lookup);\n\t\t}\n\t}\n\n\treturn {\n\t\tversion: { major: majorVersion, minor: minorVersion },\n\t\tscriptList,\n\t\tfeatureList,\n\t\tlookups,\n\t};\n}\n\nfunction parseGsubLookup(\n\treader: Reader,\n\t_lookupListReader: Reader,\n\t_lookupOffset: number,\n): AnyGsubLookup | null {\n\tconst lookupType = reader.uint16();\n\tconst lookupFlag = reader.uint16();\n\tconst subtableCount = reader.uint16();\n\tconst subtableOffsets = Array.from(reader.uint16Array(subtableCount));\n\n\tlet markFilteringSet: uint16 | undefined;\n\tif (lookupFlag & LookupFlag.UseMarkFilteringSet) {\n\t\tmarkFilteringSet = reader.uint16();\n\t}\n\n\tconst baseProps = { flag: lookupFlag, markFilteringSet };\n\n\tswitch (lookupType) {\n\t\tcase GsubLookupType.Single:\n\t\t\treturn {\n\t\t\t\ttype: GsubLookupType.Single,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseSingleSubst(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GsubLookupType.Multiple:\n\t\t\treturn {\n\t\t\t\ttype: GsubLookupType.Multiple,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseMultipleSubst(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GsubLookupType.Alternate:\n\t\t\treturn {\n\t\t\t\ttype: GsubLookupType.Alternate,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseAlternateSubst(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GsubLookupType.Ligature:\n\t\t\treturn {\n\t\t\t\ttype: GsubLookupType.Ligature,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseLigatureSubst(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GsubLookupType.Context:\n\t\t\treturn {\n\t\t\t\ttype: GsubLookupType.Context,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseContextSubst(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GsubLookupType.ChainingContext:\n\t\t\treturn {\n\t\t\t\ttype: GsubLookupType.ChainingContext,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseChainingContextSubst(reader, subtableOffsets),\n\t\t\t};\n\n\t\tcase GsubLookupType.Extension:\n\t\t\treturn parseExtensionLookup(reader, subtableOffsets, baseProps);\n\n\t\tcase GsubLookupType.ReverseChainingSingle:\n\t\t\treturn {\n\t\t\t\ttype: GsubLookupType.ReverseChainingSingle,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables: parseReverseChainingSingleSubst(reader, subtableOffsets),\n\t\t\t};\n\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\nfunction parseSingleSubst(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): SingleSubstSubtable[] {\n\tconst subtables: SingleSubstSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconst coverageOffset = r.offset16();\n\t\t\tconst deltaGlyphId = r.int16();\n\t\t\tconst coverage = parseCoverageAt(r, coverageOffset);\n\t\t\tsubtables.push({ format: 1, coverage, deltaGlyphId });\n\t\t} else if (format === 2) {\n\t\t\tconst coverageOffset = r.offset16();\n\t\t\tconst glyphCount = r.uint16();\n\t\t\tconst substituteGlyphIds = Array.from(r.uint16Array(glyphCount));\n\t\t\tconst coverage = parseCoverageAt(r, coverageOffset);\n\t\t\tsubtables.push({ format: 2, coverage, substituteGlyphIds });\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parseMultipleSubst(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): MultipleSubstSubtable[] {\n\tconst subtables: MultipleSubstSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconst coverageOffset = r.offset16();\n\t\t\tconst sequenceCount = r.uint16();\n\t\t\tconst sequenceOffsets = r.uint16Array(sequenceCount);\n\n\t\t\tconst coverage = parseCoverageAt(r, coverageOffset);\n\t\t\tconst sequences: GlyphId[][] = [];\n\n\t\t\tfor (const seqOffset of sequenceOffsets) {\n\t\t\t\tconst seqReader = r.sliceFrom(seqOffset);\n\t\t\t\tconst glyphCount = seqReader.uint16();\n\t\t\t\tsequences.push(Array.from(seqReader.uint16Array(glyphCount)));\n\t\t\t}\n\n\t\t\tsubtables.push({ coverage, sequences });\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parseAlternateSubst(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): AlternateSubstSubtable[] {\n\tconst subtables: AlternateSubstSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconst coverageOffset = r.offset16();\n\t\t\tconst alternateSetCount = r.uint16();\n\t\t\tconst alternateSetOffsets = r.uint16Array(alternateSetCount);\n\n\t\t\tconst coverage = parseCoverageAt(r, coverageOffset);\n\t\t\tconst alternateSets: GlyphId[][] = [];\n\n\t\t\tfor (const altOffset of alternateSetOffsets) {\n\t\t\t\tconst altReader = r.sliceFrom(altOffset);\n\t\t\t\tconst glyphCount = altReader.uint16();\n\t\t\t\talternateSets.push(Array.from(altReader.uint16Array(glyphCount)));\n\t\t\t}\n\n\t\t\tsubtables.push({ coverage, alternateSets });\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parseLigatureSubst(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): LigatureSubstSubtable[] {\n\tconst subtables: LigatureSubstSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconst coverageOffset = r.offset16();\n\t\t\tconst ligatureSetCount = r.uint16();\n\t\t\tconst ligatureSetOffsets = r.uint16Array(ligatureSetCount);\n\n\t\t\tconst coverage = parseCoverageAt(r, coverageOffset);\n\t\t\tconst ligatureSets: LigatureSet[] = [];\n\n\t\t\tfor (const setOffset of ligatureSetOffsets) {\n\t\t\t\tconst setReader = r.sliceFrom(setOffset);\n\t\t\t\tconst ligatureCount = setReader.uint16();\n\t\t\t\tconst ligatureOffsets = setReader.uint16Array(ligatureCount);\n\n\t\t\t\tconst ligatures: Ligature[] = [];\n\t\t\t\tfor (const ligOffset of ligatureOffsets) {\n\t\t\t\t\tconst ligReader = setReader.sliceFrom(ligOffset);\n\t\t\t\t\tconst ligatureGlyph = ligReader.uint16();\n\t\t\t\t\tconst componentCount = ligReader.uint16();\n\t\t\t\t\tconst componentGlyphIds = Array.from(\n\t\t\t\t\t\tligReader.uint16Array(componentCount - 1),\n\t\t\t\t\t);\n\t\t\t\t\tligatures.push({ ligatureGlyph, componentGlyphIds });\n\t\t\t\t}\n\n\t\t\t\tligatureSets.push({ ligatures });\n\t\t\t}\n\n\t\t\tsubtables.push({ coverage, ligatureSets });\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parseReverseChainingSingleSubst(\n\treader: Reader,\n\tsubtableOffsets: number[],\n): ReverseChainingSingleSubstSubtable[] {\n\tconst subtables: ReverseChainingSingleSubstSubtable[] = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst r = reader.sliceFrom(offset);\n\t\tconst format = r.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconst coverageOffset = r.offset16();\n\n\t\t\tconst backtrackCount = r.uint16();\n\t\t\tconst backtrackCoverageOffsets = r.uint16Array(backtrackCount);\n\n\t\t\tconst lookaheadCount = r.uint16();\n\t\t\tconst lookaheadCoverageOffsets = r.uint16Array(lookaheadCount);\n\n\t\t\tconst glyphCount = r.uint16();\n\t\t\tconst substituteGlyphIds = Array.from(r.uint16Array(glyphCount));\n\n\t\t\tconst coverage = parseCoverageAt(r, coverageOffset);\n\n\t\t\tconst backtrackCoverages: Coverage[] = [];\n\t\t\tfor (const covOffset of backtrackCoverageOffsets) {\n\t\t\t\tbacktrackCoverages.push(parseCoverageAt(r, covOffset));\n\t\t\t}\n\n\t\t\tconst lookaheadCoverages: Coverage[] = [];\n\t\t\tfor (const covOffset of lookaheadCoverageOffsets) {\n\t\t\t\tlookaheadCoverages.push(parseCoverageAt(r, covOffset));\n\t\t\t}\n\n\t\t\tsubtables.push({\n\t\t\t\tcoverage,\n\t\t\t\tbacktrackCoverages,\n\t\t\t\tlookaheadCoverages,\n\t\t\t\tsubstituteGlyphIds,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn subtables;\n}\n\nfunction parseExtensionLookup(\n\treader: Reader,\n\tsubtableOffsets: number[],\n\tbaseProps: { flag: uint16; markFilteringSet?: uint16 },\n): AnyGsubLookup | null {\n\tif (subtableOffsets.length === 0) return null;\n\n\t// Parse all extension subtables\n\tconst extSubtables: Array<{ type: number; reader: Reader }> = [];\n\n\tfor (const offset of subtableOffsets) {\n\t\tconst extReader = reader.sliceFrom(offset);\n\t\tconst format = extReader.uint16();\n\t\tif (format !== 1) continue;\n\n\t\tconst extensionLookupType = extReader.uint16();\n\t\tconst extensionOffset = extReader.uint32();\n\n\t\textSubtables.push({\n\t\t\ttype: extensionLookupType,\n\t\t\treader: extReader.sliceFrom(extensionOffset - 8),\n\t\t});\n\t}\n\n\tif (extSubtables.length === 0) return null;\n\n\tconst actualType = extSubtables[0]?.type;\n\tconst _actualOffsets = extSubtables.map((_, _i) => 0); // All at offset 0 of their readers\n\n\t// Create a combined reader for all subtables\n\tswitch (actualType) {\n\t\tcase GsubLookupType.Single: {\n\t\t\tconst subtables: SingleSubstSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseSingleSubst(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GsubLookupType.Single, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GsubLookupType.Multiple: {\n\t\t\tconst subtables: MultipleSubstSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseMultipleSubst(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GsubLookupType.Multiple, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GsubLookupType.Alternate: {\n\t\t\tconst subtables: AlternateSubstSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseAlternateSubst(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GsubLookupType.Alternate, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GsubLookupType.Ligature: {\n\t\t\tconst subtables: LigatureSubstSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseLigatureSubst(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GsubLookupType.Ligature, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GsubLookupType.Context: {\n\t\t\tconst subtables: ContextSubstSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseContextSubst(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GsubLookupType.Context, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GsubLookupType.ChainingContext: {\n\t\t\tconst subtables: ChainingContextSubstSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseChainingContextSubst(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn { type: GsubLookupType.ChainingContext, ...baseProps, subtables };\n\t\t}\n\n\t\tcase GsubLookupType.ReverseChainingSingle: {\n\t\t\tconst subtables: ReverseChainingSingleSubstSubtable[] = [];\n\t\t\tfor (const ext of extSubtables) {\n\t\t\t\tsubtables.push(...parseReverseChainingSingleSubst(ext.reader, [0]));\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ttype: GsubLookupType.ReverseChainingSingle,\n\t\t\t\t...baseProps,\n\t\t\t\tsubtables,\n\t\t\t};\n\t\t}\n\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\n// Utility functions for applying lookups\n\nexport function applySingleSubst(\n\tlookup: SingleSubstLookup,\n\tglyphId: GlyphId,\n): GlyphId | null {\n\tfor (const subtable of lookup.subtables) {\n\t\tconst coverageIndex = subtable.coverage.get(glyphId);\n\t\tif (coverageIndex === null) continue;\n\n\t\tif (subtable.format === 1 && subtable.deltaGlyphId !== undefined) {\n\t\t\treturn (glyphId + subtable.deltaGlyphId) & 0xffff;\n\t\t}\n\n\t\tif (subtable.format === 2 && subtable.substituteGlyphIds) {\n\t\t\treturn subtable.substituteGlyphIds[coverageIndex] ?? null;\n\t\t}\n\t}\n\n\treturn null;\n}\n\nexport function applyLigatureSubst(\n\tlookup: LigatureSubstLookup,\n\tglyphIds: GlyphId[],\n\tstartIndex: number,\n): { ligatureGlyph: GlyphId; consumed: number } | null {\n\tconst firstGlyph = glyphIds[startIndex];\n\tif (firstGlyph === undefined) return null;\n\n\tfor (const subtable of lookup.subtables) {\n\t\tconst coverageIndex = subtable.coverage.get(firstGlyph);\n\t\tif (coverageIndex === null) continue;\n\n\t\tconst ligatureSet = subtable.ligatureSets[coverageIndex];\n\t\tif (!ligatureSet) continue;\n\n\t\tfor (const ligature of ligatureSet.ligatures) {\n\t\t\tconst componentCount = ligature.componentGlyphIds.length;\n\n\t\t\tif (startIndex + 1 + componentCount > glyphIds.length) continue;\n\n\t\t\tlet matches = true;\n\t\t\tfor (let i = 0; i < componentCount; i++) {\n\t\t\t\tif (glyphIds[startIndex + 1 + i] !== ligature.componentGlyphIds[i]) {\n\t\t\t\t\tmatches = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matches) {\n\t\t\t\treturn {\n\t\t\t\t\tligatureGlyph: ligature.ligatureGlyph,\n\t\t\t\t\tconsumed: 1 + componentCount,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n",
34
+ "import type { Fixed, FWord, int16, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\nconst HEAD_MAGIC_NUMBER = 0x5f0f3cf5;\n\n/** Font header table */\nexport interface HeadTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\tfontRevision: Fixed;\n\tchecksumAdjustment: uint32;\n\tmagicNumber: uint32;\n\tflags: uint16;\n\tunitsPerEm: uint16;\n\tcreated: bigint;\n\tmodified: bigint;\n\txMin: FWord;\n\tyMin: FWord;\n\txMax: FWord;\n\tyMax: FWord;\n\tmacStyle: uint16;\n\tlowestRecPPEM: uint16;\n\tfontDirectionHint: int16;\n\t/** 0 = short offsets (uint16), 1 = long offsets (uint32) in loca table */\n\tindexToLocFormat: int16;\n\tglyphDataFormat: int16;\n}\n\n/** Head table flags */\nexport const HeadFlags = {\n\tBaselineAtY0: 0x0001,\n\tLeftSidebearingAtX0: 0x0002,\n\tInstructionsDependOnPointSize: 0x0004,\n\tForcePPEMToInteger: 0x0008,\n\tInstructionsAlterAdvanceWidth: 0x0010,\n\tLossless: 0x0800,\n\tConverted: 0x1000,\n\tOptimizedForClearType: 0x2000,\n\tLastResortFont: 0x4000,\n} as const;\n\n/** Mac style flags */\nexport const MacStyle = {\n\tBold: 0x0001,\n\tItalic: 0x0002,\n\tUnderline: 0x0004,\n\tOutline: 0x0008,\n\tShadow: 0x0010,\n\tCondensed: 0x0020,\n\tExtended: 0x0040,\n} as const;\n\nexport function parseHead(reader: Reader): HeadTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst fontRevision = reader.fixed();\n\tconst checksumAdjustment = reader.uint32();\n\tconst magicNumber = reader.uint32();\n\n\tif (magicNumber !== HEAD_MAGIC_NUMBER) {\n\t\tthrow new Error(\n\t\t\t`Invalid head table magic number: 0x${magicNumber.toString(16)}`,\n\t\t);\n\t}\n\n\tconst flags = reader.uint16();\n\tconst unitsPerEm = reader.uint16();\n\tconst created = reader.longDateTime();\n\tconst modified = reader.longDateTime();\n\tconst xMin = reader.fword();\n\tconst yMin = reader.fword();\n\tconst xMax = reader.fword();\n\tconst yMax = reader.fword();\n\tconst macStyle = reader.uint16();\n\tconst lowestRecPPEM = reader.uint16();\n\tconst fontDirectionHint = reader.int16();\n\tconst indexToLocFormat = reader.int16();\n\tconst glyphDataFormat = reader.int16();\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\tfontRevision,\n\t\tchecksumAdjustment,\n\t\tmagicNumber,\n\t\tflags,\n\t\tunitsPerEm,\n\t\tcreated,\n\t\tmodified,\n\t\txMin,\n\t\tyMin,\n\t\txMax,\n\t\tyMax,\n\t\tmacStyle,\n\t\tlowestRecPPEM,\n\t\tfontDirectionHint,\n\t\tindexToLocFormat,\n\t\tglyphDataFormat,\n\t};\n}\n",
35
+ "import type { FWord, int16, UFWord, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/** Horizontal header table */\nexport interface HheaTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\tascender: FWord;\n\tdescender: FWord;\n\tlineGap: FWord;\n\tadvanceWidthMax: UFWord;\n\tminLeftSideBearing: FWord;\n\tminRightSideBearing: FWord;\n\txMaxExtent: FWord;\n\tcaretSlopeRise: int16;\n\tcaretSlopeRun: int16;\n\tcaretOffset: int16;\n\treserved1: int16;\n\treserved2: int16;\n\treserved3: int16;\n\treserved4: int16;\n\tmetricDataFormat: int16;\n\tnumberOfHMetrics: uint16;\n}\n\nexport function parseHhea(reader: Reader): HheaTable {\n\treturn {\n\t\tmajorVersion: reader.uint16(),\n\t\tminorVersion: reader.uint16(),\n\t\tascender: reader.fword(),\n\t\tdescender: reader.fword(),\n\t\tlineGap: reader.fword(),\n\t\tadvanceWidthMax: reader.ufword(),\n\t\tminLeftSideBearing: reader.fword(),\n\t\tminRightSideBearing: reader.fword(),\n\t\txMaxExtent: reader.fword(),\n\t\tcaretSlopeRise: reader.int16(),\n\t\tcaretSlopeRun: reader.int16(),\n\t\tcaretOffset: reader.int16(),\n\t\treserved1: reader.int16(),\n\t\treserved2: reader.int16(),\n\t\treserved3: reader.int16(),\n\t\treserved4: reader.int16(),\n\t\tmetricDataFormat: reader.int16(),\n\t\tnumberOfHMetrics: reader.uint16(),\n\t};\n}\n",
36
+ "import type { FWord, GlyphId, UFWord } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/** Horizontal metric for a glyph */\nexport interface LongHorMetric {\n\tadvanceWidth: UFWord;\n\tlsb: FWord; // left side bearing\n}\n\n/** Horizontal metrics table */\nexport interface HmtxTable {\n\thMetrics: LongHorMetric[];\n\tleftSideBearings: FWord[];\n}\n\n/**\n * Parse hmtx table.\n * @param reader - Reader positioned at hmtx table start\n * @param numberOfHMetrics - From hhea table\n * @param numGlyphs - From maxp table\n */\nexport function parseHmtx(\n\treader: Reader,\n\tnumberOfHMetrics: number,\n\tnumGlyphs: number,\n): HmtxTable {\n\t// Read full metrics (advanceWidth + lsb)\n\tconst hMetrics: LongHorMetric[] = new Array(numberOfHMetrics);\n\tfor (let i = 0; i < numberOfHMetrics; i++) {\n\t\thMetrics[i] = {\n\t\t\tadvanceWidth: reader.ufword(),\n\t\t\tlsb: reader.fword(),\n\t\t};\n\t}\n\n\t// Remaining glyphs share the last advanceWidth, only store lsb\n\tconst numLeftSideBearings = numGlyphs - numberOfHMetrics;\n\tconst leftSideBearings: FWord[] = new Array(numLeftSideBearings);\n\tfor (let i = 0; i < numLeftSideBearings; i++) {\n\t\tleftSideBearings[i] = reader.fword();\n\t}\n\n\treturn { hMetrics, leftSideBearings };\n}\n\n/** Get advance width for a glyph */\nexport function getAdvanceWidth(hmtx: HmtxTable, glyphId: GlyphId): number {\n\tif (glyphId < hmtx.hMetrics.length) {\n\t\treturn hmtx.hMetrics[glyphId]?.advanceWidth;\n\t}\n\t// Use last advanceWidth for remaining glyphs\n\treturn hmtx.hMetrics[hmtx.hMetrics.length - 1]?.advanceWidth;\n}\n\n/** Get left side bearing for a glyph */\nexport function getLeftSideBearing(hmtx: HmtxTable, glyphId: GlyphId): number {\n\tif (glyphId < hmtx.hMetrics.length) {\n\t\treturn hmtx.hMetrics[glyphId]?.lsb;\n\t}\n\tconst idx = glyphId - hmtx.hMetrics.length;\n\treturn hmtx.leftSideBearings[idx] ?? 0;\n}\n",
37
+ "import type { uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * JSTF table - Justification data\n * Provides justification alternatives for scripts\n */\n\n/** Justification priority levels */\nexport const JstfPriority = {\n\t/** Shrink GPOS lookups */\n\tShrinkGpos: 0,\n\t/** Disable GPOS lookups */\n\tDisableGpos: 1,\n\t/** Shrink GSUB lookups */\n\tShrinkGsub: 2,\n\t/** Disable GSUB lookups */\n\tDisableGsub: 3,\n\t/** Enable GPOS lookups */\n\tEnableGpos: 4,\n\t/** Enable GSUB lookups */\n\tEnableGsub: 5,\n\t/** Max extension GPOS lookups */\n\tMaxExtendGpos: 6,\n\t/** Max extension GSUB lookups */\n\tMaxExtendGsub: 7,\n} as const;\n\n/** JstfMax table - lookup indices for maximum extension */\nexport interface JstfMax {\n\tlookupIndices: uint16[];\n}\n\n/** JstfModList - enable/disable lookup list */\nexport interface JstfModList {\n\tlookupIndices: uint16[];\n}\n\n/** Justification priority record */\nexport interface JstfPriorityRecord {\n\t/** GSUB lookups to enable for shrinkage */\n\tshrinkageEnableGsub: JstfModList | null;\n\t/** GSUB lookups to disable for shrinkage */\n\tshrinkageDisableGsub: JstfModList | null;\n\t/** GPOS lookups to enable for shrinkage */\n\tshrinkageEnableGpos: JstfModList | null;\n\t/** GPOS lookups to disable for shrinkage */\n\tshrinkageDisableGpos: JstfModList | null;\n\t/** Maximum shrinkage GSUB */\n\tshrinkageJstfMax: JstfMax | null;\n\t/** GSUB lookups to enable for extension */\n\textensionEnableGsub: JstfModList | null;\n\t/** GSUB lookups to disable for extension */\n\textensionDisableGsub: JstfModList | null;\n\t/** GPOS lookups to enable for extension */\n\textensionEnableGpos: JstfModList | null;\n\t/** GPOS lookups to disable for extension */\n\textensionDisableGpos: JstfModList | null;\n\t/** Maximum extension GSUB */\n\textensionJstfMax: JstfMax | null;\n}\n\n/** Justification language system */\nexport interface JstfLangSys {\n\tpriorities: JstfPriorityRecord[];\n}\n\n/** Justification script record */\nexport interface JstfScriptRecord {\n\tscriptTag: number;\n\t/** Extender glyphs for Kashida-like justification */\n\textenderGlyphs: uint16[];\n\t/** Default language system */\n\tdefaultLangSys: JstfLangSys | null;\n\t/** Language-specific systems */\n\tlangSysRecords: Map<number, JstfLangSys>;\n}\n\n/** JSTF table */\nexport interface JstfTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\tscripts: JstfScriptRecord[];\n}\n\nfunction parseJstfModList(reader: Reader, offset: number): JstfModList | null {\n\tif (offset === 0) return null;\n\n\tconst modReader = reader.sliceFrom(offset);\n\tconst lookupCount = modReader.uint16();\n\tconst lookupIndices: uint16[] = [];\n\n\tfor (let i = 0; i < lookupCount; i++) {\n\t\tlookupIndices.push(modReader.uint16());\n\t}\n\n\treturn { lookupIndices };\n}\n\nfunction parseJstfMax(reader: Reader, offset: number): JstfMax | null {\n\tif (offset === 0) return null;\n\n\tconst maxReader = reader.sliceFrom(offset);\n\tconst lookupCount = maxReader.uint16();\n\tconst lookupIndices: uint16[] = [];\n\n\tfor (let i = 0; i < lookupCount; i++) {\n\t\tlookupIndices.push(maxReader.uint16());\n\t}\n\n\treturn { lookupIndices };\n}\n\nfunction parseJstfPriority(reader: Reader, offset: number): JstfPriorityRecord {\n\tconst priReader = reader.sliceFrom(offset);\n\n\tconst shrinkageEnableGsubOffset = priReader.uint16();\n\tconst shrinkageDisableGsubOffset = priReader.uint16();\n\tconst shrinkageEnableGposOffset = priReader.uint16();\n\tconst shrinkageDisableGposOffset = priReader.uint16();\n\tconst shrinkageJstfMaxOffset = priReader.uint16();\n\tconst extensionEnableGsubOffset = priReader.uint16();\n\tconst extensionDisableGsubOffset = priReader.uint16();\n\tconst extensionEnableGposOffset = priReader.uint16();\n\tconst extensionDisableGposOffset = priReader.uint16();\n\tconst extensionJstfMaxOffset = priReader.uint16();\n\n\treturn {\n\t\tshrinkageEnableGsub: parseJstfModList(\n\t\t\treader,\n\t\t\toffset + shrinkageEnableGsubOffset,\n\t\t),\n\t\tshrinkageDisableGsub: parseJstfModList(\n\t\t\treader,\n\t\t\toffset + shrinkageDisableGsubOffset,\n\t\t),\n\t\tshrinkageEnableGpos: parseJstfModList(\n\t\t\treader,\n\t\t\toffset + shrinkageEnableGposOffset,\n\t\t),\n\t\tshrinkageDisableGpos: parseJstfModList(\n\t\t\treader,\n\t\t\toffset + shrinkageDisableGposOffset,\n\t\t),\n\t\tshrinkageJstfMax: parseJstfMax(reader, offset + shrinkageJstfMaxOffset),\n\t\textensionEnableGsub: parseJstfModList(\n\t\t\treader,\n\t\t\toffset + extensionEnableGsubOffset,\n\t\t),\n\t\textensionDisableGsub: parseJstfModList(\n\t\t\treader,\n\t\t\toffset + extensionDisableGsubOffset,\n\t\t),\n\t\textensionEnableGpos: parseJstfModList(\n\t\t\treader,\n\t\t\toffset + extensionEnableGposOffset,\n\t\t),\n\t\textensionDisableGpos: parseJstfModList(\n\t\t\treader,\n\t\t\toffset + extensionDisableGposOffset,\n\t\t),\n\t\textensionJstfMax: parseJstfMax(reader, offset + extensionJstfMaxOffset),\n\t};\n}\n\nfunction parseJstfLangSys(reader: Reader, offset: number): JstfLangSys {\n\tconst langReader = reader.sliceFrom(offset);\n\tconst jstfPriorityCount = langReader.uint16();\n\n\tconst priorityOffsets: uint16[] = [];\n\tfor (let i = 0; i < jstfPriorityCount; i++) {\n\t\tpriorityOffsets.push(langReader.uint16());\n\t}\n\n\tconst priorities: JstfPriorityRecord[] = [];\n\tfor (const priOffset of priorityOffsets) {\n\t\tpriorities.push(parseJstfPriority(reader, offset + priOffset));\n\t}\n\n\treturn { priorities };\n}\n\nfunction parseJstfScript(\n\treader: Reader,\n\toffset: number,\n): Omit<JstfScriptRecord, \"scriptTag\"> {\n\tconst scriptReader = reader.sliceFrom(offset);\n\tconst extenderGlyphOffset = scriptReader.uint16();\n\tconst defJstfLangSysOffset = scriptReader.uint16();\n\tconst jstfLangSysCount = scriptReader.uint16();\n\n\t// Parse language system records\n\tconst langSysData: Array<{ tag: number; offset: number }> = [];\n\tfor (let i = 0; i < jstfLangSysCount; i++) {\n\t\tconst tag = scriptReader.uint32();\n\t\tconst langOffset = scriptReader.uint16();\n\t\tlangSysData.push({ tag, offset: langOffset });\n\t}\n\n\t// Parse extender glyphs\n\tconst extenderGlyphs: uint16[] = [];\n\tif (extenderGlyphOffset !== 0) {\n\t\tconst extReader = reader.sliceFrom(offset + extenderGlyphOffset);\n\t\tconst glyphCount = extReader.uint16();\n\t\tfor (let i = 0; i < glyphCount; i++) {\n\t\t\textenderGlyphs.push(extReader.uint16());\n\t\t}\n\t}\n\n\t// Parse default lang sys\n\tconst defaultLangSys =\n\t\tdefJstfLangSysOffset !== 0\n\t\t\t? parseJstfLangSys(reader, offset + defJstfLangSysOffset)\n\t\t\t: null;\n\n\t// Parse language-specific systems\n\tconst langSysRecords = new Map<number, JstfLangSys>();\n\tfor (const { tag, offset: langOffset } of langSysData) {\n\t\tlangSysRecords.set(tag, parseJstfLangSys(reader, offset + langOffset));\n\t}\n\n\treturn { extenderGlyphs, defaultLangSys, langSysRecords };\n}\n\nexport function parseJstf(reader: Reader): JstfTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst jstfScriptCount = reader.uint16();\n\n\t// Read script record offsets\n\tconst scriptData: Array<{ tag: number; offset: number }> = [];\n\tfor (let i = 0; i < jstfScriptCount; i++) {\n\t\tconst tag = reader.uint32();\n\t\tconst offset = reader.uint16();\n\t\tscriptData.push({ tag, offset });\n\t}\n\n\t// Parse scripts\n\tconst scripts: JstfScriptRecord[] = [];\n\tfor (const { tag, offset } of scriptData) {\n\t\tconst script = parseJstfScript(reader, offset);\n\t\tscripts.push({ scriptTag: tag, ...script });\n\t}\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\tscripts,\n\t};\n}\n\n/** Get extender glyphs for a script (e.g., Kashida for Arabic) */\nexport function getExtenderGlyphs(\n\tjstf: JstfTable,\n\tscriptTag: number,\n): uint16[] {\n\tconst script = jstf.scripts.find((s) => s.scriptTag === scriptTag);\n\treturn script?.extenderGlyphs ?? [];\n}\n\n/** Get justification priorities for a script/language */\nexport function getJstfPriorities(\n\tjstf: JstfTable,\n\tscriptTag: number,\n\tlanguageTag?: number,\n): JstfPriorityRecord[] {\n\tconst script = jstf.scripts.find((s) => s.scriptTag === scriptTag);\n\tif (!script) return [];\n\n\t// Try language-specific first\n\tif (languageTag !== undefined) {\n\t\tconst langSys = script.langSysRecords.get(languageTag);\n\t\tif (langSys) return langSys.priorities;\n\t}\n\n\t// Fall back to default\n\treturn script.defaultLangSys?.priorities ?? [];\n}\n\n/** Get lookup modifications for shrinkage at a given priority level */\nexport function getShrinkageMods(priority: JstfPriorityRecord): {\n\tenableGsub: uint16[];\n\tdisableGsub: uint16[];\n\tenableGpos: uint16[];\n\tdisableGpos: uint16[];\n\tmaxLookups: uint16[];\n} {\n\treturn {\n\t\tenableGsub: priority.shrinkageEnableGsub?.lookupIndices ?? [],\n\t\tdisableGsub: priority.shrinkageDisableGsub?.lookupIndices ?? [],\n\t\tenableGpos: priority.shrinkageEnableGpos?.lookupIndices ?? [],\n\t\tdisableGpos: priority.shrinkageDisableGpos?.lookupIndices ?? [],\n\t\tmaxLookups: priority.shrinkageJstfMax?.lookupIndices ?? [],\n\t};\n}\n\n/** Get lookup modifications for extension at a given priority level */\nexport function getExtensionMods(priority: JstfPriorityRecord): {\n\tenableGsub: uint16[];\n\tdisableGsub: uint16[];\n\tenableGpos: uint16[];\n\tdisableGpos: uint16[];\n\tmaxLookups: uint16[];\n} {\n\treturn {\n\t\tenableGsub: priority.extensionEnableGsub?.lookupIndices ?? [],\n\t\tdisableGsub: priority.extensionDisableGsub?.lookupIndices ?? [],\n\t\tenableGpos: priority.extensionEnableGpos?.lookupIndices ?? [],\n\t\tdisableGpos: priority.extensionDisableGpos?.lookupIndices ?? [],\n\t\tmaxLookups: priority.extensionJstfMax?.lookupIndices ?? [],\n\t};\n}\n",
38
+ "import type { GlyphId, int16, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Legacy kern table for kerning pairs\n * Used when GPOS kerning is not available\n */\nexport interface KernTable {\n\tversion: number;\n\tsubtables: KernSubtable[];\n}\n\nexport type KernSubtable = KernFormat0 | KernFormat2;\n\n/**\n * Format 0: Ordered list of kerning pairs\n */\nexport interface KernFormat0 {\n\tformat: 0;\n\tcoverage: KernCoverage;\n\tpairs: Map<number, int16>; // key = (left << 16) | right, value = kerning\n}\n\n/**\n * Format 2: Class-based kerning (two-dimensional array)\n */\nexport interface KernFormat2 {\n\tformat: 2;\n\tcoverage: KernCoverage;\n\trowWidth: uint16;\n\tleftClassTable: Map<GlyphId, uint16>;\n\trightClassTable: Map<GlyphId, uint16>;\n\tkerningValues: int16[][];\n}\n\nexport interface KernCoverage {\n\thorizontal: boolean;\n\tminimum: boolean;\n\tcrossStream: boolean;\n\toverride: boolean;\n}\n\n/**\n * Parse kern table\n */\nexport function parseKern(reader: Reader): KernTable {\n\tconst version = reader.uint16();\n\tconst subtables: KernSubtable[] = [];\n\n\tif (version === 0) {\n\t\t// Microsoft format\n\t\tconst nTables = reader.uint16();\n\t\tfor (let i = 0; i < nTables; i++) {\n\t\t\tconst subtable = parseKernSubtable(reader);\n\t\t\tif (subtable) subtables.push(subtable);\n\t\t}\n\t} else if (version === 1) {\n\t\t// Apple format (version is actually 0x00010000)\n\t\treader.skip(2); // Skip rest of version\n\t\tconst nTables = reader.uint32();\n\t\tfor (let i = 0; i < nTables; i++) {\n\t\t\tconst subtable = parseAppleKernSubtable(reader);\n\t\t\tif (subtable) subtables.push(subtable);\n\t\t}\n\t}\n\n\treturn { version, subtables };\n}\n\nfunction parseKernSubtable(reader: Reader): KernSubtable | null {\n\tconst _version = reader.uint16();\n\tconst length = reader.uint16();\n\tconst coverageBits = reader.uint16();\n\n\tconst coverage: KernCoverage = {\n\t\thorizontal: (coverageBits & 0x0001) !== 0,\n\t\tminimum: (coverageBits & 0x0002) !== 0,\n\t\tcrossStream: (coverageBits & 0x0004) !== 0,\n\t\toverride: (coverageBits & 0x0008) !== 0,\n\t};\n\n\tconst format = (coverageBits >> 8) & 0xff;\n\n\tif (format === 0) {\n\t\treturn parseKernFormat0(reader, coverage);\n\t} else if (format === 2) {\n\t\treturn parseKernFormat2(reader, coverage, length - 6);\n\t}\n\n\t// Skip unknown format\n\treader.skip(length - 6);\n\treturn null;\n}\n\nfunction parseAppleKernSubtable(reader: Reader): KernSubtable | null {\n\tconst length = reader.uint32();\n\tconst coverageBits = reader.uint16();\n\tconst _tupleIndex = reader.uint16();\n\n\tconst coverage: KernCoverage = {\n\t\thorizontal: (coverageBits & 0x8000) === 0, // bit 15: 0=horizontal\n\t\tminimum: false,\n\t\tcrossStream: (coverageBits & 0x4000) !== 0,\n\t\toverride: (coverageBits & 0x2000) !== 0,\n\t};\n\n\tconst format = coverageBits & 0x00ff;\n\n\tif (format === 0) {\n\t\treturn parseKernFormat0(reader, coverage);\n\t} else if (format === 2) {\n\t\treturn parseKernFormat2(reader, coverage, length - 8);\n\t}\n\n\t// Skip unknown format\n\treader.skip(length - 8);\n\treturn null;\n}\n\nfunction parseKernFormat0(reader: Reader, coverage: KernCoverage): KernFormat0 {\n\tconst nPairs = reader.uint16();\n\treader.skip(6); // searchRange, entrySelector, rangeShift\n\n\tconst pairs = new Map<number, int16>();\n\n\tfor (let i = 0; i < nPairs; i++) {\n\t\tconst left = reader.uint16();\n\t\tconst right = reader.uint16();\n\t\tconst value = reader.int16();\n\t\tconst key = (left << 16) | right;\n\t\tpairs.set(key, value);\n\t}\n\n\treturn { format: 0, coverage, pairs };\n}\n\nfunction parseKernFormat2(\n\treader: Reader,\n\tcoverage: KernCoverage,\n\tdataLength: number,\n): KernFormat2 {\n\tconst startOffset = reader.offset;\n\tconst rowWidth = reader.uint16();\n\tconst leftClassOffset = reader.uint16();\n\tconst rightClassOffset = reader.uint16();\n\tconst arrayOffset = reader.uint16();\n\n\t// Parse left class table\n\tconst leftClassTable = new Map<GlyphId, uint16>();\n\treader.seek(startOffset + leftClassOffset);\n\tconst leftFirstGlyph = reader.uint16();\n\tconst leftNGlyphs = reader.uint16();\n\tfor (let i = 0; i < leftNGlyphs; i++) {\n\t\tconst classValue = reader.uint16();\n\t\tif (classValue !== 0) {\n\t\t\tleftClassTable.set(leftFirstGlyph + i, classValue);\n\t\t}\n\t}\n\n\t// Parse right class table\n\tconst rightClassTable = new Map<GlyphId, uint16>();\n\treader.seek(startOffset + rightClassOffset);\n\tconst rightFirstGlyph = reader.uint16();\n\tconst rightNGlyphs = reader.uint16();\n\tfor (let i = 0; i < rightNGlyphs; i++) {\n\t\tconst classValue = reader.uint16();\n\t\tif (classValue !== 0) {\n\t\t\trightClassTable.set(rightFirstGlyph + i, classValue);\n\t\t}\n\t}\n\n\t// Parse kerning array\n\treader.seek(startOffset + arrayOffset);\n\tconst numRows = rowWidth > 0 ? Math.floor(dataLength / rowWidth) : 0;\n\tconst numCols = rowWidth / 2;\n\tconst kerningValues: int16[][] = [];\n\n\tfor (let row = 0; row < numRows; row++) {\n\t\tconst rowValues: int16[] = [];\n\t\tfor (let col = 0; col < numCols; col++) {\n\t\t\trowValues.push(reader.int16());\n\t\t}\n\t\tkerningValues.push(rowValues);\n\t}\n\n\treturn {\n\t\tformat: 2,\n\t\tcoverage,\n\t\trowWidth,\n\t\tleftClassTable,\n\t\trightClassTable,\n\t\tkerningValues,\n\t};\n}\n\n/**\n * Get kerning value from kern table\n */\nexport function getKernValue(\n\tkern: KernTable,\n\tleft: GlyphId,\n\tright: GlyphId,\n): number {\n\tlet total = 0;\n\n\tfor (const subtable of kern.subtables) {\n\t\tif (!subtable.coverage.horizontal) continue; // Only horizontal for now\n\n\t\tif (subtable.format === 0) {\n\t\t\tconst key = (left << 16) | right;\n\t\t\tconst value = subtable.pairs.get(key);\n\t\t\tif (value !== undefined) {\n\t\t\t\tif (subtable.coverage.override) {\n\t\t\t\t\ttotal = value;\n\t\t\t\t} else {\n\t\t\t\t\ttotal += value;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (subtable.format === 2) {\n\t\t\tconst leftClass = subtable.leftClassTable.get(left) ?? 0;\n\t\t\tconst rightClass = subtable.rightClassTable.get(right) ?? 0;\n\n\t\t\tif (leftClass > 0 && rightClass > 0) {\n\t\t\t\tconst rowIndex = Math.floor(leftClass / 2);\n\t\t\t\tconst colIndex = Math.floor(rightClass / 2);\n\t\t\t\tconst row = subtable.kerningValues[rowIndex];\n\t\t\t\tif (row) {\n\t\t\t\t\tconst value = row[colIndex];\n\t\t\t\t\tif (value !== undefined) {\n\t\t\t\t\t\tif (subtable.coverage.override) {\n\t\t\t\t\t\t\ttotal = value;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttotal += value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn total;\n}\n",
39
+ "import type { GlyphId, int16, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Extended Kerning table (kerx)\n * Apple Advanced Typography kerning\n */\nexport interface KerxTable {\n\tversion: uint16;\n\tnTables: uint32;\n\tsubtables: KerxSubtable[];\n}\n\n/**\n * kerx subtable types\n */\nexport enum KerxSubtableType {\n\tOrderedList = 0,\n\tStateTable = 1,\n\tSimpleArray = 2,\n\tControlPoint = 4,\n\tFormat6 = 6,\n}\n\n/**\n * Coverage flags\n */\nexport interface KerxCoverage {\n\tvertical: boolean;\n\tcrossStream: boolean;\n\tvariation: boolean;\n}\n\n/**\n * Base subtable\n */\nexport interface KerxSubtableBase {\n\tlength: uint32;\n\tcoverage: KerxCoverage;\n\ttupleCount: uint16;\n}\n\nexport type KerxSubtable =\n\t| KerxOrderedListSubtable\n\t| KerxStateTableSubtable\n\t| KerxSimpleArraySubtable\n\t| KerxControlPointSubtable\n\t| KerxFormat6Subtable;\n\n/**\n * Format 0: Ordered list of kerning pairs\n */\nexport interface KerxOrderedListSubtable extends KerxSubtableBase {\n\tformat: KerxSubtableType.OrderedList;\n\tnPairs: uint32;\n\tpairs: KerxPair[];\n}\n\nexport interface KerxPair {\n\tleft: GlyphId;\n\tright: GlyphId;\n\tvalue: int16;\n}\n\n/**\n * Format 1: State table\n */\nexport interface KerxStateTableSubtable extends KerxSubtableBase {\n\tformat: KerxSubtableType.StateTable;\n\tstateHeader: KerxStateHeader;\n\t// State machine data\n}\n\nexport interface KerxStateHeader {\n\tnClasses: uint32;\n\tclassTableOffset: uint32;\n\tstateArrayOffset: uint32;\n\tentryTableOffset: uint32;\n\tvalueTableOffset: uint32;\n}\n\n/**\n * Format 2: Simple array\n */\nexport interface KerxSimpleArraySubtable extends KerxSubtableBase {\n\tformat: KerxSubtableType.SimpleArray;\n\trowWidth: uint16;\n\tleftClassTable: KerxClassTable;\n\trightClassTable: KerxClassTable;\n\tkerningArray: Int16Array;\n}\n\nexport interface KerxClassTable {\n\tfirstGlyph: GlyphId;\n\tnGlyphs: uint16;\n\tclasses: Uint8Array;\n}\n\n/**\n * Format 4: Control point actions\n */\nexport interface KerxControlPointSubtable extends KerxSubtableBase {\n\tformat: KerxSubtableType.ControlPoint;\n\tflags: uint32;\n\t// Control point data\n}\n\n/**\n * Format 6: Extended kerning pairs\n */\nexport interface KerxFormat6Subtable extends KerxSubtableBase {\n\tformat: KerxSubtableType.Format6;\n\tflags: uint32;\n\trowCount: uint16;\n\tcolumnCount: uint16;\n\trowIndexTableOffset: uint32;\n\tcolumnIndexTableOffset: uint32;\n\tkerningArrayOffset: uint32;\n\tkerningVectorOffset: uint32;\n}\n\n/**\n * Parse kerx table\n */\nexport function parseKerx(reader: Reader): KerxTable {\n\tconst version = reader.uint16();\n\treader.skip(2); // padding\n\tconst nTables = reader.uint32();\n\n\tconst subtables: KerxSubtable[] = [];\n\n\tfor (let i = 0; i < nTables; i++) {\n\t\tconst subtable = parseKerxSubtable(reader);\n\t\tif (subtable) subtables.push(subtable);\n\t}\n\n\treturn { version, nTables, subtables };\n}\n\nfunction parseKerxSubtable(reader: Reader): KerxSubtable | null {\n\tconst length = reader.uint32();\n\tconst coverageAndFormat = reader.uint32();\n\tconst tupleCount = reader.uint16();\n\treader.skip(2); // padding\n\n\tconst format = coverageAndFormat & 0xff;\n\tconst coverage: KerxCoverage = {\n\t\tvertical: (coverageAndFormat & 0x80000000) !== 0,\n\t\tcrossStream: (coverageAndFormat & 0x40000000) !== 0,\n\t\tvariation: (coverageAndFormat & 0x20000000) !== 0,\n\t};\n\n\tconst base: KerxSubtableBase = { length, coverage, tupleCount };\n\tconst subtableEnd = reader.offset + length - 12; // Already read 12 bytes\n\n\tlet subtable: KerxSubtable | null = null;\n\n\tswitch (format) {\n\t\tcase KerxSubtableType.OrderedList:\n\t\t\tsubtable = parseKerxFormat0(reader, base);\n\t\t\tbreak;\n\t\tcase KerxSubtableType.StateTable:\n\t\t\tsubtable = parseKerxFormat1(reader, base);\n\t\t\tbreak;\n\t\tcase KerxSubtableType.SimpleArray:\n\t\t\tsubtable = parseKerxFormat2(reader, base);\n\t\t\tbreak;\n\t\tcase KerxSubtableType.Format6:\n\t\t\tsubtable = parseKerxFormat6(reader, base);\n\t\t\tbreak;\n\t}\n\n\t// Skip to end of subtable\n\treader.seek(subtableEnd);\n\n\treturn subtable;\n}\n\nfunction parseKerxFormat0(\n\treader: Reader,\n\tbase: KerxSubtableBase,\n): KerxOrderedListSubtable {\n\tconst nPairs = reader.uint32();\n\treader.skip(12); // searchRange, entrySelector, rangeShift\n\n\tconst pairs: KerxPair[] = [];\n\tfor (let i = 0; i < nPairs; i++) {\n\t\tpairs.push({\n\t\t\tleft: reader.uint16(),\n\t\t\tright: reader.uint16(),\n\t\t\tvalue: reader.int16(),\n\t\t});\n\t\treader.skip(2); // padding\n\t}\n\n\treturn {\n\t\t...base,\n\t\tformat: KerxSubtableType.OrderedList,\n\t\tnPairs,\n\t\tpairs,\n\t};\n}\n\nfunction parseKerxFormat1(\n\treader: Reader,\n\tbase: KerxSubtableBase,\n): KerxStateTableSubtable {\n\tconst stateHeader: KerxStateHeader = {\n\t\tnClasses: reader.uint32(),\n\t\tclassTableOffset: reader.offset32(),\n\t\tstateArrayOffset: reader.offset32(),\n\t\tentryTableOffset: reader.offset32(),\n\t\tvalueTableOffset: reader.offset32(),\n\t};\n\n\treturn {\n\t\t...base,\n\t\tformat: KerxSubtableType.StateTable,\n\t\tstateHeader,\n\t};\n}\n\nfunction parseKerxFormat2(\n\treader: Reader,\n\tbase: KerxSubtableBase,\n): KerxSimpleArraySubtable {\n\tconst rowWidth = reader.uint16();\n\treader.skip(2); // padding\n\n\tconst leftClassTableOffset = reader.offset32();\n\tconst rightClassTableOffset = reader.offset32();\n\tconst kerningArrayOffset = reader.offset32();\n\n\t// Parse class tables\n\tconst leftClassTable = parseKerxClassTable(\n\t\treader.sliceFrom(leftClassTableOffset),\n\t);\n\tconst rightClassTable = parseKerxClassTable(\n\t\treader.sliceFrom(rightClassTableOffset),\n\t);\n\n\t// Parse kerning array\n\tconst arrayReader = reader.sliceFrom(kerningArrayOffset);\n\tconst numRows =\n\t\tleftClassTable.nGlyphs > 0\n\t\t\t? Math.max(...Array.from(leftClassTable.classes)) + 1\n\t\t\t: 0;\n\tconst numCols = rowWidth / 2;\n\tconst kerningArray = new Int16Array(numRows * numCols);\n\n\tfor (const [i, _] of kerningArray.entries()) {\n\t\tkerningArray[i] = arrayReader.int16();\n\t}\n\n\treturn {\n\t\t...base,\n\t\tformat: KerxSubtableType.SimpleArray,\n\t\trowWidth,\n\t\tleftClassTable,\n\t\trightClassTable,\n\t\tkerningArray,\n\t};\n}\n\nfunction parseKerxClassTable(reader: Reader): KerxClassTable {\n\tconst firstGlyph = reader.uint16();\n\tconst nGlyphs = reader.uint16();\n\tconst classes = new Uint8Array(nGlyphs);\n\n\tfor (let i = 0; i < nGlyphs; i++) {\n\t\tclasses[i] = reader.uint8();\n\t}\n\n\treturn { firstGlyph, nGlyphs, classes };\n}\n\nfunction parseKerxFormat6(\n\treader: Reader,\n\tbase: KerxSubtableBase,\n): KerxFormat6Subtable {\n\tconst flags = reader.uint32();\n\tconst rowCount = reader.uint16();\n\tconst columnCount = reader.uint16();\n\tconst rowIndexTableOffset = reader.offset32();\n\tconst columnIndexTableOffset = reader.offset32();\n\tconst kerningArrayOffset = reader.offset32();\n\tconst kerningVectorOffset = reader.offset32();\n\n\treturn {\n\t\t...base,\n\t\tformat: KerxSubtableType.Format6,\n\t\tflags,\n\t\trowCount,\n\t\tcolumnCount,\n\t\trowIndexTableOffset,\n\t\tcolumnIndexTableOffset,\n\t\tkerningArrayOffset,\n\t\tkerningVectorOffset,\n\t};\n}\n\n/**\n * Get kerning value from kerx table\n */\nexport function getKerxValue(\n\tkerx: KerxTable,\n\tleft: GlyphId,\n\tright: GlyphId,\n): number {\n\tfor (const subtable of kerx.subtables) {\n\t\tif (subtable.coverage.vertical) continue; // Skip vertical kerning\n\n\t\tswitch (subtable.format) {\n\t\t\tcase KerxSubtableType.OrderedList: {\n\t\t\t\t// Binary search for the pair\n\t\t\t\tconst pairs = subtable.pairs;\n\t\t\t\tlet lo = 0;\n\t\t\t\tlet hi = pairs.length - 1;\n\n\t\t\t\twhile (lo <= hi) {\n\t\t\t\t\tconst mid = (lo + hi) >> 1;\n\t\t\t\t\tconst pair = pairs[mid];\n\t\t\t\t\tif (!pair) break;\n\n\t\t\t\t\tconst key = (pair.left << 16) | pair.right;\n\t\t\t\t\tconst target = (left << 16) | right;\n\n\t\t\t\t\tif (key === target) {\n\t\t\t\t\t\treturn pair.value;\n\t\t\t\t\t} else if (key < target) {\n\t\t\t\t\t\tlo = mid + 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\thi = mid - 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase KerxSubtableType.SimpleArray: {\n\t\t\t\tconst leftTable = subtable.leftClassTable;\n\t\t\t\tconst rightTable = subtable.rightClassTable;\n\n\t\t\t\tif (\n\t\t\t\t\tleft < leftTable.firstGlyph ||\n\t\t\t\t\tleft >= leftTable.firstGlyph + leftTable.nGlyphs\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tright < rightTable.firstGlyph ||\n\t\t\t\t\tright >= rightTable.firstGlyph + rightTable.nGlyphs\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst leftClass = leftTable.classes[left - leftTable.firstGlyph];\n\t\t\t\tconst rightClass = rightTable.classes[right - rightTable.firstGlyph];\n\t\t\t\tif (leftClass === undefined || rightClass === undefined) continue;\n\n\t\t\t\tconst numCols = subtable.rowWidth / 2;\n\t\t\t\tconst index = leftClass * numCols + rightClass;\n\n\t\t\t\tif (index < subtable.kerningArray.length) {\n\t\t\t\t\tconst value = subtable.kerningArray[index];\n\t\t\t\t\tif (value !== undefined && value !== 0) return value;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 0;\n}\n",
40
+ "import {\n\ttype Coverage,\n\tparseCoverageAt,\n} from \"../../layout/structures/coverage.ts\";\nimport {\n\ttype DeviceOrVariationIndex,\n\tparseDeviceAt,\n} from \"../../layout/structures/device.ts\";\nimport type { GlyphId, int16, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * MATH table - Mathematical typesetting data\n * Provides metrics and glyph information for math layout\n */\n\n/** MathValueRecord - value with optional device correction */\nexport interface MathValueRecord {\n\tvalue: int16;\n\tdevice: DeviceOrVariationIndex | null;\n}\n\n/** MathConstants - global math constants */\nexport interface MathConstants {\n\tscriptPercentScaleDown: int16;\n\tscriptScriptPercentScaleDown: int16;\n\tdelimitedSubFormulaMinHeight: uint16;\n\tdisplayOperatorMinHeight: uint16;\n\tmathLeading: MathValueRecord;\n\taxisHeight: MathValueRecord;\n\taccentBaseHeight: MathValueRecord;\n\tflattenedAccentBaseHeight: MathValueRecord;\n\tsubscriptShiftDown: MathValueRecord;\n\tsubscriptTopMax: MathValueRecord;\n\tsubscriptBaselineDropMin: MathValueRecord;\n\tsuperscriptShiftUp: MathValueRecord;\n\tsuperscriptShiftUpCramped: MathValueRecord;\n\tsuperscriptBottomMin: MathValueRecord;\n\tsuperscriptBaselineDropMax: MathValueRecord;\n\tsubSuperscriptGapMin: MathValueRecord;\n\tsuperscriptBottomMaxWithSubscript: MathValueRecord;\n\tspaceAfterScript: MathValueRecord;\n\tupperLimitGapMin: MathValueRecord;\n\tupperLimitBaselineRiseMin: MathValueRecord;\n\tlowerLimitGapMin: MathValueRecord;\n\tlowerLimitBaselineDropMin: MathValueRecord;\n\tstackTopShiftUp: MathValueRecord;\n\tstackTopDisplayStyleShiftUp: MathValueRecord;\n\tstackBottomShiftDown: MathValueRecord;\n\tstackBottomDisplayStyleShiftDown: MathValueRecord;\n\tstackGapMin: MathValueRecord;\n\tstackDisplayStyleGapMin: MathValueRecord;\n\tstretchStackTopShiftUp: MathValueRecord;\n\tstretchStackBottomShiftDown: MathValueRecord;\n\tstretchStackGapAboveMin: MathValueRecord;\n\tstretchStackGapBelowMin: MathValueRecord;\n\tfractionNumeratorShiftUp: MathValueRecord;\n\tfractionNumeratorDisplayStyleShiftUp: MathValueRecord;\n\tfractionDenominatorShiftDown: MathValueRecord;\n\tfractionDenominatorDisplayStyleShiftDown: MathValueRecord;\n\tfractionNumeratorGapMin: MathValueRecord;\n\tfractionNumDisplayStyleGapMin: MathValueRecord;\n\tfractionRuleThickness: MathValueRecord;\n\tfractionDenominatorGapMin: MathValueRecord;\n\tfractionDenomDisplayStyleGapMin: MathValueRecord;\n\tskewedFractionHorizontalGap: MathValueRecord;\n\tskewedFractionVerticalGap: MathValueRecord;\n\toverbarVerticalGap: MathValueRecord;\n\toverbarRuleThickness: MathValueRecord;\n\toverbarExtraAscender: MathValueRecord;\n\tunderbarVerticalGap: MathValueRecord;\n\tunderbarRuleThickness: MathValueRecord;\n\tunderbarExtraDescender: MathValueRecord;\n\tradicalVerticalGap: MathValueRecord;\n\tradicalDisplayStyleVerticalGap: MathValueRecord;\n\tradicalRuleThickness: MathValueRecord;\n\tradicalExtraAscender: MathValueRecord;\n\tradicalKernBeforeDegree: MathValueRecord;\n\tradicalKernAfterDegree: MathValueRecord;\n\tradicalDegreeBottomRaisePercent: int16;\n}\n\n/** Italic correction info */\nexport interface MathItalicsCorrection {\n\tcoverage: Coverage;\n\tvalues: MathValueRecord[];\n}\n\n/** Top accent attachment */\nexport interface MathTopAccentAttachment {\n\tcoverage: Coverage;\n\tvalues: MathValueRecord[];\n}\n\n/** Extended shape coverage */\nexport interface ExtendedShapeCoverage {\n\tcoverage: Coverage;\n}\n\n/** Math kern record for corner kerns */\nexport interface MathKernRecord {\n\tcorrectionHeights: MathValueRecord[];\n\tkernValues: MathValueRecord[];\n}\n\n/** Math kern info for a glyph */\nexport interface MathKernInfo {\n\ttopRight: MathKernRecord | null;\n\ttopLeft: MathKernRecord | null;\n\tbottomRight: MathKernRecord | null;\n\tbottomLeft: MathKernRecord | null;\n}\n\n/** Math kern info table */\nexport interface MathKernInfoTable {\n\tcoverage: Coverage;\n\tkernInfo: MathKernInfo[];\n}\n\n/** MathGlyphInfo - per-glyph math info */\nexport interface MathGlyphInfo {\n\titalicsCorrection: MathItalicsCorrection | null;\n\ttopAccentAttachment: MathTopAccentAttachment | null;\n\textendedShapeCoverage: ExtendedShapeCoverage | null;\n\tkernInfo: MathKernInfoTable | null;\n}\n\n/** Glyph part record for assembly */\nexport interface GlyphPartRecord {\n\tglyphId: GlyphId;\n\tstartConnectorLength: uint16;\n\tendConnectorLength: uint16;\n\tfullAdvance: uint16;\n\tpartFlags: uint16;\n}\n\n/** Glyph assembly */\nexport interface GlyphAssembly {\n\titalicsCorrection: MathValueRecord;\n\tparts: GlyphPartRecord[];\n}\n\n/** Math glyph construction */\nexport interface MathGlyphConstruction {\n\tglyphAssembly: GlyphAssembly | null;\n\tvariants: Array<{ variantGlyph: GlyphId; advanceMeasurement: uint16 }>;\n}\n\n/** MathVariants - glyph variants and construction */\nexport interface MathVariants {\n\tminConnectorOverlap: uint16;\n\tvertGlyphCoverage: Coverage | null;\n\thorizGlyphCoverage: Coverage | null;\n\tvertGlyphConstruction: MathGlyphConstruction[];\n\thorizGlyphConstruction: MathGlyphConstruction[];\n}\n\n/** MATH table */\nexport interface MathTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\tconstants: MathConstants | null;\n\tglyphInfo: MathGlyphInfo | null;\n\tvariants: MathVariants | null;\n}\n\nfunction parseMathValueRecord(\n\treader: Reader,\n\ttableReader: Reader,\n): MathValueRecord {\n\tconst value = reader.int16();\n\tconst deviceOffset = reader.uint16();\n\treturn {\n\t\tvalue,\n\t\tdevice: parseDeviceAt(tableReader, deviceOffset),\n\t};\n}\n\nfunction parseMathConstants(reader: Reader): MathConstants {\n\tconst tableReader = reader;\n\tconst scriptPercentScaleDown = reader.int16();\n\tconst scriptScriptPercentScaleDown = reader.int16();\n\tconst delimitedSubFormulaMinHeight = reader.uint16();\n\tconst displayOperatorMinHeight = reader.uint16();\n\n\treturn {\n\t\tscriptPercentScaleDown,\n\t\tscriptScriptPercentScaleDown,\n\t\tdelimitedSubFormulaMinHeight,\n\t\tdisplayOperatorMinHeight,\n\t\tmathLeading: parseMathValueRecord(reader, tableReader),\n\t\taxisHeight: parseMathValueRecord(reader, tableReader),\n\t\taccentBaseHeight: parseMathValueRecord(reader, tableReader),\n\t\tflattenedAccentBaseHeight: parseMathValueRecord(reader, tableReader),\n\t\tsubscriptShiftDown: parseMathValueRecord(reader, tableReader),\n\t\tsubscriptTopMax: parseMathValueRecord(reader, tableReader),\n\t\tsubscriptBaselineDropMin: parseMathValueRecord(reader, tableReader),\n\t\tsuperscriptShiftUp: parseMathValueRecord(reader, tableReader),\n\t\tsuperscriptShiftUpCramped: parseMathValueRecord(reader, tableReader),\n\t\tsuperscriptBottomMin: parseMathValueRecord(reader, tableReader),\n\t\tsuperscriptBaselineDropMax: parseMathValueRecord(reader, tableReader),\n\t\tsubSuperscriptGapMin: parseMathValueRecord(reader, tableReader),\n\t\tsuperscriptBottomMaxWithSubscript: parseMathValueRecord(\n\t\t\treader,\n\t\t\ttableReader,\n\t\t),\n\t\tspaceAfterScript: parseMathValueRecord(reader, tableReader),\n\t\tupperLimitGapMin: parseMathValueRecord(reader, tableReader),\n\t\tupperLimitBaselineRiseMin: parseMathValueRecord(reader, tableReader),\n\t\tlowerLimitGapMin: parseMathValueRecord(reader, tableReader),\n\t\tlowerLimitBaselineDropMin: parseMathValueRecord(reader, tableReader),\n\t\tstackTopShiftUp: parseMathValueRecord(reader, tableReader),\n\t\tstackTopDisplayStyleShiftUp: parseMathValueRecord(reader, tableReader),\n\t\tstackBottomShiftDown: parseMathValueRecord(reader, tableReader),\n\t\tstackBottomDisplayStyleShiftDown: parseMathValueRecord(reader, tableReader),\n\t\tstackGapMin: parseMathValueRecord(reader, tableReader),\n\t\tstackDisplayStyleGapMin: parseMathValueRecord(reader, tableReader),\n\t\tstretchStackTopShiftUp: parseMathValueRecord(reader, tableReader),\n\t\tstretchStackBottomShiftDown: parseMathValueRecord(reader, tableReader),\n\t\tstretchStackGapAboveMin: parseMathValueRecord(reader, tableReader),\n\t\tstretchStackGapBelowMin: parseMathValueRecord(reader, tableReader),\n\t\tfractionNumeratorShiftUp: parseMathValueRecord(reader, tableReader),\n\t\tfractionNumeratorDisplayStyleShiftUp: parseMathValueRecord(\n\t\t\treader,\n\t\t\ttableReader,\n\t\t),\n\t\tfractionDenominatorShiftDown: parseMathValueRecord(reader, tableReader),\n\t\tfractionDenominatorDisplayStyleShiftDown: parseMathValueRecord(\n\t\t\treader,\n\t\t\ttableReader,\n\t\t),\n\t\tfractionNumeratorGapMin: parseMathValueRecord(reader, tableReader),\n\t\tfractionNumDisplayStyleGapMin: parseMathValueRecord(reader, tableReader),\n\t\tfractionRuleThickness: parseMathValueRecord(reader, tableReader),\n\t\tfractionDenominatorGapMin: parseMathValueRecord(reader, tableReader),\n\t\tfractionDenomDisplayStyleGapMin: parseMathValueRecord(reader, tableReader),\n\t\tskewedFractionHorizontalGap: parseMathValueRecord(reader, tableReader),\n\t\tskewedFractionVerticalGap: parseMathValueRecord(reader, tableReader),\n\t\toverbarVerticalGap: parseMathValueRecord(reader, tableReader),\n\t\toverbarRuleThickness: parseMathValueRecord(reader, tableReader),\n\t\toverbarExtraAscender: parseMathValueRecord(reader, tableReader),\n\t\tunderbarVerticalGap: parseMathValueRecord(reader, tableReader),\n\t\tunderbarRuleThickness: parseMathValueRecord(reader, tableReader),\n\t\tunderbarExtraDescender: parseMathValueRecord(reader, tableReader),\n\t\tradicalVerticalGap: parseMathValueRecord(reader, tableReader),\n\t\tradicalDisplayStyleVerticalGap: parseMathValueRecord(reader, tableReader),\n\t\tradicalRuleThickness: parseMathValueRecord(reader, tableReader),\n\t\tradicalExtraAscender: parseMathValueRecord(reader, tableReader),\n\t\tradicalKernBeforeDegree: parseMathValueRecord(reader, tableReader),\n\t\tradicalKernAfterDegree: parseMathValueRecord(reader, tableReader),\n\t\tradicalDegreeBottomRaisePercent: reader.int16(),\n\t};\n}\n\nfunction parseMathItalicsCorrection(reader: Reader): MathItalicsCorrection {\n\tconst coverageOffset = reader.uint16();\n\tconst count = reader.uint16();\n\n\tconst values: MathValueRecord[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tvalues.push(parseMathValueRecord(reader, reader));\n\t}\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\n\treturn { coverage, values };\n}\n\nfunction parseMathTopAccentAttachment(reader: Reader): MathTopAccentAttachment {\n\tconst coverageOffset = reader.uint16();\n\tconst count = reader.uint16();\n\n\tconst values: MathValueRecord[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tvalues.push(parseMathValueRecord(reader, reader));\n\t}\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\n\treturn { coverage, values };\n}\n\nfunction parseMathKernRecord(reader: Reader, offset: number): MathKernRecord {\n\tconst kernReader = reader.sliceFrom(offset);\n\tconst heightCount = kernReader.uint16();\n\n\tconst correctionHeights: MathValueRecord[] = [];\n\tfor (let i = 0; i < heightCount; i++) {\n\t\tcorrectionHeights.push(parseMathValueRecord(kernReader, kernReader));\n\t}\n\n\tconst kernValues: MathValueRecord[] = [];\n\tfor (let i = 0; i < heightCount + 1; i++) {\n\t\tkernValues.push(parseMathValueRecord(kernReader, kernReader));\n\t}\n\n\treturn { correctionHeights, kernValues };\n}\n\nfunction parseMathKernInfoTable(reader: Reader): MathKernInfoTable {\n\tconst coverageOffset = reader.uint16();\n\tconst count = reader.uint16();\n\n\tconst kernInfoRecords: Array<{\n\t\ttopRightOffset: uint16;\n\t\ttopLeftOffset: uint16;\n\t\tbottomRightOffset: uint16;\n\t\tbottomLeftOffset: uint16;\n\t}> = [];\n\n\tfor (let i = 0; i < count; i++) {\n\t\tkernInfoRecords.push({\n\t\t\ttopRightOffset: reader.uint16(),\n\t\t\ttopLeftOffset: reader.uint16(),\n\t\t\tbottomRightOffset: reader.uint16(),\n\t\t\tbottomLeftOffset: reader.uint16(),\n\t\t});\n\t}\n\n\tconst coverage = parseCoverageAt(reader, coverageOffset);\n\n\tconst kernInfo: MathKernInfo[] = kernInfoRecords.map((record) => ({\n\t\ttopRight:\n\t\t\trecord.topRightOffset !== 0\n\t\t\t\t? parseMathKernRecord(reader, record.topRightOffset)\n\t\t\t\t: null,\n\t\ttopLeft:\n\t\t\trecord.topLeftOffset !== 0\n\t\t\t\t? parseMathKernRecord(reader, record.topLeftOffset)\n\t\t\t\t: null,\n\t\tbottomRight:\n\t\t\trecord.bottomRightOffset !== 0\n\t\t\t\t? parseMathKernRecord(reader, record.bottomRightOffset)\n\t\t\t\t: null,\n\t\tbottomLeft:\n\t\t\trecord.bottomLeftOffset !== 0\n\t\t\t\t? parseMathKernRecord(reader, record.bottomLeftOffset)\n\t\t\t\t: null,\n\t}));\n\n\treturn { coverage, kernInfo };\n}\n\nfunction parseMathGlyphInfo(reader: Reader): MathGlyphInfo {\n\tconst italicsCorrectionOffset = reader.uint16();\n\tconst topAccentAttachmentOffset = reader.uint16();\n\tconst extendedShapeCoverageOffset = reader.uint16();\n\tconst kernInfoOffset = reader.uint16();\n\n\tlet italicsCorrection: MathItalicsCorrection | null = null;\n\tif (italicsCorrectionOffset !== 0) {\n\t\titalicsCorrection = parseMathItalicsCorrection(\n\t\t\treader.sliceFrom(italicsCorrectionOffset),\n\t\t);\n\t}\n\n\tlet topAccentAttachment: MathTopAccentAttachment | null = null;\n\tif (topAccentAttachmentOffset !== 0) {\n\t\ttopAccentAttachment = parseMathTopAccentAttachment(\n\t\t\treader.sliceFrom(topAccentAttachmentOffset),\n\t\t);\n\t}\n\n\tlet extendedShapeCoverage: ExtendedShapeCoverage | null = null;\n\tif (extendedShapeCoverageOffset !== 0) {\n\t\tconst coverage = parseCoverageAt(reader, extendedShapeCoverageOffset);\n\t\textendedShapeCoverage = { coverage };\n\t}\n\n\tlet kernInfo: MathKernInfoTable | null = null;\n\tif (kernInfoOffset !== 0) {\n\t\tkernInfo = parseMathKernInfoTable(reader.sliceFrom(kernInfoOffset));\n\t}\n\n\treturn {\n\t\titalicsCorrection,\n\t\ttopAccentAttachment,\n\t\textendedShapeCoverage,\n\t\tkernInfo,\n\t};\n}\n\nfunction parseGlyphAssembly(reader: Reader): GlyphAssembly {\n\tconst italicsCorrection = parseMathValueRecord(reader, reader);\n\tconst partCount = reader.uint16();\n\n\tconst parts: GlyphPartRecord[] = [];\n\tfor (let i = 0; i < partCount; i++) {\n\t\tparts.push({\n\t\t\tglyphId: reader.uint16(),\n\t\t\tstartConnectorLength: reader.uint16(),\n\t\t\tendConnectorLength: reader.uint16(),\n\t\t\tfullAdvance: reader.uint16(),\n\t\t\tpartFlags: reader.uint16(),\n\t\t});\n\t}\n\n\treturn { italicsCorrection, parts };\n}\n\nfunction parseMathGlyphConstruction(reader: Reader): MathGlyphConstruction {\n\tconst glyphAssemblyOffset = reader.uint16();\n\tconst variantCount = reader.uint16();\n\n\tconst variants: Array<{ variantGlyph: GlyphId; advanceMeasurement: uint16 }> =\n\t\t[];\n\tfor (let i = 0; i < variantCount; i++) {\n\t\tvariants.push({\n\t\t\tvariantGlyph: reader.uint16(),\n\t\t\tadvanceMeasurement: reader.uint16(),\n\t\t});\n\t}\n\n\tlet glyphAssembly: GlyphAssembly | null = null;\n\tif (glyphAssemblyOffset !== 0) {\n\t\tglyphAssembly = parseGlyphAssembly(reader.sliceFrom(glyphAssemblyOffset));\n\t}\n\n\treturn { glyphAssembly, variants };\n}\n\nfunction parseMathVariants(reader: Reader): MathVariants {\n\tconst minConnectorOverlap = reader.uint16();\n\tconst vertGlyphCoverageOffset = reader.uint16();\n\tconst horizGlyphCoverageOffset = reader.uint16();\n\tconst vertGlyphCount = reader.uint16();\n\tconst horizGlyphCount = reader.uint16();\n\n\tconst vertGlyphConstructionOffsets: uint16[] = [];\n\tfor (let i = 0; i < vertGlyphCount; i++) {\n\t\tvertGlyphConstructionOffsets.push(reader.uint16());\n\t}\n\n\tconst horizGlyphConstructionOffsets: uint16[] = [];\n\tfor (let i = 0; i < horizGlyphCount; i++) {\n\t\thorizGlyphConstructionOffsets.push(reader.uint16());\n\t}\n\n\tconst vertGlyphCoverage =\n\t\tvertGlyphCoverageOffset !== 0\n\t\t\t? parseCoverageAt(reader, vertGlyphCoverageOffset)\n\t\t\t: null;\n\n\tconst horizGlyphCoverage =\n\t\thorizGlyphCoverageOffset !== 0\n\t\t\t? parseCoverageAt(reader, horizGlyphCoverageOffset)\n\t\t\t: null;\n\n\tconst vertGlyphConstruction = vertGlyphConstructionOffsets.map((offset) =>\n\t\tparseMathGlyphConstruction(reader.sliceFrom(offset)),\n\t);\n\n\tconst horizGlyphConstruction = horizGlyphConstructionOffsets.map((offset) =>\n\t\tparseMathGlyphConstruction(reader.sliceFrom(offset)),\n\t);\n\n\treturn {\n\t\tminConnectorOverlap,\n\t\tvertGlyphCoverage,\n\t\thorizGlyphCoverage,\n\t\tvertGlyphConstruction,\n\t\thorizGlyphConstruction,\n\t};\n}\n\nexport function parseMath(reader: Reader): MathTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst mathConstantsOffset = reader.uint16();\n\tconst mathGlyphInfoOffset = reader.uint16();\n\tconst mathVariantsOffset = reader.uint16();\n\n\tlet constants: MathConstants | null = null;\n\tif (mathConstantsOffset !== 0) {\n\t\tconstants = parseMathConstants(reader.sliceFrom(mathConstantsOffset));\n\t}\n\n\tlet glyphInfo: MathGlyphInfo | null = null;\n\tif (mathGlyphInfoOffset !== 0) {\n\t\tglyphInfo = parseMathGlyphInfo(reader.sliceFrom(mathGlyphInfoOffset));\n\t}\n\n\tlet variants: MathVariants | null = null;\n\tif (mathVariantsOffset !== 0) {\n\t\tvariants = parseMathVariants(reader.sliceFrom(mathVariantsOffset));\n\t}\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\tconstants,\n\t\tglyphInfo,\n\t\tvariants,\n\t};\n}\n\n// Helper functions\n\n/** Get italic correction for a glyph */\nexport function getItalicsCorrection(\n\tmath: MathTable,\n\tglyphId: GlyphId,\n): MathValueRecord | null {\n\tconst italics = math.glyphInfo?.italicsCorrection;\n\tif (!italics) return null;\n\n\tconst index = italics.coverage.get(glyphId);\n\tif (index === null) return null;\n\n\treturn italics.values[index] ?? null;\n}\n\n/** Get top accent attachment for a glyph */\nexport function getTopAccentAttachment(\n\tmath: MathTable,\n\tglyphId: GlyphId,\n): MathValueRecord | null {\n\tconst attachment = math.glyphInfo?.topAccentAttachment;\n\tif (!attachment) return null;\n\n\tconst index = attachment.coverage.get(glyphId);\n\tif (index === null) return null;\n\n\treturn attachment.values[index] ?? null;\n}\n\n/** Check if glyph is an extended shape */\nexport function isExtendedShape(math: MathTable, glyphId: GlyphId): boolean {\n\tconst extended = math.glyphInfo?.extendedShapeCoverage;\n\tif (!extended) return false;\n\n\treturn extended.coverage.get(glyphId) !== null;\n}\n\n/** Get vertical glyph variants */\nexport function getVerticalVariants(\n\tmath: MathTable,\n\tglyphId: GlyphId,\n): Array<{ variantGlyph: GlyphId; advanceMeasurement: uint16 }> | null {\n\tconst variants = math.variants;\n\tif (!variants?.vertGlyphCoverage) return null;\n\n\tconst index = variants.vertGlyphCoverage.get(glyphId);\n\tif (index === null) return null;\n\n\treturn variants.vertGlyphConstruction[index]?.variants ?? null;\n}\n\n/** Get horizontal glyph variants */\nexport function getHorizontalVariants(\n\tmath: MathTable,\n\tglyphId: GlyphId,\n): Array<{ variantGlyph: GlyphId; advanceMeasurement: uint16 }> | null {\n\tconst variants = math.variants;\n\tif (!variants?.horizGlyphCoverage) return null;\n\n\tconst index = variants.horizGlyphCoverage.get(glyphId);\n\tif (index === null) return null;\n\n\treturn variants.horizGlyphConstruction[index]?.variants ?? null;\n}\n\n/** Get vertical glyph assembly */\nexport function getVerticalAssembly(\n\tmath: MathTable,\n\tglyphId: GlyphId,\n): GlyphAssembly | null {\n\tconst variants = math.variants;\n\tif (!variants?.vertGlyphCoverage) return null;\n\n\tconst index = variants.vertGlyphCoverage.get(glyphId);\n\tif (index === null) return null;\n\n\treturn variants.vertGlyphConstruction[index]?.glyphAssembly ?? null;\n}\n\n/** Get horizontal glyph assembly */\nexport function getHorizontalAssembly(\n\tmath: MathTable,\n\tglyphId: GlyphId,\n): GlyphAssembly | null {\n\tconst variants = math.variants;\n\tif (!variants?.horizGlyphCoverage) return null;\n\n\tconst index = variants.horizGlyphCoverage.get(glyphId);\n\tif (index === null) return null;\n\n\treturn variants.horizGlyphConstruction[index]?.glyphAssembly ?? null;\n}\n",
41
+ "import type { uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/** Maximum profile table (version 0.5 - CFF) */\nexport interface MaxpTable05 {\n\tversion: 0x00005000;\n\tnumGlyphs: uint16;\n}\n\n/** Maximum profile table (version 1.0 - TrueType) */\nexport interface MaxpTable10 {\n\tversion: 0x00010000;\n\tnumGlyphs: uint16;\n\tmaxPoints: uint16;\n\tmaxContours: uint16;\n\tmaxCompositePoints: uint16;\n\tmaxCompositeContours: uint16;\n\tmaxZones: uint16;\n\tmaxTwilightPoints: uint16;\n\tmaxStorage: uint16;\n\tmaxFunctionDefs: uint16;\n\tmaxInstructionDefs: uint16;\n\tmaxStackElements: uint16;\n\tmaxSizeOfInstructions: uint16;\n\tmaxComponentElements: uint16;\n\tmaxComponentDepth: uint16;\n}\n\nexport type MaxpTable = MaxpTable05 | MaxpTable10;\n\nexport function parseMaxp(reader: Reader): MaxpTable {\n\tconst version = reader.uint32();\n\tconst numGlyphs = reader.uint16();\n\n\tif (version === 0x00005000) {\n\t\t// Version 0.5 (CFF fonts)\n\t\treturn { version, numGlyphs };\n\t}\n\n\tif (version === 0x00010000) {\n\t\t// Version 1.0 (TrueType fonts)\n\t\treturn {\n\t\t\tversion,\n\t\t\tnumGlyphs,\n\t\t\tmaxPoints: reader.uint16(),\n\t\t\tmaxContours: reader.uint16(),\n\t\t\tmaxCompositePoints: reader.uint16(),\n\t\t\tmaxCompositeContours: reader.uint16(),\n\t\t\tmaxZones: reader.uint16(),\n\t\t\tmaxTwilightPoints: reader.uint16(),\n\t\t\tmaxStorage: reader.uint16(),\n\t\t\tmaxFunctionDefs: reader.uint16(),\n\t\t\tmaxInstructionDefs: reader.uint16(),\n\t\t\tmaxStackElements: reader.uint16(),\n\t\t\tmaxSizeOfInstructions: reader.uint16(),\n\t\t\tmaxComponentElements: reader.uint16(),\n\t\t\tmaxComponentDepth: reader.uint16(),\n\t\t};\n\t}\n\n\tthrow new Error(`Unknown maxp version: 0x${version.toString(16)}`);\n}\n",
42
+ "import type { GlyphId, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Extended Glyph Metamorphosis table (morx)\n * Apple Advanced Typography substitution\n */\nexport interface MorxTable {\n\tversion: number;\n\tchains: MorxChain[];\n}\n\n/**\n * Feature chain in morx\n */\nexport interface MorxChain {\n\tdefaultFlags: uint32;\n\tfeatures: MorxFeature[];\n\tsubtables: MorxSubtable[];\n}\n\n/**\n * Feature entry\n */\nexport interface MorxFeature {\n\tfeatureType: uint16;\n\tfeatureSetting: uint16;\n\tenableFlags: uint32;\n\tdisableFlags: uint32;\n}\n\n/**\n * Subtable types\n */\nexport enum MorxSubtableType {\n\tRearrangement = 0,\n\tContextual = 1,\n\tLigature = 2,\n\tNonContextual = 4,\n\tInsertion = 5,\n}\n\n/**\n * Base subtable\n */\nexport interface MorxSubtableBase {\n\ttype: MorxSubtableType;\n\tcoverage: MorxCoverage;\n\tsubFeatureFlags: uint32;\n}\n\nexport interface MorxCoverage {\n\tvertical: boolean;\n\tdescending: boolean;\n\tlogical: boolean;\n}\n\nexport type MorxSubtable =\n\t| MorxRearrangementSubtable\n\t| MorxContextualSubtable\n\t| MorxLigatureSubtable\n\t| MorxNonContextualSubtable\n\t| MorxInsertionSubtable;\n\n/**\n * Type 0: Rearrangement (reorders glyphs)\n */\nexport interface MorxRearrangementSubtable extends MorxSubtableBase {\n\ttype: MorxSubtableType.Rearrangement;\n\tstateTable: StateTable<RearrangementEntry>;\n}\n\nexport interface RearrangementEntry {\n\tnewState: uint16;\n\tflags: uint16;\n}\n\n/**\n * Type 1: Contextual substitution\n */\nexport interface MorxContextualSubtable extends MorxSubtableBase {\n\ttype: MorxSubtableType.Contextual;\n\tstateTable: StateTable<ContextualEntry>;\n\tsubstitutionTable: Map<GlyphId, GlyphId>[];\n}\n\nexport interface ContextualEntry {\n\tnewState: uint16;\n\tflags: uint16;\n\tmarkIndex: uint16;\n\tcurrentIndex: uint16;\n}\n\n/**\n * Type 2: Ligature\n */\nexport interface MorxLigatureSubtable extends MorxSubtableBase {\n\ttype: MorxSubtableType.Ligature;\n\tstateTable: StateTable<LigatureEntry>;\n\tligatureActions: uint32[];\n\tcomponents: uint16[];\n\tligatures: GlyphId[];\n}\n\nexport interface LigatureEntry {\n\tnewState: uint16;\n\tflags: uint16;\n\tligActionIndex: uint16;\n}\n\n/**\n * Type 4: Non-contextual (simple substitution)\n */\nexport interface MorxNonContextualSubtable extends MorxSubtableBase {\n\ttype: MorxSubtableType.NonContextual;\n\tlookupTable: LookupTable;\n}\n\n/**\n * Type 5: Insertion\n */\nexport interface MorxInsertionSubtable extends MorxSubtableBase {\n\ttype: MorxSubtableType.Insertion;\n\tstateTable: StateTable<InsertionEntry>;\n\tinsertionGlyphs: GlyphId[];\n}\n\nexport interface InsertionEntry {\n\tnewState: uint16;\n\tflags: uint16;\n\tcurrentInsertIndex: uint16;\n\tmarkedInsertIndex: uint16;\n}\n\n/**\n * State table for state machine processing\n */\nexport interface StateTable<E> {\n\tnClasses: uint32;\n\tclassTable: ClassTable;\n\tstateArray: E[][];\n}\n\n/**\n * Class lookup table\n */\nexport interface ClassTable {\n\tformat: number;\n\tclassArray: number[]; // Maps glyph ID to class\n}\n\n/**\n * Lookup table for substitutions\n */\nexport interface LookupTable {\n\tformat: number;\n\tmapping: Map<GlyphId, GlyphId>;\n}\n\n/**\n * Parse morx table\n */\nexport function parseMorx(reader: Reader): MorxTable {\n\tconst version = reader.uint16();\n\treader.skip(2); // unused\n\n\tif (version < 2) {\n\t\t// Version 1 (mort) - not supported\n\t\treturn { version, chains: [] };\n\t}\n\n\tconst nChains = reader.uint32();\n\tconst chains: MorxChain[] = [];\n\n\tfor (let i = 0; i < nChains; i++) {\n\t\tconst chain = parseMorxChain(reader);\n\t\tchains.push(chain);\n\t}\n\n\treturn { version, chains };\n}\n\nfunction parseMorxChain(reader: Reader): MorxChain {\n\tconst defaultFlags = reader.uint32();\n\tconst _chainLength = reader.uint32();\n\tconst nFeatureEntries = reader.uint32();\n\tconst nSubtables = reader.uint32();\n\n\t// Parse features\n\tconst features: MorxFeature[] = [];\n\tfor (let i = 0; i < nFeatureEntries; i++) {\n\t\tfeatures.push({\n\t\t\tfeatureType: reader.uint16(),\n\t\t\tfeatureSetting: reader.uint16(),\n\t\t\tenableFlags: reader.uint32(),\n\t\t\tdisableFlags: reader.uint32(),\n\t\t});\n\t}\n\n\t// Parse subtables\n\tconst subtables: MorxSubtable[] = [];\n\tfor (let i = 0; i < nSubtables; i++) {\n\t\tconst subtable = parseMorxSubtable(reader);\n\t\tif (subtable) subtables.push(subtable);\n\t}\n\n\treturn { defaultFlags, features, subtables };\n}\n\nfunction parseMorxSubtable(reader: Reader): MorxSubtable | null {\n\tconst length = reader.uint32();\n\tconst coverageBits = reader.uint32();\n\tconst subFeatureFlags = reader.uint32();\n\n\tconst type = coverageBits & 0xff;\n\tconst coverage: MorxCoverage = {\n\t\tvertical: (coverageBits & 0x80000000) !== 0,\n\t\tdescending: (coverageBits & 0x40000000) !== 0,\n\t\tlogical: (coverageBits & 0x10000000) !== 0,\n\t};\n\n\tconst subtableStart = reader.offset;\n\tconst subtableEnd = subtableStart + length - 12;\n\n\tlet subtable: MorxSubtable | null = null;\n\n\tswitch (type) {\n\t\tcase MorxSubtableType.Rearrangement:\n\t\t\tsubtable = parseRearrangementSubtable(reader, coverage, subFeatureFlags);\n\t\t\tbreak;\n\t\tcase MorxSubtableType.Contextual:\n\t\t\tsubtable = parseContextualSubtable(reader, coverage, subFeatureFlags);\n\t\t\tbreak;\n\t\tcase MorxSubtableType.Ligature:\n\t\t\tsubtable = parseLigatureSubtable(reader, coverage, subFeatureFlags);\n\t\t\tbreak;\n\t\tcase MorxSubtableType.NonContextual:\n\t\t\tsubtable = parseNonContextualSubtable(reader, coverage, subFeatureFlags);\n\t\t\tbreak;\n\t\tcase MorxSubtableType.Insertion:\n\t\t\tsubtable = parseInsertionSubtable(reader, coverage, subFeatureFlags);\n\t\t\tbreak;\n\t}\n\n\t// Skip to end of subtable\n\treader.seek(subtableEnd);\n\n\treturn subtable;\n}\n\nfunction parseNonContextualSubtable(\n\treader: Reader,\n\tcoverage: MorxCoverage,\n\tsubFeatureFlags: uint32,\n): MorxNonContextualSubtable {\n\tconst lookupTable = parseLookupTable(reader);\n\n\treturn {\n\t\ttype: MorxSubtableType.NonContextual,\n\t\tcoverage,\n\t\tsubFeatureFlags,\n\t\tlookupTable,\n\t};\n}\n\nfunction parseContextualSubtable(\n\treader: Reader,\n\tcoverage: MorxCoverage,\n\tsubFeatureFlags: uint32,\n): MorxContextualSubtable {\n\tconst stateTableOffset = reader.offset;\n\tconst nClasses = reader.uint32();\n\tconst classTableOffset = reader.offset32();\n\tconst _stateArrayOffset = reader.offset32();\n\tconst _entryTableOffset = reader.offset32();\n\tconst _substitutionTableOffset = reader.offset32();\n\n\t// Parse class table\n\tconst classTable = parseClassTable(\n\t\treader.sliceFrom(stateTableOffset + classTableOffset),\n\t);\n\n\t// Parse state array and entries (simplified)\n\tconst stateTable: StateTable<ContextualEntry> = {\n\t\tnClasses,\n\t\tclassTable,\n\t\tstateArray: [],\n\t};\n\n\tconst substitutionTable: Map<GlyphId, GlyphId>[] = [];\n\n\treturn {\n\t\ttype: MorxSubtableType.Contextual,\n\t\tcoverage,\n\t\tsubFeatureFlags,\n\t\tstateTable,\n\t\tsubstitutionTable,\n\t};\n}\n\nfunction parseLigatureSubtable(\n\treader: Reader,\n\tcoverage: MorxCoverage,\n\tsubFeatureFlags: uint32,\n): MorxLigatureSubtable {\n\tconst stateTableOffset = reader.offset;\n\tconst nClasses = reader.uint32();\n\tconst classTableOffset = reader.offset32();\n\tconst _stateArrayOffset = reader.offset32();\n\tconst _entryTableOffset = reader.offset32();\n\tconst _ligatureActionsOffset = reader.offset32();\n\tconst _componentsOffset = reader.offset32();\n\tconst _ligaturesOffset = reader.offset32();\n\n\t// Parse class table\n\tconst classTable = parseClassTable(\n\t\treader.sliceFrom(stateTableOffset + classTableOffset),\n\t);\n\n\t// State table (simplified)\n\tconst stateTable: StateTable<LigatureEntry> = {\n\t\tnClasses,\n\t\tclassTable,\n\t\tstateArray: [],\n\t};\n\n\treturn {\n\t\ttype: MorxSubtableType.Ligature,\n\t\tcoverage,\n\t\tsubFeatureFlags,\n\t\tstateTable,\n\t\tligatureActions: [],\n\t\tcomponents: [],\n\t\tligatures: [],\n\t};\n}\n\nfunction parseRearrangementSubtable(\n\treader: Reader,\n\tcoverage: MorxCoverage,\n\tsubFeatureFlags: uint32,\n): MorxRearrangementSubtable {\n\tconst stateTableOffset = reader.offset;\n\tconst nClasses = reader.uint32();\n\tconst classTableOffset = reader.offset32();\n\tconst stateArrayOffset = reader.offset32();\n\tconst entryTableOffset = reader.offset32();\n\n\t// Parse class table\n\tconst classTable = parseClassTable(\n\t\treader.sliceFrom(stateTableOffset + classTableOffset),\n\t);\n\n\t// Parse state array\n\tconst stateArrayReader = reader.sliceFrom(\n\t\tstateTableOffset + stateArrayOffset,\n\t);\n\tconst entryReader = reader.sliceFrom(stateTableOffset + entryTableOffset);\n\n\t// Parse entries (each entry is 4 bytes: newState uint16, flags uint16)\n\tconst entries: RearrangementEntry[] = [];\n\tconst entryCount = 256; // Reasonable max\n\tfor (let i = 0; i < entryCount; i++) {\n\t\tentries.push({\n\t\t\tnewState: entryReader.uint16(),\n\t\t\tflags: entryReader.uint16(),\n\t\t});\n\t}\n\n\t// Build state array\n\tconst stateArray: RearrangementEntry[][] = [];\n\tconst stateCount = Math.min(\n\t\t256,\n\t\tMath.ceil((entryTableOffset - stateArrayOffset) / (nClasses * 2)),\n\t);\n\tfor (let s = 0; s < stateCount; s++) {\n\t\tconst row: RearrangementEntry[] = [];\n\t\tfor (let c = 0; c < nClasses; c++) {\n\t\t\tconst entryIndex = stateArrayReader.uint16();\n\t\t\trow.push(entries[entryIndex] ?? { newState: 0, flags: 0 });\n\t\t}\n\t\tstateArray.push(row);\n\t}\n\n\treturn {\n\t\ttype: MorxSubtableType.Rearrangement,\n\t\tcoverage,\n\t\tsubFeatureFlags,\n\t\tstateTable: {\n\t\t\tnClasses,\n\t\t\tclassTable,\n\t\t\tstateArray,\n\t\t},\n\t};\n}\n\nfunction parseInsertionSubtable(\n\treader: Reader,\n\tcoverage: MorxCoverage,\n\tsubFeatureFlags: uint32,\n): MorxInsertionSubtable {\n\tconst stateTableOffset = reader.offset;\n\tconst nClasses = reader.uint32();\n\tconst classTableOffset = reader.offset32();\n\tconst stateArrayOffset = reader.offset32();\n\tconst entryTableOffset = reader.offset32();\n\tconst insertionActionOffset = reader.offset32();\n\n\t// Parse class table\n\tconst classTable = parseClassTable(\n\t\treader.sliceFrom(stateTableOffset + classTableOffset),\n\t);\n\n\t// Parse insertion glyphs array\n\tconst insertionReader = reader.sliceFrom(\n\t\tstateTableOffset + insertionActionOffset,\n\t);\n\tconst insertionGlyphs: GlyphId[] = [];\n\t// Read a reasonable number of insertion glyphs\n\tconst maxInsertionGlyphs = 1024;\n\tfor (let i = 0; i < maxInsertionGlyphs; i++) {\n\t\ttry {\n\t\t\tinsertionGlyphs.push(insertionReader.uint16());\n\t\t} catch {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Parse entries\n\tconst entryReader = reader.sliceFrom(stateTableOffset + entryTableOffset);\n\tconst entries: InsertionEntry[] = [];\n\tconst entryCount = 256;\n\tfor (let i = 0; i < entryCount; i++) {\n\t\tentries.push({\n\t\t\tnewState: entryReader.uint16(),\n\t\t\tflags: entryReader.uint16(),\n\t\t\tcurrentInsertIndex: entryReader.uint16(),\n\t\t\tmarkedInsertIndex: entryReader.uint16(),\n\t\t});\n\t}\n\n\t// Build state array\n\tconst stateArrayReader = reader.sliceFrom(\n\t\tstateTableOffset + stateArrayOffset,\n\t);\n\tconst stateArray: InsertionEntry[][] = [];\n\tconst stateCount = Math.min(\n\t\t256,\n\t\tMath.ceil((entryTableOffset - stateArrayOffset) / (nClasses * 2)),\n\t);\n\tfor (let s = 0; s < stateCount; s++) {\n\t\tconst row: InsertionEntry[] = [];\n\t\tfor (let c = 0; c < nClasses; c++) {\n\t\t\tconst entryIndex = stateArrayReader.uint16();\n\t\t\trow.push(\n\t\t\t\tentries[entryIndex] ?? {\n\t\t\t\t\tnewState: 0,\n\t\t\t\t\tflags: 0,\n\t\t\t\t\tcurrentInsertIndex: 0xffff,\n\t\t\t\t\tmarkedInsertIndex: 0xffff,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\tstateArray.push(row);\n\t}\n\n\treturn {\n\t\ttype: MorxSubtableType.Insertion,\n\t\tcoverage,\n\t\tsubFeatureFlags,\n\t\tstateTable: {\n\t\t\tnClasses,\n\t\t\tclassTable,\n\t\t\tstateArray,\n\t\t},\n\t\tinsertionGlyphs,\n\t};\n}\n\nfunction parseLookupTable(reader: Reader): LookupTable {\n\tconst format = reader.uint16();\n\tconst mapping = new Map<GlyphId, GlyphId>();\n\n\tswitch (format) {\n\t\tcase 0: {\n\t\t\t// Simple array\n\t\t\t// Format 0 uses lookup by glyph index directly\n\t\t\tbreak;\n\t\t}\n\t\tcase 2: {\n\t\t\t// Segment single\n\t\t\tconst _unitSize = reader.uint16();\n\t\t\tconst nUnits = reader.uint16();\n\t\t\treader.skip(6); // searchRange, entrySelector, rangeShift\n\n\t\t\tfor (let i = 0; i < nUnits; i++) {\n\t\t\t\tconst lastGlyph = reader.uint16();\n\t\t\t\tconst firstGlyph = reader.uint16();\n\t\t\t\tconst value = reader.uint16();\n\n\t\t\t\tfor (let g = firstGlyph; g <= lastGlyph; g++) {\n\t\t\t\t\tmapping.set(g, value);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 4: {\n\t\t\t// Segment array\n\t\t\tconst _unitSize = reader.uint16();\n\t\t\tconst nUnits = reader.uint16();\n\t\t\treader.skip(6);\n\n\t\t\tfor (let i = 0; i < nUnits; i++) {\n\t\t\t\tconst _lastGlyph = reader.uint16();\n\t\t\t\tconst _firstGlyph = reader.uint16();\n\t\t\t\tconst _valueOffset = reader.uint16();\n\n\t\t\t\t// Values would be read from valueOffset\n\t\t\t\t// Simplified: skip for now\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 6: {\n\t\t\t// Single table\n\t\t\tconst _unitSize = reader.uint16();\n\t\t\tconst nUnits = reader.uint16();\n\t\t\treader.skip(6);\n\n\t\t\tfor (let i = 0; i < nUnits; i++) {\n\t\t\t\tconst glyph = reader.uint16();\n\t\t\t\tconst value = reader.uint16();\n\t\t\t\tmapping.set(glyph, value);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase 8: {\n\t\t\t// Trimmed array\n\t\t\tconst firstGlyph = reader.uint16();\n\t\t\tconst glyphCount = reader.uint16();\n\n\t\t\tfor (let i = 0; i < glyphCount; i++) {\n\t\t\t\tconst value = reader.uint16();\n\t\t\t\tif (value !== 0) {\n\t\t\t\t\tmapping.set(firstGlyph + i, value);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn { format, mapping };\n}\n\nfunction parseClassTable(reader: Reader): ClassTable {\n\tconst format = reader.uint16();\n\tconst classArray: number[] = [];\n\n\tif (format === 2) {\n\t\t// Binary search segments\n\t\tconst _unitSize = reader.uint16();\n\t\tconst nUnits = reader.uint16();\n\t\treader.skip(6);\n\n\t\tconst segments: { first: number; last: number; classValue: number }[] = [];\n\t\tfor (let i = 0; i < nUnits; i++) {\n\t\t\tsegments.push({\n\t\t\t\tlast: reader.uint16(),\n\t\t\t\tfirst: reader.uint16(),\n\t\t\t\tclassValue: reader.uint16(),\n\t\t\t});\n\t\t}\n\n\t\t// Build class array (simplified, might be large)\n\t\tconst maxGlyph = Math.max(...segments.map((s) => s.last), 0);\n\t\tfor (let g = 0; g <= maxGlyph; g++) {\n\t\t\tconst seg = segments.find((s) => g >= s.first && g <= s.last);\n\t\t\tclassArray[g] = seg?.classValue ?? 1; // Class 1 = out of bounds\n\t\t}\n\t}\n\n\treturn { format, classArray };\n}\n\n/**\n * Apply non-contextual substitution\n */\nexport function applyNonContextual(\n\tsubtable: MorxNonContextualSubtable,\n\tglyphId: GlyphId,\n): GlyphId | null {\n\treturn subtable.lookupTable.mapping.get(glyphId) ?? null;\n}\n",
43
+ "import type { Tag, uint16, uint32 } from \"../../types.ts\";\nimport { tag } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\nimport {\n\tcalculateRegionScalar,\n\ttype ItemVariationStore,\n\ttype VariationRegion,\n} from \"./hvar.ts\";\n\n/**\n * Metrics Variations table (MVAR)\n * Provides variations for global font metrics\n */\nexport interface MvarTable {\n\tmajorVersion: number;\n\tminorVersion: number;\n\titemVariationStore: ItemVariationStore;\n\tvalueRecords: MvarValueRecord[];\n}\n\nexport interface MvarValueRecord {\n\tvalueTag: Tag;\n\tdeltaSetOuterIndex: number;\n\tdeltaSetInnerIndex: number;\n}\n\n/**\n * Common MVAR value tags\n */\nexport const MvarTags = {\n\t// Horizontal metrics\n\thasc: tag(\"hasc\"), // horizontal ascender\n\thdsc: tag(\"hdsc\"), // horizontal descender\n\thlgp: tag(\"hlgp\"), // horizontal line gap\n\thcla: tag(\"hcla\"), // horizontal clipping ascent\n\thcld: tag(\"hcld\"), // horizontal clipping descent\n\thcof: tag(\"hcof\"), // horizontal caret offset\n\thcrn: tag(\"hcrn\"), // horizontal caret run\n\thcrs: tag(\"hcrs\"), // horizontal caret rise\n\n\t// Vertical metrics\n\tvasc: tag(\"vasc\"), // vertical ascender\n\tvdsc: tag(\"vdsc\"), // vertical descender\n\tvlgp: tag(\"vlgp\"), // vertical line gap\n\tvcof: tag(\"vcof\"), // vertical caret offset\n\tvcrn: tag(\"vcrn\"), // vertical caret run\n\tvcrs: tag(\"vcrs\"), // vertical caret rise\n\n\t// OS/2 table values\n\txhgt: tag(\"xhgt\"), // x height\n\tcpht: tag(\"cpht\"), // cap height\n\tsbxs: tag(\"sbxs\"), // subscript x size\n\tsbys: tag(\"sbys\"), // subscript y size\n\tsbxo: tag(\"sbxo\"), // subscript x offset\n\tsbyo: tag(\"sbyo\"), // subscript y offset\n\tspxs: tag(\"spxs\"), // superscript x size\n\tspys: tag(\"spys\"), // superscript y size\n\tspxo: tag(\"spxo\"), // superscript x offset\n\tspyo: tag(\"spyo\"), // superscript y offset\n\tstrs: tag(\"strs\"), // strikeout size\n\tstro: tag(\"stro\"), // strikeout offset\n\tundo: tag(\"undo\"), // underline offset\n\tunds: tag(\"unds\"), // underline size\n\n\t// Glyph bounds\n\tgsp0: tag(\"gsp0\"), // glyph bounding box x min\n\tgsp1: tag(\"gsp1\"), // glyph bounding box y min\n\tgsp2: tag(\"gsp2\"), // glyph bounding box x max\n\tgsp3: tag(\"gsp3\"), // glyph bounding box y max\n} as const;\n\n/**\n * Parse MVAR table\n */\nexport function parseMvar(reader: Reader): MvarTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\treader.uint16(); // reserved\n\tconst valueRecordSize = reader.uint16();\n\tconst valueRecordCount = reader.uint16();\n\tconst itemVariationStoreOffset = reader.offset16();\n\n\t// Parse value records\n\tconst valueRecords: MvarValueRecord[] = [];\n\tfor (let i = 0; i < valueRecordCount; i++) {\n\t\tvalueRecords.push({\n\t\t\tvalueTag: reader.tag(),\n\t\t\tdeltaSetOuterIndex: reader.uint16(),\n\t\t\tdeltaSetInnerIndex: reader.uint16(),\n\t\t});\n\t\t// Skip any additional bytes if valueRecordSize > 8\n\t\tif (valueRecordSize > 8) {\n\t\t\treader.skip(valueRecordSize - 8);\n\t\t}\n\t}\n\n\t// Parse item variation store\n\tconst itemVariationStore = parseItemVariationStore(\n\t\treader.sliceFrom(itemVariationStoreOffset),\n\t);\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\titemVariationStore,\n\t\tvalueRecords,\n\t};\n}\n\nfunction parseItemVariationStore(reader: Reader): ItemVariationStore {\n\tconst format = reader.uint16();\n\tconst variationRegionListOffset = reader.offset32();\n\tconst itemVariationDataCount = reader.uint16();\n\n\tconst itemVariationDataOffsets: uint32[] = [];\n\tfor (let i = 0; i < itemVariationDataCount; i++) {\n\t\titemVariationDataOffsets.push(reader.offset32());\n\t}\n\n\t// Parse variation regions\n\tconst regionReader = reader.sliceFrom(variationRegionListOffset);\n\tconst axisCount = regionReader.uint16();\n\tconst regionCount = regionReader.uint16();\n\n\tconst variationRegions: VariationRegion[] = [];\n\tfor (let i = 0; i < regionCount; i++) {\n\t\tconst regionAxes: {\n\t\t\tstartCoord: number;\n\t\t\tpeakCoord: number;\n\t\t\tendCoord: number;\n\t\t}[] = [];\n\t\tfor (let j = 0; j < axisCount; j++) {\n\t\t\tregionAxes.push({\n\t\t\t\tstartCoord: regionReader.f2dot14(),\n\t\t\t\tpeakCoord: regionReader.f2dot14(),\n\t\t\t\tendCoord: regionReader.f2dot14(),\n\t\t\t});\n\t\t}\n\t\tvariationRegions.push({ regionAxes });\n\t}\n\n\t// Parse item variation data\n\tconst itemVariationData: {\n\t\titemCount: uint16;\n\t\tregionIndexes: uint16[];\n\t\tdeltaSets: number[][];\n\t}[] = [];\n\tfor (const offset of itemVariationDataOffsets) {\n\t\tconst dataReader = reader.sliceFrom(offset);\n\t\tconst itemCount = dataReader.uint16();\n\t\tconst wordDeltaCount = dataReader.uint16();\n\t\tconst regionIndexCount = dataReader.uint16();\n\n\t\tconst regionIndexes: uint16[] = [];\n\t\tfor (let i = 0; i < regionIndexCount; i++) {\n\t\t\tregionIndexes.push(dataReader.uint16());\n\t\t}\n\n\t\t// Parse delta sets\n\t\tconst longWords = (wordDeltaCount & 0x8000) !== 0;\n\t\tconst wordCount = wordDeltaCount & 0x7fff;\n\t\tconst shortCount = regionIndexCount - wordCount;\n\n\t\tconst deltaSets: number[][] = [];\n\t\tfor (let i = 0; i < itemCount; i++) {\n\t\t\tconst deltas: number[] = [];\n\t\t\t// Read word-sized deltas\n\t\t\tfor (let j = 0; j < wordCount; j++) {\n\t\t\t\tif (longWords) {\n\t\t\t\t\tdeltas.push(dataReader.int32());\n\t\t\t\t} else {\n\t\t\t\t\tdeltas.push(dataReader.int16());\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Read short-sized deltas\n\t\t\tfor (let j = 0; j < shortCount; j++) {\n\t\t\t\tif (longWords) {\n\t\t\t\t\tdeltas.push(dataReader.int16());\n\t\t\t\t} else {\n\t\t\t\t\tdeltas.push(dataReader.int8());\n\t\t\t\t}\n\t\t\t}\n\t\t\tdeltaSets.push(deltas);\n\t\t}\n\n\t\titemVariationData.push({ itemCount, regionIndexes, deltaSets });\n\t}\n\n\treturn { format, variationRegions, itemVariationData };\n}\n\n/**\n * Get metric delta by tag\n */\nexport function getMetricDelta(\n\tmvar: MvarTable,\n\tvalueTag: Tag,\n\tcoords: number[],\n): number {\n\t// Find value record for this tag\n\tconst record = mvar.valueRecords.find((r) => r.valueTag === valueTag);\n\tif (!record) return 0;\n\n\tconst outer = record.deltaSetOuterIndex;\n\tconst inner = record.deltaSetInnerIndex;\n\n\tconst varData = mvar.itemVariationStore.itemVariationData[outer];\n\tif (!varData || inner >= varData.itemCount) {\n\t\treturn 0;\n\t}\n\n\tconst deltaSet = varData.deltaSets[inner];\n\tif (!deltaSet) {\n\t\treturn 0;\n\t}\n\n\t// Calculate total delta\n\tlet delta = 0;\n\tfor (const [i, regionIndex] of varData.regionIndexes.entries()) {\n\t\tconst region = mvar.itemVariationStore.variationRegions[regionIndex];\n\t\tif (!region) continue;\n\n\t\tconst scalar = calculateRegionScalar(region, coords);\n\t\tconst regionDelta = deltaSet[i] ?? 0;\n\t\tdelta += scalar * regionDelta;\n\t}\n\n\treturn Math.round(delta);\n}\n\n/**\n * Get horizontal ascender delta\n */\nexport function getHAscenderDelta(mvar: MvarTable, coords: number[]): number {\n\treturn getMetricDelta(mvar, MvarTags.hasc, coords);\n}\n\n/**\n * Get horizontal descender delta\n */\nexport function getHDescenderDelta(mvar: MvarTable, coords: number[]): number {\n\treturn getMetricDelta(mvar, MvarTags.hdsc, coords);\n}\n\n/**\n * Get horizontal line gap delta\n */\nexport function getHLineGapDelta(mvar: MvarTable, coords: number[]): number {\n\treturn getMetricDelta(mvar, MvarTags.hlgp, coords);\n}\n\n/**\n * Get x-height delta\n */\nexport function getXHeightDelta(mvar: MvarTable, coords: number[]): number {\n\treturn getMetricDelta(mvar, MvarTags.xhgt, coords);\n}\n\n/**\n * Get cap height delta\n */\nexport function getCapHeightDelta(mvar: MvarTable, coords: number[]): number {\n\treturn getMetricDelta(mvar, MvarTags.cpht, coords);\n}\n\n/**\n * Get underline offset delta\n */\nexport function getUnderlineOffsetDelta(\n\tmvar: MvarTable,\n\tcoords: number[],\n): number {\n\treturn getMetricDelta(mvar, MvarTags.undo, coords);\n}\n\n/**\n * Get underline size delta\n */\nexport function getUnderlineSizeDelta(\n\tmvar: MvarTable,\n\tcoords: number[],\n): number {\n\treturn getMetricDelta(mvar, MvarTags.unds, coords);\n}\n\n/**\n * Get strikeout offset delta\n */\nexport function getStrikeoutOffsetDelta(\n\tmvar: MvarTable,\n\tcoords: number[],\n): number {\n\treturn getMetricDelta(mvar, MvarTags.stro, coords);\n}\n\n/**\n * Get strikeout size delta\n */\nexport function getStrikeoutSizeDelta(\n\tmvar: MvarTable,\n\tcoords: number[],\n): number {\n\treturn getMetricDelta(mvar, MvarTags.strs, coords);\n}\n",
44
+ "import type { uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/** Name IDs */\nexport const NameId = {\n\tCopyright: 0,\n\tFontFamily: 1,\n\tFontSubfamily: 2,\n\tUniqueID: 3,\n\tFullName: 4,\n\tVersion: 5,\n\tPostScriptName: 6,\n\tTrademark: 7,\n\tManufacturer: 8,\n\tDesigner: 9,\n\tDescription: 10,\n\tManufacturerURL: 11,\n\tDesignerURL: 12,\n\tLicense: 13,\n\tLicenseURL: 14,\n\tReserved: 15,\n\tTypographicFamily: 16,\n\tTypographicSubfamily: 17,\n\tCompatibleFullName: 18,\n\tSampleText: 19,\n\tPostScriptCIDFindfontName: 20,\n\tWWSFamily: 21,\n\tWWSSubfamily: 22,\n\tLightBackgroundPalette: 23,\n\tDarkBackgroundPalette: 24,\n\tVariationsPostScriptNamePrefix: 25,\n} as const;\n\n/** Platform IDs */\nexport const PlatformId = {\n\tUnicode: 0,\n\tMacintosh: 1,\n\tReserved: 2,\n\tWindows: 3,\n} as const;\n\n/** Windows encoding IDs */\nexport const WindowsEncodingId = {\n\tSymbol: 0,\n\tUnicodeBMP: 1,\n\tShiftJIS: 2,\n\tPRC: 3,\n\tBig5: 4,\n\tWansung: 5,\n\tJohab: 6,\n\tUnicodeFullRepertoire: 10,\n} as const;\n\n/** A single name record */\nexport interface NameRecord {\n\tplatformId: uint16;\n\tencodingId: uint16;\n\tlanguageId: uint16;\n\tnameId: uint16;\n\tvalue: string;\n}\n\n/** Name table */\nexport interface NameTable {\n\tformat: uint16;\n\trecords: NameRecord[];\n}\n\nexport function parseName(reader: Reader): NameTable {\n\tconst format = reader.uint16();\n\tconst count = reader.uint16();\n\tconst stringOffset = reader.uint16();\n\n\tconst records: NameRecord[] = [];\n\n\t// Parse name records\n\tconst recordData: Array<{\n\t\tplatformId: uint16;\n\t\tencodingId: uint16;\n\t\tlanguageId: uint16;\n\t\tnameId: uint16;\n\t\tlength: uint16;\n\t\toffset: uint16;\n\t}> = [];\n\n\tfor (let i = 0; i < count; i++) {\n\t\trecordData.push({\n\t\t\tplatformId: reader.uint16(),\n\t\t\tencodingId: reader.uint16(),\n\t\t\tlanguageId: reader.uint16(),\n\t\t\tnameId: reader.uint16(),\n\t\t\tlength: reader.uint16(),\n\t\t\toffset: reader.uint16(),\n\t\t});\n\t}\n\n\t// Decode strings\n\tfor (const rd of recordData) {\n\t\tconst strReader = reader.sliceFrom(stringOffset + rd.offset);\n\t\tconst value = decodeNameString(\n\t\t\tstrReader,\n\t\t\trd.length,\n\t\t\trd.platformId,\n\t\t\trd.encodingId,\n\t\t);\n\n\t\tif (value !== null) {\n\t\t\trecords.push({\n\t\t\t\tplatformId: rd.platformId,\n\t\t\t\tencodingId: rd.encodingId,\n\t\t\t\tlanguageId: rd.languageId,\n\t\t\t\tnameId: rd.nameId,\n\t\t\t\tvalue,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { format, records };\n}\n\n/** Decode name string based on platform and encoding */\nfunction decodeNameString(\n\treader: Reader,\n\tlength: number,\n\tplatformId: number,\n\tencodingId: number,\n): string | null {\n\t// Unicode platform or Windows platform with Unicode encoding\n\tif (\n\t\tplatformId === PlatformId.Unicode ||\n\t\t(platformId === PlatformId.Windows &&\n\t\t\t(encodingId === 1 || encodingId === 10))\n\t) {\n\t\t// UTF-16BE\n\t\tconst chars: string[] = [];\n\t\tfor (let i = 0; i < length; i += 2) {\n\t\t\tconst code = reader.uint16();\n\t\t\tchars.push(String.fromCharCode(code));\n\t\t}\n\t\treturn chars.join(\"\");\n\t}\n\n\t// Macintosh Roman (basic ASCII-compatible)\n\tif (platformId === PlatformId.Macintosh && encodingId === 0) {\n\t\tconst bytes: number[] = [];\n\t\tfor (let i = 0; i < length; i++) {\n\t\t\tbytes.push(reader.uint8());\n\t\t}\n\t\t// Simple ASCII decoding for Mac Roman (limited support)\n\t\treturn String.fromCharCode(...bytes);\n\t}\n\n\t// Skip unsupported encodings\n\treturn null;\n}\n\n/** Get a specific name by ID, preferring Windows Unicode */\nexport function getNameById(\n\ttable: NameTable,\n\tnameId: number,\n\tlanguageId?: number,\n): string | null {\n\t// Prefer Windows Unicode (platform 3, encoding 1)\n\tfor (const record of table.records) {\n\t\tif (record.nameId !== nameId) continue;\n\t\tif (record.platformId === PlatformId.Windows && record.encodingId === 1) {\n\t\t\tif (languageId === undefined || record.languageId === languageId) {\n\t\t\t\treturn record.value;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fallback to Unicode platform\n\tfor (const record of table.records) {\n\t\tif (record.nameId !== nameId) continue;\n\t\tif (record.platformId === PlatformId.Unicode) {\n\t\t\tif (languageId === undefined || record.languageId === languageId) {\n\t\t\t\treturn record.value;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fallback to any platform\n\tfor (const record of table.records) {\n\t\tif (record.nameId !== nameId) continue;\n\t\tif (languageId === undefined || record.languageId === languageId) {\n\t\t\treturn record.value;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/** Get font family name */\nexport function getFontFamily(table: NameTable): string | null {\n\t// Prefer typographic family (16) over basic family (1)\n\treturn (\n\t\tgetNameById(table, NameId.TypographicFamily) ??\n\t\tgetNameById(table, NameId.FontFamily)\n\t);\n}\n\n/** Get font subfamily (style) */\nexport function getFontSubfamily(table: NameTable): string | null {\n\treturn (\n\t\tgetNameById(table, NameId.TypographicSubfamily) ??\n\t\tgetNameById(table, NameId.FontSubfamily)\n\t);\n}\n\n/** Get full font name */\nexport function getFullName(table: NameTable): string | null {\n\treturn getNameById(table, NameId.FullName);\n}\n\n/** Get PostScript name */\nexport function getPostScriptName(table: NameTable): string | null {\n\treturn getNameById(table, NameId.PostScriptName);\n}\n\n/** Get version string */\nexport function getVersion(table: NameTable): string | null {\n\treturn getNameById(table, NameId.Version);\n}\n",
45
+ "import type { int16, uint8, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * OS/2 table - Font metrics and classification\n * Contains Windows-specific metrics and font embedding information\n */\nexport interface Os2Table {\n\tversion: uint16;\n\txAvgCharWidth: int16;\n\tusWeightClass: uint16;\n\tusWidthClass: uint16;\n\tfsType: uint16;\n\tySubscriptXSize: int16;\n\tySubscriptYSize: int16;\n\tySubscriptXOffset: int16;\n\tySubscriptYOffset: int16;\n\tySuperscriptXSize: int16;\n\tySuperscriptYSize: int16;\n\tySuperscriptXOffset: int16;\n\tySuperscriptYOffset: int16;\n\tyStrikeoutSize: int16;\n\tyStrikeoutPosition: int16;\n\tsFamilyClass: int16;\n\tpanose: uint8[];\n\tulUnicodeRange1: uint32;\n\tulUnicodeRange2: uint32;\n\tulUnicodeRange3: uint32;\n\tulUnicodeRange4: uint32;\n\tachVendID: string;\n\tfsSelection: uint16;\n\tusFirstCharIndex: uint16;\n\tusLastCharIndex: uint16;\n\tsTypoAscender: int16;\n\tsTypoDescender: int16;\n\tsTypoLineGap: int16;\n\tusWinAscent: uint16;\n\tusWinDescent: uint16;\n\t// Version 1+\n\tulCodePageRange1?: uint32;\n\tulCodePageRange2?: uint32;\n\t// Version 2+\n\tsxHeight?: int16;\n\tsCapHeight?: int16;\n\tusDefaultChar?: uint16;\n\tusBreakChar?: uint16;\n\tusMaxContext?: uint16;\n\t// Version 5+\n\tusLowerOpticalPointSize?: uint16;\n\tusUpperOpticalPointSize?: uint16;\n}\n\n/** Weight class constants */\nexport const WeightClass = {\n\tThin: 100,\n\tExtraLight: 200,\n\tLight: 300,\n\tNormal: 400,\n\tMedium: 500,\n\tSemiBold: 600,\n\tBold: 700,\n\tExtraBold: 800,\n\tBlack: 900,\n} as const;\n\n/** Width class constants */\nexport const WidthClass = {\n\tUltraCondensed: 1,\n\tExtraCondensed: 2,\n\tCondensed: 3,\n\tSemiCondensed: 4,\n\tNormal: 5,\n\tSemiExpanded: 6,\n\tExpanded: 7,\n\tExtraExpanded: 8,\n\tUltraExpanded: 9,\n} as const;\n\n/** Font selection flags (fsSelection) */\nexport const FsSelection = {\n\tItalic: 0x0001,\n\tUnderscore: 0x0002,\n\tNegative: 0x0004,\n\tOutlined: 0x0008,\n\tStrikeout: 0x0010,\n\tBold: 0x0020,\n\tRegular: 0x0040,\n\tUseTypoMetrics: 0x0080,\n\tWWS: 0x0100,\n\tOblique: 0x0200,\n} as const;\n\n/** Font embedding permissions (fsType) */\nexport const FsType = {\n\tInstallableEmbedding: 0x0000,\n\tRestrictedLicense: 0x0002,\n\tPreviewAndPrint: 0x0004,\n\tEditable: 0x0008,\n\tNoSubsetting: 0x0100,\n\tBitmapOnly: 0x0200,\n} as const;\n\nexport function parseOs2(reader: Reader): Os2Table {\n\tconst version = reader.uint16();\n\tconst xAvgCharWidth = reader.int16();\n\tconst usWeightClass = reader.uint16();\n\tconst usWidthClass = reader.uint16();\n\tconst fsType = reader.uint16();\n\tconst ySubscriptXSize = reader.int16();\n\tconst ySubscriptYSize = reader.int16();\n\tconst ySubscriptXOffset = reader.int16();\n\tconst ySubscriptYOffset = reader.int16();\n\tconst ySuperscriptXSize = reader.int16();\n\tconst ySuperscriptYSize = reader.int16();\n\tconst ySuperscriptXOffset = reader.int16();\n\tconst ySuperscriptYOffset = reader.int16();\n\tconst yStrikeoutSize = reader.int16();\n\tconst yStrikeoutPosition = reader.int16();\n\tconst sFamilyClass = reader.int16();\n\n\t// PANOSE classification (10 bytes)\n\tconst panose: uint8[] = [];\n\tfor (let i = 0; i < 10; i++) {\n\t\tpanose.push(reader.uint8());\n\t}\n\n\tconst ulUnicodeRange1 = reader.uint32();\n\tconst ulUnicodeRange2 = reader.uint32();\n\tconst ulUnicodeRange3 = reader.uint32();\n\tconst ulUnicodeRange4 = reader.uint32();\n\n\t// Vendor ID (4 bytes as ASCII)\n\tconst achVendID = String.fromCharCode(\n\t\treader.uint8(),\n\t\treader.uint8(),\n\t\treader.uint8(),\n\t\treader.uint8(),\n\t);\n\n\tconst fsSelection = reader.uint16();\n\tconst usFirstCharIndex = reader.uint16();\n\tconst usLastCharIndex = reader.uint16();\n\tconst sTypoAscender = reader.int16();\n\tconst sTypoDescender = reader.int16();\n\tconst sTypoLineGap = reader.int16();\n\tconst usWinAscent = reader.uint16();\n\tconst usWinDescent = reader.uint16();\n\n\tconst result: Os2Table = {\n\t\tversion,\n\t\txAvgCharWidth,\n\t\tusWeightClass,\n\t\tusWidthClass,\n\t\tfsType,\n\t\tySubscriptXSize,\n\t\tySubscriptYSize,\n\t\tySubscriptXOffset,\n\t\tySubscriptYOffset,\n\t\tySuperscriptXSize,\n\t\tySuperscriptYSize,\n\t\tySuperscriptXOffset,\n\t\tySuperscriptYOffset,\n\t\tyStrikeoutSize,\n\t\tyStrikeoutPosition,\n\t\tsFamilyClass,\n\t\tpanose,\n\t\tulUnicodeRange1,\n\t\tulUnicodeRange2,\n\t\tulUnicodeRange3,\n\t\tulUnicodeRange4,\n\t\tachVendID,\n\t\tfsSelection,\n\t\tusFirstCharIndex,\n\t\tusLastCharIndex,\n\t\tsTypoAscender,\n\t\tsTypoDescender,\n\t\tsTypoLineGap,\n\t\tusWinAscent,\n\t\tusWinDescent,\n\t};\n\n\t// Version 1+ fields\n\tif (version >= 1) {\n\t\tresult.ulCodePageRange1 = reader.uint32();\n\t\tresult.ulCodePageRange2 = reader.uint32();\n\t}\n\n\t// Version 2+ fields\n\tif (version >= 2) {\n\t\tresult.sxHeight = reader.int16();\n\t\tresult.sCapHeight = reader.int16();\n\t\tresult.usDefaultChar = reader.uint16();\n\t\tresult.usBreakChar = reader.uint16();\n\t\tresult.usMaxContext = reader.uint16();\n\t}\n\n\t// Version 5+ fields\n\tif (version >= 5) {\n\t\tresult.usLowerOpticalPointSize = reader.uint16();\n\t\tresult.usUpperOpticalPointSize = reader.uint16();\n\t}\n\n\treturn result;\n}\n\n/** Check if font is italic */\nexport function isItalic(os2: Os2Table): boolean {\n\treturn (os2.fsSelection & FsSelection.Italic) !== 0;\n}\n\n/** Check if font is bold */\nexport function isBold(os2: Os2Table): boolean {\n\treturn (os2.fsSelection & FsSelection.Bold) !== 0;\n}\n\n/** Check if USE_TYPO_METRICS flag is set */\nexport function useTypoMetrics(os2: Os2Table): boolean {\n\treturn (os2.fsSelection & FsSelection.UseTypoMetrics) !== 0;\n}\n\n/** Get embedding permission level */\nexport function getEmbeddingPermission(\n\tos2: Os2Table,\n): \"installable\" | \"restricted\" | \"preview\" | \"editable\" {\n\tconst fsType = os2.fsType;\n\tif ((fsType & FsType.RestrictedLicense) !== 0) return \"restricted\";\n\tif ((fsType & FsType.PreviewAndPrint) !== 0) return \"preview\";\n\tif ((fsType & FsType.Editable) !== 0) return \"editable\";\n\treturn \"installable\";\n}\n",
46
+ "import type { int16, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * post table - PostScript font information\n * Contains additional PostScript info like glyph names and italic angle\n */\nexport interface PostTable {\n\tversion: number;\n\titalicAngle: number;\n\tunderlinePosition: int16;\n\tunderlineThickness: int16;\n\tisFixedPitch: uint32;\n\tminMemType42: uint32;\n\tmaxMemType42: uint32;\n\tminMemType1: uint32;\n\tmaxMemType1: uint32;\n\t// Version 2.0 only\n\tnumberOfGlyphs?: uint16;\n\tglyphNameIndex?: uint16[];\n\tnames?: string[];\n}\n\n/** Standard PostScript glyph names (first 258) */\nconst standardNames: string[] = [\n\t\".notdef\",\n\t\".null\",\n\t\"nonmarkingreturn\",\n\t\"space\",\n\t\"exclam\",\n\t\"quotedbl\",\n\t\"numbersign\",\n\t\"dollar\",\n\t\"percent\",\n\t\"ampersand\",\n\t\"quotesingle\",\n\t\"parenleft\",\n\t\"parenright\",\n\t\"asterisk\",\n\t\"plus\",\n\t\"comma\",\n\t\"hyphen\",\n\t\"period\",\n\t\"slash\",\n\t\"zero\",\n\t\"one\",\n\t\"two\",\n\t\"three\",\n\t\"four\",\n\t\"five\",\n\t\"six\",\n\t\"seven\",\n\t\"eight\",\n\t\"nine\",\n\t\"colon\",\n\t\"semicolon\",\n\t\"less\",\n\t\"equal\",\n\t\"greater\",\n\t\"question\",\n\t\"at\",\n\t\"A\",\n\t\"B\",\n\t\"C\",\n\t\"D\",\n\t\"E\",\n\t\"F\",\n\t\"G\",\n\t\"H\",\n\t\"I\",\n\t\"J\",\n\t\"K\",\n\t\"L\",\n\t\"M\",\n\t\"N\",\n\t\"O\",\n\t\"P\",\n\t\"Q\",\n\t\"R\",\n\t\"S\",\n\t\"T\",\n\t\"U\",\n\t\"V\",\n\t\"W\",\n\t\"X\",\n\t\"Y\",\n\t\"Z\",\n\t\"bracketleft\",\n\t\"backslash\",\n\t\"bracketright\",\n\t\"asciicircum\",\n\t\"underscore\",\n\t\"grave\",\n\t\"a\",\n\t\"b\",\n\t\"c\",\n\t\"d\",\n\t\"e\",\n\t\"f\",\n\t\"g\",\n\t\"h\",\n\t\"i\",\n\t\"j\",\n\t\"k\",\n\t\"l\",\n\t\"m\",\n\t\"n\",\n\t\"o\",\n\t\"p\",\n\t\"q\",\n\t\"r\",\n\t\"s\",\n\t\"t\",\n\t\"u\",\n\t\"v\",\n\t\"w\",\n\t\"x\",\n\t\"y\",\n\t\"z\",\n\t\"braceleft\",\n\t\"bar\",\n\t\"braceright\",\n\t\"asciitilde\",\n\t\"Adieresis\",\n\t\"Aring\",\n\t\"Ccedilla\",\n\t\"Eacute\",\n\t\"Ntilde\",\n\t\"Odieresis\",\n\t\"Udieresis\",\n\t\"aacute\",\n\t\"agrave\",\n\t\"acircumflex\",\n\t\"adieresis\",\n\t\"atilde\",\n\t\"aring\",\n\t\"ccedilla\",\n\t\"eacute\",\n\t\"egrave\",\n\t\"ecircumflex\",\n\t\"edieresis\",\n\t\"iacute\",\n\t\"igrave\",\n\t\"icircumflex\",\n\t\"idieresis\",\n\t\"ntilde\",\n\t\"oacute\",\n\t\"ograve\",\n\t\"ocircumflex\",\n\t\"odieresis\",\n\t\"otilde\",\n\t\"uacute\",\n\t\"ugrave\",\n\t\"ucircumflex\",\n\t\"udieresis\",\n\t\"dagger\",\n\t\"degree\",\n\t\"cent\",\n\t\"sterling\",\n\t\"section\",\n\t\"bullet\",\n\t\"paragraph\",\n\t\"germandbls\",\n\t\"registered\",\n\t\"copyright\",\n\t\"trademark\",\n\t\"acute\",\n\t\"dieresis\",\n\t\"notequal\",\n\t\"AE\",\n\t\"Oslash\",\n\t\"infinity\",\n\t\"plusminus\",\n\t\"lessequal\",\n\t\"greaterequal\",\n\t\"yen\",\n\t\"mu\",\n\t\"partialdiff\",\n\t\"summation\",\n\t\"product\",\n\t\"pi\",\n\t\"integral\",\n\t\"ordfeminine\",\n\t\"ordmasculine\",\n\t\"Omega\",\n\t\"ae\",\n\t\"oslash\",\n\t\"questiondown\",\n\t\"exclamdown\",\n\t\"logicalnot\",\n\t\"radical\",\n\t\"florin\",\n\t\"approxequal\",\n\t\"Delta\",\n\t\"guillemotleft\",\n\t\"guillemotright\",\n\t\"ellipsis\",\n\t\"nonbreakingspace\",\n\t\"Agrave\",\n\t\"Atilde\",\n\t\"Otilde\",\n\t\"OE\",\n\t\"oe\",\n\t\"endash\",\n\t\"emdash\",\n\t\"quotedblleft\",\n\t\"quotedblright\",\n\t\"quoteleft\",\n\t\"quoteright\",\n\t\"divide\",\n\t\"lozenge\",\n\t\"ydieresis\",\n\t\"Ydieresis\",\n\t\"fraction\",\n\t\"currency\",\n\t\"guilsinglleft\",\n\t\"guilsinglright\",\n\t\"fi\",\n\t\"fl\",\n\t\"daggerdbl\",\n\t\"periodcentered\",\n\t\"quotesinglbase\",\n\t\"quotedblbase\",\n\t\"perthousand\",\n\t\"Acircumflex\",\n\t\"Ecircumflex\",\n\t\"Aacute\",\n\t\"Edieresis\",\n\t\"Egrave\",\n\t\"Iacute\",\n\t\"Icircumflex\",\n\t\"Idieresis\",\n\t\"Igrave\",\n\t\"Oacute\",\n\t\"Ocircumflex\",\n\t\"apple\",\n\t\"Ograve\",\n\t\"Uacute\",\n\t\"Ucircumflex\",\n\t\"Ugrave\",\n\t\"dotlessi\",\n\t\"circumflex\",\n\t\"tilde\",\n\t\"macron\",\n\t\"breve\",\n\t\"dotaccent\",\n\t\"ring\",\n\t\"cedilla\",\n\t\"hungarumlaut\",\n\t\"ogonek\",\n\t\"caron\",\n\t\"Lslash\",\n\t\"lslash\",\n\t\"Scaron\",\n\t\"scaron\",\n\t\"Zcaron\",\n\t\"zcaron\",\n\t\"brokenbar\",\n\t\"Eth\",\n\t\"eth\",\n\t\"Yacute\",\n\t\"yacute\",\n\t\"Thorn\",\n\t\"thorn\",\n\t\"minus\",\n\t\"multiply\",\n\t\"onesuperior\",\n\t\"twosuperior\",\n\t\"threesuperior\",\n\t\"onehalf\",\n\t\"onequarter\",\n\t\"threequarters\",\n\t\"franc\",\n\t\"Gbreve\",\n\t\"gbreve\",\n\t\"Idotaccent\",\n\t\"Scedilla\",\n\t\"scedilla\",\n\t\"Cacute\",\n\t\"cacute\",\n\t\"Ccaron\",\n\t\"ccaron\",\n\t\"dcroat\",\n];\n\nexport function parsePost(reader: Reader): PostTable {\n\tconst versionMajor = reader.uint16();\n\tconst versionMinor = reader.uint16();\n\tconst version = versionMajor + versionMinor / 0x10000;\n\n\tconst italicAngle = reader.fixed();\n\tconst underlinePosition = reader.int16();\n\tconst underlineThickness = reader.int16();\n\tconst isFixedPitch = reader.uint32();\n\tconst minMemType42 = reader.uint32();\n\tconst maxMemType42 = reader.uint32();\n\tconst minMemType1 = reader.uint32();\n\tconst maxMemType1 = reader.uint32();\n\n\tconst result: PostTable = {\n\t\tversion,\n\t\titalicAngle,\n\t\tunderlinePosition,\n\t\tunderlineThickness,\n\t\tisFixedPitch,\n\t\tminMemType42,\n\t\tmaxMemType42,\n\t\tminMemType1,\n\t\tmaxMemType1,\n\t};\n\n\t// Version 2.0: includes glyph names\n\tif (version === 2.0) {\n\t\tconst numberOfGlyphs = reader.uint16();\n\t\tconst glyphNameIndex: uint16[] = [];\n\n\t\tfor (let i = 0; i < numberOfGlyphs; i++) {\n\t\t\tglyphNameIndex.push(reader.uint16());\n\t\t}\n\n\t\t// Collect custom names (indexes >= 258)\n\t\tconst customNames: string[] = [];\n\t\tlet maxIndex = 0;\n\t\tfor (const idx of glyphNameIndex) {\n\t\t\tif (idx >= 258 && idx > maxIndex) {\n\t\t\t\tmaxIndex = idx;\n\t\t\t}\n\t\t}\n\n\t\t// Read custom names\n\t\tconst numCustomNames = maxIndex >= 258 ? maxIndex - 257 : 0;\n\t\tfor (let i = 0; i < numCustomNames; i++) {\n\t\t\tconst length = reader.uint8();\n\t\t\tconst chars: string[] = [];\n\t\t\tfor (let j = 0; j < length; j++) {\n\t\t\t\tchars.push(String.fromCharCode(reader.uint8()));\n\t\t\t}\n\t\t\tcustomNames.push(chars.join(\"\"));\n\t\t}\n\n\t\tresult.numberOfGlyphs = numberOfGlyphs;\n\t\tresult.glyphNameIndex = glyphNameIndex;\n\t\tresult.names = customNames;\n\t}\n\n\treturn result;\n}\n\n/** Get glyph name by glyph ID */\nexport function getGlyphName(post: PostTable, glyphId: number): string | null {\n\t// Version 1: standard 258 names\n\tif (post.version === 1.0) {\n\t\tconst name = standardNames[glyphId];\n\t\treturn name !== undefined ? name : null;\n\t}\n\n\t// Version 2: indexed names\n\tif (post.version === 2.0 && post.glyphNameIndex) {\n\t\tconst index = post.glyphNameIndex[glyphId];\n\t\tif (index === undefined) return null;\n\n\t\t// Standard name\n\t\tif (index < 258) {\n\t\t\treturn standardNames[index] ?? null;\n\t\t}\n\n\t\t// Custom name\n\t\tconst customIndex = index - 258;\n\t\treturn post.names?.[customIndex] ?? null;\n\t}\n\n\t// Version 3: no names stored\n\treturn null;\n}\n\n/** Check if font is monospaced */\nexport function isMonospaced(post: PostTable): boolean {\n\treturn post.isFixedPitch !== 0;\n}\n",
47
+ "import type { GlyphId, int16, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Standard Bitmap Graphics table (sbix)\n * Apple's bitmap/PNG glyph table for color emoji and bitmap fonts\n */\nexport interface SbixTable {\n\tversion: uint16;\n\tflags: uint16;\n\tstrikes: SbixStrike[];\n}\n\n/**\n * Strike (bitmap size) in sbix\n */\nexport interface SbixStrike {\n\tppem: uint16;\n\tppi: uint16;\n\tglyphData: Map<GlyphId, SbixGlyph>;\n}\n\n/**\n * Glyph data in sbix\n */\nexport interface SbixGlyph {\n\toriginOffsetX: int16;\n\toriginOffsetY: int16;\n\tgraphicType: string; // 4-char tag: 'png ', 'jpg ', 'tiff', 'pdf ', etc.\n\tdata: Uint8Array;\n}\n\n/**\n * Common graphic types in sbix\n */\nexport const SbixGraphicType = {\n\tPNG: \"png \",\n\tJPG: \"jpg \",\n\tTIFF: \"tiff\",\n\tPDF: \"pdf \",\n\tMASK: \"mask\", // Mask for another glyph\n\tDUPE: \"dupe\", // Duplicate of another glyph (data is glyph ID)\n} as const;\n\n/**\n * Parse sbix table\n */\nexport function parseSbix(reader: Reader, numGlyphs: number): SbixTable {\n\tconst tableStart = reader.offset;\n\tconst version = reader.uint16();\n\tconst flags = reader.uint16();\n\tconst numStrikes = reader.uint32();\n\n\t// Read strike offsets\n\tconst strikeOffsets: uint32[] = [];\n\tfor (let i = 0; i < numStrikes; i++) {\n\t\tstrikeOffsets.push(reader.uint32());\n\t}\n\n\t// Parse each strike\n\tconst strikes: SbixStrike[] = [];\n\tfor (const strikeOffset of strikeOffsets) {\n\t\tconst strike = parseStrike(reader, tableStart + strikeOffset, numGlyphs);\n\t\tstrikes.push(strike);\n\t}\n\n\treturn { version, flags, strikes };\n}\n\nfunction parseStrike(\n\treader: Reader,\n\tstrikeOffset: number,\n\tnumGlyphs: number,\n): SbixStrike {\n\tconst strikeReader = reader.sliceFrom(strikeOffset);\n\tconst ppem = strikeReader.uint16();\n\tconst ppi = strikeReader.uint16();\n\n\t// Read glyph data offsets (numGlyphs + 1 for sentinel)\n\tconst glyphDataOffsets: uint32[] = [];\n\tfor (let i = 0; i <= numGlyphs; i++) {\n\t\tglyphDataOffsets.push(strikeReader.uint32());\n\t}\n\n\t// Parse glyph data\n\tconst glyphData = new Map<GlyphId, SbixGlyph>();\n\n\tfor (let glyphId = 0; glyphId < numGlyphs; glyphId++) {\n\t\tconst offset = glyphDataOffsets[glyphId]!;\n\t\tconst nextOffset = glyphDataOffsets[glyphId + 1]!;\n\t\tconst dataLength = nextOffset - offset;\n\n\t\tif (dataLength <= 8) {\n\t\t\t// No data or just header (minimum is 8 bytes for header)\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst glyphReader = reader.sliceFrom(strikeOffset + offset);\n\t\tconst originOffsetX = glyphReader.int16();\n\t\tconst originOffsetY = glyphReader.int16();\n\t\tconst graphicType = glyphReader.tagString();\n\n\t\t// Read actual image data\n\t\tconst imageDataLength = dataLength - 8;\n\t\tconst data = glyphReader.bytes(imageDataLength);\n\n\t\tglyphData.set(glyphId, {\n\t\t\toriginOffsetX,\n\t\t\toriginOffsetY,\n\t\t\tgraphicType,\n\t\t\tdata,\n\t\t});\n\t}\n\n\treturn { ppem, ppi, glyphData };\n}\n\n/**\n * Get glyph bitmap for a specific ppem\n * Returns the best matching strike\n */\nexport function getGlyphBitmap(\n\tsbix: SbixTable,\n\tglyphId: GlyphId,\n\tppem: number,\n): SbixGlyph | null {\n\t// Find best matching strike\n\tlet bestStrike: SbixStrike | null = null;\n\tlet bestDiff = Infinity;\n\n\tfor (const strike of sbix.strikes) {\n\t\tconst diff = Math.abs(strike.ppem - ppem);\n\t\tif (diff < bestDiff) {\n\t\t\tbestDiff = diff;\n\t\t\tbestStrike = strike;\n\t\t}\n\t}\n\n\tif (!bestStrike) return null;\n\n\treturn bestStrike.glyphData.get(glyphId) ?? null;\n}\n\n/**\n * Get exact ppem strike\n */\nexport function getStrikeForPpem(\n\tsbix: SbixTable,\n\tppem: number,\n): SbixStrike | null {\n\treturn sbix.strikes.find((s) => s.ppem === ppem) ?? null;\n}\n\n/**\n * Get all available ppem sizes\n */\nexport function getAvailablePpemSizes(sbix: SbixTable): number[] {\n\treturn sbix.strikes.map((s) => s.ppem).sort((a, b) => a - b);\n}\n\n/**\n * Check if glyph has bitmap data\n */\nexport function hasGlyphBitmap(\n\tsbix: SbixTable,\n\tglyphId: GlyphId,\n\tppem?: number,\n): boolean {\n\tif (ppem !== undefined) {\n\t\tconst strike = getStrikeForPpem(sbix, ppem);\n\t\treturn strike?.glyphData.has(glyphId) ?? false;\n\t}\n\n\t// Check any strike\n\tfor (const strike of sbix.strikes) {\n\t\tif (strike.glyphData.has(glyphId)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Resolve dupe graphic type\n * Returns the actual glyph data for duplicates\n */\nexport function resolveDupeGlyph(\n\tsbix: SbixTable,\n\tstrike: SbixStrike,\n\tglyph: SbixGlyph,\n): SbixGlyph | null {\n\tif (glyph.graphicType !== SbixGraphicType.DUPE) {\n\t\treturn glyph;\n\t}\n\n\t// Data contains the glyph ID to reference\n\tif (glyph.data.length < 2) return null;\n\n\tconst dupeGlyphId = (glyph.data[0]! << 8) | glyph.data[1]!;\n\tconst resolved = strike.glyphData.get(dupeGlyphId);\n\n\tif (!resolved) return null;\n\n\t// Recursively resolve if it's also a dupe\n\tif (resolved.graphicType === SbixGraphicType.DUPE) {\n\t\treturn resolveDupeGlyph(sbix, strike, resolved);\n\t}\n\n\treturn resolved;\n}\n",
48
+ "import type { TableRecord, Tag } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/** Supported sfnt version tags */\nconst SFNT_VERSION_TRUETYPE = 0x00010000; // TrueType\nconst SFNT_VERSION_OPENTYPE = 0x4f54544f; // 'OTTO' - CFF\nconst SFNT_VERSION_TRUE = 0x74727565; // 'true' - Apple TrueType\n\n/** Font directory containing table records */\nexport interface FontDirectory {\n\tsfntVersion: number;\n\tnumTables: number;\n\tsearchRange: number;\n\tentrySelector: number;\n\trangeShift: number;\n\ttables: Map<Tag, TableRecord>;\n}\n\n/**\n * Parse the sfnt font directory (table of contents).\n * This is the first thing read from any TrueType/OpenType font.\n */\nexport function parseFontDirectory(reader: Reader): FontDirectory {\n\tconst sfntVersion = reader.uint32();\n\n\t// Validate sfnt version\n\tif (\n\t\tsfntVersion !== SFNT_VERSION_TRUETYPE &&\n\t\tsfntVersion !== SFNT_VERSION_OPENTYPE &&\n\t\tsfntVersion !== SFNT_VERSION_TRUE\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid sfnt version: 0x${sfntVersion.toString(16).padStart(8, \"0\")}`,\n\t\t);\n\t}\n\n\tconst numTables = reader.uint16();\n\tconst searchRange = reader.uint16();\n\tconst entrySelector = reader.uint16();\n\tconst rangeShift = reader.uint16();\n\n\tconst tables = new Map<Tag, TableRecord>();\n\n\tfor (let i = 0; i < numTables; i++) {\n\t\tconst tag = reader.tag();\n\t\tconst checksum = reader.uint32();\n\t\tconst offset = reader.uint32();\n\t\tconst length = reader.uint32();\n\n\t\ttables.set(tag, { tag, checksum, offset, length });\n\t}\n\n\treturn {\n\t\tsfntVersion,\n\t\tnumTables,\n\t\tsearchRange,\n\t\tentrySelector,\n\t\trangeShift,\n\t\ttables,\n\t};\n}\n\n/** Check if this is a TrueType font (vs CFF) */\nexport function isTrueType(directory: FontDirectory): boolean {\n\treturn (\n\t\tdirectory.sfntVersion === SFNT_VERSION_TRUETYPE ||\n\t\tdirectory.sfntVersion === SFNT_VERSION_TRUE\n\t);\n}\n\n/** Check if this is a CFF font */\nexport function isCFF(directory: FontDirectory): boolean {\n\treturn directory.sfntVersion === SFNT_VERSION_OPENTYPE;\n}\n",
49
+ "import type { uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * AAT Feature Name table (feat)\n * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html\n *\n * Defines the font's typographic features that can be controlled by the user.\n * Each feature has a type and settings with human-readable names.\n */\nexport interface FeatTable {\n\tversion: number;\n\tfeatures: FeatureRecord[];\n}\n\n/**\n * A single feature record\n */\nexport interface FeatureRecord {\n\t/** Feature type (e.g., 1 = ligatures, 2 = cursive connection) */\n\tfeatureType: uint16;\n\t/** Number of settings for this feature */\n\tnSettings: uint16;\n\t/** Offset to setting name array */\n\tsettingTableOffset: uint32;\n\t/** Feature flags */\n\tfeatureFlags: uint16;\n\t/** Default setting index */\n\tdefaultSettingIndex: uint16;\n\t/** Name table ID for feature name */\n\tnameId: uint16;\n\t/** Parsed settings */\n\tsettings: FeatureSetting[];\n}\n\n/**\n * A single feature setting\n */\nexport interface FeatureSetting {\n\t/** Setting value to use in morx feature table */\n\tsettingValue: uint16;\n\t/** Name table ID for setting name */\n\tnameId: uint16;\n}\n\n/**\n * Feature type constants (Apple-defined)\n */\nexport enum FeatureType {\n\t/** All typographic features */\n\tAllTypographicFeatures = 0,\n\t/** Ligatures */\n\tLigatures = 1,\n\t/** Cursive connection */\n\tCursiveConnection = 2,\n\t/** Letter case */\n\tLetterCase = 3,\n\t/** Vertical substitution */\n\tVerticalSubstitution = 4,\n\t/** Linguistic rearrangement */\n\tLinguisticRearrangement = 5,\n\t/** Number spacing */\n\tNumberSpacing = 6,\n\t/** Smart swashes */\n\tSmartSwashes = 8,\n\t/** Diacritics */\n\tDiacritics = 9,\n\t/** Vertical position */\n\tVerticalPosition = 10,\n\t/** Fractions */\n\tFractions = 11,\n\t/** Overlapping characters */\n\tOverlappingCharacters = 13,\n\t/** Typographic extras */\n\tTypographicExtras = 14,\n\t/** Mathematical extras */\n\tMathematicalExtras = 15,\n\t/** Ornament sets */\n\tOrnamentSets = 16,\n\t/** Character alternatives */\n\tCharacterAlternatives = 17,\n\t/** Design complexity */\n\tDesignComplexity = 18,\n\t/** Style options */\n\tStyleOptions = 19,\n\t/** Character shape */\n\tCharacterShape = 20,\n\t/** Number case */\n\tNumberCase = 21,\n\t/** Text spacing */\n\tTextSpacing = 22,\n\t/** Transliteration */\n\tTransliteration = 23,\n\t/** Annotation */\n\tAnnotation = 24,\n\t/** Kana spacing */\n\tKanaSpacing = 25,\n\t/** Ideographic spacing */\n\tIdeographicSpacing = 26,\n\t/** Unicode decomposition */\n\tUnicodeDecomposition = 27,\n\t/** Ruby kana */\n\tRubyKana = 28,\n\t/** CJK symbol alternatives */\n\tCJKSymbolAlternatives = 29,\n\t/** Ideographic alternatives */\n\tIdeographicAlternatives = 30,\n\t/** CJK vertical roman placement */\n\tCJKVerticalRomanPlacement = 31,\n\t/** Italic CJK roman */\n\tItalicCJKRoman = 32,\n\t/** Case-sensitive layout */\n\tCaseSensitiveLayout = 33,\n\t/** Alternate kana */\n\tAlternateKana = 34,\n\t/** Stylistic alternatives */\n\tStylisticAlternatives = 35,\n\t/** Contextual alternatives */\n\tContextualAlternatives = 36,\n\t/** Lower case */\n\tLowerCase = 37,\n\t/** Upper case */\n\tUpperCase = 38,\n\t/** Language tag */\n\tLanguageTag = 39,\n\t/** CJK roman spacing */\n\tCJKRomanSpacing = 103,\n}\n\n/**\n * Common ligature settings\n */\nexport enum LigatureSetting {\n\tRequiredLigaturesOn = 0,\n\tRequiredLigaturesOff = 1,\n\tCommonLigaturesOn = 2,\n\tCommonLigaturesOff = 3,\n\tRareLigaturesOn = 4,\n\tRareLigaturesOff = 5,\n\tLogosOn = 6,\n\tLogosOff = 7,\n\tRebusPicturesOn = 8,\n\tRebusPicturesOff = 9,\n\tDiphthongLigaturesOn = 10,\n\tDiphthongLigaturesOff = 11,\n\tSquaredLigaturesOn = 12,\n\tSquaredLigaturesOff = 13,\n\tAbbrevSquaredLigaturesOn = 14,\n\tAbbrevSquaredLigaturesOff = 15,\n\tSymbolLigaturesOn = 16,\n\tSymbolLigaturesOff = 17,\n\tContextualLigaturesOn = 18,\n\tContextualLigaturesOff = 19,\n\tHistoricalLigaturesOn = 20,\n\tHistoricalLigaturesOff = 21,\n}\n\n/**\n * Vertical position settings\n */\nexport enum VerticalPositionSetting {\n\tNormalPosition = 0,\n\tSuperiors = 1,\n\tInferiors = 2,\n\tOrdinals = 3,\n\tScientificInferiors = 4,\n}\n\n/**\n * Number case settings\n */\nexport enum NumberCaseSetting {\n\tLowerCaseNumbers = 0,\n\tUpperCaseNumbers = 1,\n}\n\n/**\n * Number spacing settings\n */\nexport enum NumberSpacingSetting {\n\tMonospacedNumbers = 0,\n\tProportionalNumbers = 1,\n\tThirdWidthNumbers = 2,\n\tQuarterWidthNumbers = 3,\n}\n\n/**\n * Fractions settings\n */\nexport enum FractionsSetting {\n\tNoFractions = 0,\n\tVerticalFractions = 1,\n\tDiagonalFractions = 2,\n}\n\n/**\n * Case-sensitive layout settings\n */\nexport enum CaseSensitiveLayoutSetting {\n\tCaseSensitiveLayoutOn = 0,\n\tCaseSensitiveLayoutOff = 1,\n\tCaseSensitiveSpacingOn = 2,\n\tCaseSensitiveSpacingOff = 3,\n}\n\n/**\n * Stylistic alternatives settings\n */\nexport enum StylisticAlternativesSetting {\n\tNoStylisticAlternates = 0,\n\tStylisticAltOneOn = 2,\n\tStylisticAltOneOff = 3,\n\tStylisticAltTwoOn = 4,\n\tStylisticAltTwoOff = 5,\n\tStylisticAltThreeOn = 6,\n\tStylisticAltThreeOff = 7,\n\tStylisticAltFourOn = 8,\n\tStylisticAltFourOff = 9,\n\tStylisticAltFiveOn = 10,\n\tStylisticAltFiveOff = 11,\n\tStylisticAltSixOn = 12,\n\tStylisticAltSixOff = 13,\n\tStylisticAltSevenOn = 14,\n\tStylisticAltSevenOff = 15,\n\tStylisticAltEightOn = 16,\n\tStylisticAltEightOff = 17,\n\tStylisticAltNineOn = 18,\n\tStylisticAltNineOff = 19,\n\tStylisticAltTenOn = 20,\n\tStylisticAltTenOff = 21,\n\tStylisticAltElevenOn = 22,\n\tStylisticAltElevenOff = 23,\n\tStylisticAltTwelveOn = 24,\n\tStylisticAltTwelveOff = 25,\n\tStylisticAltThirteenOn = 26,\n\tStylisticAltThirteenOff = 27,\n\tStylisticAltFourteenOn = 28,\n\tStylisticAltFourteenOff = 29,\n\tStylisticAltFifteenOn = 30,\n\tStylisticAltFifteenOff = 31,\n\tStylisticAltSixteenOn = 32,\n\tStylisticAltSixteenOff = 33,\n\tStylisticAltSeventeenOn = 34,\n\tStylisticAltSeventeenOff = 35,\n\tStylisticAltEighteenOn = 36,\n\tStylisticAltEighteenOff = 37,\n\tStylisticAltNineteenOn = 38,\n\tStylisticAltNineteenOff = 39,\n\tStylisticAltTwentyOn = 40,\n\tStylisticAltTwentyOff = 41,\n}\n\n/**\n * Contextual alternatives settings\n */\nexport enum ContextualAlternativesSetting {\n\tContextualAlternatesOn = 0,\n\tContextualAlternatesOff = 1,\n\tSwashAlternatesOn = 2,\n\tSwashAlternatesOff = 3,\n\tContextualSwashAlternatesOn = 4,\n\tContextualSwashAlternatesOff = 5,\n}\n\n/**\n * Lower case settings\n */\nexport enum LowerCaseSetting {\n\tDefaultLowerCase = 0,\n\tLowerCaseSmallCaps = 1,\n\tLowerCasePetiteCaps = 2,\n}\n\n/**\n * Upper case settings\n */\nexport enum UpperCaseSetting {\n\tDefaultUpperCase = 0,\n\tUpperCaseSmallCaps = 1,\n\tUpperCasePetiteCaps = 2,\n}\n\n/**\n * Smart swash settings\n */\nexport enum SmartSwashSetting {\n\tWordInitialSwashesOn = 0,\n\tWordInitialSwashesOff = 1,\n\tWordFinalSwashesOn = 2,\n\tWordFinalSwashesOff = 3,\n\tLineInitialSwashesOn = 4,\n\tLineInitialSwashesOff = 5,\n\tLineFinalSwashesOn = 6,\n\tLineFinalSwashesOff = 7,\n\tNonFinalSwashesOn = 8,\n\tNonFinalSwashesOff = 9,\n}\n\n/**\n * Diacritics settings\n */\nexport enum DiacriticsSetting {\n\tShowDiacritics = 0,\n\tHideDiacritics = 1,\n\tDecomposeDiacritics = 2,\n}\n\n/**\n * Character shape settings (CJK)\n */\nexport enum CharacterShapeSetting {\n\tTraditionalCharacters = 0,\n\tSimplifiedCharacters = 1,\n\tJIS1978Characters = 2,\n\tJIS1983Characters = 3,\n\tJIS1990Characters = 4,\n\tTraditionalAltOne = 5,\n\tTraditionalAltTwo = 6,\n\tTraditionalAltThree = 7,\n\tTraditionalAltFour = 8,\n\tTraditionalAltFive = 9,\n\tExpertCharacters = 10,\n\tNLCCharacters = 13,\n\tJIS2004Characters = 11,\n\tHojoCharacters = 12,\n}\n\n/**\n * Feature flag bits\n */\nexport enum FeatureFlags {\n\t/** Feature settings are mutually exclusive */\n\tExclusive = 0x8000,\n\t/** Use default setting index if not specified */\n\tUseDefault = 0x4000,\n}\n\n/**\n * Parse feat table\n */\nexport function parseFeat(reader: Reader): FeatTable {\n\tconst tableStart = reader.offset;\n\n\tconst version = reader.fixed();\n\tconst featureNameCount = reader.uint16();\n\treader.skip(2); // reserved\n\treader.skip(4); // reserved\n\n\tconst features: FeatureRecord[] = [];\n\n\tfor (let i = 0; i < featureNameCount; i++) {\n\t\tconst featureType = reader.uint16();\n\t\tconst nSettings = reader.uint16();\n\t\tconst settingTableOffset = reader.offset32();\n\t\tconst featureFlags = reader.uint16();\n\t\tconst defaultSettingIndex = featureFlags & 0xff;\n\t\tconst nameId = reader.uint16();\n\n\t\t// Parse settings\n\t\tconst settings: FeatureSetting[] = [];\n\t\tconst savedOffset = reader.offset;\n\n\t\treader.seek(tableStart + settingTableOffset);\n\t\tfor (let j = 0; j < nSettings; j++) {\n\t\t\tsettings.push({\n\t\t\t\tsettingValue: reader.uint16(),\n\t\t\t\tnameId: reader.uint16(),\n\t\t\t});\n\t\t}\n\n\t\treader.seek(savedOffset);\n\n\t\tfeatures.push({\n\t\t\tfeatureType,\n\t\t\tnSettings,\n\t\t\tsettingTableOffset,\n\t\t\tfeatureFlags,\n\t\t\tdefaultSettingIndex,\n\t\t\tnameId,\n\t\t\tsettings,\n\t\t});\n\t}\n\n\treturn { version, features };\n}\n\n/**\n * Get a feature by type\n */\nexport function getFeature(\n\ttable: FeatTable,\n\tfeatureType: FeatureType | uint16,\n): FeatureRecord | undefined {\n\treturn table.features.find((f) => f.featureType === featureType);\n}\n\n/**\n * Get all features of a given type\n */\nexport function getAllFeatures(table: FeatTable): FeatureRecord[] {\n\treturn table.features;\n}\n\n/**\n * Check if a feature is exclusive (only one setting can be active)\n */\nexport function isExclusiveFeature(feature: FeatureRecord): boolean {\n\treturn (feature.featureFlags & FeatureFlags.Exclusive) !== 0;\n}\n\n/**\n * Get the default setting for a feature\n */\nexport function getDefaultSetting(\n\tfeature: FeatureRecord,\n): FeatureSetting | undefined {\n\treturn feature.settings[feature.defaultSettingIndex];\n}\n\n/**\n * Get a setting by value\n */\nexport function getSettingByValue(\n\tfeature: FeatureRecord,\n\tsettingValue: uint16,\n): FeatureSetting | undefined {\n\treturn feature.settings.find((s) => s.settingValue === settingValue);\n}\n\n/**\n * Check if a feature has a specific setting\n */\nexport function hasSettingValue(\n\tfeature: FeatureRecord,\n\tsettingValue: uint16,\n): boolean {\n\treturn feature.settings.some((s) => s.settingValue === settingValue);\n}\n\n/**\n * Convert AAT feature type/setting to OpenType feature tag\n * This is a best-effort mapping as there's no 1:1 correspondence\n */\nexport function aatToOpenTypeTag(\n\tfeatureType: FeatureType | uint16,\n\tsettingValue: uint16,\n): string | null {\n\tswitch (featureType) {\n\t\tcase FeatureType.Ligatures:\n\t\t\tswitch (settingValue) {\n\t\t\t\tcase LigatureSetting.CommonLigaturesOn:\n\t\t\t\t\treturn \"liga\";\n\t\t\t\tcase LigatureSetting.RareLigaturesOn:\n\t\t\t\t\treturn \"dlig\";\n\t\t\t\tcase LigatureSetting.HistoricalLigaturesOn:\n\t\t\t\t\treturn \"hlig\";\n\t\t\t\tcase LigatureSetting.ContextualLigaturesOn:\n\t\t\t\t\treturn \"clig\";\n\t\t\t\tcase LigatureSetting.RequiredLigaturesOn:\n\t\t\t\t\treturn \"rlig\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.VerticalPosition:\n\t\t\tswitch (settingValue) {\n\t\t\t\tcase VerticalPositionSetting.Superiors:\n\t\t\t\t\treturn \"sups\";\n\t\t\t\tcase VerticalPositionSetting.Inferiors:\n\t\t\t\t\treturn \"subs\";\n\t\t\t\tcase VerticalPositionSetting.Ordinals:\n\t\t\t\t\treturn \"ordn\";\n\t\t\t\tcase VerticalPositionSetting.ScientificInferiors:\n\t\t\t\t\treturn \"sinf\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.Fractions:\n\t\t\tif (\n\t\t\t\tsettingValue === FractionsSetting.VerticalFractions ||\n\t\t\t\tsettingValue === FractionsSetting.DiagonalFractions\n\t\t\t) {\n\t\t\t\treturn \"frac\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.NumberCase:\n\t\t\tswitch (settingValue) {\n\t\t\t\tcase NumberCaseSetting.LowerCaseNumbers:\n\t\t\t\t\treturn \"onum\";\n\t\t\t\tcase NumberCaseSetting.UpperCaseNumbers:\n\t\t\t\t\treturn \"lnum\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.NumberSpacing:\n\t\t\tswitch (settingValue) {\n\t\t\t\tcase NumberSpacingSetting.MonospacedNumbers:\n\t\t\t\t\treturn \"tnum\";\n\t\t\t\tcase NumberSpacingSetting.ProportionalNumbers:\n\t\t\t\t\treturn \"pnum\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.CaseSensitiveLayout:\n\t\t\tif (settingValue === CaseSensitiveLayoutSetting.CaseSensitiveLayoutOn) {\n\t\t\t\treturn \"case\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.LowerCase:\n\t\t\tswitch (settingValue) {\n\t\t\t\tcase LowerCaseSetting.LowerCaseSmallCaps:\n\t\t\t\t\treturn \"smcp\";\n\t\t\t\tcase LowerCaseSetting.LowerCasePetiteCaps:\n\t\t\t\t\treturn \"pcap\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.UpperCase:\n\t\t\tswitch (settingValue) {\n\t\t\t\tcase UpperCaseSetting.UpperCaseSmallCaps:\n\t\t\t\t\treturn \"c2sc\";\n\t\t\t\tcase UpperCaseSetting.UpperCasePetiteCaps:\n\t\t\t\t\treturn \"c2pc\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.SmartSwashes:\n\t\t\tif (\n\t\t\t\tsettingValue === SmartSwashSetting.WordInitialSwashesOn ||\n\t\t\t\tsettingValue === SmartSwashSetting.WordFinalSwashesOn\n\t\t\t) {\n\t\t\t\treturn \"swsh\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.ContextualAlternatives:\n\t\t\tswitch (settingValue) {\n\t\t\t\tcase ContextualAlternativesSetting.ContextualAlternatesOn:\n\t\t\t\t\treturn \"calt\";\n\t\t\t\tcase ContextualAlternativesSetting.SwashAlternatesOn:\n\t\t\t\t\treturn \"swsh\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.StylisticAlternatives:\n\t\t\t// Stylistic sets ss01-ss20\n\t\t\tif (settingValue >= 2 && settingValue <= 41) {\n\t\t\t\tconst setNum = Math.floor((settingValue - 2) / 2) + 1;\n\t\t\t\tif (setNum <= 20) {\n\t\t\t\t\treturn `ss${setNum.toString().padStart(2, \"0\")}`;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.CharacterShape:\n\t\t\tswitch (settingValue) {\n\t\t\t\tcase CharacterShapeSetting.TraditionalCharacters:\n\t\t\t\t\treturn \"trad\";\n\t\t\t\tcase CharacterShapeSetting.SimplifiedCharacters:\n\t\t\t\t\treturn \"smpl\";\n\t\t\t\tcase CharacterShapeSetting.JIS1978Characters:\n\t\t\t\t\treturn \"jp78\";\n\t\t\t\tcase CharacterShapeSetting.JIS1983Characters:\n\t\t\t\t\treturn \"jp83\";\n\t\t\t\tcase CharacterShapeSetting.JIS1990Characters:\n\t\t\t\t\treturn \"jp90\";\n\t\t\t\tcase CharacterShapeSetting.JIS2004Characters:\n\t\t\t\t\treturn \"jp04\";\n\t\t\t\tcase CharacterShapeSetting.NLCCharacters:\n\t\t\t\t\treturn \"nlck\";\n\t\t\t\tcase CharacterShapeSetting.ExpertCharacters:\n\t\t\t\t\treturn \"expt\";\n\t\t\t\tcase CharacterShapeSetting.HojoCharacters:\n\t\t\t\t\treturn \"hojo\";\n\t\t\t}\n\t\t\tbreak;\n\t\tcase FeatureType.VerticalSubstitution:\n\t\t\treturn \"vert\";\n\t\tcase FeatureType.Annotation:\n\t\t\treturn \"nalt\";\n\t\tcase FeatureType.RubyKana:\n\t\t\treturn \"ruby\";\n\t}\n\n\treturn null;\n}\n\n/**\n * Convert OpenType feature tag to AAT feature type/setting\n * Returns null if no mapping exists\n */\nexport function openTypeTagToAat(\n\ttag: string,\n): { featureType: FeatureType; settingValue: uint16 } | null {\n\tswitch (tag) {\n\t\tcase \"liga\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.Ligatures,\n\t\t\t\tsettingValue: LigatureSetting.CommonLigaturesOn,\n\t\t\t};\n\t\tcase \"dlig\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.Ligatures,\n\t\t\t\tsettingValue: LigatureSetting.RareLigaturesOn,\n\t\t\t};\n\t\tcase \"hlig\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.Ligatures,\n\t\t\t\tsettingValue: LigatureSetting.HistoricalLigaturesOn,\n\t\t\t};\n\t\tcase \"clig\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.Ligatures,\n\t\t\t\tsettingValue: LigatureSetting.ContextualLigaturesOn,\n\t\t\t};\n\t\tcase \"rlig\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.Ligatures,\n\t\t\t\tsettingValue: LigatureSetting.RequiredLigaturesOn,\n\t\t\t};\n\t\tcase \"sups\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.VerticalPosition,\n\t\t\t\tsettingValue: VerticalPositionSetting.Superiors,\n\t\t\t};\n\t\tcase \"subs\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.VerticalPosition,\n\t\t\t\tsettingValue: VerticalPositionSetting.Inferiors,\n\t\t\t};\n\t\tcase \"ordn\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.VerticalPosition,\n\t\t\t\tsettingValue: VerticalPositionSetting.Ordinals,\n\t\t\t};\n\t\tcase \"sinf\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.VerticalPosition,\n\t\t\t\tsettingValue: VerticalPositionSetting.ScientificInferiors,\n\t\t\t};\n\t\tcase \"frac\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.Fractions,\n\t\t\t\tsettingValue: FractionsSetting.DiagonalFractions,\n\t\t\t};\n\t\tcase \"onum\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.NumberCase,\n\t\t\t\tsettingValue: NumberCaseSetting.LowerCaseNumbers,\n\t\t\t};\n\t\tcase \"lnum\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.NumberCase,\n\t\t\t\tsettingValue: NumberCaseSetting.UpperCaseNumbers,\n\t\t\t};\n\t\tcase \"tnum\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.NumberSpacing,\n\t\t\t\tsettingValue: NumberSpacingSetting.MonospacedNumbers,\n\t\t\t};\n\t\tcase \"pnum\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.NumberSpacing,\n\t\t\t\tsettingValue: NumberSpacingSetting.ProportionalNumbers,\n\t\t\t};\n\t\tcase \"case\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.CaseSensitiveLayout,\n\t\t\t\tsettingValue: CaseSensitiveLayoutSetting.CaseSensitiveLayoutOn,\n\t\t\t};\n\t\tcase \"smcp\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.LowerCase,\n\t\t\t\tsettingValue: LowerCaseSetting.LowerCaseSmallCaps,\n\t\t\t};\n\t\tcase \"pcap\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.LowerCase,\n\t\t\t\tsettingValue: LowerCaseSetting.LowerCasePetiteCaps,\n\t\t\t};\n\t\tcase \"c2sc\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.UpperCase,\n\t\t\t\tsettingValue: UpperCaseSetting.UpperCaseSmallCaps,\n\t\t\t};\n\t\tcase \"c2pc\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.UpperCase,\n\t\t\t\tsettingValue: UpperCaseSetting.UpperCasePetiteCaps,\n\t\t\t};\n\t\tcase \"swsh\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.SmartSwashes,\n\t\t\t\tsettingValue: SmartSwashSetting.WordInitialSwashesOn,\n\t\t\t};\n\t\tcase \"calt\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.ContextualAlternatives,\n\t\t\t\tsettingValue: ContextualAlternativesSetting.ContextualAlternatesOn,\n\t\t\t};\n\t\tcase \"trad\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.CharacterShape,\n\t\t\t\tsettingValue: CharacterShapeSetting.TraditionalCharacters,\n\t\t\t};\n\t\tcase \"smpl\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.CharacterShape,\n\t\t\t\tsettingValue: CharacterShapeSetting.SimplifiedCharacters,\n\t\t\t};\n\t\tcase \"jp78\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.CharacterShape,\n\t\t\t\tsettingValue: CharacterShapeSetting.JIS1978Characters,\n\t\t\t};\n\t\tcase \"jp83\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.CharacterShape,\n\t\t\t\tsettingValue: CharacterShapeSetting.JIS1983Characters,\n\t\t\t};\n\t\tcase \"jp90\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.CharacterShape,\n\t\t\t\tsettingValue: CharacterShapeSetting.JIS1990Characters,\n\t\t\t};\n\t\tcase \"jp04\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.CharacterShape,\n\t\t\t\tsettingValue: CharacterShapeSetting.JIS2004Characters,\n\t\t\t};\n\t\tcase \"nlck\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.CharacterShape,\n\t\t\t\tsettingValue: CharacterShapeSetting.NLCCharacters,\n\t\t\t};\n\t\tcase \"expt\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.CharacterShape,\n\t\t\t\tsettingValue: CharacterShapeSetting.ExpertCharacters,\n\t\t\t};\n\t\tcase \"hojo\":\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.CharacterShape,\n\t\t\t\tsettingValue: CharacterShapeSetting.HojoCharacters,\n\t\t\t};\n\t\tcase \"vert\":\n\t\t\treturn { featureType: FeatureType.VerticalSubstitution, settingValue: 0 };\n\t\tcase \"nalt\":\n\t\t\treturn { featureType: FeatureType.Annotation, settingValue: 0 };\n\t\tcase \"ruby\":\n\t\t\treturn { featureType: FeatureType.RubyKana, settingValue: 0 };\n\t}\n\n\t// Handle stylistic sets ss01-ss20\n\tif (tag.startsWith(\"ss\") && tag.length === 4) {\n\t\tconst num = parseInt(tag.slice(2), 10);\n\t\tif (num >= 1 && num <= 20) {\n\t\t\treturn {\n\t\t\t\tfeatureType: FeatureType.StylisticAlternatives,\n\t\t\t\tsettingValue: (num - 1) * 2 + 2,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn null;\n}\n",
50
+ "import type { Tag, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Style Attributes table (STAT)\n * Provides style information for variable fonts\n * Used for font selection and naming\n */\nexport interface StatTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\tdesignAxisCount: uint16;\n\tdesignAxes: AxisRecord[];\n\taxisValueCount: uint16;\n\taxisValues: AxisValue[];\n\telidedFallbackNameID?: uint16;\n}\n\n/**\n * Design axis record\n */\nexport interface AxisRecord {\n\taxisTag: Tag;\n\taxisNameID: uint16;\n\taxisOrdering: uint16;\n}\n\n/**\n * Axis value flags\n */\nexport const AxisValueFlags = {\n\tOlderSiblingFontAttribute: 0x0001,\n\tElidableAxisValueName: 0x0002,\n} as const;\n\n/**\n * Base axis value\n */\nexport interface AxisValueBase {\n\tformat: number;\n\taxisIndex: uint16;\n\tflags: uint16;\n\tvalueNameID: uint16;\n}\n\n/**\n * Format 1: Single axis value\n */\nexport interface AxisValueFormat1 extends AxisValueBase {\n\tformat: 1;\n\tvalue: number; // Fixed 16.16\n}\n\n/**\n * Format 2: Axis value range\n */\nexport interface AxisValueFormat2 extends AxisValueBase {\n\tformat: 2;\n\tnominalValue: number;\n\trangeMinValue: number;\n\trangeMaxValue: number;\n}\n\n/**\n * Format 3: Linked axis value\n */\nexport interface AxisValueFormat3 extends AxisValueBase {\n\tformat: 3;\n\tvalue: number;\n\tlinkedValue: number;\n}\n\n/**\n * Format 4: Multiple axis values\n */\nexport interface AxisValueFormat4 {\n\tformat: 4;\n\taxisCount: uint16;\n\tflags: uint16;\n\tvalueNameID: uint16;\n\taxisValues: { axisIndex: uint16; value: number }[];\n}\n\nexport type AxisValue =\n\t| AxisValueFormat1\n\t| AxisValueFormat2\n\t| AxisValueFormat3\n\t| AxisValueFormat4;\n\n/**\n * Parse STAT table\n */\nexport function parseStat(reader: Reader): StatTable {\n\tconst tableStart = reader.offset;\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst designAxisSize = reader.uint16();\n\tconst designAxisCount = reader.uint16();\n\tconst designAxesOffset = reader.offset32();\n\tconst axisValueCount = reader.uint16();\n\tconst axisValueArrayOffset = reader.offset32();\n\n\tlet elidedFallbackNameID: uint16 | undefined;\n\tif (majorVersion >= 1 && minorVersion >= 1) {\n\t\telidedFallbackNameID = reader.uint16();\n\t}\n\n\t// Parse design axes\n\tconst designAxes: AxisRecord[] = [];\n\tif (designAxesOffset !== 0) {\n\t\tconst axesReader = reader.sliceFrom(tableStart + designAxesOffset);\n\t\tfor (let i = 0; i < designAxisCount; i++) {\n\t\t\tdesignAxes.push({\n\t\t\t\taxisTag: axesReader.tag(),\n\t\t\t\taxisNameID: axesReader.uint16(),\n\t\t\t\taxisOrdering: axesReader.uint16(),\n\t\t\t});\n\t\t\t// Skip any additional bytes if designAxisSize > 8\n\t\t\tif (designAxisSize > 8) {\n\t\t\t\taxesReader.skip(designAxisSize - 8);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Parse axis values\n\tconst axisValues: AxisValue[] = [];\n\tif (axisValueArrayOffset !== 0 && axisValueCount > 0) {\n\t\tconst arrayReader = reader.sliceFrom(tableStart + axisValueArrayOffset);\n\n\t\t// Read axis value offsets\n\t\tconst axisValueOffsets: uint16[] = [];\n\t\tfor (let i = 0; i < axisValueCount; i++) {\n\t\t\taxisValueOffsets.push(arrayReader.uint16());\n\t\t}\n\n\t\t// Parse each axis value\n\t\tfor (const offset of axisValueOffsets) {\n\t\t\tconst valueReader = reader.sliceFrom(\n\t\t\t\ttableStart + axisValueArrayOffset + offset,\n\t\t\t);\n\t\t\tconst axisValue = parseAxisValue(valueReader);\n\t\t\tif (axisValue) {\n\t\t\t\taxisValues.push(axisValue);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\tdesignAxisCount,\n\t\tdesignAxes,\n\t\taxisValueCount,\n\t\taxisValues,\n\t\telidedFallbackNameID,\n\t};\n}\n\nfunction parseAxisValue(reader: Reader): AxisValue | null {\n\tconst format = reader.uint16();\n\n\tswitch (format) {\n\t\tcase 1: {\n\t\t\treturn {\n\t\t\t\tformat: 1,\n\t\t\t\taxisIndex: reader.uint16(),\n\t\t\t\tflags: reader.uint16(),\n\t\t\t\tvalueNameID: reader.uint16(),\n\t\t\t\tvalue: reader.fixed(),\n\t\t\t};\n\t\t}\n\t\tcase 2: {\n\t\t\treturn {\n\t\t\t\tformat: 2,\n\t\t\t\taxisIndex: reader.uint16(),\n\t\t\t\tflags: reader.uint16(),\n\t\t\t\tvalueNameID: reader.uint16(),\n\t\t\t\tnominalValue: reader.fixed(),\n\t\t\t\trangeMinValue: reader.fixed(),\n\t\t\t\trangeMaxValue: reader.fixed(),\n\t\t\t};\n\t\t}\n\t\tcase 3: {\n\t\t\treturn {\n\t\t\t\tformat: 3,\n\t\t\t\taxisIndex: reader.uint16(),\n\t\t\t\tflags: reader.uint16(),\n\t\t\t\tvalueNameID: reader.uint16(),\n\t\t\t\tvalue: reader.fixed(),\n\t\t\t\tlinkedValue: reader.fixed(),\n\t\t\t};\n\t\t}\n\t\tcase 4: {\n\t\t\tconst axisCount = reader.uint16();\n\t\t\tconst flags = reader.uint16();\n\t\t\tconst valueNameID = reader.uint16();\n\n\t\t\tconst axisValues: { axisIndex: uint16; value: number }[] = [];\n\t\t\tfor (let i = 0; i < axisCount; i++) {\n\t\t\t\taxisValues.push({\n\t\t\t\t\taxisIndex: reader.uint16(),\n\t\t\t\t\tvalue: reader.fixed(),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tformat: 4,\n\t\t\t\taxisCount,\n\t\t\t\tflags,\n\t\t\t\tvalueNameID,\n\t\t\t\taxisValues,\n\t\t\t};\n\t\t}\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\n/**\n * Get axis record by tag\n */\nexport function getAxisRecord(\n\tstat: StatTable,\n\taxisTag: Tag,\n): AxisRecord | null {\n\treturn stat.designAxes.find((a) => a.axisTag === axisTag) ?? null;\n}\n\n/**\n * Get axis index by tag\n */\nexport function getAxisIndex(stat: StatTable, axisTag: Tag): number {\n\treturn stat.designAxes.findIndex((a) => a.axisTag === axisTag);\n}\n\n/**\n * Get axis values for a specific axis\n */\nexport function getAxisValuesForAxis(\n\tstat: StatTable,\n\taxisIndex: number,\n): AxisValue[] {\n\treturn stat.axisValues.filter((v) => {\n\t\tif (v.format === 4) {\n\t\t\treturn v.axisValues.some((av) => av.axisIndex === axisIndex);\n\t\t}\n\t\treturn v.axisIndex === axisIndex;\n\t});\n}\n\n/**\n * Find axis value by name ID\n */\nexport function findAxisValueByNameId(\n\tstat: StatTable,\n\tnameId: uint16,\n): AxisValue | null {\n\treturn stat.axisValues.find((v) => v.valueNameID === nameId) ?? null;\n}\n\n/**\n * Check if axis value is elidable\n */\nexport function isElidableAxisValue(axisValue: AxisValue): boolean {\n\treturn (axisValue.flags & AxisValueFlags.ElidableAxisValueName) !== 0;\n}\n\n/**\n * Check if axis value represents an older sibling font\n */\nexport function isOlderSiblingFont(axisValue: AxisValue): boolean {\n\treturn (axisValue.flags & AxisValueFlags.OlderSiblingFontAttribute) !== 0;\n}\n\n/**\n * Get the value for a format 1-3 axis value\n */\nexport function getAxisValueNumber(axisValue: AxisValue): number | null {\n\tswitch (axisValue.format) {\n\t\tcase 1:\n\t\tcase 3:\n\t\t\treturn axisValue.value;\n\t\tcase 2:\n\t\t\treturn axisValue.nominalValue;\n\t\tcase 4:\n\t\t\treturn null; // Format 4 has multiple values\n\t}\n}\n\n/**\n * Match axis value to coordinates\n * Returns true if the axis value matches the given coordinates\n */\nexport function matchAxisValue(\n\taxisValue: AxisValue,\n\tcoords: Map<number, number>,\n): boolean {\n\tswitch (axisValue.format) {\n\t\tcase 1:\n\t\tcase 3: {\n\t\t\tconst coord = coords.get(axisValue.axisIndex);\n\t\t\treturn coord !== undefined && coord === axisValue.value;\n\t\t}\n\t\tcase 2: {\n\t\t\tconst coord = coords.get(axisValue.axisIndex);\n\t\t\treturn (\n\t\t\t\tcoord !== undefined &&\n\t\t\t\tcoord >= axisValue.rangeMinValue &&\n\t\t\t\tcoord <= axisValue.rangeMaxValue\n\t\t\t);\n\t\t}\n\t\tcase 4: {\n\t\t\treturn axisValue.axisValues.every((av) => {\n\t\t\t\tconst coord = coords.get(av.axisIndex);\n\t\t\t\treturn coord !== undefined && coord === av.value;\n\t\t\t});\n\t\t}\n\t}\n}\n",
51
+ "import type { GlyphId, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * SVG table\n * Contains SVG documents for color glyph rendering\n */\nexport interface SvgTable {\n\tversion: uint16;\n\tdocumentRecords: SvgDocumentRecord[];\n}\n\n/**\n * SVG document record\n * Maps a range of glyphs to an SVG document\n */\nexport interface SvgDocumentRecord {\n\tstartGlyphID: GlyphId;\n\tendGlyphID: GlyphId;\n\tsvgDoc: string;\n}\n\n/**\n * Parse SVG table\n */\nexport function parseSvg(reader: Reader): SvgTable {\n\tconst version = reader.uint16();\n\n\t// SVG Document List offset (from start of SVG table)\n\tconst svgDocumentListOffset = reader.offset32();\n\n\t// Reserved\n\treader.skip(4);\n\n\t// Parse document list\n\tconst listReader = reader.sliceFrom(svgDocumentListOffset);\n\tconst numEntries = listReader.uint16();\n\n\t// Read document index entries\n\tconst entries: {\n\t\tstartGlyphID: uint16;\n\t\tendGlyphID: uint16;\n\t\tsvgDocOffset: uint32;\n\t\tsvgDocLength: uint32;\n\t}[] = [];\n\n\tfor (let i = 0; i < numEntries; i++) {\n\t\tentries.push({\n\t\t\tstartGlyphID: listReader.uint16(),\n\t\t\tendGlyphID: listReader.uint16(),\n\t\t\tsvgDocOffset: listReader.offset32(),\n\t\t\tsvgDocLength: listReader.uint32(),\n\t\t});\n\t}\n\n\t// Parse SVG documents\n\tconst documentRecords: SvgDocumentRecord[] = [];\n\tconst decoder = new TextDecoder(\"utf-8\");\n\n\tfor (const entry of entries) {\n\t\t// SVG doc offset is relative to SVG Document List\n\t\tconst docReader = listReader.sliceFrom(entry.svgDocOffset);\n\t\tconst svgBytes = docReader.bytes(entry.svgDocLength);\n\n\t\t// Decompress if gzipped (starts with 0x1F 0x8B)\n\t\tlet svgDoc: string;\n\t\tif (svgBytes[0] === 0x1f && svgBytes[1] === 0x8b) {\n\t\t\t// Gzipped SVG - need to decompress\n\t\t\ttry {\n\t\t\t\tconst decompressed = decompressGzip(svgBytes);\n\t\t\t\tsvgDoc = decoder.decode(decompressed);\n\t\t\t} catch {\n\t\t\t\t// If decompression fails, try as plain text\n\t\t\t\tsvgDoc = decoder.decode(svgBytes);\n\t\t\t}\n\t\t} else {\n\t\t\tsvgDoc = decoder.decode(svgBytes);\n\t\t}\n\n\t\tdocumentRecords.push({\n\t\t\tstartGlyphID: entry.startGlyphID,\n\t\t\tendGlyphID: entry.endGlyphID,\n\t\t\tsvgDoc,\n\t\t});\n\t}\n\n\treturn { version, documentRecords };\n}\n\n/**\n * Get SVG document for a glyph\n * Returns null if no SVG exists for this glyph\n */\nexport function getSvgDocument(svg: SvgTable, glyphId: GlyphId): string | null {\n\tfor (const record of svg.documentRecords) {\n\t\tif (glyphId >= record.startGlyphID && glyphId <= record.endGlyphID) {\n\t\t\treturn record.svgDoc;\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * Check if a glyph has an SVG representation\n */\nexport function hasSvgGlyph(svg: SvgTable, glyphId: GlyphId): boolean {\n\treturn getSvgDocument(svg, glyphId) !== null;\n}\n\n/**\n * Get all glyph IDs that have SVG representations\n */\nexport function getSvgGlyphIds(svg: SvgTable): GlyphId[] {\n\tconst glyphIds: GlyphId[] = [];\n\n\tfor (const record of svg.documentRecords) {\n\t\tfor (let gid = record.startGlyphID; gid <= record.endGlyphID; gid++) {\n\t\t\tglyphIds.push(gid);\n\t\t}\n\t}\n\n\treturn glyphIds;\n}\n\n/**\n * Simple gzip decompression using DecompressionStream (if available)\n * Falls back to returning original data if not supported\n */\nfunction decompressGzip(data: Uint8Array): Uint8Array {\n\t// Use DecompressionStream if available (modern browsers/Bun)\n\tif (typeof DecompressionStream !== \"undefined\") {\n\t\t// This is async in nature, but we need sync.\n\t\t// For now, return original - proper implementation needs async\n\t\t// In practice, most SVG fonts use uncompressed SVG\n\t\treturn data;\n\t}\n\n\t// No decompression available, return as-is\n\treturn data;\n}\n\n/**\n * Async version of gzip decompression\n */\nexport async function decompressSvgDocument(data: Uint8Array): Promise<string> {\n\tconst decoder = new TextDecoder(\"utf-8\");\n\n\t// Check for gzip magic bytes\n\tif (data[0] === 0x1f && data[1] === 0x8b) {\n\t\tif (typeof DecompressionStream !== \"undefined\") {\n\t\t\tconst stream = new DecompressionStream(\"gzip\");\n\t\t\tconst writer = stream.writable.getWriter();\n\t\t\tconst reader = stream.readable.getReader();\n\n\t\t\twriter.write(data as unknown as BufferSource);\n\t\t\twriter.close();\n\n\t\t\tconst chunks: Uint8Array[] = [];\n\t\t\tlet result = await reader.read();\n\t\t\twhile (!result.done) {\n\t\t\t\tchunks.push(result.value);\n\t\t\t\tresult = await reader.read();\n\t\t\t}\n\n\t\t\tconst totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);\n\t\t\tconst decompressed = new Uint8Array(totalLength);\n\t\t\tlet offset = 0;\n\t\t\tfor (const chunk of chunks) {\n\t\t\t\tdecompressed.set(chunk, offset);\n\t\t\t\toffset += chunk.length;\n\t\t\t}\n\n\t\t\treturn decoder.decode(decompressed);\n\t\t}\n\t}\n\n\treturn decoder.decode(data);\n}\n",
52
+ "import type { int16, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Tracking table (trak)\n * Apple Advanced Typography tracking\n */\nexport interface TrakTable {\n\tversion: number;\n\tformat: uint16;\n\thorizData: TrackData | null;\n\tvertData: TrackData | null;\n}\n\n/**\n * Track data for one direction\n */\nexport interface TrackData {\n\tnTracks: uint16;\n\tnSizes: uint16;\n\tsizeTableOffset: uint32;\n\ttrackTable: TrackTableEntry[];\n\tsizeTable: number[]; // Fixed point sizes\n}\n\n/**\n * Track table entry\n */\nexport interface TrackTableEntry {\n\ttrack: number; // Fixed 16.16\n\tnameIndex: uint16;\n\toffset: uint16;\n\tperSizeTracking: int16[];\n}\n\n/**\n * Parse trak table\n */\nexport function parseTrak(reader: Reader): TrakTable {\n\tconst version = reader.uint32() / 65536; // Fixed 16.16\n\tconst format = reader.uint16();\n\tconst horizOffset = reader.offset16();\n\tconst vertOffset = reader.offset16();\n\treader.skip(2); // reserved\n\n\tlet horizData: TrackData | null = null;\n\tlet vertData: TrackData | null = null;\n\n\tif (horizOffset !== 0) {\n\t\thorizData = parseTrackData(reader.sliceFrom(horizOffset));\n\t}\n\n\tif (vertOffset !== 0) {\n\t\tvertData = parseTrackData(reader.sliceFrom(vertOffset));\n\t}\n\n\treturn {\n\t\tversion,\n\t\tformat,\n\t\thorizData,\n\t\tvertData,\n\t};\n}\n\nfunction parseTrackData(reader: Reader): TrackData {\n\tconst nTracks = reader.uint16();\n\tconst nSizes = reader.uint16();\n\tconst sizeTableOffset = reader.offset32();\n\n\tconst trackTable: TrackTableEntry[] = [];\n\n\t// Read track entries\n\tfor (let i = 0; i < nTracks; i++) {\n\t\tconst track = reader.int32() / 65536; // Fixed 16.16\n\t\tconst nameIndex = reader.uint16();\n\t\tconst offset = reader.uint16();\n\n\t\ttrackTable.push({\n\t\t\ttrack,\n\t\t\tnameIndex,\n\t\t\toffset,\n\t\t\tperSizeTracking: [],\n\t\t});\n\t}\n\n\t// Read per-size tracking values for each track\n\tfor (const entry of trackTable) {\n\t\tconst trackReader = reader.sliceFrom(entry.offset);\n\t\tentry.perSizeTracking = [];\n\t\tfor (let i = 0; i < nSizes; i++) {\n\t\t\tentry.perSizeTracking.push(trackReader.int16());\n\t\t}\n\t}\n\n\t// Read size table\n\tconst sizeReader = reader.sliceFrom(sizeTableOffset);\n\tconst sizeTable: number[] = [];\n\tfor (let i = 0; i < nSizes; i++) {\n\t\tsizeTable.push(sizeReader.int32() / 65536); // Fixed 16.16\n\t}\n\n\treturn {\n\t\tnTracks,\n\t\tnSizes,\n\t\tsizeTableOffset,\n\t\ttrackTable,\n\t\tsizeTable,\n\t};\n}\n\n/**\n * Get tracking value for a given track and point size\n */\nexport function getTrackingValue(\n\ttrackData: TrackData,\n\ttrack: number,\n\tpointSize: number,\n): number {\n\t// Find the track entry\n\tlet trackEntry: TrackTableEntry | null = null;\n\n\tfor (const entry of trackData.trackTable) {\n\t\tif (entry.track === track) {\n\t\t\ttrackEntry = entry;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// If exact track not found, interpolate between nearest\n\tif (!trackEntry) {\n\t\tlet lower: TrackTableEntry | null = null;\n\t\tlet upper: TrackTableEntry | null = null;\n\n\t\tfor (const entry of trackData.trackTable) {\n\t\t\tif (entry.track <= track && (!lower || entry.track > lower.track)) {\n\t\t\t\tlower = entry;\n\t\t\t}\n\t\t\tif (entry.track >= track && (!upper || entry.track < upper.track)) {\n\t\t\t\tupper = entry;\n\t\t\t}\n\t\t}\n\n\t\tif (lower && upper && lower !== upper) {\n\t\t\t// Interpolate between tracks\n\t\t\tconst t = (track - lower.track) / (upper.track - lower.track);\n\t\t\tconst lowerValue = getSizeValue(trackData, lower, pointSize);\n\t\t\tconst upperValue = getSizeValue(trackData, upper, pointSize);\n\t\t\treturn Math.round(lowerValue + t * (upperValue - lowerValue));\n\t\t} else if (lower) {\n\t\t\ttrackEntry = lower;\n\t\t} else if (upper) {\n\t\t\ttrackEntry = upper;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tif (!trackEntry) return 0;\n\n\treturn getSizeValue(trackData, trackEntry, pointSize);\n}\n\nfunction getSizeValue(\n\ttrackData: TrackData,\n\tentry: TrackTableEntry,\n\tpointSize: number,\n): number {\n\tconst sizes = trackData.sizeTable;\n\tconst values = entry.perSizeTracking;\n\n\tif (sizes.length === 0 || values.length === 0) return 0;\n\n\tconst firstSize = sizes[0];\n\tconst firstValue = values[0];\n\tif (firstSize === undefined || firstValue === undefined) return 0;\n\n\t// Find size range\n\tif (pointSize <= firstSize) {\n\t\treturn firstValue;\n\t}\n\n\tconst lastSize = sizes[sizes.length - 1];\n\tconst lastValue = values[values.length - 1];\n\tif (lastSize === undefined || lastValue === undefined) return 0;\n\n\tif (pointSize >= lastSize) {\n\t\treturn lastValue;\n\t}\n\n\t// Interpolate\n\tfor (let i = 0; i < sizes.length - 1; i++) {\n\t\tconst size1 = sizes[i];\n\t\tconst size2 = sizes[i + 1];\n\t\tconst value1 = values[i];\n\t\tconst value2 = values[i + 1];\n\t\tif (\n\t\t\tsize1 === undefined ||\n\t\t\tsize2 === undefined ||\n\t\t\tvalue1 === undefined ||\n\t\t\tvalue2 === undefined\n\t\t)\n\t\t\tcontinue;\n\n\t\tif (pointSize >= size1 && pointSize <= size2) {\n\t\t\tconst t = (pointSize - size1) / (size2 - size1);\n\t\t\treturn Math.round(value1 + t * (value2 - value1));\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n/**\n * Apply tracking to advance widths\n */\nexport function applyTracking(\n\ttrak: TrakTable,\n\tadvances: number[],\n\tpointSize: number,\n\ttrack: number = 0,\n\tvertical: boolean = false,\n): void {\n\tconst trackData = vertical ? trak.vertData : trak.horizData;\n\tif (!trackData) return;\n\n\tconst trackingValue = getTrackingValue(trackData, track, pointSize);\n\tif (trackingValue === 0) return;\n\n\t// Add tracking to each advance\n\tfor (const [i, advance] of advances.entries()) {\n\t\tadvances[i] = (advance ?? 0) + trackingValue;\n\t}\n}\n",
53
+ "import type { FWord, int16, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Vertical Header table (vhea)\n * Contains information for vertical layout\n */\nexport interface VheaTable {\n\t/** Table version (1.0 or 1.1) */\n\tversion: { major: number; minor: number };\n\t/** Typographic ascent (vertical) */\n\tascender: FWord;\n\t/** Typographic descent (vertical) */\n\tdescender: FWord;\n\t/** Typographic line gap (vertical) */\n\tlineGap: FWord;\n\t/** Maximum advance height */\n\tadvanceHeightMax: uint16;\n\t/** Minimum top side bearing */\n\tminTopSideBearing: FWord;\n\t/** Minimum bottom side bearing */\n\tminBottomSideBearing: FWord;\n\t/** Maximum y extent (yMax - yMin) */\n\tyMaxExtent: FWord;\n\t/** Caret slope rise (for vertical text) */\n\tcaretSlopeRise: int16;\n\t/** Caret slope run */\n\tcaretSlopeRun: int16;\n\t/** Caret offset */\n\tcaretOffset: int16;\n\t/** Metric data format (0 for current) */\n\tmetricDataFormat: int16;\n\t/** Number of vertical metrics in vmtx */\n\tnumberOfVMetrics: uint16;\n}\n\n/**\n * Parse vhea table\n */\nexport function parseVhea(reader: Reader): VheaTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst ascender = reader.fword();\n\tconst descender = reader.fword();\n\tconst lineGap = reader.fword();\n\tconst advanceHeightMax = reader.uint16();\n\tconst minTopSideBearing = reader.fword();\n\tconst minBottomSideBearing = reader.fword();\n\tconst yMaxExtent = reader.fword();\n\tconst caretSlopeRise = reader.int16();\n\tconst caretSlopeRun = reader.int16();\n\tconst caretOffset = reader.int16();\n\n\t// Skip reserved fields\n\treader.skip(8);\n\n\tconst metricDataFormat = reader.int16();\n\tconst numberOfVMetrics = reader.uint16();\n\n\treturn {\n\t\tversion: { major: majorVersion, minor: minorVersion },\n\t\tascender,\n\t\tdescender,\n\t\tlineGap,\n\t\tadvanceHeightMax,\n\t\tminTopSideBearing,\n\t\tminBottomSideBearing,\n\t\tyMaxExtent,\n\t\tcaretSlopeRise,\n\t\tcaretSlopeRun,\n\t\tcaretOffset,\n\t\tmetricDataFormat,\n\t\tnumberOfVMetrics,\n\t};\n}\n",
54
+ "import type { GlyphId, int16, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Vertical Metrics table (vmtx)\n * Contains vertical metrics for each glyph\n */\nexport interface VmtxTable {\n\t/** Vertical metrics (advance height + top side bearing) */\n\tvMetrics: VerticalMetric[];\n\t/** Top side bearings for remaining glyphs */\n\ttopSideBearings: int16[];\n}\n\n/**\n * Vertical metric record\n */\nexport interface VerticalMetric {\n\t/** Advance height in font units */\n\tadvanceHeight: uint16;\n\t/** Top side bearing in font units */\n\ttopSideBearing: int16;\n}\n\n/**\n * Parse vmtx table\n * @param reader Binary reader\n * @param numberOfVMetrics From vhea table\n * @param numGlyphs Total number of glyphs\n */\nexport function parseVmtx(\n\treader: Reader,\n\tnumberOfVMetrics: number,\n\tnumGlyphs: number,\n): VmtxTable {\n\tconst vMetrics: VerticalMetric[] = [];\n\n\t// Read full vertical metrics\n\tfor (let i = 0; i < numberOfVMetrics; i++) {\n\t\tvMetrics.push({\n\t\t\tadvanceHeight: reader.uint16(),\n\t\t\ttopSideBearing: reader.int16(),\n\t\t});\n\t}\n\n\t// Read additional top side bearings\n\tconst topSideBearings: int16[] = [];\n\tconst remaining = numGlyphs - numberOfVMetrics;\n\n\tfor (let i = 0; i < remaining; i++) {\n\t\ttopSideBearings.push(reader.int16());\n\t}\n\n\treturn { vMetrics, topSideBearings };\n}\n\n/**\n * Get vertical metrics for a glyph\n */\nexport function getVerticalMetrics(\n\tvmtx: VmtxTable,\n\tglyphId: GlyphId,\n): { advanceHeight: number; topSideBearing: number } {\n\tif (glyphId < vmtx.vMetrics.length) {\n\t\tconst metric = vmtx.vMetrics[glyphId];\n\t\tif (metric) {\n\t\t\treturn {\n\t\t\t\tadvanceHeight: metric.advanceHeight,\n\t\t\t\ttopSideBearing: metric.topSideBearing,\n\t\t\t};\n\t\t}\n\t}\n\n\t// Use last advance height, get TSB from array\n\tconst lastMetric = vmtx.vMetrics[vmtx.vMetrics.length - 1];\n\tconst advanceHeight = lastMetric?.advanceHeight ?? 0;\n\tconst tsbIndex = glyphId - vmtx.vMetrics.length;\n\tconst topSideBearing = vmtx.topSideBearings[tsbIndex] ?? 0;\n\n\treturn { advanceHeight, topSideBearing };\n}\n",
55
+ "import type { GlyphId, int16, uint16 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\n\n/**\n * Vertical Origin table (VORG)\n * Provides y-coordinate of vertical origin for CFF fonts\n * Used for proper vertical text layout in CJK fonts\n */\nexport interface VorgTable {\n\tmajorVersion: uint16;\n\tminorVersion: uint16;\n\tdefaultVertOriginY: int16;\n\tvertOriginYMetrics: VertOriginYMetric[];\n}\n\n/**\n * Vertical origin metric for a specific glyph\n */\nexport interface VertOriginYMetric {\n\tglyphIndex: GlyphId;\n\tvertOriginY: int16;\n}\n\n/**\n * Parse VORG table\n */\nexport function parseVorg(reader: Reader): VorgTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst defaultVertOriginY = reader.int16();\n\tconst numVertOriginYMetrics = reader.uint16();\n\n\tconst vertOriginYMetrics: VertOriginYMetric[] = [];\n\tfor (let i = 0; i < numVertOriginYMetrics; i++) {\n\t\tvertOriginYMetrics.push({\n\t\t\tglyphIndex: reader.uint16(),\n\t\t\tvertOriginY: reader.int16(),\n\t\t});\n\t}\n\n\t// Sort by glyph index for binary search\n\tvertOriginYMetrics.sort((a, b) => a.glyphIndex - b.glyphIndex);\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\tdefaultVertOriginY,\n\t\tvertOriginYMetrics,\n\t};\n}\n\n/**\n * Get vertical origin Y coordinate for a glyph\n * Returns the y-coordinate of the glyph's vertical origin\n */\nexport function getVertOriginY(vorg: VorgTable, glyphId: GlyphId): int16 {\n\t// Binary search for the glyph\n\tconst metrics = vorg.vertOriginYMetrics;\n\tlet lo = 0;\n\tlet hi = metrics.length - 1;\n\n\twhile (lo <= hi) {\n\t\tconst mid = (lo + hi) >>> 1;\n\t\tconst metric = metrics[mid]!;\n\n\t\tif (metric.glyphIndex === glyphId) {\n\t\t\treturn metric.vertOriginY;\n\t\t} else if (metric.glyphIndex < glyphId) {\n\t\t\tlo = mid + 1;\n\t\t} else {\n\t\t\thi = mid - 1;\n\t\t}\n\t}\n\n\t// Not found, use default\n\treturn vorg.defaultVertOriginY;\n}\n\n/**\n * Check if a glyph has a specific vertical origin entry\n */\nexport function hasVertOriginY(vorg: VorgTable, glyphId: GlyphId): boolean {\n\tconst metrics = vorg.vertOriginYMetrics;\n\tlet lo = 0;\n\tlet hi = metrics.length - 1;\n\n\twhile (lo <= hi) {\n\t\tconst mid = (lo + hi) >>> 1;\n\t\tconst metric = metrics[mid]!;\n\n\t\tif (metric.glyphIndex === glyphId) {\n\t\t\treturn true;\n\t\t} else if (metric.glyphIndex < glyphId) {\n\t\t\tlo = mid + 1;\n\t\t} else {\n\t\t\thi = mid - 1;\n\t\t}\n\t}\n\n\treturn false;\n}\n",
56
+ "import type { GlyphId, uint16, uint32 } from \"../../types.ts\";\nimport type { Reader } from \"../binary/reader.ts\";\nimport {\n\tcalculateRegionScalar,\n\ttype DeltaSetIndexMap,\n\ttype ItemVariationStore,\n\ttype VariationRegion,\n} from \"./hvar.ts\";\n\n/**\n * Vertical Metrics Variations table (VVAR)\n * Provides variations for vertical advance heights and side bearings\n */\nexport interface VvarTable {\n\tmajorVersion: number;\n\tminorVersion: number;\n\titemVariationStore: ItemVariationStore;\n\tadvanceHeightMapping: DeltaSetIndexMap | null;\n\ttsbMapping: DeltaSetIndexMap | null; // Top side bearing\n\tbsbMapping: DeltaSetIndexMap | null; // Bottom side bearing\n\tvOrgMapping: DeltaSetIndexMap | null; // Vertical origin\n}\n\n/**\n * Parse VVAR table\n */\nexport function parseVvar(reader: Reader): VvarTable {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst itemVariationStoreOffset = reader.offset32();\n\tconst advanceHeightMappingOffset = reader.offset32();\n\tconst tsbMappingOffset = reader.offset32();\n\tconst bsbMappingOffset = reader.offset32();\n\tconst vOrgMappingOffset = reader.offset32();\n\n\t// Parse item variation store\n\tconst itemVariationStore = parseItemVariationStore(\n\t\treader.sliceFrom(itemVariationStoreOffset),\n\t);\n\n\t// Parse mappings\n\tconst advanceHeightMapping =\n\t\tadvanceHeightMappingOffset !== 0\n\t\t\t? parseDeltaSetIndexMap(reader.sliceFrom(advanceHeightMappingOffset))\n\t\t\t: null;\n\n\tconst tsbMapping =\n\t\ttsbMappingOffset !== 0\n\t\t\t? parseDeltaSetIndexMap(reader.sliceFrom(tsbMappingOffset))\n\t\t\t: null;\n\n\tconst bsbMapping =\n\t\tbsbMappingOffset !== 0\n\t\t\t? parseDeltaSetIndexMap(reader.sliceFrom(bsbMappingOffset))\n\t\t\t: null;\n\n\tconst vOrgMapping =\n\t\tvOrgMappingOffset !== 0\n\t\t\t? parseDeltaSetIndexMap(reader.sliceFrom(vOrgMappingOffset))\n\t\t\t: null;\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\titemVariationStore,\n\t\tadvanceHeightMapping,\n\t\ttsbMapping,\n\t\tbsbMapping,\n\t\tvOrgMapping,\n\t};\n}\n\nfunction parseItemVariationStore(reader: Reader): ItemVariationStore {\n\tconst format = reader.uint16();\n\tconst variationRegionListOffset = reader.offset32();\n\tconst itemVariationDataCount = reader.uint16();\n\n\tconst itemVariationDataOffsets: uint32[] = [];\n\tfor (let i = 0; i < itemVariationDataCount; i++) {\n\t\titemVariationDataOffsets.push(reader.offset32());\n\t}\n\n\t// Parse variation regions\n\tconst regionReader = reader.sliceFrom(variationRegionListOffset);\n\tconst axisCount = regionReader.uint16();\n\tconst regionCount = regionReader.uint16();\n\n\tconst variationRegions: VariationRegion[] = [];\n\tfor (let i = 0; i < regionCount; i++) {\n\t\tconst regionAxes: {\n\t\t\tstartCoord: number;\n\t\t\tpeakCoord: number;\n\t\t\tendCoord: number;\n\t\t}[] = [];\n\t\tfor (let j = 0; j < axisCount; j++) {\n\t\t\tregionAxes.push({\n\t\t\t\tstartCoord: regionReader.f2dot14(),\n\t\t\t\tpeakCoord: regionReader.f2dot14(),\n\t\t\t\tendCoord: regionReader.f2dot14(),\n\t\t\t});\n\t\t}\n\t\tvariationRegions.push({ regionAxes });\n\t}\n\n\t// Parse item variation data\n\tconst itemVariationData: {\n\t\titemCount: uint16;\n\t\tregionIndexes: uint16[];\n\t\tdeltaSets: number[][];\n\t}[] = [];\n\tfor (const offset of itemVariationDataOffsets) {\n\t\tconst dataReader = reader.sliceFrom(offset);\n\t\tconst itemCount = dataReader.uint16();\n\t\tconst wordDeltaCount = dataReader.uint16();\n\t\tconst regionIndexCount = dataReader.uint16();\n\n\t\tconst regionIndexes: uint16[] = [];\n\t\tfor (let i = 0; i < regionIndexCount; i++) {\n\t\t\tregionIndexes.push(dataReader.uint16());\n\t\t}\n\n\t\t// Parse delta sets\n\t\tconst longWords = (wordDeltaCount & 0x8000) !== 0;\n\t\tconst wordCount = wordDeltaCount & 0x7fff;\n\t\tconst shortCount = regionIndexCount - wordCount;\n\n\t\tconst deltaSets: number[][] = [];\n\t\tfor (let i = 0; i < itemCount; i++) {\n\t\t\tconst deltas: number[] = [];\n\t\t\t// Read word-sized deltas\n\t\t\tfor (let j = 0; j < wordCount; j++) {\n\t\t\t\tif (longWords) {\n\t\t\t\t\tdeltas.push(dataReader.int32());\n\t\t\t\t} else {\n\t\t\t\t\tdeltas.push(dataReader.int16());\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Read short-sized deltas\n\t\t\tfor (let j = 0; j < shortCount; j++) {\n\t\t\t\tif (longWords) {\n\t\t\t\t\tdeltas.push(dataReader.int16());\n\t\t\t\t} else {\n\t\t\t\t\tdeltas.push(dataReader.int8());\n\t\t\t\t}\n\t\t\t}\n\t\t\tdeltaSets.push(deltas);\n\t\t}\n\n\t\titemVariationData.push({ itemCount, regionIndexes, deltaSets });\n\t}\n\n\treturn { format, variationRegions, itemVariationData };\n}\n\nfunction parseDeltaSetIndexMap(reader: Reader): DeltaSetIndexMap {\n\tconst format = reader.uint8();\n\tconst entryFormat = reader.uint8();\n\tconst mapCount = format === 0 ? reader.uint16() : reader.uint32();\n\n\tconst innerIndexBitCount = (entryFormat & 0x0f) + 1;\n\tconst mapEntrySize = ((entryFormat >> 4) & 0x03) + 1;\n\n\tconst mapData: { outer: number; inner: number }[] = [];\n\tfor (let i = 0; i < mapCount; i++) {\n\t\tlet entry = 0;\n\t\tfor (let j = 0; j < mapEntrySize; j++) {\n\t\t\tentry = (entry << 8) | reader.uint8();\n\t\t}\n\n\t\tconst inner = entry & ((1 << innerIndexBitCount) - 1);\n\t\tconst outer = entry >> innerIndexBitCount;\n\t\tmapData.push({ outer, inner });\n\t}\n\n\treturn { format, mapCount, entryFormat, innerIndexBitCount, mapData };\n}\n\n/**\n * Get advance height delta for a glyph at given variation coordinates\n */\nexport function getAdvanceHeightDelta(\n\tvvar: VvarTable,\n\tglyphId: GlyphId,\n\tcoords: number[],\n): number {\n\tconst mapping = vvar.advanceHeightMapping;\n\n\t// Get outer/inner index\n\tlet outer: number;\n\tlet inner: number;\n\n\tif (mapping && glyphId < mapping.mapData.length) {\n\t\tconst entry = mapping.mapData[glyphId];\n\t\tif (!entry) {\n\t\t\treturn 0;\n\t\t}\n\t\touter = entry.outer;\n\t\tinner = entry.inner;\n\t} else {\n\t\t// Direct mapping: outer = 0, inner = glyphId\n\t\touter = 0;\n\t\tinner = glyphId;\n\t}\n\n\treturn calculateDelta(vvar.itemVariationStore, outer, inner, coords);\n}\n\n/**\n * Get top side bearing delta for a glyph at given variation coordinates\n */\nexport function getTsbDelta(\n\tvvar: VvarTable,\n\tglyphId: GlyphId,\n\tcoords: number[],\n): number {\n\tconst mapping = vvar.tsbMapping;\n\tif (!mapping) return 0;\n\n\tif (glyphId >= mapping.mapData.length) return 0;\n\n\tconst entry = mapping.mapData[glyphId];\n\tif (!entry) return 0;\n\n\treturn calculateDelta(\n\t\tvvar.itemVariationStore,\n\t\tentry.outer,\n\t\tentry.inner,\n\t\tcoords,\n\t);\n}\n\n/**\n * Get bottom side bearing delta for a glyph at given variation coordinates\n */\nexport function getBsbDelta(\n\tvvar: VvarTable,\n\tglyphId: GlyphId,\n\tcoords: number[],\n): number {\n\tconst mapping = vvar.bsbMapping;\n\tif (!mapping) return 0;\n\n\tif (glyphId >= mapping.mapData.length) return 0;\n\n\tconst entry = mapping.mapData[glyphId];\n\tif (!entry) return 0;\n\n\treturn calculateDelta(\n\t\tvvar.itemVariationStore,\n\t\tentry.outer,\n\t\tentry.inner,\n\t\tcoords,\n\t);\n}\n\n/**\n * Get vertical origin delta for a glyph at given variation coordinates\n */\nexport function getVorgDelta(\n\tvvar: VvarTable,\n\tglyphId: GlyphId,\n\tcoords: number[],\n): number {\n\tconst mapping = vvar.vOrgMapping;\n\tif (!mapping) return 0;\n\n\tif (glyphId >= mapping.mapData.length) return 0;\n\n\tconst entry = mapping.mapData[glyphId];\n\tif (!entry) return 0;\n\n\treturn calculateDelta(\n\t\tvvar.itemVariationStore,\n\t\tentry.outer,\n\t\tentry.inner,\n\t\tcoords,\n\t);\n}\n\n/**\n * Calculate delta from variation store\n */\nfunction calculateDelta(\n\tstore: ItemVariationStore,\n\touter: number,\n\tinner: number,\n\tcoords: number[],\n): number {\n\tconst varData = store.itemVariationData[outer];\n\tif (!varData || inner >= varData.itemCount) {\n\t\treturn 0;\n\t}\n\n\tconst deltaSet = varData.deltaSets[inner];\n\tif (!deltaSet) {\n\t\treturn 0;\n\t}\n\n\t// Calculate total delta\n\tlet delta = 0;\n\tfor (const [i, regionIndex] of varData.regionIndexes.entries()) {\n\t\tconst region = store.variationRegions[regionIndex];\n\t\tif (!region) continue;\n\n\t\tconst scalar = calculateRegionScalar(region, coords);\n\t\tconst regionDelta = deltaSet[i] ?? 0;\n\t\tdelta += scalar * regionDelta;\n\t}\n\n\treturn Math.round(delta);\n}\n",
57
+ "import type { GlyphId, TableRecord, Tag } from \"../types.ts\";\nimport { Tags, tagToString } from \"../types.ts\";\nimport { Reader } from \"./binary/reader.ts\";\nimport { type AvarTable, parseAvar } from \"./tables/avar.ts\";\nimport { type BaseTable, parseBase } from \"./tables/base.ts\";\nimport {\n\ttype CbdtTable,\n\ttype CblcTable,\n\tparseCbdt,\n\tparseCblc,\n} from \"./tables/cbdt.ts\";\nimport { type CffTable, parseCff } from \"./tables/cff.ts\";\nimport { type Cff2Table, parseCff2 } from \"./tables/cff2.ts\";\nimport { type CmapTable, getGlyphId, parseCmap } from \"./tables/cmap.ts\";\nimport { type ColrTable, parseColr } from \"./tables/colr.ts\";\nimport { type CpalTable, parseCpal } from \"./tables/cpal.ts\";\nimport { type FvarTable, parseFvar } from \"./tables/fvar.ts\";\nimport { type GdefTable, parseGdef } from \"./tables/gdef.ts\";\nimport {\n\ttype Contour,\n\ttype GlyfTable,\n\ttype Glyph,\n\tgetGlyphBounds,\n\tgetGlyphContours,\n\tgetGlyphContoursWithVariation,\n\tparseGlyf,\n\tparseGlyph,\n} from \"./tables/glyf.ts\";\nimport { type GposTable, parseGpos } from \"./tables/gpos.ts\";\nimport { type GsubTable, parseGsub } from \"./tables/gsub.ts\";\nimport { type GvarTable, parseGvar } from \"./tables/gvar.ts\";\nimport { type HeadTable, parseHead } from \"./tables/head.ts\";\nimport { type HheaTable, parseHhea } from \"./tables/hhea.ts\";\nimport {\n\tgetAdvanceWidth,\n\tgetLeftSideBearing,\n\ttype HmtxTable,\n\tparseHmtx,\n} from \"./tables/hmtx.ts\";\nimport { type HvarTable, parseHvar } from \"./tables/hvar.ts\";\nimport { type JstfTable, parseJstf } from \"./tables/jstf.ts\";\nimport { type KernTable, parseKern } from \"./tables/kern.ts\";\nimport { type KerxTable, parseKerx } from \"./tables/kerx.ts\";\nimport { type LocaTable, parseLoca } from \"./tables/loca.ts\";\nimport { type MathTable, parseMath } from \"./tables/math.ts\";\nimport { type MaxpTable, parseMaxp } from \"./tables/maxp.ts\";\nimport { type MorxTable, parseMorx } from \"./tables/morx.ts\";\nimport { type MvarTable, parseMvar } from \"./tables/mvar.ts\";\nimport { type NameTable, parseName } from \"./tables/name.ts\";\nimport { type Os2Table, parseOs2 } from \"./tables/os2.ts\";\nimport { type PostTable, parsePost } from \"./tables/post.ts\";\nimport { parseSbix, type SbixTable } from \"./tables/sbix.ts\";\nimport {\n\ttype FontDirectory,\n\tisTrueType,\n\tparseFontDirectory,\n} from \"./tables/sfnt.ts\";\nimport { parseFeat, type FeatTable } from \"./tables/feat.ts\";\nimport { parseStat, type StatTable } from \"./tables/stat.ts\";\nimport { parseSvg, type SvgTable } from \"./tables/svg.ts\";\nimport { parseTrak, type TrakTable } from \"./tables/trak.ts\";\nimport { parseVhea, type VheaTable } from \"./tables/vhea.ts\";\nimport { parseVmtx, type VmtxTable } from \"./tables/vmtx.ts\";\nimport { parseVorg, type VorgTable } from \"./tables/vorg.ts\";\nimport { parseVvar, type VvarTable } from \"./tables/vvar.ts\";\n\n/** Font loading options */\nexport interface FontLoadOptions {\n\t/** Tables to parse eagerly (default: lazy) */\n\teagerTables?: Tag[];\n}\n\n/**\n * Represents a loaded font file.\n * Tables are parsed lazily on first access.\n */\nexport class Font {\n\tprivate readonly reader: Reader;\n\tprivate readonly directory: FontDirectory;\n\n\t// Lazy-loaded tables\n\tprivate _head: HeadTable | null = null;\n\tprivate _maxp: MaxpTable | null = null;\n\tprivate _hhea: HheaTable | null = null;\n\tprivate _hmtx: HmtxTable | null = null;\n\tprivate _cmap: CmapTable | null = null;\n\tprivate _gdef: GdefTable | null | undefined = undefined;\n\tprivate _gsub: GsubTable | null | undefined = undefined;\n\tprivate _gpos: GposTable | null | undefined = undefined;\n\tprivate _kern: KernTable | null | undefined = undefined;\n\tprivate _fvar: FvarTable | null | undefined = undefined;\n\tprivate _hvar: HvarTable | null | undefined = undefined;\n\tprivate _vhea: VheaTable | null | undefined = undefined;\n\tprivate _vmtx: VmtxTable | null | undefined = undefined;\n\tprivate _morx: MorxTable | null | undefined = undefined;\n\tprivate _gvar: GvarTable | null | undefined = undefined;\n\tprivate _avar: AvarTable | null | undefined = undefined;\n\tprivate _kerx: KerxTable | null | undefined = undefined;\n\tprivate _trak: TrakTable | null | undefined = undefined;\n\tprivate _cff: CffTable | null | undefined = undefined;\n\tprivate _cff2: Cff2Table | null | undefined = undefined;\n\tprivate _colr: ColrTable | null | undefined = undefined;\n\tprivate _cpal: CpalTable | null | undefined = undefined;\n\tprivate _vvar: VvarTable | null | undefined = undefined;\n\tprivate _mvar: MvarTable | null | undefined = undefined;\n\tprivate _os2: Os2Table | null | undefined = undefined;\n\tprivate _name: NameTable | null | undefined = undefined;\n\tprivate _post: PostTable | null | undefined = undefined;\n\tprivate _base: BaseTable | null | undefined = undefined;\n\tprivate _jstf: JstfTable | null | undefined = undefined;\n\tprivate _math: MathTable | null | undefined = undefined;\n\tprivate _loca: LocaTable | null | undefined = undefined;\n\tprivate _glyf: GlyfTable | null | undefined = undefined;\n\tprivate _svg: SvgTable | null | undefined = undefined;\n\tprivate _vorg: VorgTable | null | undefined = undefined;\n\tprivate _sbix: SbixTable | null | undefined = undefined;\n\tprivate _stat: StatTable | null | undefined = undefined;\n\tprivate _cbdt: CbdtTable | null | undefined = undefined;\n\tprivate _cblc: CblcTable | null | undefined = undefined;\n\tprivate _feat: FeatTable | null | undefined = undefined;\n\n\tprivate constructor(buffer: ArrayBuffer, _options: FontLoadOptions = {}) {\n\t\tthis.reader = new Reader(buffer);\n\t\tthis.directory = parseFontDirectory(this.reader);\n\t}\n\n\t/** Load font from ArrayBuffer */\n\tstatic load(buffer: ArrayBuffer, options?: FontLoadOptions): Font {\n\t\treturn new Font(buffer, options);\n\t}\n\n\t/** Load font from URL (works in browser and Bun) */\n\tstatic async fromURL(url: string, options?: FontLoadOptions): Promise<Font> {\n\t\tconst response = await fetch(url);\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to fetch font: ${response.status} ${response.statusText}`,\n\t\t\t);\n\t\t}\n\t\tconst buffer = await response.arrayBuffer();\n\t\treturn Font.load(buffer, options);\n\t}\n\n\t/** Load font from file path (Bun only) */\n\tstatic async fromFile(\n\t\tpath: string,\n\t\toptions?: FontLoadOptions,\n\t): Promise<Font> {\n\t\tconst file = Bun.file(path);\n\t\tconst buffer = await file.arrayBuffer();\n\t\treturn Font.load(buffer, options);\n\t}\n\n\t// Table accessors\n\n\t/** Check if font has a specific table */\n\thasTable(tag: Tag): boolean {\n\t\treturn this.directory.tables.has(tag);\n\t}\n\n\t/** Get table record */\n\tgetTableRecord(tag: Tag): TableRecord | undefined {\n\t\treturn this.directory.tables.get(tag);\n\t}\n\n\t/** Get reader for a table */\n\tgetTableReader(tag: Tag): Reader | null {\n\t\tconst record = this.directory.tables.get(tag);\n\t\tif (!record) return null;\n\t\treturn this.reader.slice(record.offset, record.length);\n\t}\n\n\t// Required tables (lazy-loaded)\n\n\tget head(): HeadTable {\n\t\tif (!this._head) {\n\t\t\tconst reader = this.getTableReader(Tags.head);\n\t\t\tif (!reader) throw new Error(\"Missing required 'head' table\");\n\t\t\tthis._head = parseHead(reader);\n\t\t}\n\t\treturn this._head;\n\t}\n\n\tget maxp(): MaxpTable {\n\t\tif (!this._maxp) {\n\t\t\tconst reader = this.getTableReader(Tags.maxp);\n\t\t\tif (!reader) throw new Error(\"Missing required 'maxp' table\");\n\t\t\tthis._maxp = parseMaxp(reader);\n\t\t}\n\t\treturn this._maxp;\n\t}\n\n\tget hhea(): HheaTable {\n\t\tif (!this._hhea) {\n\t\t\tconst reader = this.getTableReader(Tags.hhea);\n\t\t\tif (!reader) throw new Error(\"Missing required 'hhea' table\");\n\t\t\tthis._hhea = parseHhea(reader);\n\t\t}\n\t\treturn this._hhea;\n\t}\n\n\tget hmtx(): HmtxTable {\n\t\tif (!this._hmtx) {\n\t\t\tconst reader = this.getTableReader(Tags.hmtx);\n\t\t\tif (!reader) throw new Error(\"Missing required 'hmtx' table\");\n\t\t\tthis._hmtx = parseHmtx(\n\t\t\t\treader,\n\t\t\t\tthis.hhea.numberOfHMetrics,\n\t\t\t\tthis.numGlyphs,\n\t\t\t);\n\t\t}\n\t\treturn this._hmtx;\n\t}\n\n\tget cmap(): CmapTable {\n\t\tif (!this._cmap) {\n\t\t\tconst record = this.getTableRecord(Tags.cmap);\n\t\t\tconst reader = this.getTableReader(Tags.cmap);\n\t\t\tif (!reader || !record) throw new Error(\"Missing required 'cmap' table\");\n\t\t\tthis._cmap = parseCmap(reader, record.length);\n\t\t}\n\t\treturn this._cmap;\n\t}\n\n\tget gdef(): GdefTable | null {\n\t\tif (this._gdef === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.GDEF);\n\t\t\tthis._gdef = reader ? parseGdef(reader) : null;\n\t\t}\n\t\treturn this._gdef;\n\t}\n\n\tget gsub(): GsubTable | null {\n\t\tif (this._gsub === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.GSUB);\n\t\t\tthis._gsub = reader ? parseGsub(reader) : null;\n\t\t}\n\t\treturn this._gsub;\n\t}\n\n\tget gpos(): GposTable | null {\n\t\tif (this._gpos === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.GPOS);\n\t\t\tthis._gpos = reader ? parseGpos(reader) : null;\n\t\t}\n\t\treturn this._gpos;\n\t}\n\n\tget kern(): KernTable | null {\n\t\tif (this._kern === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.kern);\n\t\t\tthis._kern = reader ? parseKern(reader) : null;\n\t\t}\n\t\treturn this._kern;\n\t}\n\n\tget fvar(): FvarTable | null {\n\t\tif (this._fvar === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.fvar);\n\t\t\tthis._fvar = reader ? parseFvar(reader) : null;\n\t\t}\n\t\treturn this._fvar;\n\t}\n\n\tget hvar(): HvarTable | null {\n\t\tif (this._hvar === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.HVAR);\n\t\t\tthis._hvar = reader ? parseHvar(reader) : null;\n\t\t}\n\t\treturn this._hvar;\n\t}\n\n\tget vhea(): VheaTable | null {\n\t\tif (this._vhea === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.vhea);\n\t\t\tthis._vhea = reader ? parseVhea(reader) : null;\n\t\t}\n\t\treturn this._vhea;\n\t}\n\n\tget vmtx(): VmtxTable | null {\n\t\tif (this._vmtx === undefined) {\n\t\t\tconst vhea = this.vhea;\n\t\t\tif (!vhea) {\n\t\t\t\tthis._vmtx = null;\n\t\t\t} else {\n\t\t\t\tconst reader = this.getTableReader(Tags.vmtx);\n\t\t\t\tthis._vmtx = reader\n\t\t\t\t\t? parseVmtx(reader, vhea.numberOfVMetrics, this.numGlyphs)\n\t\t\t\t\t: null;\n\t\t\t}\n\t\t}\n\t\treturn this._vmtx;\n\t}\n\n\tget morx(): MorxTable | null {\n\t\tif (this._morx === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.morx);\n\t\t\tthis._morx = reader ? parseMorx(reader) : null;\n\t\t}\n\t\treturn this._morx;\n\t}\n\n\tget gvar(): GvarTable | null {\n\t\tif (this._gvar === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.gvar);\n\t\t\tthis._gvar = reader ? parseGvar(reader, this.numGlyphs) : null;\n\t\t}\n\t\treturn this._gvar;\n\t}\n\n\tget avar(): AvarTable | null {\n\t\tif (this._avar === undefined) {\n\t\t\tconst fvar = this.fvar;\n\t\t\tif (!fvar) {\n\t\t\t\tthis._avar = null;\n\t\t\t} else {\n\t\t\t\tconst reader = this.getTableReader(Tags.avar);\n\t\t\t\tthis._avar = reader ? parseAvar(reader, fvar.axes.length) : null;\n\t\t\t}\n\t\t}\n\t\treturn this._avar;\n\t}\n\n\tget kerx(): KerxTable | null {\n\t\tif (this._kerx === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.kerx);\n\t\t\tthis._kerx = reader ? parseKerx(reader) : null;\n\t\t}\n\t\treturn this._kerx;\n\t}\n\n\tget trak(): TrakTable | null {\n\t\tif (this._trak === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.trak);\n\t\t\tthis._trak = reader ? parseTrak(reader) : null;\n\t\t}\n\t\treturn this._trak;\n\t}\n\n\tget cff(): CffTable | null {\n\t\tif (this._cff === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.CFF);\n\t\t\tthis._cff = reader ? parseCff(reader) : null;\n\t\t}\n\t\treturn this._cff;\n\t}\n\n\tget cff2(): Cff2Table | null {\n\t\tif (this._cff2 === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.CFF2);\n\t\t\tthis._cff2 = reader ? parseCff2(reader) : null;\n\t\t}\n\t\treturn this._cff2;\n\t}\n\n\tget colr(): ColrTable | null {\n\t\tif (this._colr === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.COLR);\n\t\t\tthis._colr = reader ? parseColr(reader) : null;\n\t\t}\n\t\treturn this._colr;\n\t}\n\n\tget cpal(): CpalTable | null {\n\t\tif (this._cpal === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.CPAL);\n\t\t\tthis._cpal = reader ? parseCpal(reader) : null;\n\t\t}\n\t\treturn this._cpal;\n\t}\n\n\tget vvar(): VvarTable | null {\n\t\tif (this._vvar === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.VVAR);\n\t\t\tthis._vvar = reader ? parseVvar(reader) : null;\n\t\t}\n\t\treturn this._vvar;\n\t}\n\n\tget mvar(): MvarTable | null {\n\t\tif (this._mvar === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.MVAR);\n\t\t\tthis._mvar = reader ? parseMvar(reader) : null;\n\t\t}\n\t\treturn this._mvar;\n\t}\n\n\tget os2(): Os2Table | null {\n\t\tif (this._os2 === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.OS2);\n\t\t\tthis._os2 = reader ? parseOs2(reader) : null;\n\t\t}\n\t\treturn this._os2;\n\t}\n\n\tget name(): NameTable | null {\n\t\tif (this._name === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.name);\n\t\t\tthis._name = reader ? parseName(reader) : null;\n\t\t}\n\t\treturn this._name;\n\t}\n\n\tget post(): PostTable | null {\n\t\tif (this._post === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.post);\n\t\t\tthis._post = reader ? parsePost(reader) : null;\n\t\t}\n\t\treturn this._post;\n\t}\n\n\tget base(): BaseTable | null {\n\t\tif (this._base === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.BASE);\n\t\t\tthis._base = reader ? parseBase(reader) : null;\n\t\t}\n\t\treturn this._base;\n\t}\n\n\tget jstf(): JstfTable | null {\n\t\tif (this._jstf === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.JSTF);\n\t\t\tthis._jstf = reader ? parseJstf(reader) : null;\n\t\t}\n\t\treturn this._jstf;\n\t}\n\n\tget math(): MathTable | null {\n\t\tif (this._math === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.MATH);\n\t\t\tthis._math = reader ? parseMath(reader) : null;\n\t\t}\n\t\treturn this._math;\n\t}\n\n\tget loca(): LocaTable | null {\n\t\tif (this._loca === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.loca);\n\t\t\tthis._loca = reader\n\t\t\t\t? parseLoca(reader, this.numGlyphs, this.head.indexToLocFormat)\n\t\t\t\t: null;\n\t\t}\n\t\treturn this._loca;\n\t}\n\n\tget glyf(): GlyfTable | null {\n\t\tif (this._glyf === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.glyf);\n\t\t\tthis._glyf = reader ? parseGlyf(reader) : null;\n\t\t}\n\t\treturn this._glyf;\n\t}\n\n\tget svg(): SvgTable | null {\n\t\tif (this._svg === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.SVG);\n\t\t\tthis._svg = reader ? parseSvg(reader) : null;\n\t\t}\n\t\treturn this._svg;\n\t}\n\n\tget vorg(): VorgTable | null {\n\t\tif (this._vorg === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.VORG);\n\t\t\tthis._vorg = reader ? parseVorg(reader) : null;\n\t\t}\n\t\treturn this._vorg;\n\t}\n\n\tget sbix(): SbixTable | null {\n\t\tif (this._sbix === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.sbix);\n\t\t\tthis._sbix = reader ? parseSbix(reader, this.numGlyphs) : null;\n\t\t}\n\t\treturn this._sbix;\n\t}\n\n\tget stat(): StatTable | null {\n\t\tif (this._stat === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.STAT);\n\t\t\tthis._stat = reader ? parseStat(reader) : null;\n\t\t}\n\t\treturn this._stat;\n\t}\n\n\tget cblc(): CblcTable | null {\n\t\tif (this._cblc === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.CBLC);\n\t\t\tthis._cblc = reader ? parseCblc(reader) : null;\n\t\t}\n\t\treturn this._cblc;\n\t}\n\n\tget cbdt(): CbdtTable | null {\n\t\tif (this._cbdt === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.CBDT);\n\t\t\tthis._cbdt = reader ? parseCbdt(reader) : null;\n\t\t}\n\t\treturn this._cbdt;\n\t}\n\n\tget feat(): FeatTable | null {\n\t\tif (this._feat === undefined) {\n\t\t\tconst reader = this.getTableReader(Tags.feat);\n\t\t\tthis._feat = reader ? parseFeat(reader) : null;\n\t\t}\n\t\treturn this._feat;\n\t}\n\n\t// Convenience properties\n\n\t/** Number of glyphs in the font */\n\tget numGlyphs(): number {\n\t\treturn this.maxp.numGlyphs;\n\t}\n\n\t/** Units per em */\n\tget unitsPerEm(): number {\n\t\treturn this.head.unitsPerEm;\n\t}\n\n\t/** Ascender (from hhea) */\n\tget ascender(): number {\n\t\treturn this.hhea.ascender;\n\t}\n\n\t/** Descender (from hhea) */\n\tget descender(): number {\n\t\treturn this.hhea.descender;\n\t}\n\n\t/** Line gap (from hhea) */\n\tget lineGap(): number {\n\t\treturn this.hhea.lineGap;\n\t}\n\n\t/** Is this a TrueType font (vs CFF)? */\n\tget isTrueType(): boolean {\n\t\treturn isTrueType(this.directory);\n\t}\n\n\t/** Is this a CFF font? */\n\tget isCFF(): boolean {\n\t\treturn this.hasTable(Tags.CFF) || this.hasTable(Tags.CFF2);\n\t}\n\n\t/** Is this a variable font? */\n\tget isVariable(): boolean {\n\t\treturn this.hasTable(Tags.fvar);\n\t}\n\n\t/** Has OpenType layout tables? */\n\tget hasOpenTypeLayout(): boolean {\n\t\treturn this.hasTable(Tags.GSUB) || this.hasTable(Tags.GPOS);\n\t}\n\n\t/** Has AAT layout tables? */\n\tget hasAATLayout(): boolean {\n\t\treturn this.hasTable(Tags.morx) || this.hasTable(Tags.kerx);\n\t}\n\n\t/** Is this a color font? */\n\tget isColorFont(): boolean {\n\t\treturn (\n\t\t\tthis.hasTable(Tags.COLR) ||\n\t\t\tthis.hasTable(Tags.SVG) ||\n\t\t\tthis.hasTable(Tags.sbix) ||\n\t\t\tthis.hasTable(Tags.CBDT)\n\t\t);\n\t}\n\n\t// Glyph operations\n\n\t/** Get glyph ID for a Unicode codepoint */\n\tglyphId(codepoint: number): GlyphId {\n\t\treturn getGlyphId(this.cmap, codepoint);\n\t}\n\n\t/** Get glyph ID for a character */\n\tglyphIdForChar(char: string): GlyphId {\n\t\tconst codepoint = char.codePointAt(0);\n\t\tif (codepoint === undefined) return 0;\n\t\treturn this.glyphId(codepoint);\n\t}\n\n\t/** Get advance width for a glyph */\n\tadvanceWidth(glyphId: GlyphId): number {\n\t\treturn getAdvanceWidth(this.hmtx, glyphId);\n\t}\n\n\t/** Get left side bearing for a glyph */\n\tleftSideBearing(glyphId: GlyphId): number {\n\t\treturn getLeftSideBearing(this.hmtx, glyphId);\n\t}\n\n\t/** List all table tags in the font */\n\tlistTables(): string[] {\n\t\treturn Array.from(this.directory.tables.keys()).map(tagToString);\n\t}\n\n\t// Glyph outline operations (TrueType only)\n\n\t/** Get raw glyph data (simple or composite) */\n\tgetGlyph(glyphId: GlyphId): Glyph | null {\n\t\tif (!this.glyf || !this.loca) return null;\n\t\treturn parseGlyph(this.glyf, this.loca, glyphId);\n\t}\n\n\t/** Get flattened contours for a glyph (resolves composites) */\n\tgetGlyphContours(glyphId: GlyphId): Contour[] | null {\n\t\tif (!this.glyf || !this.loca) return null;\n\t\treturn getGlyphContours(this.glyf, this.loca, glyphId);\n\t}\n\n\t/** Get bounding box for a glyph */\n\tgetGlyphBounds(\n\t\tglyphId: GlyphId,\n\t): { xMin: number; yMin: number; xMax: number; yMax: number } | null {\n\t\tif (!this.glyf || !this.loca) return null;\n\t\treturn getGlyphBounds(this.glyf, this.loca, glyphId);\n\t}\n\n\t/** Get contours for a glyph with variation applied */\n\tgetGlyphContoursWithVariation(\n\t\tglyphId: GlyphId,\n\t\taxisCoords: number[],\n\t): Contour[] | null {\n\t\tif (!this.glyf || !this.loca) return null;\n\t\treturn getGlyphContoursWithVariation(\n\t\t\tthis.glyf,\n\t\t\tthis.loca,\n\t\t\tthis.gvar,\n\t\t\tglyphId,\n\t\t\taxisCoords,\n\t\t);\n\t}\n}\n",
58
+ "import type { GlyphId } from \"../../types.ts\";\nimport type { CffTable, PrivateDict } from \"./cff.ts\";\nimport type { Cff2Table, ItemVariationStore } from \"./cff2.ts\";\nimport type { Contour, GlyphPoint } from \"./glyf.ts\";\n\n/**\n * CFF CharString interpreter\n * Executes Type 2 CharString programs to produce glyph outlines\n */\n\n// CharString operators\nenum Op {\n\t// Path construction\n\thstem = 1,\n\tvstem = 3,\n\tvmoveto = 4,\n\trlineto = 5,\n\thlineto = 6,\n\tvlineto = 7,\n\trrcurveto = 8,\n\tcallsubr = 10,\n\treturn_ = 11,\n\tendchar = 14,\n\thstemhm = 18,\n\thintmask = 19,\n\tcntrmask = 20,\n\trmoveto = 21,\n\thmoveto = 22,\n\tvstemhm = 23,\n\trcurveline = 24,\n\trlinecurve = 25,\n\tvvcurveto = 26,\n\thhcurveto = 27,\n\tcallgsubr = 29,\n\tvhcurveto = 30,\n\thvcurveto = 31,\n\n\t// Two-byte operators (12 xx)\n\tdotsection = 0x0c00,\n\tand_ = 0x0c03,\n\tor_ = 0x0c04,\n\tnot_ = 0x0c05,\n\tabs_ = 0x0c09,\n\tadd_ = 0x0c0a,\n\tsub_ = 0x0c0b,\n\tdiv_ = 0x0c0c,\n\tneg_ = 0x0c0e,\n\teq_ = 0x0c0f,\n\tdrop_ = 0x0c12,\n\tput_ = 0x0c14,\n\tget_ = 0x0c15,\n\tifelse_ = 0x0c16,\n\trandom_ = 0x0c17,\n\tmul_ = 0x0c18,\n\tsqrt_ = 0x0c1a,\n\tdup_ = 0x0c1b,\n\texch_ = 0x0c1c,\n\tindex_ = 0x0c1d,\n\troll_ = 0x0c1e,\n\thflex = 0x0c22,\n\tflex = 0x0c23,\n\thflex1 = 0x0c24,\n\tflex1 = 0x0c25,\n\n\t// CFF2 operators\n\tvsindex = 15,\n\tblend = 16,\n}\n\ninterface CharStringState {\n\tx: number;\n\ty: number;\n\tstack: number[];\n\tnStems: number;\n\thaveWidth: boolean;\n\twidth: number;\n\tcontours: Contour[];\n\tcurrentContour: GlyphPoint[];\n\ttransientArray: number[];\n\t// For subroutine calls\n\tcallStack: { data: Uint8Array; pos: number }[];\n\t// For CFF2 blending\n\tvsindex: number;\n\taxisCoords: number[] | null;\n\tvstore: ItemVariationStore | null;\n}\n\n/**\n * Execute a CFF charstring and return contours\n */\nexport function executeCffCharString(\n\tcff: CffTable,\n\tglyphId: GlyphId,\n\tfontIndex: number = 0,\n): Contour[] | null {\n\tconst charStrings = cff.charStrings[fontIndex];\n\tif (!charStrings || glyphId >= charStrings.length) return null;\n\n\tconst charString = charStrings[glyphId];\n\tif (!charString) return null;\n\n\tconst globalSubrs = cff.globalSubrs;\n\tconst localSubrs = cff.localSubrs[fontIndex] || [];\n\n\t// Get private dict for default/nominal width\n\tconst _topDict = cff.topDicts[fontIndex];\n\tconst privateDict: PrivateDict = {};\n\n\tconst state: CharStringState = {\n\t\tx: 0,\n\t\ty: 0,\n\t\tstack: [],\n\t\tnStems: 0,\n\t\thaveWidth: false,\n\t\twidth: privateDict.defaultWidthX ?? 0,\n\t\tcontours: [],\n\t\tcurrentContour: [],\n\t\ttransientArray: new Array(32).fill(0),\n\t\tcallStack: [],\n\t\tvsindex: 0,\n\t\taxisCoords: null,\n\t\tvstore: null,\n\t};\n\n\texecuteCharString(state, charString, globalSubrs, localSubrs);\n\n\t// Close any open contour\n\tif (state.currentContour.length > 0) {\n\t\tstate.contours.push(state.currentContour);\n\t}\n\n\treturn state.contours;\n}\n\n/**\n * Execute a CFF2 charstring with variation support\n */\nexport function executeCff2CharString(\n\tcff2: Cff2Table,\n\tglyphId: GlyphId,\n\taxisCoords: number[] | null = null,\n): Contour[] | null {\n\tif (glyphId >= cff2.charStrings.length) return null;\n\n\tconst charString = cff2.charStrings[glyphId];\n\tif (!charString) return null;\n\n\tconst globalSubrs = cff2.globalSubrs;\n\n\t// Get FD index and local subrs\n\tconst fdIndex = cff2.fdSelect?.select(glyphId) ?? 0;\n\tconst fd = cff2.fdArray[fdIndex];\n\tconst localSubrs = fd?.localSubrs || [];\n\n\tconst state: CharStringState = {\n\t\tx: 0,\n\t\ty: 0,\n\t\tstack: [],\n\t\tnStems: 0,\n\t\thaveWidth: true, // CFF2 doesn't have width in charstring\n\t\twidth: 0,\n\t\tcontours: [],\n\t\tcurrentContour: [],\n\t\ttransientArray: new Array(32).fill(0),\n\t\tcallStack: [],\n\t\tvsindex: fd?.private?.vsindex ?? 0,\n\t\taxisCoords,\n\t\tvstore: cff2.vstore,\n\t};\n\n\texecuteCharString(state, charString, globalSubrs, localSubrs);\n\n\t// Close any open contour\n\tif (state.currentContour.length > 0) {\n\t\tstate.contours.push(state.currentContour);\n\t}\n\n\treturn state.contours;\n}\n\nfunction executeCharString(\n\tstate: CharStringState,\n\tdata: Uint8Array,\n\tglobalSubrs: Uint8Array[],\n\tlocalSubrs: Uint8Array[],\n): void {\n\tlet pos = 0;\n\n\twhile (pos < data.length) {\n\t\tconst b0 = data[pos++];\n\t\tif (b0 === undefined) return;\n\n\t\tif (b0 === 28) {\n\t\t\t// 16-bit signed integer\n\t\t\tconst b1 = data[pos++];\n\t\t\tif (b1 === undefined) return;\n\t\t\tconst b2 = data[pos++];\n\t\t\tif (b2 === undefined) return;\n\t\t\tstate.stack.push((((b1 << 8) | b2) << 16) >> 16);\n\t\t} else if (b0 === 255) {\n\t\t\t// 32-bit fixed point (16.16)\n\t\t\tconst b1 = data[pos++];\n\t\t\tif (b1 === undefined) return;\n\t\t\tconst b2 = data[pos++];\n\t\t\tif (b2 === undefined) return;\n\t\t\tconst b3 = data[pos++];\n\t\t\tif (b3 === undefined) return;\n\t\t\tconst b4 = data[pos++];\n\t\t\tif (b4 === undefined) return;\n\t\t\tconst val = ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) >> 0;\n\t\t\tstate.stack.push(val / 65536);\n\t\t} else if (b0 >= 32 && b0 <= 246) {\n\t\t\tstate.stack.push(b0 - 139);\n\t\t} else if (b0 >= 247 && b0 <= 250) {\n\t\t\tconst b1 = data[pos++];\n\t\t\tif (b1 === undefined) return;\n\t\t\tstate.stack.push((b0 - 247) * 256 + b1 + 108);\n\t\t} else if (b0 >= 251 && b0 <= 254) {\n\t\t\tconst b1 = data[pos++];\n\t\t\tif (b1 === undefined) return;\n\t\t\tstate.stack.push(-(b0 - 251) * 256 - b1 - 108);\n\t\t} else if (b0 === 12) {\n\t\t\t// Two-byte operator\n\t\t\tconst b1 = data[pos++];\n\t\t\tif (b1 === undefined) return;\n\t\t\tconst op = 0x0c00 | b1;\n\t\t\texecuteOperator(state, op, globalSubrs, localSubrs);\n\t\t} else {\n\t\t\t// Single-byte operator\n\t\t\texecuteOperator(state, b0, globalSubrs, localSubrs);\n\t\t}\n\n\t\t// Handle return from subroutine\n\t\tif (state.callStack.length > 0) {\n\t\t\tconst frame = state.callStack[state.callStack.length - 1];\n\t\t\tif (frame && frame.pos >= frame.data.length) {\n\t\t\t\tstate.callStack.pop();\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction executeOperator(\n\tstate: CharStringState,\n\top: number,\n\tglobalSubrs: Uint8Array[],\n\tlocalSubrs: Uint8Array[],\n): void {\n\tconst stack = state.stack;\n\n\tswitch (op) {\n\t\tcase Op.hstem:\n\t\tcase Op.vstem:\n\t\tcase Op.hstemhm:\n\t\tcase Op.vstemhm: {\n\t\t\t// Stem hints\n\t\t\tconst hasWidth = stack.length % 2 !== 0;\n\t\t\tif (hasWidth && !state.haveWidth) {\n\t\t\t\tconst width = stack.shift();\n\t\t\t\tif (width === undefined) break;\n\t\t\t\tstate.width = width;\n\t\t\t\tstate.haveWidth = true;\n\t\t\t}\n\t\t\tstate.nStems += stack.length / 2;\n\t\t\tstack.length = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.hintmask:\n\t\tcase Op.cntrmask: {\n\t\t\t// Hint/counter mask - stems may be implicit\n\t\t\tconst hasWidth = stack.length % 2 !== 0;\n\t\t\tif (hasWidth && !state.haveWidth) {\n\t\t\t\tconst width = stack.shift();\n\t\t\t\tif (width === undefined) break;\n\t\t\t\tstate.width = width;\n\t\t\t\tstate.haveWidth = true;\n\t\t\t}\n\t\t\tstate.nStems += stack.length / 2;\n\t\t\tstack.length = 0;\n\t\t\t// Skip mask bytes (not handled here, would need to track position)\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.rmoveto: {\n\t\t\tif (stack.length > 2 && !state.haveWidth) {\n\t\t\t\tconst width = stack.shift();\n\t\t\t\tif (width === undefined) break;\n\t\t\t\tstate.width = width;\n\t\t\t\tstate.haveWidth = true;\n\t\t\t}\n\t\t\t// Close current contour if any\n\t\t\tif (state.currentContour.length > 0) {\n\t\t\t\tstate.contours.push(state.currentContour);\n\t\t\t\tstate.currentContour = [];\n\t\t\t}\n\t\t\tconst dy = stack.pop();\n\t\t\tif (dy === undefined) break;\n\t\t\tconst dx = stack.pop();\n\t\t\tif (dx === undefined) break;\n\t\t\tstate.x += dx;\n\t\t\tstate.y += dy;\n\t\t\tstate.currentContour.push({ x: state.x, y: state.y, onCurve: true });\n\t\t\tstack.length = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.hmoveto: {\n\t\t\tif (stack.length > 1 && !state.haveWidth) {\n\t\t\t\tconst width = stack.shift();\n\t\t\t\tif (width === undefined) break;\n\t\t\t\tstate.width = width;\n\t\t\t\tstate.haveWidth = true;\n\t\t\t}\n\t\t\tif (state.currentContour.length > 0) {\n\t\t\t\tstate.contours.push(state.currentContour);\n\t\t\t\tstate.currentContour = [];\n\t\t\t}\n\t\t\tconst dx = stack.pop();\n\t\t\tif (dx === undefined) break;\n\t\t\tstate.x += dx;\n\t\t\tstate.currentContour.push({ x: state.x, y: state.y, onCurve: true });\n\t\t\tstack.length = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.vmoveto: {\n\t\t\tif (stack.length > 1 && !state.haveWidth) {\n\t\t\t\tconst width = stack.shift();\n\t\t\t\tif (width === undefined) break;\n\t\t\t\tstate.width = width;\n\t\t\t\tstate.haveWidth = true;\n\t\t\t}\n\t\t\tif (state.currentContour.length > 0) {\n\t\t\t\tstate.contours.push(state.currentContour);\n\t\t\t\tstate.currentContour = [];\n\t\t\t}\n\t\t\tconst dy = stack.pop();\n\t\t\tif (dy === undefined) break;\n\t\t\tstate.y += dy;\n\t\t\tstate.currentContour.push({ x: state.x, y: state.y, onCurve: true });\n\t\t\tstack.length = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.rlineto: {\n\t\t\twhile (stack.length >= 2) {\n\t\t\t\tconst dx = stack.shift();\n\t\t\t\tif (dx === undefined) break;\n\t\t\t\tconst dy = stack.shift();\n\t\t\t\tif (dy === undefined) break;\n\t\t\t\tstate.x += dx;\n\t\t\t\tstate.y += dy;\n\t\t\t\tstate.currentContour.push({ x: state.x, y: state.y, onCurve: true });\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.hlineto: {\n\t\t\tlet isHorizontal = true;\n\t\t\twhile (stack.length >= 1) {\n\t\t\t\tconst val = stack.shift();\n\t\t\t\tif (val === undefined) break;\n\t\t\t\tif (isHorizontal) {\n\t\t\t\t\tstate.x += val;\n\t\t\t\t} else {\n\t\t\t\t\tstate.y += val;\n\t\t\t\t}\n\t\t\t\tstate.currentContour.push({ x: state.x, y: state.y, onCurve: true });\n\t\t\t\tisHorizontal = !isHorizontal;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.vlineto: {\n\t\t\tlet isVertical = true;\n\t\t\twhile (stack.length >= 1) {\n\t\t\t\tconst val = stack.shift();\n\t\t\t\tif (val === undefined) break;\n\t\t\t\tif (isVertical) {\n\t\t\t\t\tstate.y += val;\n\t\t\t\t} else {\n\t\t\t\t\tstate.x += val;\n\t\t\t\t}\n\t\t\t\tstate.currentContour.push({ x: state.x, y: state.y, onCurve: true });\n\t\t\t\tisVertical = !isVertical;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.rrcurveto: {\n\t\t\twhile (stack.length >= 6) {\n\t\t\t\tconst dx1 = stack.shift();\n\t\t\t\tif (dx1 === undefined) break;\n\t\t\t\tconst dy1 = stack.shift();\n\t\t\t\tif (dy1 === undefined) break;\n\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\tconst dx3 = stack.shift();\n\t\t\t\tif (dx3 === undefined) break;\n\t\t\t\tconst dy3 = stack.shift();\n\t\t\t\tif (dy3 === undefined) break;\n\t\t\t\taddCubicBezier(state, dx1, dy1, dx2, dy2, dx3, dy3);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.hhcurveto: {\n\t\t\tlet dy1 = 0;\n\t\t\tif (stack.length % 4 === 1) {\n\t\t\t\tconst val = stack.shift();\n\t\t\t\tif (val === undefined) break;\n\t\t\t\tdy1 = val;\n\t\t\t}\n\t\t\twhile (stack.length >= 4) {\n\t\t\t\tconst dx1 = stack.shift();\n\t\t\t\tif (dx1 === undefined) break;\n\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\tconst dx3 = stack.shift();\n\t\t\t\tif (dx3 === undefined) break;\n\t\t\t\taddCubicBezier(state, dx1, dy1, dx2, dy2, dx3, 0);\n\t\t\t\tdy1 = 0;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.vvcurveto: {\n\t\t\tlet dx1 = 0;\n\t\t\tif (stack.length % 4 === 1) {\n\t\t\t\tconst val = stack.shift();\n\t\t\t\tif (val === undefined) break;\n\t\t\t\tdx1 = val;\n\t\t\t}\n\t\t\twhile (stack.length >= 4) {\n\t\t\t\tconst dy1 = stack.shift();\n\t\t\t\tif (dy1 === undefined) break;\n\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\tconst dy3 = stack.shift();\n\t\t\t\tif (dy3 === undefined) break;\n\t\t\t\taddCubicBezier(state, dx1, dy1, dx2, dy2, 0, dy3);\n\t\t\t\tdx1 = 0;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.hvcurveto: {\n\t\t\t// Alternates horizontal/vertical starting tangent\n\t\t\tlet isHorizontal = true;\n\t\t\twhile (stack.length >= 4) {\n\t\t\t\tif (isHorizontal) {\n\t\t\t\t\tconst dx1 = stack.shift();\n\t\t\t\t\tif (dx1 === undefined) break;\n\t\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\t\tconst dy3 = stack.shift();\n\t\t\t\t\tif (dy3 === undefined) break;\n\t\t\t\t\tconst dx3 = stack.length === 1 ? (stack.shift() ?? 0) : 0;\n\t\t\t\t\taddCubicBezier(state, dx1, 0, dx2, dy2, dx3, dy3);\n\t\t\t\t} else {\n\t\t\t\t\tconst dy1 = stack.shift();\n\t\t\t\t\tif (dy1 === undefined) break;\n\t\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\t\tconst dx3 = stack.shift();\n\t\t\t\t\tif (dx3 === undefined) break;\n\t\t\t\t\tconst dy3 = stack.length === 1 ? (stack.shift() ?? 0) : 0;\n\t\t\t\t\taddCubicBezier(state, 0, dy1, dx2, dy2, dx3, dy3);\n\t\t\t\t}\n\t\t\t\tisHorizontal = !isHorizontal;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.vhcurveto: {\n\t\t\t// Alternates vertical/horizontal starting tangent\n\t\t\tlet isVertical = true;\n\t\t\twhile (stack.length >= 4) {\n\t\t\t\tif (isVertical) {\n\t\t\t\t\tconst dy1 = stack.shift();\n\t\t\t\t\tif (dy1 === undefined) break;\n\t\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\t\tconst dx3 = stack.shift();\n\t\t\t\t\tif (dx3 === undefined) break;\n\t\t\t\t\tconst dy3 = stack.length === 1 ? (stack.shift() ?? 0) : 0;\n\t\t\t\t\taddCubicBezier(state, 0, dy1, dx2, dy2, dx3, dy3);\n\t\t\t\t} else {\n\t\t\t\t\tconst dx1 = stack.shift();\n\t\t\t\t\tif (dx1 === undefined) break;\n\t\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\t\tconst dy3 = stack.shift();\n\t\t\t\t\tif (dy3 === undefined) break;\n\t\t\t\t\tconst dx3 = stack.length === 1 ? (stack.shift() ?? 0) : 0;\n\t\t\t\t\taddCubicBezier(state, dx1, 0, dx2, dy2, dx3, dy3);\n\t\t\t\t}\n\t\t\t\tisVertical = !isVertical;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.rcurveline: {\n\t\t\twhile (stack.length >= 8) {\n\t\t\t\tconst dx1 = stack.shift();\n\t\t\t\tif (dx1 === undefined) break;\n\t\t\t\tconst dy1 = stack.shift();\n\t\t\t\tif (dy1 === undefined) break;\n\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\tconst dx3 = stack.shift();\n\t\t\t\tif (dx3 === undefined) break;\n\t\t\t\tconst dy3 = stack.shift();\n\t\t\t\tif (dy3 === undefined) break;\n\t\t\t\taddCubicBezier(state, dx1, dy1, dx2, dy2, dx3, dy3);\n\t\t\t}\n\t\t\t// Final line\n\t\t\tif (stack.length >= 2) {\n\t\t\t\tconst dx = stack.shift();\n\t\t\t\tif (dx === undefined) break;\n\t\t\t\tconst dy = stack.shift();\n\t\t\t\tif (dy === undefined) break;\n\t\t\t\tstate.x += dx;\n\t\t\t\tstate.y += dy;\n\t\t\t\tstate.currentContour.push({ x: state.x, y: state.y, onCurve: true });\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.rlinecurve: {\n\t\t\twhile (stack.length >= 8) {\n\t\t\t\tconst dx = stack.shift();\n\t\t\t\tif (dx === undefined) break;\n\t\t\t\tconst dy = stack.shift();\n\t\t\t\tif (dy === undefined) break;\n\t\t\t\tstate.x += dx;\n\t\t\t\tstate.y += dy;\n\t\t\t\tstate.currentContour.push({ x: state.x, y: state.y, onCurve: true });\n\t\t\t}\n\t\t\t// Final curve\n\t\t\tif (stack.length >= 6) {\n\t\t\t\tconst dx1 = stack.shift();\n\t\t\t\tif (dx1 === undefined) break;\n\t\t\t\tconst dy1 = stack.shift();\n\t\t\t\tif (dy1 === undefined) break;\n\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\tconst dx3 = stack.shift();\n\t\t\t\tif (dx3 === undefined) break;\n\t\t\t\tconst dy3 = stack.shift();\n\t\t\t\tif (dy3 === undefined) break;\n\t\t\t\taddCubicBezier(state, dx1, dy1, dx2, dy2, dx3, dy3);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.callsubr: {\n\t\t\tconst index = stack.pop();\n\t\t\tif (index === undefined) break;\n\t\t\tconst biasedIndex = index + getSubrBias(localSubrs.length);\n\t\t\tconst subr = localSubrs[biasedIndex];\n\t\t\tif (subr) {\n\t\t\t\texecuteCharString(state, subr, globalSubrs, localSubrs);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.callgsubr: {\n\t\t\tconst index = stack.pop();\n\t\t\tif (index === undefined) break;\n\t\t\tconst biasedIndex = index + getSubrBias(globalSubrs.length);\n\t\t\tconst subr = globalSubrs[biasedIndex];\n\t\t\tif (subr) {\n\t\t\t\texecuteCharString(state, subr, globalSubrs, localSubrs);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.return_:\n\t\t\t// Return from subroutine - handled by caller\n\t\t\tbreak;\n\n\t\tcase Op.endchar: {\n\t\t\tif (stack.length > 0 && !state.haveWidth) {\n\t\t\t\tconst width = stack.shift();\n\t\t\t\tif (width === undefined) break;\n\t\t\t\tstate.width = width;\n\t\t\t\tstate.haveWidth = true;\n\t\t\t}\n\t\t\t// Close current contour\n\t\t\tif (state.currentContour.length > 0) {\n\t\t\t\tstate.contours.push(state.currentContour);\n\t\t\t\tstate.currentContour = [];\n\t\t\t}\n\t\t\tstack.length = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\t// Flex operators\n\t\tcase Op.flex: {\n\t\t\t// 12 arguments: dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd\n\t\t\tif (stack.length >= 13) {\n\t\t\t\tconst dx1 = stack.shift();\n\t\t\t\tif (dx1 === undefined) break;\n\t\t\t\tconst dy1 = stack.shift();\n\t\t\t\tif (dy1 === undefined) break;\n\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\tconst dx3 = stack.shift();\n\t\t\t\tif (dx3 === undefined) break;\n\t\t\t\tconst dy3 = stack.shift();\n\t\t\t\tif (dy3 === undefined) break;\n\t\t\t\tconst dx4 = stack.shift();\n\t\t\t\tif (dx4 === undefined) break;\n\t\t\t\tconst dy4 = stack.shift();\n\t\t\t\tif (dy4 === undefined) break;\n\t\t\t\tconst dx5 = stack.shift();\n\t\t\t\tif (dx5 === undefined) break;\n\t\t\t\tconst dy5 = stack.shift();\n\t\t\t\tif (dy5 === undefined) break;\n\t\t\t\tconst dx6 = stack.shift();\n\t\t\t\tif (dx6 === undefined) break;\n\t\t\t\tconst dy6 = stack.shift();\n\t\t\t\tif (dy6 === undefined) break;\n\t\t\t\tstack.shift(); // fd (flex depth) - not used for rendering\n\t\t\t\taddCubicBezier(state, dx1, dy1, dx2, dy2, dx3, dy3);\n\t\t\t\taddCubicBezier(state, dx4, dy4, dx5, dy5, dx6, dy6);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.hflex: {\n\t\t\t// dx1 dx2 dy2 dx3 dx4 dx5 dx6\n\t\t\tif (stack.length >= 7) {\n\t\t\t\tconst dx1 = stack.shift();\n\t\t\t\tif (dx1 === undefined) break;\n\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\tconst dx3 = stack.shift();\n\t\t\t\tif (dx3 === undefined) break;\n\t\t\t\tconst dx4 = stack.shift();\n\t\t\t\tif (dx4 === undefined) break;\n\t\t\t\tconst dx5 = stack.shift();\n\t\t\t\tif (dx5 === undefined) break;\n\t\t\t\tconst dx6 = stack.shift();\n\t\t\t\tif (dx6 === undefined) break;\n\t\t\t\taddCubicBezier(state, dx1, 0, dx2, dy2, dx3, 0);\n\t\t\t\taddCubicBezier(state, dx4, 0, dx5, -dy2, dx6, 0);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.hflex1: {\n\t\t\t// dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6\n\t\t\tif (stack.length >= 9) {\n\t\t\t\tconst dx1 = stack.shift();\n\t\t\t\tif (dx1 === undefined) break;\n\t\t\t\tconst dy1 = stack.shift();\n\t\t\t\tif (dy1 === undefined) break;\n\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\tconst dx3 = stack.shift();\n\t\t\t\tif (dx3 === undefined) break;\n\t\t\t\tconst dx4 = stack.shift();\n\t\t\t\tif (dx4 === undefined) break;\n\t\t\t\tconst dx5 = stack.shift();\n\t\t\t\tif (dx5 === undefined) break;\n\t\t\t\tconst dy5 = stack.shift();\n\t\t\t\tif (dy5 === undefined) break;\n\t\t\t\tconst dx6 = stack.shift();\n\t\t\t\tif (dx6 === undefined) break;\n\t\t\t\taddCubicBezier(state, dx1, dy1, dx2, dy2, dx3, 0);\n\t\t\t\taddCubicBezier(state, dx4, 0, dx5, dy5, dx6, -(dy1 + dy2 + dy5));\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.flex1: {\n\t\t\t// dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6\n\t\t\tif (stack.length >= 11) {\n\t\t\t\tconst dx1 = stack.shift();\n\t\t\t\tif (dx1 === undefined) break;\n\t\t\t\tconst dy1 = stack.shift();\n\t\t\t\tif (dy1 === undefined) break;\n\t\t\t\tconst dx2 = stack.shift();\n\t\t\t\tif (dx2 === undefined) break;\n\t\t\t\tconst dy2 = stack.shift();\n\t\t\t\tif (dy2 === undefined) break;\n\t\t\t\tconst dx3 = stack.shift();\n\t\t\t\tif (dx3 === undefined) break;\n\t\t\t\tconst dy3 = stack.shift();\n\t\t\t\tif (dy3 === undefined) break;\n\t\t\t\tconst dx4 = stack.shift();\n\t\t\t\tif (dx4 === undefined) break;\n\t\t\t\tconst dy4 = stack.shift();\n\t\t\t\tif (dy4 === undefined) break;\n\t\t\t\tconst dx5 = stack.shift();\n\t\t\t\tif (dx5 === undefined) break;\n\t\t\t\tconst dy5 = stack.shift();\n\t\t\t\tif (dy5 === undefined) break;\n\t\t\t\tconst d6 = stack.shift();\n\t\t\t\tif (d6 === undefined) break;\n\n\t\t\t\tconst dx = dx1 + dx2 + dx3 + dx4 + dx5;\n\t\t\t\tconst dy = dy1 + dy2 + dy3 + dy4 + dy5;\n\n\t\t\t\tlet dx6: number, dy6: number;\n\t\t\t\tif (Math.abs(dx) > Math.abs(dy)) {\n\t\t\t\t\tdx6 = d6;\n\t\t\t\t\tdy6 = -dy;\n\t\t\t\t} else {\n\t\t\t\t\tdx6 = -dx;\n\t\t\t\t\tdy6 = d6;\n\t\t\t\t}\n\n\t\t\t\taddCubicBezier(state, dx1, dy1, dx2, dy2, dx3, dy3);\n\t\t\t\taddCubicBezier(state, dx4, dy4, dx5, dy5, dx6, dy6);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t// Arithmetic operators\n\t\tcase Op.and_: {\n\t\t\tconst b = stack.pop();\n\t\t\tif (b === undefined) break;\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(a && b ? 1 : 0);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.or_: {\n\t\t\tconst b = stack.pop();\n\t\t\tif (b === undefined) break;\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(a || b ? 1 : 0);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.not_: {\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(a ? 0 : 1);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.abs_: {\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(Math.abs(a));\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.add_: {\n\t\t\tconst b = stack.pop();\n\t\t\tif (b === undefined) break;\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(a + b);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.sub_: {\n\t\t\tconst b = stack.pop();\n\t\t\tif (b === undefined) break;\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(a - b);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.div_: {\n\t\t\tconst b = stack.pop();\n\t\t\tif (b === undefined) break;\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(a / b);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.neg_: {\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(-a);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.eq_: {\n\t\t\tconst b = stack.pop();\n\t\t\tif (b === undefined) break;\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(a === b ? 1 : 0);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.drop_: {\n\t\t\tstack.pop();\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.put_: {\n\t\t\tconst i = stack.pop();\n\t\t\tif (i === undefined) break;\n\t\t\tconst val = stack.pop();\n\t\t\tif (val === undefined) break;\n\t\t\tstate.transientArray[i] = val;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.get_: {\n\t\t\tconst i = stack.pop();\n\t\t\tif (i === undefined) break;\n\t\t\tstack.push(state.transientArray[i] ?? 0);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.ifelse_: {\n\t\t\tconst v2 = stack.pop();\n\t\t\tif (v2 === undefined) break;\n\t\t\tconst v1 = stack.pop();\n\t\t\tif (v1 === undefined) break;\n\t\t\tconst s2 = stack.pop();\n\t\t\tif (s2 === undefined) break;\n\t\t\tconst s1 = stack.pop();\n\t\t\tif (s1 === undefined) break;\n\t\t\tstack.push(v1 <= v2 ? s1 : s2);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.random_: {\n\t\t\tstack.push(Math.random());\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.mul_: {\n\t\t\tconst b = stack.pop();\n\t\t\tif (b === undefined) break;\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(a * b);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.sqrt_: {\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(Math.sqrt(a));\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.dup_: {\n\t\t\tconst a = stack[stack.length - 1];\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(a);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.exch_: {\n\t\t\tconst b = stack.pop();\n\t\t\tif (b === undefined) break;\n\t\t\tconst a = stack.pop();\n\t\t\tif (a === undefined) break;\n\t\t\tstack.push(b, a);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.index_: {\n\t\t\tconst i = stack.pop();\n\t\t\tif (i === undefined) break;\n\t\t\tconst idx = stack.length - 1 - i;\n\t\t\tstack.push(stack[idx] ?? 0);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.roll_: {\n\t\t\tconst j = stack.pop();\n\t\t\tif (j === undefined) break;\n\t\t\tconst n = stack.pop();\n\t\t\tif (n === undefined) break;\n\t\t\tif (n > 0) {\n\t\t\t\tconst items = stack.splice(-n);\n\t\t\t\tconst shift = ((j % n) + n) % n;\n\t\t\t\tfor (let i = 0; i < n; i++) {\n\t\t\t\t\tconst item = items[(i + shift) % n];\n\t\t\t\t\tif (item !== undefined) {\n\t\t\t\t\t\tstack.push(item);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t// CFF2 blend operator\n\t\tcase Op.blend: {\n\t\t\tif (!state.axisCoords || !state.vstore) break;\n\n\t\t\tconst n = stack.pop();\n\t\t\tif (n === undefined) break;\n\t\t\tconst regionCount =\n\t\t\t\tstate.vstore.itemVariationData[state.vsindex]?.regionIndexCount ?? 0;\n\n\t\t\t// For each of n values, there are regionCount deltas\n\t\t\tconst totalDeltaCount = n * regionCount;\n\t\t\tconst deltas = stack.splice(-totalDeltaCount);\n\t\t\tconst defaults = stack.splice(-n);\n\n\t\t\tfor (let i = 0; i < n; i++) {\n\t\t\t\tconst defaultVal = defaults[i];\n\t\t\t\tif (defaultVal === undefined) continue;\n\t\t\t\tlet value = defaultVal;\n\t\t\t\tfor (let r = 0; r < regionCount; r++) {\n\t\t\t\t\tconst delta = deltas[i * regionCount + r];\n\t\t\t\t\tif (delta === undefined) continue;\n\t\t\t\t\tconst scalar = computeRegionScalar(\n\t\t\t\t\t\tstate.vstore,\n\t\t\t\t\t\tstate.vsindex,\n\t\t\t\t\t\tr,\n\t\t\t\t\t\tstate.axisCoords,\n\t\t\t\t\t);\n\t\t\t\t\tvalue += delta * scalar;\n\t\t\t\t}\n\t\t\t\tstack.push(value);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.vsindex: {\n\t\t\tconst vsindex = stack.pop();\n\t\t\tif (vsindex === undefined) break;\n\t\t\tstate.vsindex = vsindex;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase Op.dotsection:\n\t\t\t// Deprecated, ignore\n\t\t\tbreak;\n\t}\n}\n\nfunction addCubicBezier(\n\tstate: CharStringState,\n\tdx1: number,\n\tdy1: number,\n\tdx2: number,\n\tdy2: number,\n\tdx3: number,\n\tdy3: number,\n): void {\n\t// CFF uses cubic Beziers. We need to convert to quadratic for TrueType-style contours\n\t// or keep as cubic if our path system supports it.\n\t// For simplicity, we'll approximate cubics with multiple quadratics.\n\n\tconst x0 = state.x;\n\tconst y0 = state.y;\n\tconst x1 = x0 + dx1;\n\tconst y1 = y0 + dy1;\n\tconst x2 = x1 + dx2;\n\tconst y2 = y1 + dy2;\n\tconst x3 = x2 + dx3;\n\tconst y3 = y2 + dy3;\n\n\t// Approximate cubic with quadratics\n\t// Simple approach: use midpoint approximation\n\t// For better quality, use adaptive subdivision\n\n\tapproximateCubicWithQuadratics(state, x0, y0, x1, y1, x2, y2, x3, y3, 0);\n\n\tstate.x = x3;\n\tstate.y = y3;\n}\n\nfunction approximateCubicWithQuadratics(\n\tstate: CharStringState,\n\tx0: number,\n\ty0: number,\n\tx1: number,\n\ty1: number,\n\tx2: number,\n\ty2: number,\n\tx3: number,\n\ty3: number,\n\tdepth: number,\n): void {\n\t// Maximum recursion depth\n\tif (depth > 4) {\n\t\t// Just use a simple quadratic approximation\n\t\tconst qx = (3 * (x1 + x2) - (x0 + x3)) / 4;\n\t\tconst qy = (3 * (y1 + y2) - (y0 + y3)) / 4;\n\t\tstate.currentContour.push({ x: qx, y: qy, onCurve: false });\n\t\tstate.currentContour.push({ x: x3, y: y3, onCurve: true });\n\t\treturn;\n\t}\n\n\t// Check if cubic is close enough to a quadratic\n\t// by measuring the distance from control points to the line\n\tconst tolerance = 0.5;\n\n\t// Calculate the quadratic control point that would give the same tangents\n\tconst qx = (3 * (x1 + x2) - (x0 + x3)) / 4;\n\tconst qy = (3 * (y1 + y2) - (y0 + y3)) / 4;\n\n\t// Check error - simplified check\n\tconst err1 =\n\t\tMath.abs(x1 - (x0 + 2 * qx) / 3 - x0 / 3) +\n\t\tMath.abs(y1 - (y0 + 2 * qy) / 3 - y0 / 3);\n\tconst err2 =\n\t\tMath.abs(x2 - (2 * qx + x3) / 3 - x3 / 3) +\n\t\tMath.abs(y2 - (2 * qy + y3) / 3 - y3 / 3);\n\n\tif (err1 + err2 < tolerance) {\n\t\t// Good enough approximation\n\t\tstate.currentContour.push({ x: qx, y: qy, onCurve: false });\n\t\tstate.currentContour.push({ x: x3, y: y3, onCurve: true });\n\t} else {\n\t\t// Subdivide the cubic\n\t\tconst mx1 = (x0 + x1) / 2;\n\t\tconst my1 = (y0 + y1) / 2;\n\t\tconst mx2 = (x1 + x2) / 2;\n\t\tconst my2 = (y1 + y2) / 2;\n\t\tconst mx3 = (x2 + x3) / 2;\n\t\tconst my3 = (y2 + y3) / 2;\n\n\t\tconst mmx1 = (mx1 + mx2) / 2;\n\t\tconst mmy1 = (my1 + my2) / 2;\n\t\tconst mmx2 = (mx2 + mx3) / 2;\n\t\tconst mmy2 = (my2 + my3) / 2;\n\n\t\tconst midx = (mmx1 + mmx2) / 2;\n\t\tconst midy = (mmy1 + mmy2) / 2;\n\n\t\t// Recurse on both halves\n\t\tapproximateCubicWithQuadratics(\n\t\t\tstate,\n\t\t\tx0,\n\t\t\ty0,\n\t\t\tmx1,\n\t\t\tmy1,\n\t\t\tmmx1,\n\t\t\tmmy1,\n\t\t\tmidx,\n\t\t\tmidy,\n\t\t\tdepth + 1,\n\t\t);\n\t\tapproximateCubicWithQuadratics(\n\t\t\tstate,\n\t\t\tmidx,\n\t\t\tmidy,\n\t\t\tmmx2,\n\t\t\tmmy2,\n\t\t\tmx3,\n\t\t\tmy3,\n\t\t\tx3,\n\t\t\ty3,\n\t\t\tdepth + 1,\n\t\t);\n\t}\n}\n\nfunction getSubrBias(count: number): number {\n\tif (count < 1240) return 107;\n\tif (count < 33900) return 1131;\n\treturn 32768;\n}\n\nfunction computeRegionScalar(\n\tvstore: ItemVariationStore,\n\tvsindex: number,\n\tregionIndex: number,\n\taxisCoords: number[],\n): number {\n\tconst data = vstore.itemVariationData[vsindex];\n\tif (!data) return 0;\n\n\tconst actualRegionIndex = data.regionIndexes[regionIndex];\n\tif (actualRegionIndex === undefined) return 0;\n\n\tconst region = vstore.variationRegionList.regions[actualRegionIndex];\n\tif (!region) return 0;\n\n\tlet scalar = 1;\n\tfor (let i = 0; i < region.axes.length && i < axisCoords.length; i++) {\n\t\tconst coords = region.axes[i];\n\t\tif (!coords) continue;\n\t\tconst coord = axisCoords[i];\n\t\tif (coord === undefined) continue;\n\n\t\tif (coord < coords.startCoord || coord > coords.endCoord) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (coord === coords.peakCoord) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (coord < coords.peakCoord) {\n\t\t\tscalar *=\n\t\t\t\t(coord - coords.startCoord) / (coords.peakCoord - coords.startCoord);\n\t\t} else {\n\t\t\tscalar *=\n\t\t\t\t(coords.endCoord - coord) / (coords.endCoord - coords.peakCoord);\n\t\t}\n\t}\n\n\treturn scalar;\n}\n\n/**\n * Get glyph width from CFF charstring\n */\nexport function getCffGlyphWidth(\n\tcff: CffTable,\n\t_glyphId: GlyphId,\n\tfontIndex: number = 0,\n): number {\n\t// Would need to parse charstring just enough to get width\n\t// For now, return nominalWidthX as default\n\tconst _topDict = cff.topDicts[fontIndex];\n\treturn 0; // Proper implementation would parse the charstring\n}\n",
59
+ "import { GlyphBuffer } from \"../buffer/glyph-buffer.ts\";\nimport type { Font } from \"../font/font.ts\";\nimport {\n\tgetExtenderGlyphs,\n\tgetExtensionMods,\n\tgetJstfPriorities,\n\tgetShrinkageMods,\n} from \"../font/tables/jstf.ts\";\nimport type { GlyphId, Tag } from \"../types.ts\";\nimport { tag } from \"../types.ts\";\n\n/**\n * Justification mode\n */\nexport enum JustifyMode {\n\t/** Shrink text to fit */\n\tShrink = \"shrink\",\n\t/** Extend text to fit */\n\tExtend = \"extend\",\n\t/** Auto-select based on delta */\n\tAuto = \"auto\",\n}\n\n/**\n * Justification options\n */\nexport interface JustifyOptions {\n\t/** Target line width */\n\ttargetWidth: number;\n\t/** Script tag */\n\tscript?: Tag;\n\t/** Language tag */\n\tlanguage?: Tag;\n\t/** Justification mode */\n\tmode?: JustifyMode;\n\t/** Maximum priority level to use (0-based) */\n\tmaxPriority?: number;\n\t/** Enable Kashida insertion for Arabic */\n\tenableKashida?: boolean;\n\t/** Minimum word spacing factor (default: 0.8) */\n\tminWordSpacingFactor?: number;\n\t/** Maximum word spacing factor (default: 1.5) */\n\tmaxWordSpacingFactor?: number;\n\t/** Enable inter-character spacing adjustment */\n\tenableLetterSpacing?: boolean;\n\t/** Maximum letter spacing in font units */\n\tmaxLetterSpacing?: number;\n}\n\n/**\n * Justification result\n */\nexport interface JustifyResult {\n\t/** Whether justification succeeded */\n\tsuccess: boolean;\n\t/** Final line width after justification */\n\tfinalWidth: number;\n\t/** Delta from target (positive = too wide, negative = too narrow) */\n\tdelta: number;\n\t/** Priority level used */\n\tpriorityLevel: number;\n\t/** Adjustments applied */\n\tadjustments: JustifyAdjustment[];\n}\n\n/**\n * Individual justification adjustment\n */\nexport interface JustifyAdjustment {\n\ttype: \"spacing\" | \"kashida\" | \"lookup\";\n\t/** Glyph indices affected */\n\tglyphIndices: number[];\n\t/** Adjustment value */\n\tvalue: number;\n}\n\n/**\n * Calculate current line width from glyph buffer\n */\nexport function calculateLineWidth(buffer: GlyphBuffer): number {\n\tlet width = 0;\n\tfor (const pos of buffer.positions) {\n\t\twidth += pos.xAdvance;\n\t}\n\treturn width;\n}\n\n/**\n * Justify a shaped glyph buffer to fit a target width\n */\nexport function justify(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\toptions: JustifyOptions,\n): JustifyResult {\n\tconst {\n\t\ttargetWidth,\n\t\tscript = tag(\"DFLT\"),\n\t\tlanguage,\n\t\tmode = JustifyMode.Auto,\n\t\tmaxPriority = 10,\n\t\tenableKashida = true,\n\t\tminWordSpacingFactor = 0.8,\n\t\tmaxWordSpacingFactor = 1.5,\n\t\tenableLetterSpacing = true,\n\t\tmaxLetterSpacing = 100,\n\t} = options;\n\n\tconst currentWidth = calculateLineWidth(buffer);\n\tconst delta = targetWidth - currentWidth;\n\n\t// Already at target width\n\tif (Math.abs(delta) < 1) {\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tfinalWidth: currentWidth,\n\t\t\tdelta: 0,\n\t\t\tpriorityLevel: 0,\n\t\t\tadjustments: [],\n\t\t};\n\t}\n\n\t// Determine mode\n\tlet actualMode: JustifyMode.Shrink | JustifyMode.Extend;\n\tif (mode === JustifyMode.Auto) {\n\t\tactualMode = delta > 0 ? JustifyMode.Extend : JustifyMode.Shrink;\n\t} else {\n\t\tactualMode = mode as JustifyMode.Shrink | JustifyMode.Extend;\n\t}\n\n\tconst adjustments: JustifyAdjustment[] = [];\n\tlet remainingDelta = delta;\n\tlet priorityLevel = 0;\n\n\t// Try JSTF-based justification first\n\tconst jstf = font.jstf;\n\tif (jstf) {\n\t\tconst priorities = getJstfPriorities(jstf, script, language);\n\n\t\tfor (let i = 0; i < Math.min(priorities.length, maxPriority); i++) {\n\t\t\tconst priority = priorities[i]!;\n\t\t\tconst mods =\n\t\t\t\tactualMode === JustifyMode.Shrink\n\t\t\t\t\t? getShrinkageMods(priority)\n\t\t\t\t\t: getExtensionMods(priority);\n\n\t\t\t// Apply JSTF lookup modifications\n\t\t\t// Note: This would require reshaping with modified lookups\n\t\t\t// For now, we just record the modifications needed\n\t\t\tif (\n\t\t\t\tmods.enableGsub.length > 0 ||\n\t\t\t\tmods.disableGsub.length > 0 ||\n\t\t\t\tmods.enableGpos.length > 0 ||\n\t\t\t\tmods.disableGpos.length > 0\n\t\t\t) {\n\t\t\t\tadjustments.push({\n\t\t\t\t\ttype: \"lookup\",\n\t\t\t\t\tglyphIndices: [],\n\t\t\t\t\tvalue: i,\n\t\t\t\t});\n\t\t\t\tpriorityLevel = i;\n\t\t\t}\n\t\t}\n\n\t\t// Kashida insertion for Arabic\n\t\tif (enableKashida && actualMode === JustifyMode.Extend) {\n\t\t\tconst extenderGlyphs = getExtenderGlyphs(jstf, script);\n\t\t\tif (extenderGlyphs.length > 0) {\n\t\t\t\tconst kashidaResult = insertKashida(\n\t\t\t\t\tbuffer,\n\t\t\t\t\textenderGlyphs[0]!,\n\t\t\t\t\tremainingDelta,\n\t\t\t\t\tfont,\n\t\t\t\t);\n\t\t\t\tremainingDelta -= kashidaResult.totalExtension;\n\t\t\t\tadjustments.push(...kashidaResult.adjustments);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Apply word spacing adjustment\n\tconst spaceGlyphId = font.glyphId(0x0020); // Space character\n\tif (spaceGlyphId !== 0) {\n\t\tconst spaceResult = adjustWordSpacing(\n\t\t\tbuffer,\n\t\t\tspaceGlyphId,\n\t\t\tremainingDelta,\n\t\t\tactualMode === JustifyMode.Shrink\n\t\t\t\t? minWordSpacingFactor\n\t\t\t\t: maxWordSpacingFactor,\n\t\t);\n\t\tremainingDelta -= spaceResult.totalAdjustment;\n\t\tadjustments.push(...spaceResult.adjustments);\n\t}\n\n\t// Apply letter spacing if still needed\n\tif (enableLetterSpacing && Math.abs(remainingDelta) > 1) {\n\t\tconst letterResult = adjustLetterSpacing(\n\t\t\tbuffer,\n\t\t\tremainingDelta,\n\t\t\tmaxLetterSpacing,\n\t\t);\n\t\tremainingDelta -= letterResult.totalAdjustment;\n\t\tadjustments.push(...letterResult.adjustments);\n\t}\n\n\tconst finalWidth = calculateLineWidth(buffer);\n\n\treturn {\n\t\tsuccess: Math.abs(remainingDelta) < 1,\n\t\tfinalWidth,\n\t\tdelta: targetWidth - finalWidth,\n\t\tpriorityLevel,\n\t\tadjustments,\n\t};\n}\n\n/**\n * Insert Kashida (tatweel) characters for Arabic justification\n */\nfunction insertKashida(\n\tbuffer: GlyphBuffer,\n\tkashidaGlyph: GlyphId,\n\ttargetExtension: number,\n\tfont: Font,\n): { totalExtension: number; adjustments: JustifyAdjustment[] } {\n\tconst adjustments: JustifyAdjustment[] = [];\n\tlet totalExtension = 0;\n\n\t// Find valid Kashida insertion points (between Arabic letters)\n\tconst insertionPoints: number[] = [];\n\tfor (let i = 0; i < buffer.infos.length - 1; i++) {\n\t\tconst info = buffer.infos[i]!;\n\t\t// Check if this is a valid insertion point\n\t\t// (between joining Arabic characters)\n\t\tif (isValidKashidaPoint(info.codepoint)) {\n\t\t\tinsertionPoints.push(i);\n\t\t}\n\t}\n\n\tif (insertionPoints.length === 0) {\n\t\treturn { totalExtension: 0, adjustments: [] };\n\t}\n\n\t// Get Kashida width\n\tconst kashidaWidth = font.advanceWidth(kashidaGlyph);\n\tif (kashidaWidth <= 0) {\n\t\treturn { totalExtension: 0, adjustments: [] };\n\t}\n\n\t// Distribute Kashida evenly\n\tconst kashidaPerPoint = Math.ceil(\n\t\ttargetExtension / kashidaWidth / insertionPoints.length,\n\t);\n\tconst adjustmentPerPoint = Math.min(\n\t\tkashidaPerPoint * kashidaWidth,\n\t\ttargetExtension / insertionPoints.length,\n\t);\n\n\tfor (const point of insertionPoints) {\n\t\tif (totalExtension >= targetExtension) break;\n\n\t\t// Add Kashida extension via xAdvance\n\t\tbuffer.positions[point]!.xAdvance += adjustmentPerPoint;\n\t\ttotalExtension += adjustmentPerPoint;\n\n\t\tadjustments.push({\n\t\t\ttype: \"kashida\",\n\t\t\tglyphIndices: [point],\n\t\t\tvalue: adjustmentPerPoint,\n\t\t});\n\t}\n\n\treturn { totalExtension, adjustments };\n}\n\n/**\n * Check if a codepoint is a valid Kashida insertion point\n */\nfunction isValidKashidaPoint(codepoint: number): boolean {\n\t// Arabic letters that can have Kashida after them\n\t// Simplified check - in reality need to check joining behavior\n\treturn codepoint >= 0x0620 && codepoint <= 0x06ff;\n}\n\n/**\n * Adjust word spacing (space character width)\n */\nfunction adjustWordSpacing(\n\tbuffer: GlyphBuffer,\n\tspaceGlyph: GlyphId,\n\ttargetAdjustment: number,\n\tlimitFactor: number,\n): { totalAdjustment: number; adjustments: JustifyAdjustment[] } {\n\tconst adjustments: JustifyAdjustment[] = [];\n\tlet totalAdjustment = 0;\n\n\t// Find all space glyphs\n\tconst spaceIndices: number[] = [];\n\tlet totalSpaceWidth = 0;\n\n\tfor (let i = 0; i < buffer.infos.length; i++) {\n\t\tif (buffer.infos[i]?.glyphId === spaceGlyph) {\n\t\t\tspaceIndices.push(i);\n\t\t\ttotalSpaceWidth += buffer.positions[i]?.xAdvance;\n\t\t}\n\t}\n\n\tif (spaceIndices.length === 0) {\n\t\treturn { totalAdjustment: 0, adjustments: [] };\n\t}\n\n\t// Calculate adjustment per space\n\tconst adjustmentPerSpace = targetAdjustment / spaceIndices.length;\n\tconst originalSpaceWidth = totalSpaceWidth / spaceIndices.length;\n\tconst maxAdjustment = originalSpaceWidth * (limitFactor - 1);\n\n\tconst clampedAdjustment =\n\t\ttargetAdjustment > 0\n\t\t\t? Math.min(adjustmentPerSpace, maxAdjustment)\n\t\t\t: Math.max(adjustmentPerSpace, -maxAdjustment);\n\n\tfor (const idx of spaceIndices) {\n\t\tbuffer.positions[idx]!.xAdvance += clampedAdjustment;\n\t\ttotalAdjustment += clampedAdjustment;\n\t}\n\n\tif (totalAdjustment !== 0) {\n\t\tadjustments.push({\n\t\t\ttype: \"spacing\",\n\t\t\tglyphIndices: spaceIndices,\n\t\t\tvalue: clampedAdjustment,\n\t\t});\n\t}\n\n\treturn { totalAdjustment, adjustments };\n}\n\n/**\n * Adjust letter spacing (inter-character spacing)\n */\nfunction adjustLetterSpacing(\n\tbuffer: GlyphBuffer,\n\ttargetAdjustment: number,\n\tmaxAdjustment: number,\n): { totalAdjustment: number; adjustments: JustifyAdjustment[] } {\n\tconst adjustments: JustifyAdjustment[] = [];\n\n\tconst numGlyphs = buffer.infos.length;\n\tif (numGlyphs <= 1) {\n\t\treturn { totalAdjustment: 0, adjustments: [] };\n\t}\n\n\t// Distribute across all inter-glyph gaps (n-1 gaps for n glyphs)\n\tconst numGaps = numGlyphs - 1;\n\tconst adjustmentPerGap = targetAdjustment / numGaps;\n\n\t// Clamp to max\n\tconst clampedAdjustment =\n\t\ttargetAdjustment > 0\n\t\t\t? Math.min(adjustmentPerGap, maxAdjustment)\n\t\t\t: Math.max(adjustmentPerGap, -maxAdjustment);\n\n\tconst affectedIndices: number[] = [];\n\tlet totalAdjustment = 0;\n\n\tfor (let i = 0; i < numGlyphs - 1; i++) {\n\t\tbuffer.positions[i]!.xAdvance += clampedAdjustment;\n\t\ttotalAdjustment += clampedAdjustment;\n\t\taffectedIndices.push(i);\n\t}\n\n\tif (totalAdjustment !== 0) {\n\t\tadjustments.push({\n\t\t\ttype: \"spacing\",\n\t\t\tglyphIndices: affectedIndices,\n\t\t\tvalue: clampedAdjustment,\n\t\t});\n\t}\n\n\treturn { totalAdjustment, adjustments };\n}\n\n/**\n * Simple line breaking for multi-line text\n */\nexport interface LineBreakResult {\n\tlines: GlyphBuffer[];\n\tbreakPoints: number[];\n}\n\n/**\n * Break shaped text into lines at a given width\n * Uses simple greedy algorithm\n */\nexport function breakIntoLines(\n\tbuffer: GlyphBuffer,\n\tmaxWidth: number,\n\tspaceGlyph?: GlyphId,\n): LineBreakResult {\n\tconst lines: GlyphBuffer[] = [];\n\tconst breakPoints: number[] = [];\n\n\tif (buffer.infos.length === 0) {\n\t\treturn { lines: [], breakPoints: [] };\n\t}\n\n\tlet lineStart = 0;\n\tlet currentWidth = 0;\n\tlet lastBreakPoint = -1;\n\tlet _lastBreakWidth = 0;\n\n\tfor (let i = 0; i < buffer.infos.length; i++) {\n\t\tconst pos = buffer.positions[i]!;\n\t\tconst info = buffer.infos[i]!;\n\n\t\tcurrentWidth += pos.xAdvance;\n\n\t\t// Track potential break points (after spaces)\n\t\tif (spaceGlyph !== undefined && info.glyphId === spaceGlyph) {\n\t\t\tlastBreakPoint = i;\n\t\t\t_lastBreakWidth = currentWidth;\n\t\t}\n\n\t\t// Check if we need to break\n\t\tif (currentWidth > maxWidth && lineStart < i) {\n\t\t\tlet breakAt: number;\n\n\t\t\tif (lastBreakPoint > lineStart) {\n\t\t\t\t// Break at last space\n\t\t\t\tbreakAt = lastBreakPoint + 1;\n\t\t\t} else {\n\t\t\t\t// Force break at current position\n\t\t\t\tbreakAt = i;\n\t\t\t}\n\n\t\t\t// Create line buffer\n\t\t\tconst lineBuffer = createLineBuffer(buffer, lineStart, breakAt);\n\t\t\tlines.push(lineBuffer);\n\t\t\tbreakPoints.push(breakAt);\n\n\t\t\t// Start new line\n\t\t\tlineStart = breakAt;\n\t\t\tcurrentWidth = 0;\n\t\t\tlastBreakPoint = -1;\n\n\t\t\t// Recalculate width from line start\n\t\t\tfor (let j = lineStart; j <= i; j++) {\n\t\t\t\tcurrentWidth += buffer.positions[j]?.xAdvance;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add final line\n\tif (lineStart < buffer.infos.length) {\n\t\tconst lineBuffer = createLineBuffer(buffer, lineStart, buffer.infos.length);\n\t\tlines.push(lineBuffer);\n\t}\n\n\treturn { lines, breakPoints };\n}\n\n/**\n * Create a new GlyphBuffer from a slice of an existing buffer\n */\nfunction createLineBuffer(\n\tsource: GlyphBuffer,\n\tstart: number,\n\tend: number,\n): GlyphBuffer {\n\tconst lineBuffer = new GlyphBuffer();\n\tlineBuffer.direction = source.direction;\n\tlineBuffer.script = source.script;\n\tlineBuffer.language = source.language;\n\n\tfor (let i = start; i < end; i++) {\n\t\tlineBuffer.infos.push({ ...source.infos[i]! });\n\t\tlineBuffer.positions.push({ ...source.positions[i]! });\n\t}\n\n\treturn lineBuffer;\n}\n\n/**\n * Justify all lines in a paragraph to the same width\n */\nexport function justifyParagraph(\n\tfont: Font,\n\tlines: GlyphBuffer[],\n\toptions: JustifyOptions,\n): JustifyResult[] {\n\tconst results: JustifyResult[] = [];\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i]!;\n\t\tconst isLastLine = i === lines.length - 1;\n\n\t\t// Don't justify the last line (or justify less aggressively)\n\t\tif (isLastLine) {\n\t\t\tresults.push({\n\t\t\t\tsuccess: true,\n\t\t\t\tfinalWidth: calculateLineWidth(line),\n\t\t\t\tdelta: 0,\n\t\t\t\tpriorityLevel: 0,\n\t\t\t\tadjustments: [],\n\t\t\t});\n\t\t} else {\n\t\t\tresults.push(justify(font, line, options));\n\t\t}\n\t}\n\n\treturn results;\n}\n",
60
+ "import type { Reader } from \"../../font/binary/reader.ts\";\nimport type { Tag, uint16, uint32 } from \"../../types.ts\";\n\n/**\n * FeatureVariations table\n * Allows different feature substitutions based on variation axis coordinates\n * Used in GSUB/GPOS for variable fonts\n */\nexport interface FeatureVariations {\n\tmajorVersion: number;\n\tminorVersion: number;\n\tfeatureVariationRecords: FeatureVariationRecord[];\n}\n\n/**\n * Feature variation record\n * Contains a condition set and feature substitutions to apply when conditions are met\n */\nexport interface FeatureVariationRecord {\n\tconditionSet: ConditionSet;\n\tfeatureTableSubstitution: FeatureTableSubstitution;\n}\n\n/**\n * Condition set - all conditions must be met\n */\nexport interface ConditionSet {\n\tconditions: Condition[];\n}\n\n/**\n * Single axis condition\n */\nexport interface Condition {\n\tformat: number;\n\taxisIndex: uint16;\n\tfilterRangeMinValue: number; // F2DOT14\n\tfilterRangeMaxValue: number; // F2DOT14\n}\n\n/**\n * Feature table substitution\n * Maps feature indices to replacement feature tables\n */\nexport interface FeatureTableSubstitution {\n\tmajorVersion: number;\n\tminorVersion: number;\n\tsubstitutions: FeatureSubstitutionRecord[];\n}\n\n/**\n * Single feature substitution record\n */\nexport interface FeatureSubstitutionRecord {\n\tfeatureIndex: uint16;\n\talternateFeature: AlternateFeature;\n}\n\n/**\n * Alternate feature table\n */\nexport interface AlternateFeature {\n\tfeatureParamsOffset: uint16;\n\tlookupListIndices: uint16[];\n}\n\n/**\n * Parse FeatureVariations table\n */\nexport function parseFeatureVariations(reader: Reader): FeatureVariations {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst featureVariationRecordCount = reader.uint32();\n\n\tconst recordOffsets: {\n\t\tconditionSetOffset: uint32;\n\t\tfeatureSubstOffset: uint32;\n\t}[] = [];\n\tfor (let i = 0; i < featureVariationRecordCount; i++) {\n\t\trecordOffsets.push({\n\t\t\tconditionSetOffset: reader.offset32(),\n\t\t\tfeatureSubstOffset: reader.offset32(),\n\t\t});\n\t}\n\n\tconst featureVariationRecords: FeatureVariationRecord[] = [];\n\tfor (const offsets of recordOffsets) {\n\t\tconst conditionSet = parseConditionSet(\n\t\t\treader.sliceFrom(offsets.conditionSetOffset),\n\t\t);\n\t\tconst featureTableSubstitution = parseFeatureTableSubstitution(\n\t\t\treader.sliceFrom(offsets.featureSubstOffset),\n\t\t);\n\n\t\tfeatureVariationRecords.push({\n\t\t\tconditionSet,\n\t\t\tfeatureTableSubstitution,\n\t\t});\n\t}\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\tfeatureVariationRecords,\n\t};\n}\n\nfunction parseConditionSet(reader: Reader): ConditionSet {\n\tconst conditionCount = reader.uint16();\n\tconst conditionOffsets: uint32[] = [];\n\tfor (let i = 0; i < conditionCount; i++) {\n\t\tconditionOffsets.push(reader.offset32());\n\t}\n\n\tconst conditions: Condition[] = [];\n\tfor (const offset of conditionOffsets) {\n\t\tconst condReader = reader.sliceFrom(offset);\n\t\tconst format = condReader.uint16();\n\n\t\tif (format === 1) {\n\t\t\tconditions.push({\n\t\t\t\tformat,\n\t\t\t\taxisIndex: condReader.uint16(),\n\t\t\t\tfilterRangeMinValue: condReader.f2dot14(),\n\t\t\t\tfilterRangeMaxValue: condReader.f2dot14(),\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { conditions };\n}\n\nfunction parseFeatureTableSubstitution(\n\treader: Reader,\n): FeatureTableSubstitution {\n\tconst majorVersion = reader.uint16();\n\tconst minorVersion = reader.uint16();\n\tconst substitutionCount = reader.uint16();\n\n\tconst substitutionRecords: { featureIndex: uint16; offset: uint32 }[] = [];\n\tfor (let i = 0; i < substitutionCount; i++) {\n\t\tsubstitutionRecords.push({\n\t\t\tfeatureIndex: reader.uint16(),\n\t\t\toffset: reader.offset32(),\n\t\t});\n\t}\n\n\tconst substitutions: FeatureSubstitutionRecord[] = [];\n\tfor (const record of substitutionRecords) {\n\t\tconst featureReader = reader.sliceFrom(record.offset);\n\t\tconst featureParamsOffset = featureReader.offset16();\n\t\tconst lookupIndexCount = featureReader.uint16();\n\t\tconst lookupListIndices = Array.from(\n\t\t\tfeatureReader.uint16Array(lookupIndexCount),\n\t\t);\n\n\t\tsubstitutions.push({\n\t\t\tfeatureIndex: record.featureIndex,\n\t\t\talternateFeature: {\n\t\t\t\tfeatureParamsOffset,\n\t\t\t\tlookupListIndices,\n\t\t\t},\n\t\t});\n\t}\n\n\treturn {\n\t\tmajorVersion,\n\t\tminorVersion,\n\t\tsubstitutions,\n\t};\n}\n\n/**\n * Evaluate condition set against axis coordinates\n * Returns true if all conditions are met\n */\nexport function evaluateConditionSet(\n\tconditionSet: ConditionSet,\n\taxisCoords: number[],\n): boolean {\n\tfor (const condition of conditionSet.conditions) {\n\t\tconst axisValue = axisCoords[condition.axisIndex] ?? 0;\n\t\tif (\n\t\t\taxisValue < condition.filterRangeMinValue ||\n\t\t\taxisValue > condition.filterRangeMaxValue\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Find matching feature variation record for given axis coordinates\n * Returns the first matching record, or null if none match\n */\nexport function findMatchingFeatureVariation(\n\tfeatureVariations: FeatureVariations,\n\taxisCoords: number[],\n): FeatureVariationRecord | null {\n\tfor (const record of featureVariations.featureVariationRecords) {\n\t\tif (evaluateConditionSet(record.conditionSet, axisCoords)) {\n\t\t\treturn record;\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * Get substituted lookup list indices for a feature\n * Returns the original lookups if no substitution applies\n */\nexport function getSubstitutedLookups(\n\tfeatureVariations: FeatureVariations | null,\n\tfeatureIndex: number,\n\toriginalLookups: uint16[],\n\taxisCoords: number[] | null,\n): uint16[] {\n\tif (!featureVariations || !axisCoords) {\n\t\treturn originalLookups;\n\t}\n\n\tconst matchingRecord = findMatchingFeatureVariation(\n\t\tfeatureVariations,\n\t\taxisCoords,\n\t);\n\tif (!matchingRecord) {\n\t\treturn originalLookups;\n\t}\n\n\t// Check if this feature has a substitution\n\tconst substitution =\n\t\tmatchingRecord.featureTableSubstitution.substitutions.find(\n\t\t\t(s) => s.featureIndex === featureIndex,\n\t\t);\n\n\tif (substitution) {\n\t\treturn substitution.alternateFeature.lookupListIndices;\n\t}\n\n\treturn originalLookups;\n}\n\n/**\n * Apply feature variations to a feature list\n * Returns a modified feature list with substituted lookup indices\n */\nexport function applyFeatureVariations(\n\tfeatureVariations: FeatureVariations | null,\n\tfeatureLookups: Map<Tag, uint16[]>,\n\tfeatureIndices: Map<Tag, number>,\n\taxisCoords: number[] | null,\n): Map<Tag, uint16[]> {\n\tif (!featureVariations || !axisCoords) {\n\t\treturn featureLookups;\n\t}\n\n\tconst matchingRecord = findMatchingFeatureVariation(\n\t\tfeatureVariations,\n\t\taxisCoords,\n\t);\n\tif (!matchingRecord) {\n\t\treturn featureLookups;\n\t}\n\n\t// Create a new map with substituted lookups\n\tconst result = new Map(featureLookups);\n\n\tfor (const substitution of matchingRecord.featureTableSubstitution\n\t\t.substitutions) {\n\t\t// Find the feature tag for this index\n\t\tfor (const [tag, index] of featureIndices) {\n\t\t\tif (index === substitution.featureIndex) {\n\t\t\t\tresult.set(tag, substitution.alternateFeature.lookupListIndices);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n",
61
+ "import type { GlyphBuffer } from \"../buffer/glyph-buffer.ts\";\nimport type { Font } from \"../font/font.ts\";\nimport type { Contour, GlyphPoint } from \"../font/tables/glyf.ts\";\nimport type { GlyphId } from \"../types.ts\";\n\n/**\n * Path command types for glyph rendering\n */\nexport type PathCommand =\n\t| { type: \"M\"; x: number; y: number }\n\t| { type: \"L\"; x: number; y: number }\n\t| { type: \"Q\"; x1: number; y1: number; x: number; y: number }\n\t| {\n\t\t\ttype: \"C\";\n\t\t\tx1: number;\n\t\t\ty1: number;\n\t\t\tx2: number;\n\t\t\ty2: number;\n\t\t\tx: number;\n\t\t\ty: number;\n\t }\n\t| { type: \"Z\" };\n\n/**\n * A glyph path is a series of drawing commands\n */\nexport interface GlyphPath {\n\tcommands: PathCommand[];\n\tbounds: { xMin: number; yMin: number; xMax: number; yMax: number } | null;\n}\n\n/**\n * Convert TrueType contours to path commands\n * TrueType uses quadratic Bézier curves with on-curve and off-curve points\n */\nexport function contourToPath(contour: Contour): PathCommand[] {\n\tif (contour.length === 0) return [];\n\n\tconst commands: PathCommand[] = [];\n\n\t// Find the first on-curve point to start\n\tlet startIndex = 0;\n\tfor (const [i, point] of contour.entries()) {\n\t\tif (point.onCurve) {\n\t\t\tstartIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// If all points are off-curve, calculate implied on-curve point\n\tconst allOffCurve = contour.every((p) => !p.onCurve);\n\tlet startPoint: GlyphPoint;\n\n\tif (allOffCurve) {\n\t\t// Start at midpoint between first and last off-curve points\n\t\tconst first = contour[0];\n\t\tconst last = contour[contour.length - 1];\n\t\tif (!first || !last) return [];\n\t\tstartPoint = {\n\t\t\tx: (first.x + last.x) / 2,\n\t\t\ty: (first.y + last.y) / 2,\n\t\t\tonCurve: true,\n\t\t};\n\t\tstartIndex = 0;\n\t} else {\n\t\tconst point = contour[startIndex];\n\t\tif (!point) return [];\n\t\tstartPoint = point;\n\t}\n\n\tcommands.push({ type: \"M\", x: startPoint.x, y: startPoint.y });\n\n\tconst n = contour.length;\n\tlet i = allOffCurve ? 0 : (startIndex + 1) % n;\n\tlet current = startPoint;\n\tlet iterations = 0;\n\n\twhile (iterations < n) {\n\t\tconst point = contour[i];\n\t\tif (!point) break;\n\n\t\tif (point.onCurve) {\n\t\t\t// Line to on-curve point\n\t\t\tcommands.push({ type: \"L\", x: point.x, y: point.y });\n\t\t\tcurrent = point;\n\t\t} else {\n\t\t\t// Off-curve point - need to find the end point\n\t\t\tconst nextIndex = (i + 1) % n;\n\t\t\tconst nextPoint = contour[nextIndex];\n\t\t\tif (!nextPoint) break;\n\n\t\t\tlet endPoint: GlyphPoint;\n\t\t\tif (nextPoint.onCurve) {\n\t\t\t\t// Next point is on-curve, use it directly\n\t\t\t\tendPoint = nextPoint;\n\t\t\t\ti = nextIndex;\n\t\t\t\titerations++;\n\t\t\t} else {\n\t\t\t\t// Next point is also off-curve, calculate implied on-curve point\n\t\t\t\tendPoint = {\n\t\t\t\t\tx: (point.x + nextPoint.x) / 2,\n\t\t\t\t\ty: (point.y + nextPoint.y) / 2,\n\t\t\t\t\tonCurve: true,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Quadratic Bézier curve\n\t\t\tcommands.push({\n\t\t\t\ttype: \"Q\",\n\t\t\t\tx1: point.x,\n\t\t\t\ty1: point.y,\n\t\t\t\tx: endPoint.x,\n\t\t\t\ty: endPoint.y,\n\t\t\t});\n\t\t\tcurrent = endPoint;\n\t\t}\n\n\t\ti = (i + 1) % n;\n\t\titerations++;\n\n\t\t// Check if we've returned to start\n\t\tif (current.x === startPoint.x && current.y === startPoint.y) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Close the path\n\tcommands.push({ type: \"Z\" });\n\n\treturn commands;\n}\n\n/**\n * Get path commands for a glyph\n */\nexport function getGlyphPath(font: Font, glyphId: GlyphId): GlyphPath | null {\n\tconst contours = font.getGlyphContours(glyphId);\n\tif (!contours) return null;\n\n\tconst commands: PathCommand[] = [];\n\tfor (const contour of contours) {\n\t\tcommands.push(...contourToPath(contour));\n\t}\n\n\tconst bounds = font.getGlyphBounds(glyphId);\n\n\treturn { commands, bounds };\n}\n\n/**\n * Convert path commands to SVG path data string\n */\nexport function pathToSVG(\n\tpath: GlyphPath,\n\toptions?: { flipY?: boolean; scale?: number },\n): string {\n\tconst scale = options?.scale ?? 1;\n\tconst flipY = options?.flipY ?? true;\n\n\tconst parts: string[] = [];\n\n\tfor (const cmd of path.commands) {\n\t\tswitch (cmd.type) {\n\t\t\tcase \"M\":\n\t\t\t\tparts.push(\n\t\t\t\t\t`M ${cmd.x * scale} ${flipY ? -cmd.y * scale : cmd.y * scale}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"L\":\n\t\t\t\tparts.push(\n\t\t\t\t\t`L ${cmd.x * scale} ${flipY ? -cmd.y * scale : cmd.y * scale}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"Q\":\n\t\t\t\tparts.push(\n\t\t\t\t\t`Q ${cmd.x1 * scale} ${flipY ? -cmd.y1 * scale : cmd.y1 * scale} ${cmd.x * scale} ${flipY ? -cmd.y * scale : cmd.y * scale}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"C\":\n\t\t\t\tparts.push(\n\t\t\t\t\t`C ${cmd.x1 * scale} ${flipY ? -cmd.y1 * scale : cmd.y1 * scale} ${cmd.x2 * scale} ${flipY ? -cmd.y2 * scale : cmd.y2 * scale} ${cmd.x * scale} ${flipY ? -cmd.y * scale : cmd.y * scale}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"Z\":\n\t\t\t\tparts.push(\"Z\");\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn parts.join(\" \");\n}\n\n/**\n * Render path commands to a Canvas 2D context\n */\nexport function pathToCanvas(\n\tctx: CanvasRenderingContext2D | Path2D,\n\tpath: GlyphPath,\n\toptions?: {\n\t\tflipY?: boolean;\n\t\tscale?: number;\n\t\toffsetX?: number;\n\t\toffsetY?: number;\n\t},\n): void {\n\tconst scale = options?.scale ?? 1;\n\tconst flipY = options?.flipY ?? true;\n\tconst offsetX = options?.offsetX ?? 0;\n\tconst offsetY = options?.offsetY ?? 0;\n\n\tfor (const cmd of path.commands) {\n\t\tswitch (cmd.type) {\n\t\t\tcase \"M\":\n\t\t\t\tctx.moveTo(\n\t\t\t\t\tcmd.x * scale + offsetX,\n\t\t\t\t\t(flipY ? -cmd.y : cmd.y) * scale + offsetY,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"L\":\n\t\t\t\tctx.lineTo(\n\t\t\t\t\tcmd.x * scale + offsetX,\n\t\t\t\t\t(flipY ? -cmd.y : cmd.y) * scale + offsetY,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"Q\":\n\t\t\t\tctx.quadraticCurveTo(\n\t\t\t\t\tcmd.x1 * scale + offsetX,\n\t\t\t\t\t(flipY ? -cmd.y1 : cmd.y1) * scale + offsetY,\n\t\t\t\t\tcmd.x * scale + offsetX,\n\t\t\t\t\t(flipY ? -cmd.y : cmd.y) * scale + offsetY,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"C\":\n\t\t\t\tctx.bezierCurveTo(\n\t\t\t\t\tcmd.x1 * scale + offsetX,\n\t\t\t\t\t(flipY ? -cmd.y1 : cmd.y1) * scale + offsetY,\n\t\t\t\t\tcmd.x2 * scale + offsetX,\n\t\t\t\t\t(flipY ? -cmd.y2 : cmd.y2) * scale + offsetY,\n\t\t\t\t\tcmd.x * scale + offsetX,\n\t\t\t\t\t(flipY ? -cmd.y : cmd.y) * scale + offsetY,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"Z\":\n\t\t\t\tctx.closePath();\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Generate an SVG element for a glyph\n */\nexport function glyphToSVG(\n\tfont: Font,\n\tglyphId: GlyphId,\n\toptions?: { fontSize?: number; fill?: string },\n): string | null {\n\tconst path = getGlyphPath(font, glyphId);\n\tif (!path) return null;\n\n\tconst fontSize = options?.fontSize ?? 100;\n\tconst fill = options?.fill ?? \"currentColor\";\n\tconst scale = fontSize / font.unitsPerEm;\n\n\tconst bounds = path.bounds;\n\tif (!bounds) return null;\n\n\tconst width = Math.ceil((bounds.xMax - bounds.xMin) * scale);\n\tconst height = Math.ceil((bounds.yMax - bounds.yMin) * scale);\n\tconst viewBox = `${bounds.xMin} ${-bounds.yMax} ${bounds.xMax - bounds.xMin} ${bounds.yMax - bounds.yMin}`;\n\n\tconst pathData = pathToSVG(path, { flipY: true, scale: 1 });\n\n\treturn `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"${viewBox}\">\n <path d=\"${pathData}\" fill=\"${fill}\"/>\n</svg>`;\n}\n\n/**\n * Render shaped text to Canvas\n */\nexport interface ShapedGlyph {\n\tglyphId: GlyphId;\n\txOffset: number;\n\tyOffset: number;\n\txAdvance: number;\n\tyAdvance: number;\n}\n\nexport function renderShapedText(\n\tctx: CanvasRenderingContext2D,\n\tfont: Font,\n\tglyphs: ShapedGlyph[],\n\toptions?: { fontSize?: number; x?: number; y?: number; fill?: string },\n): void {\n\tconst fontSize = options?.fontSize ?? 16;\n\tconst startX = options?.x ?? 0;\n\tconst startY = options?.y ?? 0;\n\tconst fill = options?.fill ?? \"black\";\n\n\tconst scale = fontSize / font.unitsPerEm;\n\n\tctx.fillStyle = fill;\n\n\tlet x = startX;\n\tlet y = startY;\n\n\tfor (const glyph of glyphs) {\n\t\tconst path = getGlyphPath(font, glyph.glyphId);\n\t\tif (path) {\n\t\t\tctx.beginPath();\n\t\t\tpathToCanvas(ctx, path, {\n\t\t\t\tscale,\n\t\t\t\tflipY: true,\n\t\t\t\toffsetX: x + glyph.xOffset * scale,\n\t\t\t\toffsetY: y - glyph.yOffset * scale,\n\t\t\t});\n\t\t\tctx.fill();\n\t\t}\n\n\t\tx += glyph.xAdvance * scale;\n\t\ty += glyph.yAdvance * scale;\n\t}\n}\n\n/**\n * Generate SVG for shaped text\n */\nexport function shapedTextToSVG(\n\tfont: Font,\n\tglyphs: ShapedGlyph[],\n\toptions?: { fontSize?: number; fill?: string },\n): string {\n\tconst fontSize = options?.fontSize ?? 100;\n\tconst fill = options?.fill ?? \"currentColor\";\n\tconst scale = fontSize / font.unitsPerEm;\n\n\tconst paths: string[] = [];\n\tlet x = 0;\n\tlet y = 0;\n\tlet minX = Infinity;\n\tlet maxX = -Infinity;\n\tlet minY = Infinity;\n\tlet maxY = -Infinity;\n\n\tfor (const glyph of glyphs) {\n\t\tconst path = getGlyphPath(font, glyph.glyphId);\n\t\tif (path?.bounds) {\n\t\t\tconst offsetX = x + glyph.xOffset * scale;\n\t\t\tconst offsetY = y - glyph.yOffset * scale;\n\n\t\t\t// Transform commands with offset\n\t\t\tconst transformedCommands = path.commands.map((cmd): PathCommand => {\n\t\t\t\tswitch (cmd.type) {\n\t\t\t\t\tcase \"M\":\n\t\t\t\t\tcase \"L\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: cmd.type,\n\t\t\t\t\t\t\tx: cmd.x * scale + offsetX,\n\t\t\t\t\t\t\ty: -cmd.y * scale + offsetY,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"Q\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"Q\",\n\t\t\t\t\t\t\tx1: cmd.x1 * scale + offsetX,\n\t\t\t\t\t\t\ty1: -cmd.y1 * scale + offsetY,\n\t\t\t\t\t\t\tx: cmd.x * scale + offsetX,\n\t\t\t\t\t\t\ty: -cmd.y * scale + offsetY,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"C\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"C\",\n\t\t\t\t\t\t\tx1: cmd.x1 * scale + offsetX,\n\t\t\t\t\t\t\ty1: -cmd.y1 * scale + offsetY,\n\t\t\t\t\t\t\tx2: cmd.x2 * scale + offsetX,\n\t\t\t\t\t\t\ty2: -cmd.y2 * scale + offsetY,\n\t\t\t\t\t\t\tx: cmd.x * scale + offsetX,\n\t\t\t\t\t\t\ty: -cmd.y * scale + offsetY,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"Z\":\n\t\t\t\t\t\treturn { type: \"Z\" };\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn cmd;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst pathStr = pathToSVG(\n\t\t\t\t{ commands: transformedCommands, bounds: null },\n\t\t\t\t{ flipY: false, scale: 1 },\n\t\t\t);\n\t\t\tpaths.push(pathStr);\n\n\t\t\t// Update bounds\n\t\t\tconst b = path.bounds;\n\t\t\tminX = Math.min(minX, offsetX + b.xMin * scale);\n\t\t\tmaxX = Math.max(maxX, offsetX + b.xMax * scale);\n\t\t\tminY = Math.min(minY, offsetY - b.yMax * scale);\n\t\t\tmaxY = Math.max(maxY, offsetY - b.yMin * scale);\n\t\t}\n\n\t\tx += glyph.xAdvance * scale;\n\t\ty += glyph.yAdvance * scale;\n\t}\n\n\tif (paths.length === 0) {\n\t\treturn '<svg xmlns=\"http://www.w3.org/2000/svg\"></svg>';\n\t}\n\n\tconst width = Math.ceil(maxX - minX);\n\tconst height = Math.ceil(maxY - minY);\n\tconst viewBox = `${Math.floor(minX)} ${Math.floor(minY)} ${width} ${height}`;\n\n\treturn `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"${viewBox}\">\n <path d=\"${paths.join(\" \")}\" fill=\"${fill}\"/>\n</svg>`;\n}\n\n/**\n * Convert GlyphBuffer output to ShapedGlyph array\n */\nexport function glyphBufferToShapedGlyphs(buffer: GlyphBuffer): ShapedGlyph[] {\n\tconst result: ShapedGlyph[] = [];\n\tfor (const [i, info] of buffer.infos.entries()) {\n\t\tconst pos = buffer.positions[i];\n\t\tif (!pos) continue;\n\t\tresult.push({\n\t\t\tglyphId: info.glyphId,\n\t\t\txOffset: pos.xOffset,\n\t\t\tyOffset: pos.yOffset,\n\t\t\txAdvance: pos.xAdvance,\n\t\t\tyAdvance: pos.yAdvance,\n\t\t});\n\t}\n\treturn result;\n}\n\n/**\n * Get glyph path with variable font variation applied\n */\nexport function getGlyphPathWithVariation(\n\tfont: Font,\n\tglyphId: GlyphId,\n\taxisCoords: number[],\n): GlyphPath | null {\n\tconst contours = font.getGlyphContoursWithVariation(glyphId, axisCoords);\n\tif (!contours) return null;\n\n\tconst commands: PathCommand[] = [];\n\tfor (const contour of contours) {\n\t\tcommands.push(...contourToPath(contour));\n\t}\n\n\tconst bounds = font.getGlyphBounds(glyphId);\n\n\treturn { commands, bounds };\n}\n\n/**\n * Render shaped text with variable font support\n */\nexport function renderShapedTextWithVariation(\n\tctx: CanvasRenderingContext2D,\n\tfont: Font,\n\tglyphs: ShapedGlyph[],\n\taxisCoords: number[],\n\toptions?: { fontSize?: number; x?: number; y?: number; fill?: string },\n): void {\n\tconst fontSize = options?.fontSize ?? 16;\n\tconst startX = options?.x ?? 0;\n\tconst startY = options?.y ?? 0;\n\tconst fill = options?.fill ?? \"black\";\n\n\tconst scale = fontSize / font.unitsPerEm;\n\n\tctx.fillStyle = fill;\n\n\tlet x = startX;\n\tlet y = startY;\n\n\tfor (const glyph of glyphs) {\n\t\tconst path = getGlyphPathWithVariation(font, glyph.glyphId, axisCoords);\n\t\tif (path) {\n\t\t\tctx.beginPath();\n\t\t\tpathToCanvas(ctx, path, {\n\t\t\t\tscale,\n\t\t\t\tflipY: true,\n\t\t\t\toffsetX: x + glyph.xOffset * scale,\n\t\t\t\toffsetY: y - glyph.yOffset * scale,\n\t\t\t});\n\t\t\tctx.fill();\n\t\t}\n\n\t\tx += glyph.xAdvance * scale;\n\t\ty += glyph.yAdvance * scale;\n\t}\n}\n\n/**\n * Generate SVG for shaped text with variable font support\n */\nexport function shapedTextToSVGWithVariation(\n\tfont: Font,\n\tglyphs: ShapedGlyph[],\n\taxisCoords: number[],\n\toptions?: { fontSize?: number; fill?: string },\n): string {\n\tconst fontSize = options?.fontSize ?? 100;\n\tconst fill = options?.fill ?? \"currentColor\";\n\tconst scale = fontSize / font.unitsPerEm;\n\n\tconst paths: string[] = [];\n\tlet x = 0;\n\tlet y = 0;\n\tlet minX = Infinity;\n\tlet maxX = -Infinity;\n\tlet minY = Infinity;\n\tlet maxY = -Infinity;\n\n\tfor (const glyph of glyphs) {\n\t\tconst path = getGlyphPathWithVariation(font, glyph.glyphId, axisCoords);\n\t\tif (path?.bounds) {\n\t\t\tconst offsetX = x + glyph.xOffset * scale;\n\t\t\tconst offsetY = y - glyph.yOffset * scale;\n\n\t\t\tconst transformedCommands = path.commands.map((cmd): PathCommand => {\n\t\t\t\tswitch (cmd.type) {\n\t\t\t\t\tcase \"M\":\n\t\t\t\t\tcase \"L\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: cmd.type,\n\t\t\t\t\t\t\tx: cmd.x * scale + offsetX,\n\t\t\t\t\t\t\ty: -cmd.y * scale + offsetY,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"Q\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"Q\",\n\t\t\t\t\t\t\tx1: cmd.x1 * scale + offsetX,\n\t\t\t\t\t\t\ty1: -cmd.y1 * scale + offsetY,\n\t\t\t\t\t\t\tx: cmd.x * scale + offsetX,\n\t\t\t\t\t\t\ty: -cmd.y * scale + offsetY,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"C\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"C\",\n\t\t\t\t\t\t\tx1: cmd.x1 * scale + offsetX,\n\t\t\t\t\t\t\ty1: -cmd.y1 * scale + offsetY,\n\t\t\t\t\t\t\tx2: cmd.x2 * scale + offsetX,\n\t\t\t\t\t\t\ty2: -cmd.y2 * scale + offsetY,\n\t\t\t\t\t\t\tx: cmd.x * scale + offsetX,\n\t\t\t\t\t\t\ty: -cmd.y * scale + offsetY,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"Z\":\n\t\t\t\t\t\treturn { type: \"Z\" };\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn cmd;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst pathStr = pathToSVG(\n\t\t\t\t{ commands: transformedCommands, bounds: null },\n\t\t\t\t{ flipY: false, scale: 1 },\n\t\t\t);\n\t\t\tpaths.push(pathStr);\n\n\t\t\tconst b = path.bounds;\n\t\t\tminX = Math.min(minX, offsetX + b.xMin * scale);\n\t\t\tmaxX = Math.max(maxX, offsetX + b.xMax * scale);\n\t\t\tminY = Math.min(minY, offsetY - b.yMax * scale);\n\t\t\tmaxY = Math.max(maxY, offsetY - b.yMin * scale);\n\t\t}\n\n\t\tx += glyph.xAdvance * scale;\n\t\ty += glyph.yAdvance * scale;\n\t}\n\n\tif (paths.length === 0) {\n\t\treturn '<svg xmlns=\"http://www.w3.org/2000/svg\"></svg>';\n\t}\n\n\tconst width = Math.ceil(maxX - minX);\n\tconst height = Math.ceil(maxY - minY);\n\tconst viewBox = `${Math.floor(minX)} ${Math.floor(minY)} ${width} ${height}`;\n\n\treturn `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"${viewBox}\">\n <path d=\"${paths.join(\" \")}\" fill=\"${fill}\"/>\n</svg>`;\n}\n\n/**\n * Calculate the total advance width of shaped text\n */\nexport function getTextWidth(\n\tglyphs: ShapedGlyph[],\n\tfont: Font,\n\tfontSize: number,\n): number {\n\tconst scale = fontSize / font.unitsPerEm;\n\tlet width = 0;\n\tfor (const glyph of glyphs) {\n\t\twidth += glyph.xAdvance;\n\t}\n\treturn width * scale;\n}\n\n/**\n * Create a Path2D object from glyph path\n */\nexport function createPath2D(\n\tpath: GlyphPath,\n\toptions?: {\n\t\tflipY?: boolean;\n\t\tscale?: number;\n\t\toffsetX?: number;\n\t\toffsetY?: number;\n\t},\n): Path2D {\n\tconst p = new Path2D();\n\tpathToCanvas(p, path, options);\n\treturn p;\n}\n",
62
+ "import type { GlyphInfo } from \"../types.ts\";\n\n/**\n * Normalization mode for shaping\n */\nexport enum NormalizationMode {\n\t/** No normalization */\n\tNone = 0,\n\t/** Decompose (NFD-like) */\n\tDecompose = 1,\n\t/** Compose (NFC-like) */\n\tCompose = 2,\n\t/** Auto-detect based on script */\n\tAuto = 3,\n}\n\n/**\n * Canonical Combining Class (ccc) for combining marks\n * Based on Unicode 15.0\n */\nexport function getCombiningClass(cp: number): number {\n\t// Common combining classes\n\t// 0 = Not_Reordered (base characters, most characters)\n\t// 1 = Overlay\n\t// 7 = Nukta\n\t// 8 = Kana_Voicing\n\t// 9 = Virama\n\t// 200-240 = Various marks\n\n\t// Hebrew combining marks (0591-05BD, 05BF, 05C1-05C2, 05C4-05C5, 05C7)\n\tif (cp >= 0x0591 && cp <= 0x05bd) return getHebrewCcc(cp);\n\tif (cp === 0x05bf) return 23;\n\tif (cp === 0x05c1) return 24;\n\tif (cp === 0x05c2) return 25;\n\tif (cp === 0x05c4) return 230;\n\tif (cp === 0x05c5) return 220;\n\tif (cp === 0x05c7) return 18;\n\n\t// Arabic combining marks (064B-065F, 0670)\n\tif (cp >= 0x064b && cp <= 0x065f) return getArabicCcc(cp);\n\tif (cp === 0x0670) return 35;\n\t// Extended Arabic marks\n\tif (cp >= 0x0610 && cp <= 0x061a) return 230;\n\tif (cp >= 0x06d6 && cp <= 0x06dc) return 230;\n\tif (cp >= 0x06df && cp <= 0x06e4) return 230;\n\tif (cp >= 0x06e7 && cp <= 0x06e8) return 230;\n\tif (cp >= 0x06ea && cp <= 0x06ed) return 220;\n\tif (cp === 0x08d4) return 230;\n\tif (cp >= 0x08e3 && cp <= 0x08ff) return 220;\n\n\t// Devanagari nukta and signs\n\tif (cp === 0x093c) return 7; // Nukta\n\tif (cp === 0x094d) return 9; // Virama\n\tif (cp >= 0x0951 && cp <= 0x0954) return 230; // Accent marks\n\tif (cp === 0x0955) return 0;\n\tif (cp >= 0x0956 && cp <= 0x0957) return 0;\n\n\t// Bengali nukta and virama\n\tif (cp === 0x09bc) return 7;\n\tif (cp === 0x09cd) return 9;\n\tif (cp === 0x09fe) return 230;\n\n\t// Gurmukhi\n\tif (cp === 0x0a3c) return 7; // Nukta\n\tif (cp === 0x0a4d) return 9; // Virama\n\n\t// Gujarati\n\tif (cp === 0x0abc) return 7; // Nukta\n\tif (cp === 0x0acd) return 9; // Virama\n\n\t// Oriya\n\tif (cp === 0x0b3c) return 7; // Nukta\n\tif (cp === 0x0b4d) return 9; // Virama\n\n\t// Tamil\n\tif (cp === 0x0bcd) return 9; // Virama\n\n\t// Telugu\n\tif (cp === 0x0c4d) return 9; // Virama\n\tif (cp === 0x0c55) return 84;\n\tif (cp === 0x0c56) return 91;\n\n\t// Kannada\n\tif (cp === 0x0cbc) return 7; // Nukta\n\tif (cp === 0x0ccd) return 9; // Virama\n\n\t// Malayalam\n\tif (cp === 0x0d4d) return 9; // Virama\n\n\t// Sinhala\n\tif (cp === 0x0dca) return 9; // Virama\n\n\t// Thai/Lao vowels and tone marks\n\tif (cp >= 0x0e31 && cp <= 0x0e3a) return 0; // Positioned, not reordered\n\tif (cp >= 0x0e47 && cp <= 0x0e4e) return getThaiCcc(cp);\n\tif (cp >= 0x0eb1 && cp <= 0x0ebc) return 0;\n\tif (cp >= 0x0ec8 && cp <= 0x0ecd) return getThaiCcc(cp);\n\n\t// Tibetan\n\tif (cp >= 0x0f18 && cp <= 0x0f19) return 220;\n\tif (cp === 0x0f35) return 220;\n\tif (cp === 0x0f37) return 220;\n\tif (cp === 0x0f39) return 216;\n\tif (cp >= 0x0f71 && cp <= 0x0f7e) return getTibetanCcc(cp);\n\tif (cp >= 0x0f80 && cp <= 0x0f84) return getTibetanCcc(cp);\n\tif (cp >= 0x0f86 && cp <= 0x0f87) return 230;\n\n\t// Myanmar\n\tif (cp === 0x1037) return 7; // Nukta\n\tif (cp === 0x1039) return 9; // Virama\n\tif (cp === 0x103a) return 9;\n\n\t// Hangul Jamo (combining)\n\tif (cp >= 0x302a && cp <= 0x302f) return getHangulCcc(cp);\n\tif (cp >= 0x3099 && cp <= 0x309a) return 8; // Kana voicing\n\n\t// General combining marks (0300-036F)\n\tif (cp >= 0x0300 && cp <= 0x036f) return getLatinCcc(cp);\n\n\t// Combining Diacritical Marks Extended (1AB0-1AFF)\n\tif (cp >= 0x1ab0 && cp <= 0x1aff) return getCdmeClass(cp);\n\n\t// Combining Diacritical Marks Supplement (1DC0-1DFF)\n\tif (cp >= 0x1dc0 && cp <= 0x1dff) return getCdmsClass(cp);\n\n\t// Combining Half Marks (FE20-FE2F)\n\tif (cp >= 0xfe20 && cp <= 0xfe2f) return 230;\n\n\treturn 0;\n}\n\nfunction getThaiCcc(cp: number): number {\n\t// Thai tone marks and vowel signs above\n\tif (cp >= 0x0e48 && cp <= 0x0e4b) return 107; // Tone marks\n\tif (cp === 0x0e4c) return 0; // Thanthakhat\n\tif (cp === 0x0e4d) return 0; // Nikhahit\n\tif (cp === 0x0e4e) return 0; // Yamakkan\n\t// Lao tone marks\n\tif (cp >= 0x0ec8 && cp <= 0x0ecb) return 122;\n\treturn 0;\n}\n\nfunction getTibetanCcc(cp: number): number {\n\tif (cp === 0x0f71) return 129;\n\tif (cp === 0x0f72) return 130;\n\tif (cp === 0x0f73) return 0; // Composed\n\tif (cp === 0x0f74) return 132;\n\tif (cp === 0x0f75) return 0; // Composed\n\tif (cp === 0x0f76) return 0; // Composed\n\tif (cp === 0x0f77) return 0; // Composed\n\tif (cp === 0x0f78) return 0; // Composed\n\tif (cp === 0x0f79) return 0; // Composed\n\tif (cp === 0x0f7a) return 130;\n\tif (cp === 0x0f7b) return 130;\n\tif (cp === 0x0f7c) return 130;\n\tif (cp === 0x0f7d) return 130;\n\tif (cp === 0x0f7e) return 0;\n\tif (cp === 0x0f80) return 130;\n\tif (cp === 0x0f81) return 0; // Composed\n\tif (cp === 0x0f82) return 230;\n\tif (cp === 0x0f83) return 230;\n\tif (cp === 0x0f84) return 9;\n\treturn 0;\n}\n\nfunction getHangulCcc(cp: number): number {\n\tif (cp === 0x302a) return 218;\n\tif (cp === 0x302b) return 228;\n\tif (cp === 0x302c) return 232;\n\tif (cp === 0x302d) return 222;\n\tif (cp === 0x302e) return 224;\n\tif (cp === 0x302f) return 224;\n\treturn 0;\n}\n\nfunction getCdmeClass(cp: number): number {\n\t// Combining Diacritical Marks Extended\n\tif (cp >= 0x1ab0 && cp <= 0x1abe) return 230;\n\tif (cp === 0x1abf) return 220;\n\tif (cp === 0x1ac0) return 220;\n\treturn 230;\n}\n\nfunction getCdmsClass(cp: number): number {\n\t// Combining Diacritical Marks Supplement\n\tif (cp >= 0x1dc0 && cp <= 0x1dc1) return 230;\n\tif (cp === 0x1dc2) return 220;\n\tif (cp >= 0x1dc3 && cp <= 0x1dca) return 230;\n\tif (cp === 0x1dcb) return 230;\n\tif (cp === 0x1dcc) return 230;\n\tif (cp === 0x1dcd) return 234;\n\tif (cp === 0x1dce) return 214;\n\tif (cp === 0x1dcf) return 220;\n\tif (cp === 0x1dd0) return 202;\n\tif (cp >= 0x1dd1 && cp <= 0x1df5) return 230;\n\tif (cp >= 0x1df6 && cp <= 0x1df8) return 232;\n\tif (cp === 0x1df9) return 220;\n\tif (cp === 0x1dfa) return 218;\n\tif (cp >= 0x1dfb && cp <= 0x1dff) return 230;\n\treturn 230;\n}\n\nfunction getHebrewCcc(cp: number): number {\n\t// Hebrew accents and marks have specific combining classes\n\tif (cp >= 0x0591 && cp <= 0x05a1) return 220; // Below marks\n\tif (cp >= 0x05a2 && cp <= 0x05af) return 230; // Above marks\n\tif (cp >= 0x05b0 && cp <= 0x05b9) {\n\t\t// Vowel points\n\t\tif (cp === 0x05b0) return 10; // Sheva\n\t\tif (cp === 0x05b1) return 11; // Hataf Segol\n\t\tif (cp === 0x05b2) return 12; // Hataf Patah\n\t\tif (cp === 0x05b3) return 13; // Hataf Qamats\n\t\tif (cp === 0x05b4) return 14; // Hiriq\n\t\tif (cp === 0x05b5) return 15; // Tsere\n\t\tif (cp === 0x05b6) return 16; // Segol\n\t\tif (cp === 0x05b7) return 17; // Patah\n\t\tif (cp === 0x05b8) return 18; // Qamats\n\t\tif (cp === 0x05b9) return 19; // Holam\n\t}\n\tif (cp === 0x05ba) return 19; // Holam Haser\n\tif (cp === 0x05bb) return 20; // Qubuts\n\tif (cp === 0x05bc) return 21; // Dagesh\n\tif (cp === 0x05bd) return 22; // Meteg\n\treturn 0;\n}\n\nfunction getArabicCcc(cp: number): number {\n\tif (cp === 0x064b) return 27; // Fathatan\n\tif (cp === 0x064c) return 28; // Dammatan\n\tif (cp === 0x064d) return 29; // Kasratan\n\tif (cp === 0x064e) return 30; // Fatha\n\tif (cp === 0x064f) return 31; // Damma\n\tif (cp === 0x0650) return 32; // Kasra\n\tif (cp === 0x0651) return 33; // Shadda\n\tif (cp === 0x0652) return 34; // Sukun\n\tif (cp >= 0x0653 && cp <= 0x0655) return 230; // Maddah, Hamza above\n\tif (cp === 0x0656) return 220; // Subscript Alef\n\tif (cp === 0x0657) return 230; // Inverted Damma\n\tif (cp === 0x0658) return 230; // Mark Noon Ghunna\n\tif (cp >= 0x0659 && cp <= 0x065f) return 230;\n\treturn 0;\n}\n\nfunction getLatinCcc(cp: number): number {\n\t// Combining diacritical marks\n\tif (cp >= 0x0300 && cp <= 0x0314) return 230; // Above marks\n\tif (cp >= 0x0315 && cp <= 0x0315) return 232; // Above right\n\tif (cp >= 0x0316 && cp <= 0x0319) return 220; // Below marks\n\tif (cp >= 0x031a && cp <= 0x031a) return 232; // Above right\n\tif (cp >= 0x031b && cp <= 0x031b) return 216; // Attached above right\n\tif (cp >= 0x031c && cp <= 0x0320) return 220; // Below\n\tif (cp >= 0x0321 && cp <= 0x0322) return 202; // Attached below\n\tif (cp >= 0x0323 && cp <= 0x0326) return 220; // Below\n\tif (cp >= 0x0327 && cp <= 0x0328) return 202; // Attached below\n\tif (cp >= 0x0329 && cp <= 0x0333) return 220; // Below\n\tif (cp >= 0x0334 && cp <= 0x0338) return 1; // Overlay\n\tif (cp >= 0x0339 && cp <= 0x033c) return 220; // Below\n\tif (cp >= 0x033d && cp <= 0x0344) return 230; // Above\n\tif (cp === 0x0345) return 240; // Iota subscript\n\tif (cp >= 0x0346 && cp <= 0x034e) return 230; // Above\n\tif (cp === 0x034f) return 0; // CGJ\n\tif (cp >= 0x0350 && cp <= 0x0352) return 230; // Above\n\tif (cp >= 0x0353 && cp <= 0x0356) return 220; // Below\n\tif (cp >= 0x0357 && cp <= 0x0358) return 230; // Above\n\tif (cp >= 0x0359 && cp <= 0x035a) return 220; // Below\n\tif (cp >= 0x035b && cp <= 0x035b) return 230; // Above\n\tif (cp >= 0x035c && cp <= 0x035c) return 233; // Double below\n\tif (cp >= 0x035d && cp <= 0x035e) return 234; // Double above\n\tif (cp >= 0x035f && cp <= 0x035f) return 233; // Double below\n\tif (cp >= 0x0360 && cp <= 0x0361) return 234; // Double above\n\tif (cp >= 0x0362 && cp <= 0x0362) return 233; // Double below\n\tif (cp >= 0x0363 && cp <= 0x036f) return 230; // Above\n\treturn 0;\n}\n\n/**\n * Reorder combining marks according to canonical combining class\n */\nexport function reorderMarks(infos: GlyphInfo[]): void {\n\t// Simple bubble sort for stability (marks with same ccc keep order)\n\tconst n = infos.length;\n\tlet i = 1;\n\n\twhile (i < n) {\n\t\tconst info = infos[i];\n\t\tif (!info) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst ccc = getCombiningClass(info.codepoint);\n\t\tif (ccc === 0) {\n\t\t\t// Non-combining, advance\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Look backward for marks to reorder with\n\t\tlet j = i;\n\t\twhile (j > 0) {\n\t\t\tconst prevInfo = infos[j - 1];\n\t\t\tif (!prevInfo) break;\n\n\t\t\tconst prevCcc = getCombiningClass(prevInfo.codepoint);\n\t\t\tif (prevCcc === 0) break; // Hit a base character\n\t\t\tif (prevCcc <= ccc) break; // Already in order\n\n\t\t\t// Swap\n\t\t\tinfos[j] = prevInfo;\n\t\t\tinfos[j - 1] = info;\n\t\t\tj--;\n\t\t}\n\n\t\ti++;\n\t}\n}\n\n/**\n * Common decomposition mappings (subset of Unicode decomposition)\n */\nconst DECOMPOSITIONS: Map<number, number[]> = new Map([\n\t// Latin precomposed characters (Latin-1 Supplement)\n\t[0x00c0, [0x0041, 0x0300]], // À = A + grave\n\t[0x00c1, [0x0041, 0x0301]], // Á = A + acute\n\t[0x00c2, [0x0041, 0x0302]], // Â = A + circumflex\n\t[0x00c3, [0x0041, 0x0303]], // Ã = A + tilde\n\t[0x00c4, [0x0041, 0x0308]], // Ä = A + diaeresis\n\t[0x00c5, [0x0041, 0x030a]], // Å = A + ring\n\t[0x00c7, [0x0043, 0x0327]], // Ç = C + cedilla\n\t[0x00c8, [0x0045, 0x0300]], // È = E + grave\n\t[0x00c9, [0x0045, 0x0301]], // É = E + acute\n\t[0x00ca, [0x0045, 0x0302]], // Ê = E + circumflex\n\t[0x00cb, [0x0045, 0x0308]], // Ë = E + diaeresis\n\t[0x00cc, [0x0049, 0x0300]], // Ì = I + grave\n\t[0x00cd, [0x0049, 0x0301]], // Í = I + acute\n\t[0x00ce, [0x0049, 0x0302]], // Î = I + circumflex\n\t[0x00cf, [0x0049, 0x0308]], // Ï = I + diaeresis\n\t[0x00d1, [0x004e, 0x0303]], // Ñ = N + tilde\n\t[0x00d2, [0x004f, 0x0300]], // Ò = O + grave\n\t[0x00d3, [0x004f, 0x0301]], // Ó = O + acute\n\t[0x00d4, [0x004f, 0x0302]], // Ô = O + circumflex\n\t[0x00d5, [0x004f, 0x0303]], // Õ = O + tilde\n\t[0x00d6, [0x004f, 0x0308]], // Ö = O + diaeresis\n\t[0x00d9, [0x0055, 0x0300]], // Ù = U + grave\n\t[0x00da, [0x0055, 0x0301]], // Ú = U + acute\n\t[0x00db, [0x0055, 0x0302]], // Û = U + circumflex\n\t[0x00dc, [0x0055, 0x0308]], // Ü = U + diaeresis\n\t[0x00dd, [0x0059, 0x0301]], // Ý = Y + acute\n\t// Lowercase Latin-1\n\t[0x00e0, [0x0061, 0x0300]], // à = a + grave\n\t[0x00e1, [0x0061, 0x0301]], // á = a + acute\n\t[0x00e2, [0x0061, 0x0302]], // â = a + circumflex\n\t[0x00e3, [0x0061, 0x0303]], // ã = a + tilde\n\t[0x00e4, [0x0061, 0x0308]], // ä = a + diaeresis\n\t[0x00e5, [0x0061, 0x030a]], // å = a + ring\n\t[0x00e7, [0x0063, 0x0327]], // ç = c + cedilla\n\t[0x00e8, [0x0065, 0x0300]], // è = e + grave\n\t[0x00e9, [0x0065, 0x0301]], // é = e + acute\n\t[0x00ea, [0x0065, 0x0302]], // ê = e + circumflex\n\t[0x00eb, [0x0065, 0x0308]], // ë = e + diaeresis\n\t[0x00ec, [0x0069, 0x0300]], // ì = i + grave\n\t[0x00ed, [0x0069, 0x0301]], // í = i + acute\n\t[0x00ee, [0x0069, 0x0302]], // î = i + circumflex\n\t[0x00ef, [0x0069, 0x0308]], // ï = i + diaeresis\n\t[0x00f1, [0x006e, 0x0303]], // ñ = n + tilde\n\t[0x00f2, [0x006f, 0x0300]], // ò = o + grave\n\t[0x00f3, [0x006f, 0x0301]], // ó = o + acute\n\t[0x00f4, [0x006f, 0x0302]], // ô = o + circumflex\n\t[0x00f5, [0x006f, 0x0303]], // õ = o + tilde\n\t[0x00f6, [0x006f, 0x0308]], // ö = o + diaeresis\n\t[0x00f9, [0x0075, 0x0300]], // ù = u + grave\n\t[0x00fa, [0x0075, 0x0301]], // ú = u + acute\n\t[0x00fb, [0x0075, 0x0302]], // û = u + circumflex\n\t[0x00fc, [0x0075, 0x0308]], // ü = u + diaeresis\n\t[0x00fd, [0x0079, 0x0301]], // ý = y + acute\n\t[0x00ff, [0x0079, 0x0308]], // ÿ = y + diaeresis\n\t// Latin Extended-A\n\t[0x0100, [0x0041, 0x0304]], // Ā = A + macron\n\t[0x0101, [0x0061, 0x0304]], // ā = a + macron\n\t[0x0102, [0x0041, 0x0306]], // Ă = A + breve\n\t[0x0103, [0x0061, 0x0306]], // ă = a + breve\n\t[0x0104, [0x0041, 0x0328]], // Ą = A + ogonek\n\t[0x0105, [0x0061, 0x0328]], // ą = a + ogonek\n\t[0x0106, [0x0043, 0x0301]], // Ć = C + acute\n\t[0x0107, [0x0063, 0x0301]], // ć = c + acute\n\t[0x0108, [0x0043, 0x0302]], // Ĉ = C + circumflex\n\t[0x0109, [0x0063, 0x0302]], // ĉ = c + circumflex\n\t[0x010a, [0x0043, 0x0307]], // Ċ = C + dot above\n\t[0x010b, [0x0063, 0x0307]], // ċ = c + dot above\n\t[0x010c, [0x0043, 0x030c]], // Č = C + caron\n\t[0x010d, [0x0063, 0x030c]], // č = c + caron\n\t[0x010e, [0x0044, 0x030c]], // Ď = D + caron\n\t[0x010f, [0x0064, 0x030c]], // ď = d + caron\n\t[0x0112, [0x0045, 0x0304]], // Ē = E + macron\n\t[0x0113, [0x0065, 0x0304]], // ē = e + macron\n\t[0x0114, [0x0045, 0x0306]], // Ĕ = E + breve\n\t[0x0115, [0x0065, 0x0306]], // ĕ = e + breve\n\t[0x0116, [0x0045, 0x0307]], // Ė = E + dot above\n\t[0x0117, [0x0065, 0x0307]], // ė = e + dot above\n\t[0x0118, [0x0045, 0x0328]], // Ę = E + ogonek\n\t[0x0119, [0x0065, 0x0328]], // ę = e + ogonek\n\t[0x011a, [0x0045, 0x030c]], // Ě = E + caron\n\t[0x011b, [0x0065, 0x030c]], // ě = e + caron\n\t[0x011c, [0x0047, 0x0302]], // Ĝ = G + circumflex\n\t[0x011d, [0x0067, 0x0302]], // ĝ = g + circumflex\n\t[0x011e, [0x0047, 0x0306]], // Ğ = G + breve\n\t[0x011f, [0x0067, 0x0306]], // ğ = g + breve\n\t[0x0120, [0x0047, 0x0307]], // Ġ = G + dot above\n\t[0x0121, [0x0067, 0x0307]], // ġ = g + dot above\n\t[0x0122, [0x0047, 0x0327]], // Ģ = G + cedilla\n\t[0x0123, [0x0067, 0x0327]], // ģ = g + cedilla\n\t[0x0124, [0x0048, 0x0302]], // Ĥ = H + circumflex\n\t[0x0125, [0x0068, 0x0302]], // ĥ = h + circumflex\n\t[0x0128, [0x0049, 0x0303]], // Ĩ = I + tilde\n\t[0x0129, [0x0069, 0x0303]], // ĩ = i + tilde\n\t[0x012a, [0x0049, 0x0304]], // Ī = I + macron\n\t[0x012b, [0x0069, 0x0304]], // ī = i + macron\n\t[0x012c, [0x0049, 0x0306]], // Ĭ = I + breve\n\t[0x012d, [0x0069, 0x0306]], // ĭ = i + breve\n\t[0x012e, [0x0049, 0x0328]], // Į = I + ogonek\n\t[0x012f, [0x0069, 0x0328]], // į = i + ogonek\n\t[0x0130, [0x0049, 0x0307]], // İ = I + dot above\n\t[0x0134, [0x004a, 0x0302]], // Ĵ = J + circumflex\n\t[0x0135, [0x006a, 0x0302]], // ĵ = j + circumflex\n\t[0x0136, [0x004b, 0x0327]], // Ķ = K + cedilla\n\t[0x0137, [0x006b, 0x0327]], // ķ = k + cedilla\n\t[0x0139, [0x004c, 0x0301]], // Ĺ = L + acute\n\t[0x013a, [0x006c, 0x0301]], // ĺ = l + acute\n\t[0x013b, [0x004c, 0x0327]], // Ļ = L + cedilla\n\t[0x013c, [0x006c, 0x0327]], // ļ = l + cedilla\n\t[0x013d, [0x004c, 0x030c]], // Ľ = L + caron\n\t[0x013e, [0x006c, 0x030c]], // ľ = l + caron\n\t[0x0143, [0x004e, 0x0301]], // Ń = N + acute\n\t[0x0144, [0x006e, 0x0301]], // ń = n + acute\n\t[0x0145, [0x004e, 0x0327]], // Ņ = N + cedilla\n\t[0x0146, [0x006e, 0x0327]], // ņ = n + cedilla\n\t[0x0147, [0x004e, 0x030c]], // Ň = N + caron\n\t[0x0148, [0x006e, 0x030c]], // ň = n + caron\n\t[0x014c, [0x004f, 0x0304]], // Ō = O + macron\n\t[0x014d, [0x006f, 0x0304]], // ō = o + macron\n\t[0x014e, [0x004f, 0x0306]], // Ŏ = O + breve\n\t[0x014f, [0x006f, 0x0306]], // ŏ = o + breve\n\t[0x0150, [0x004f, 0x030b]], // Ő = O + double acute\n\t[0x0151, [0x006f, 0x030b]], // ő = o + double acute\n\t[0x0154, [0x0052, 0x0301]], // Ŕ = R + acute\n\t[0x0155, [0x0072, 0x0301]], // ŕ = r + acute\n\t[0x0156, [0x0052, 0x0327]], // Ŗ = R + cedilla\n\t[0x0157, [0x0072, 0x0327]], // ŗ = r + cedilla\n\t[0x0158, [0x0052, 0x030c]], // Ř = R + caron\n\t[0x0159, [0x0072, 0x030c]], // ř = r + caron\n\t[0x015a, [0x0053, 0x0301]], // Ś = S + acute\n\t[0x015b, [0x0073, 0x0301]], // ś = s + acute\n\t[0x015c, [0x0053, 0x0302]], // Ŝ = S + circumflex\n\t[0x015d, [0x0073, 0x0302]], // ŝ = s + circumflex\n\t[0x015e, [0x0053, 0x0327]], // Ş = S + cedilla\n\t[0x015f, [0x0073, 0x0327]], // ş = s + cedilla\n\t[0x0160, [0x0053, 0x030c]], // Š = S + caron\n\t[0x0161, [0x0073, 0x030c]], // š = s + caron\n\t[0x0162, [0x0054, 0x0327]], // Ţ = T + cedilla\n\t[0x0163, [0x0074, 0x0327]], // ţ = t + cedilla\n\t[0x0164, [0x0054, 0x030c]], // Ť = T + caron\n\t[0x0165, [0x0074, 0x030c]], // ť = t + caron\n\t[0x0168, [0x0055, 0x0303]], // Ũ = U + tilde\n\t[0x0169, [0x0075, 0x0303]], // ũ = u + tilde\n\t[0x016a, [0x0055, 0x0304]], // Ū = U + macron\n\t[0x016b, [0x0075, 0x0304]], // ū = u + macron\n\t[0x016c, [0x0055, 0x0306]], // Ŭ = U + breve\n\t[0x016d, [0x0075, 0x0306]], // ŭ = u + breve\n\t[0x016e, [0x0055, 0x030a]], // Ů = U + ring\n\t[0x016f, [0x0075, 0x030a]], // ů = u + ring\n\t[0x0170, [0x0055, 0x030b]], // Ű = U + double acute\n\t[0x0171, [0x0075, 0x030b]], // ű = u + double acute\n\t[0x0172, [0x0055, 0x0328]], // Ų = U + ogonek\n\t[0x0173, [0x0075, 0x0328]], // ų = u + ogonek\n\t[0x0174, [0x0057, 0x0302]], // Ŵ = W + circumflex\n\t[0x0175, [0x0077, 0x0302]], // ŵ = w + circumflex\n\t[0x0176, [0x0059, 0x0302]], // Ŷ = Y + circumflex\n\t[0x0177, [0x0079, 0x0302]], // ŷ = y + circumflex\n\t[0x0178, [0x0059, 0x0308]], // Ÿ = Y + diaeresis\n\t[0x0179, [0x005a, 0x0301]], // Ź = Z + acute\n\t[0x017a, [0x007a, 0x0301]], // ź = z + acute\n\t[0x017b, [0x005a, 0x0307]], // Ż = Z + dot above\n\t[0x017c, [0x007a, 0x0307]], // ż = z + dot above\n\t[0x017d, [0x005a, 0x030c]], // Ž = Z + caron\n\t[0x017e, [0x007a, 0x030c]], // ž = z + caron\n\t// Vietnamese characters (Latin Extended Additional)\n\t[0x1ea0, [0x0041, 0x0323]], // Ạ = A + dot below\n\t[0x1ea1, [0x0061, 0x0323]], // ạ = a + dot below\n\t[0x1ea2, [0x0041, 0x0309]], // Ả = A + hook above\n\t[0x1ea3, [0x0061, 0x0309]], // ả = a + hook above\n\t[0x1eb8, [0x0045, 0x0323]], // Ẹ = E + dot below\n\t[0x1eb9, [0x0065, 0x0323]], // ẹ = e + dot below\n\t[0x1eba, [0x0045, 0x0309]], // Ẻ = E + hook above\n\t[0x1ebb, [0x0065, 0x0309]], // ẻ = e + hook above\n\t[0x1ebc, [0x0045, 0x0303]], // Ẽ = E + tilde\n\t[0x1ebd, [0x0065, 0x0303]], // ẽ = e + tilde\n\t[0x1ec8, [0x0049, 0x0309]], // Ỉ = I + hook above\n\t[0x1ec9, [0x0069, 0x0309]], // ỉ = i + hook above\n\t[0x1eca, [0x0049, 0x0323]], // Ị = I + dot below\n\t[0x1ecb, [0x0069, 0x0323]], // ị = i + dot below\n\t[0x1ecc, [0x004f, 0x0323]], // Ọ = O + dot below\n\t[0x1ecd, [0x006f, 0x0323]], // ọ = o + dot below\n\t[0x1ece, [0x004f, 0x0309]], // Ỏ = O + hook above\n\t[0x1ecf, [0x006f, 0x0309]], // ỏ = o + hook above\n\t[0x1ee4, [0x0055, 0x0323]], // Ụ = U + dot below\n\t[0x1ee5, [0x0075, 0x0323]], // ụ = u + dot below\n\t[0x1ee6, [0x0055, 0x0309]], // Ủ = U + hook above\n\t[0x1ee7, [0x0075, 0x0309]], // ủ = u + hook above\n\t[0x1ef2, [0x0059, 0x0300]], // Ỳ = Y + grave\n\t[0x1ef3, [0x0079, 0x0300]], // ỳ = y + grave\n\t[0x1ef4, [0x0059, 0x0323]], // Ỵ = Y + dot below\n\t[0x1ef5, [0x0079, 0x0323]], // ỵ = y + dot below\n\t[0x1ef6, [0x0059, 0x0309]], // Ỷ = Y + hook above\n\t[0x1ef7, [0x0079, 0x0309]], // ỷ = y + hook above\n\t[0x1ef8, [0x0059, 0x0303]], // Ỹ = Y + tilde\n\t[0x1ef9, [0x0079, 0x0303]], // ỹ = y + tilde\n\t// Greek Extended\n\t[0x1f00, [0x03b1, 0x0313]], // ἀ = α + psili\n\t[0x1f01, [0x03b1, 0x0314]], // ἁ = α + dasia\n\t[0x1f08, [0x0391, 0x0313]], // Ἀ = Α + psili\n\t[0x1f09, [0x0391, 0x0314]], // Ἁ = Α + dasia\n\t// Cyrillic (common)\n\t[0x0439, [0x0438, 0x0306]], // й = и + breve\n\t[0x0419, [0x0418, 0x0306]], // Й = И + breve\n\t[0x0451, [0x0435, 0x0308]], // ё = е + diaeresis\n\t[0x0401, [0x0415, 0x0308]], // Ё = Е + diaeresis\n]);\n\n/**\n * Decompose a codepoint if it has a canonical decomposition\n */\nexport function decompose(cp: number): number[] | null {\n\treturn DECOMPOSITIONS.get(cp) ?? null;\n}\n\n/**\n * Common composition mappings (subset of Unicode canonical composition)\n * Maps (base, combining) pairs to composed character\n */\nconst COMPOSITIONS: Map<number, Map<number, number>> = new Map([\n\t// Latin A compositions\n\t[\n\t\t0x0041,\n\t\tnew Map([\n\t\t\t[0x0300, 0x00c0], // A + grave = À\n\t\t\t[0x0301, 0x00c1], // A + acute = Á\n\t\t\t[0x0302, 0x00c2], // A + circumflex = Â\n\t\t\t[0x0303, 0x00c3], // A + tilde = Ã\n\t\t\t[0x0308, 0x00c4], // A + diaeresis = Ä\n\t\t\t[0x030a, 0x00c5], // A + ring = Å\n\t\t\t[0x0328, 0x0104], // A + ogonek = Ą\n\t\t\t[0x030c, 0x01cd], // A + caron = Ǎ\n\t\t\t[0x0304, 0x0100], // A + macron = Ā\n\t\t\t[0x0306, 0x0102], // A + breve = Ă\n\t\t]),\n\t],\n\t// Latin C compositions\n\t[\n\t\t0x0043,\n\t\tnew Map([\n\t\t\t[0x0327, 0x00c7], // C + cedilla = Ç\n\t\t\t[0x0301, 0x0106], // C + acute = Ć\n\t\t\t[0x0302, 0x0108], // C + circumflex = Ĉ\n\t\t\t[0x030c, 0x010c], // C + caron = Č\n\t\t\t[0x0307, 0x010a], // C + dot above = Ċ\n\t\t]),\n\t],\n\t// Latin E compositions\n\t[\n\t\t0x0045,\n\t\tnew Map([\n\t\t\t[0x0300, 0x00c8], // E + grave = È\n\t\t\t[0x0301, 0x00c9], // E + acute = É\n\t\t\t[0x0302, 0x00ca], // E + circumflex = Ê\n\t\t\t[0x0308, 0x00cb], // E + diaeresis = Ë\n\t\t\t[0x0328, 0x0118], // E + ogonek = Ę\n\t\t\t[0x030c, 0x011a], // E + caron = Ě\n\t\t\t[0x0304, 0x0112], // E + macron = Ē\n\t\t\t[0x0306, 0x0114], // E + breve = Ĕ\n\t\t\t[0x0307, 0x0116], // E + dot above = Ė\n\t\t]),\n\t],\n\t// Latin I compositions\n\t[\n\t\t0x0049,\n\t\tnew Map([\n\t\t\t[0x0300, 0x00cc], // I + grave = Ì\n\t\t\t[0x0301, 0x00cd], // I + acute = Í\n\t\t\t[0x0302, 0x00ce], // I + circumflex = Î\n\t\t\t[0x0308, 0x00cf], // I + diaeresis = Ï\n\t\t\t[0x0303, 0x0128], // I + tilde = Ĩ\n\t\t\t[0x0304, 0x012a], // I + macron = Ī\n\t\t\t[0x0306, 0x012c], // I + breve = Ĭ\n\t\t\t[0x0328, 0x012e], // I + ogonek = Į\n\t\t\t[0x0307, 0x0130], // I + dot above = İ\n\t\t]),\n\t],\n\t// Latin N compositions\n\t[\n\t\t0x004e,\n\t\tnew Map([\n\t\t\t[0x0303, 0x00d1], // N + tilde = Ñ\n\t\t\t[0x0301, 0x0143], // N + acute = Ń\n\t\t\t[0x0327, 0x0145], // N + cedilla = Ņ\n\t\t\t[0x030c, 0x0147], // N + caron = Ň\n\t\t]),\n\t],\n\t// Latin O compositions\n\t[\n\t\t0x004f,\n\t\tnew Map([\n\t\t\t[0x0300, 0x00d2], // O + grave = Ò\n\t\t\t[0x0301, 0x00d3], // O + acute = Ó\n\t\t\t[0x0302, 0x00d4], // O + circumflex = Ô\n\t\t\t[0x0303, 0x00d5], // O + tilde = Õ\n\t\t\t[0x0308, 0x00d6], // O + diaeresis = Ö\n\t\t\t[0x0304, 0x014c], // O + macron = Ō\n\t\t\t[0x0306, 0x014e], // O + breve = Ŏ\n\t\t\t[0x030b, 0x0150], // O + double acute = Ő\n\t\t\t[0x0328, 0x01ea], // O + ogonek = Ǫ\n\t\t]),\n\t],\n\t// Latin U compositions\n\t[\n\t\t0x0055,\n\t\tnew Map([\n\t\t\t[0x0300, 0x00d9], // U + grave = Ù\n\t\t\t[0x0301, 0x00da], // U + acute = Ú\n\t\t\t[0x0302, 0x00db], // U + circumflex = Û\n\t\t\t[0x0308, 0x00dc], // U + diaeresis = Ü\n\t\t\t[0x0303, 0x0168], // U + tilde = Ũ\n\t\t\t[0x0304, 0x016a], // U + macron = Ū\n\t\t\t[0x0306, 0x016c], // U + breve = Ŭ\n\t\t\t[0x030a, 0x016e], // U + ring = Ů\n\t\t\t[0x030b, 0x0170], // U + double acute = Ű\n\t\t\t[0x0328, 0x0172], // U + ogonek = Ų\n\t\t\t[0x030c, 0x01d3], // U + caron = Ǔ\n\t\t]),\n\t],\n\t// Latin Y compositions\n\t[\n\t\t0x0059,\n\t\tnew Map([\n\t\t\t[0x0301, 0x00dd], // Y + acute = Ý\n\t\t\t[0x0302, 0x0176], // Y + circumflex = Ŷ\n\t\t\t[0x0308, 0x0178], // Y + diaeresis = Ÿ\n\t\t]),\n\t],\n\t// Lowercase a compositions\n\t[\n\t\t0x0061,\n\t\tnew Map([\n\t\t\t[0x0300, 0x00e0], // a + grave = à\n\t\t\t[0x0301, 0x00e1], // a + acute = á\n\t\t\t[0x0302, 0x00e2], // a + circumflex = â\n\t\t\t[0x0303, 0x00e3], // a + tilde = ã\n\t\t\t[0x0308, 0x00e4], // a + diaeresis = ä\n\t\t\t[0x030a, 0x00e5], // a + ring = å\n\t\t\t[0x0328, 0x0105], // a + ogonek = ą\n\t\t\t[0x030c, 0x01ce], // a + caron = ǎ\n\t\t\t[0x0304, 0x0101], // a + macron = ā\n\t\t\t[0x0306, 0x0103], // a + breve = ă\n\t\t]),\n\t],\n\t// Lowercase c compositions\n\t[\n\t\t0x0063,\n\t\tnew Map([\n\t\t\t[0x0327, 0x00e7], // c + cedilla = ç\n\t\t\t[0x0301, 0x0107], // c + acute = ć\n\t\t\t[0x0302, 0x0109], // c + circumflex = ĉ\n\t\t\t[0x030c, 0x010d], // c + caron = č\n\t\t\t[0x0307, 0x010b], // c + dot above = ċ\n\t\t]),\n\t],\n\t// Lowercase e compositions\n\t[\n\t\t0x0065,\n\t\tnew Map([\n\t\t\t[0x0300, 0x00e8], // e + grave = è\n\t\t\t[0x0301, 0x00e9], // e + acute = é\n\t\t\t[0x0302, 0x00ea], // e + circumflex = ê\n\t\t\t[0x0308, 0x00eb], // e + diaeresis = ë\n\t\t\t[0x0328, 0x0119], // e + ogonek = ę\n\t\t\t[0x030c, 0x011b], // e + caron = ě\n\t\t\t[0x0304, 0x0113], // e + macron = ē\n\t\t\t[0x0306, 0x0115], // e + breve = ĕ\n\t\t\t[0x0307, 0x0117], // e + dot above = ė\n\t\t]),\n\t],\n\t// Lowercase i compositions\n\t[\n\t\t0x0069,\n\t\tnew Map([\n\t\t\t[0x0300, 0x00ec], // i + grave = ì\n\t\t\t[0x0301, 0x00ed], // i + acute = í\n\t\t\t[0x0302, 0x00ee], // i + circumflex = î\n\t\t\t[0x0308, 0x00ef], // i + diaeresis = ï\n\t\t\t[0x0303, 0x0129], // i + tilde = ĩ\n\t\t\t[0x0304, 0x012b], // i + macron = ī\n\t\t\t[0x0306, 0x012d], // i + breve = ĭ\n\t\t\t[0x0328, 0x012f], // i + ogonek = į\n\t\t]),\n\t],\n\t// Lowercase n compositions\n\t[\n\t\t0x006e,\n\t\tnew Map([\n\t\t\t[0x0303, 0x00f1], // n + tilde = ñ\n\t\t\t[0x0301, 0x0144], // n + acute = ń\n\t\t\t[0x0327, 0x0146], // n + cedilla = ņ\n\t\t\t[0x030c, 0x0148], // n + caron = ň\n\t\t]),\n\t],\n\t// Lowercase o compositions\n\t[\n\t\t0x006f,\n\t\tnew Map([\n\t\t\t[0x0300, 0x00f2], // o + grave = ò\n\t\t\t[0x0301, 0x00f3], // o + acute = ó\n\t\t\t[0x0302, 0x00f4], // o + circumflex = ô\n\t\t\t[0x0303, 0x00f5], // o + tilde = õ\n\t\t\t[0x0308, 0x00f6], // o + diaeresis = ö\n\t\t\t[0x0304, 0x014d], // o + macron = ō\n\t\t\t[0x0306, 0x014f], // o + breve = ŏ\n\t\t\t[0x030b, 0x0151], // o + double acute = ő\n\t\t\t[0x0328, 0x01eb], // o + ogonek = ǫ\n\t\t]),\n\t],\n\t// Lowercase u compositions\n\t[\n\t\t0x0075,\n\t\tnew Map([\n\t\t\t[0x0300, 0x00f9], // u + grave = ù\n\t\t\t[0x0301, 0x00fa], // u + acute = ú\n\t\t\t[0x0302, 0x00fb], // u + circumflex = û\n\t\t\t[0x0308, 0x00fc], // u + diaeresis = ü\n\t\t\t[0x0303, 0x0169], // u + tilde = ũ\n\t\t\t[0x0304, 0x016b], // u + macron = ū\n\t\t\t[0x0306, 0x016d], // u + breve = ŭ\n\t\t\t[0x030a, 0x016f], // u + ring = ů\n\t\t\t[0x030b, 0x0171], // u + double acute = ű\n\t\t\t[0x0328, 0x0173], // u + ogonek = ų\n\t\t\t[0x030c, 0x01d4], // u + caron = ǔ\n\t\t]),\n\t],\n\t// Lowercase y compositions\n\t[\n\t\t0x0079,\n\t\tnew Map([\n\t\t\t[0x0301, 0x00fd], // y + acute = ý\n\t\t\t[0x0308, 0x00ff], // y + diaeresis = ÿ\n\t\t\t[0x0302, 0x0177], // y + circumflex = ŷ\n\t\t]),\n\t],\n\t// Other common compositions\n\t[\n\t\t0x0053,\n\t\tnew Map([\n\t\t\t// S\n\t\t\t[0x0301, 0x015a], // S + acute = Ś\n\t\t\t[0x0302, 0x015c], // S + circumflex = Ŝ\n\t\t\t[0x0327, 0x015e], // S + cedilla = Ş\n\t\t\t[0x030c, 0x0160], // S + caron = Š\n\t\t]),\n\t],\n\t[\n\t\t0x0073,\n\t\tnew Map([\n\t\t\t// s\n\t\t\t[0x0301, 0x015b], // s + acute = ś\n\t\t\t[0x0302, 0x015d], // s + circumflex = ŝ\n\t\t\t[0x0327, 0x015f], // s + cedilla = ş\n\t\t\t[0x030c, 0x0161], // s + caron = š\n\t\t]),\n\t],\n\t[\n\t\t0x005a,\n\t\tnew Map([\n\t\t\t// Z\n\t\t\t[0x0301, 0x0179], // Z + acute = Ź\n\t\t\t[0x0307, 0x017b], // Z + dot above = Ż\n\t\t\t[0x030c, 0x017d], // Z + caron = Ž\n\t\t]),\n\t],\n\t[\n\t\t0x007a,\n\t\tnew Map([\n\t\t\t// z\n\t\t\t[0x0301, 0x017a], // z + acute = ź\n\t\t\t[0x0307, 0x017c], // z + dot above = ż\n\t\t\t[0x030c, 0x017e], // z + caron = ž\n\t\t]),\n\t],\n]);\n\n/**\n * Try to compose a base character with a combining mark\n * Returns the composed character or null if no composition exists\n */\nexport function tryCompose(base: number, combining: number): number | null {\n\tconst baseCompositions = COMPOSITIONS.get(base);\n\tif (!baseCompositions) return null;\n\treturn baseCompositions.get(combining) ?? null;\n}\n\n/**\n * Compose combining marks with their bases where possible (NFC-like)\n */\nfunction composeMarks(infos: GlyphInfo[]): GlyphInfo[] {\n\tif (infos.length === 0) return infos;\n\n\tconst result: GlyphInfo[] = [];\n\tlet i = 0;\n\n\twhile (i < infos.length) {\n\t\tconst current = infos[i];\n\t\tif (!current) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst currentCcc = getCombiningClass(current.codepoint);\n\n\t\t// If this is a base character (ccc = 0), try to compose with following marks\n\t\tif (currentCcc === 0) {\n\t\t\tlet composedCp = current.codepoint;\n\t\t\tlet lastCcc = 0;\n\t\t\tlet j = i + 1;\n\n\t\t\t// Look for combining marks that can be composed\n\t\t\twhile (j < infos.length) {\n\t\t\t\tconst mark = infos[j];\n\t\t\t\tif (!mark) break;\n\n\t\t\t\tconst markCcc = getCombiningClass(mark.codepoint);\n\n\t\t\t\t// Stop at next base character\n\t\t\t\tif (markCcc === 0) break;\n\n\t\t\t\t// Can only compose if:\n\t\t\t\t// 1. Mark has higher ccc than last composed mark (or last was base)\n\t\t\t\t// 2. Composition exists for the pair\n\t\t\t\tif (markCcc > lastCcc || lastCcc === 0) {\n\t\t\t\t\tconst composed = tryCompose(composedCp, mark.codepoint);\n\t\t\t\t\tif (composed !== null) {\n\t\t\t\t\t\tcomposedCp = composed;\n\t\t\t\t\t\t// Mark this position as consumed (will skip)\n\t\t\t\t\t\tj++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Mark wasn't composed, stop looking for compositions\n\t\t\t\t// but continue with remaining marks\n\t\t\t\tlastCcc = markCcc;\n\t\t\t\tj++;\n\t\t\t}\n\n\t\t\t// Output the (possibly composed) base\n\t\t\tresult.push({\n\t\t\t\tglyphId: current.glyphId,\n\t\t\t\tcluster: current.cluster,\n\t\t\t\tmask: current.mask,\n\t\t\t\tcodepoint: composedCp,\n\t\t\t});\n\n\t\t\t// Output any marks that weren't composed\n\t\t\tfor (let k = i + 1; k < j; k++) {\n\t\t\t\tconst mark = infos[k];\n\t\t\t\tif (!mark) continue;\n\n\t\t\t\tconst markCcc = getCombiningClass(mark.codepoint);\n\t\t\t\t// Only output marks that weren't composed (check if they're still combining marks)\n\t\t\t\t// We need to re-check if a composition exists to determine what to output\n\t\t\t\tconst compositionExists =\n\t\t\t\t\ttryCompose(composedCp, mark.codepoint) !== null;\n\t\t\t\tif (!compositionExists && markCcc !== 0) {\n\t\t\t\t\tresult.push(mark);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti = j;\n\t\t} else {\n\t\t\t// Standalone combining mark (no base), just copy it\n\t\t\tresult.push(current);\n\t\t\ti++;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Apply normalization to glyph infos\n */\nexport function normalize(\n\tinfos: GlyphInfo[],\n\tmode: NormalizationMode,\n): GlyphInfo[] {\n\tif (mode === NormalizationMode.None) {\n\t\treturn infos;\n\t}\n\n\tif (mode === NormalizationMode.Decompose) {\n\t\t// Decompose precomposed characters (NFD-like)\n\t\tconst result: GlyphInfo[] = [];\n\n\t\tfor (const info of infos) {\n\t\t\tconst decomposed = decompose(info.codepoint);\n\t\t\tif (decomposed) {\n\t\t\t\t// Replace with decomposed sequence\n\t\t\t\tfor (const cp of decomposed) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\tglyphId: info.glyphId, // Will be remapped later\n\t\t\t\t\t\tcluster: info.cluster,\n\t\t\t\t\t\tmask: info.mask,\n\t\t\t\t\t\tcodepoint: cp,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresult.push(info);\n\t\t\t}\n\t\t}\n\n\t\t// Reorder combining marks\n\t\treorderMarks(result);\n\n\t\treturn result;\n\t}\n\n\tif (mode === NormalizationMode.Compose) {\n\t\t// First decompose, reorder, then compose (NFC-like)\n\t\t// Step 1: Decompose\n\t\tconst decomposed: GlyphInfo[] = [];\n\t\tfor (const info of infos) {\n\t\t\tconst dec = decompose(info.codepoint);\n\t\t\tif (dec) {\n\t\t\t\tfor (const cp of dec) {\n\t\t\t\t\tdecomposed.push({\n\t\t\t\t\t\tglyphId: info.glyphId,\n\t\t\t\t\t\tcluster: info.cluster,\n\t\t\t\t\t\tmask: info.mask,\n\t\t\t\t\t\tcodepoint: cp,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdecomposed.push(info);\n\t\t\t}\n\t\t}\n\n\t\t// Step 2: Reorder combining marks\n\t\treorderMarks(decomposed);\n\n\t\t// Step 3: Compose\n\t\treturn composeMarks(decomposed);\n\t}\n\n\tif (mode === NormalizationMode.Auto) {\n\t\t// Auto mode: use decomposition by default (better for shaping)\n\t\tconst result: GlyphInfo[] = [];\n\n\t\tfor (const info of infos) {\n\t\t\tconst decomposed = decompose(info.codepoint);\n\t\t\tif (decomposed) {\n\t\t\t\tfor (const cp of decomposed) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\tglyphId: info.glyphId,\n\t\t\t\t\t\tcluster: info.cluster,\n\t\t\t\t\t\tmask: info.mask,\n\t\t\t\t\t\tcodepoint: cp,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresult.push(info);\n\t\t\t}\n\t\t}\n\n\t\treorderMarks(result);\n\t\treturn result;\n\t}\n\n\treturn infos;\n}\n",
63
+ "import type { Font } from \"../font/font.ts\";\nimport { getGlyphClass } from \"../font/tables/gdef.ts\";\nimport { getKernValue } from \"../font/tables/kern.ts\";\nimport type { GlyphId, GlyphInfo, GlyphPosition } from \"../types.ts\";\nimport { GlyphClass } from \"../types.ts\";\nimport { getCombiningClass } from \"../unicode/normalize.ts\";\n\n/**\n * Fallback mark positioning when GPOS is not available\n * Uses combining class information to position marks\n */\nexport function applyFallbackMarkPositioning(\n\tfont: Font,\n\tinfos: GlyphInfo[],\n\tpositions: GlyphPosition[],\n): void {\n\tfor (let i = 0; i < infos.length; i++) {\n\t\tconst info = infos[i];\n\t\tconst pos = positions[i];\n\t\tif (!info || !pos) continue;\n\n\t\tconst glyphClass = font.gdef ? getGlyphClass(font.gdef, info.glyphId) : 0;\n\t\tconst ccc = getCombiningClass(info.codepoint);\n\n\t\t// Skip if not a mark\n\t\tif (glyphClass !== GlyphClass.Mark && ccc === 0) continue;\n\n\t\t// Find the base glyph\n\t\tlet baseIndex = -1;\n\t\tfor (let j = i - 1; j >= 0; j--) {\n\t\t\tconst prevInfo = infos[j];\n\t\t\tif (!prevInfo) continue;\n\n\t\t\tconst prevClass = font.gdef\n\t\t\t\t? getGlyphClass(font.gdef, prevInfo.glyphId)\n\t\t\t\t: 0;\n\t\t\tconst prevCcc = getCombiningClass(prevInfo.codepoint);\n\n\t\t\tif (prevClass === GlyphClass.Base || (prevClass === 0 && prevCcc === 0)) {\n\t\t\t\tbaseIndex = j;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (baseIndex < 0) continue;\n\n\t\tconst baseInfo = infos[baseIndex];\n\t\tconst basePos = positions[baseIndex];\n\t\tif (!baseInfo || !basePos) continue;\n\n\t\t// Get base glyph metrics\n\t\tconst baseAdvance = font.advanceWidth(baseInfo.glyphId);\n\n\t\t// Position mark relative to base based on combining class\n\t\t// This is a simplified heuristic - real mark positioning uses anchors\n\t\tpositionMarkFallback(font, info, pos, baseInfo, basePos, baseAdvance, ccc);\n\n\t\t// Mark has zero advance (already accounted for in base)\n\t\tpos.xAdvance = 0;\n\t\tpos.yAdvance = 0;\n\t}\n}\n\nfunction positionMarkFallback(\n\tfont: Font,\n\tmarkInfo: GlyphInfo,\n\tmarkPos: GlyphPosition,\n\t_baseInfo: GlyphInfo,\n\tbasePos: GlyphPosition,\n\tbaseAdvance: number,\n\tccc: number,\n): void {\n\tconst markAdvance = font.advanceWidth(markInfo.glyphId);\n\tconst unitsPerEm = font.unitsPerEm;\n\n\t// Default: center mark over base\n\tlet xOffset = (baseAdvance - markAdvance) / 2;\n\tlet yOffset = 0;\n\n\t// Position based on combining class\n\tif (ccc >= 200 && ccc <= 240) {\n\t\t// Above marks (ccc 230 is common for above)\n\t\tyOffset = unitsPerEm * 0.7; // 70% of em height\n\t\txOffset = (baseAdvance - markAdvance) / 2;\n\t} else if (ccc >= 202 && ccc <= 220) {\n\t\t// Below marks (ccc 220 is common for below)\n\t\tyOffset = -unitsPerEm * 0.15;\n\t\txOffset = (baseAdvance - markAdvance) / 2;\n\t} else if (ccc === 1) {\n\t\t// Overlay marks\n\t\txOffset = (baseAdvance - markAdvance) / 2;\n\t\tyOffset = unitsPerEm * 0.3;\n\t} else if (ccc >= 7 && ccc <= 9) {\n\t\t// Nukta, virama (below consonant)\n\t\tyOffset = -unitsPerEm * 0.1;\n\t\txOffset = (baseAdvance - markAdvance) / 2;\n\t} else if (ccc >= 10 && ccc <= 35) {\n\t\t// Hebrew/Arabic vowels - specific positioning\n\t\tif (ccc <= 22) {\n\t\t\t// Hebrew below vowels\n\t\t\tyOffset = -unitsPerEm * 0.2;\n\t\t} else {\n\t\t\t// Arabic marks\n\t\t\tyOffset = ccc < 30 ? -unitsPerEm * 0.15 : unitsPerEm * 0.6;\n\t\t}\n\t\txOffset = (baseAdvance - markAdvance) / 2;\n\t}\n\n\t// Apply offset relative to base position\n\tmarkPos.xOffset = basePos.xOffset + xOffset - baseAdvance;\n\tmarkPos.yOffset = basePos.yOffset + yOffset;\n}\n\n/**\n * Apply fallback kerning using kern table\n */\nexport function applyFallbackKerning(\n\tfont: Font,\n\tinfos: GlyphInfo[],\n\tpositions: GlyphPosition[],\n): void {\n\tconst kern = font.kern;\n\tif (!kern) return;\n\n\tfor (let i = 0; i < infos.length - 1; i++) {\n\t\tconst info1 = infos[i];\n\t\tconst info2 = infos[i + 1];\n\t\tif (!info1 || !info2) continue;\n\n\t\tconst pos1 = positions[i];\n\t\tif (!pos1) continue;\n\n\t\t// Skip marks\n\t\tconst class1 = font.gdef ? getGlyphClass(font.gdef, info1.glyphId) : 0;\n\t\tconst class2 = font.gdef ? getGlyphClass(font.gdef, info2.glyphId) : 0;\n\t\tif (class1 === GlyphClass.Mark || class2 === GlyphClass.Mark) continue;\n\n\t\t// Get kerning from kern table\n\t\tconst kernValue = getKernValueFromTable(font, info1.glyphId, info2.glyphId);\n\t\tif (kernValue !== 0) {\n\t\t\tpos1.xAdvance += kernValue;\n\t\t}\n\t}\n}\n\nfunction getKernValueFromTable(\n\tfont: Font,\n\tleft: GlyphId,\n\tright: GlyphId,\n): number {\n\tconst kern = font.kern;\n\tif (!kern) return 0;\n\n\treturn getKernValue(kern, left, right);\n}\n\n/**\n * Recategorize combining marks for proper processing\n * Some scripts need marks to be processed in specific order\n */\nexport function recategorizeCombiningMarks(\n\t_font: Font,\n\tinfos: GlyphInfo[],\n): void {\n\t// For Hebrew, Arabic, and other scripts, ensure marks are in canonical order\n\t// This is typically handled by normalization, but we do a final check here\n\n\tlet i = 0;\n\twhile (i < infos.length) {\n\t\tconst info = infos[i];\n\t\tif (!info) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst ccc = getCombiningClass(info.codepoint);\n\t\tif (ccc === 0) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Find extent of combining sequence\n\t\tlet j = i + 1;\n\t\twhile (j < infos.length) {\n\t\t\tconst nextInfo = infos[j];\n\t\t\tif (!nextInfo) break;\n\t\t\tconst nextCcc = getCombiningClass(nextInfo.codepoint);\n\t\t\tif (nextCcc === 0) break;\n\t\t\tj++;\n\t\t}\n\n\t\t// Sort combining marks by CCC (stable sort)\n\t\tif (j - i > 1) {\n\t\t\tconst marks = infos.slice(i, j);\n\t\t\tmarks.sort((a, b) => {\n\t\t\t\tconst cccA = getCombiningClass(a.codepoint);\n\t\t\t\tconst cccB = getCombiningClass(b.codepoint);\n\t\t\t\treturn cccA - cccB;\n\t\t\t});\n\t\t\tfor (const [k, mark] of marks.entries()) {\n\t\t\t\tinfos[i + k] = mark;\n\t\t\t}\n\t\t}\n\n\t\ti = j;\n\t}\n}\n",
64
+ "import { tag } from \"../types.ts\";\nimport type { ShapeFeature } from \"./shape-plan.ts\";\n\n/**\n * Feature helper utilities\n * Provides convenient APIs for enabling OpenType features\n */\n\n/**\n * Create a ShapeFeature for a stylistic set (ss01-ss20)\n */\nexport function stylisticSet(\n\tsetNumber: number,\n\tenabled: boolean = true,\n): ShapeFeature {\n\tif (setNumber < 1 || setNumber > 20) {\n\t\tthrow new Error(`Stylistic set number must be 1-20, got ${setNumber}`);\n\t}\n\tconst tagStr = `ss${setNumber.toString().padStart(2, \"0\")}`;\n\treturn { tag: tag(tagStr), enabled };\n}\n\n/**\n * Create ShapeFeatures for multiple stylistic sets\n */\nexport function stylisticSets(\n\tsetNumbers: number[],\n\tenabled: boolean = true,\n): ShapeFeature[] {\n\treturn setNumbers.map((n) => stylisticSet(n, enabled));\n}\n\n/**\n * Create a ShapeFeature for a character variant (cv01-cv99)\n */\nexport function characterVariant(\n\tvariantNumber: number,\n\tenabled: boolean = true,\n): ShapeFeature {\n\tif (variantNumber < 1 || variantNumber > 99) {\n\t\tthrow new Error(\n\t\t\t`Character variant number must be 1-99, got ${variantNumber}`,\n\t\t);\n\t}\n\tconst tagStr = `cv${variantNumber.toString().padStart(2, \"0\")}`;\n\treturn { tag: tag(tagStr), enabled };\n}\n\n/**\n * Create ShapeFeatures for multiple character variants\n */\nexport function characterVariants(\n\tvariantNumbers: number[],\n\tenabled: boolean = true,\n): ShapeFeature[] {\n\treturn variantNumbers.map((n) => characterVariant(n, enabled));\n}\n\n/**\n * Standard ligatures (liga)\n */\nexport function standardLigatures(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"liga\"), enabled };\n}\n\n/**\n * Discretionary ligatures (dlig)\n */\nexport function discretionaryLigatures(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"dlig\"), enabled };\n}\n\n/**\n * Historical ligatures (hlig)\n */\nexport function historicalLigatures(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"hlig\"), enabled };\n}\n\n/**\n * Contextual alternates (calt)\n */\nexport function contextualAlternates(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"calt\"), enabled };\n}\n\n/**\n * Stylistic alternates (salt)\n */\nexport function stylisticAlternates(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"salt\"), enabled };\n}\n\n/**\n * Swash (swsh)\n */\nexport function swash(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"swsh\"), enabled };\n}\n\n/**\n * Small capitals (smcp)\n */\nexport function smallCaps(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"smcp\"), enabled };\n}\n\n/**\n * Capitals to small capitals (c2sc)\n */\nexport function capsToSmallCaps(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"c2sc\"), enabled };\n}\n\n/**\n * Petite capitals (pcap)\n */\nexport function petiteCaps(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"pcap\"), enabled };\n}\n\n/**\n * All small capitals (both smcp and c2sc)\n */\nexport function allSmallCaps(enabled: boolean = true): ShapeFeature[] {\n\treturn [smallCaps(enabled), capsToSmallCaps(enabled)];\n}\n\n/**\n * Oldstyle figures (onum)\n */\nexport function oldstyleFigures(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"onum\"), enabled };\n}\n\n/**\n * Lining figures (lnum)\n */\nexport function liningFigures(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"lnum\"), enabled };\n}\n\n/**\n * Proportional figures (pnum)\n */\nexport function proportionalFigures(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"pnum\"), enabled };\n}\n\n/**\n * Tabular figures (tnum)\n */\nexport function tabularFigures(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"tnum\"), enabled };\n}\n\n/**\n * Fractions (frac)\n */\nexport function fractions(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"frac\"), enabled };\n}\n\n/**\n * Ordinals (ordn)\n */\nexport function ordinals(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"ordn\"), enabled };\n}\n\n/**\n * Slashed zero (zero)\n */\nexport function slashedZero(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"zero\"), enabled };\n}\n\n/**\n * Superscript (sups)\n */\nexport function superscript(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"sups\"), enabled };\n}\n\n/**\n * Subscript (subs)\n */\nexport function subscript(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"subs\"), enabled };\n}\n\n/**\n * Scientific inferiors (sinf)\n */\nexport function scientificInferiors(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"sinf\"), enabled };\n}\n\n/**\n * Case-sensitive forms (case)\n */\nexport function caseSensitiveForms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"case\"), enabled };\n}\n\n/**\n * Capital spacing (cpsp)\n */\nexport function capitalSpacing(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"cpsp\"), enabled };\n}\n\n/**\n * Kerning (kern)\n */\nexport function kerning(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"kern\"), enabled };\n}\n\n/**\n * Vertical forms (vert) - for vertical text layout\n */\nexport function verticalForms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"vert\"), enabled };\n}\n\n/**\n * Vertical alternates and rotation (vrt2) - for vertical text layout\n */\nexport function verticalAlternatesRotation(\n\tenabled: boolean = true,\n): ShapeFeature {\n\treturn { tag: tag(\"vrt2\"), enabled };\n}\n\n/**\n * Vertical Kana alternates (vkna) - for Japanese vertical text\n */\nexport function verticalKanaAlternates(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"vkna\"), enabled };\n}\n\n/**\n * All vertical layout features\n */\nexport function verticalLayoutFeatures(\n\tenabled: boolean = true,\n): ShapeFeature[] {\n\treturn [\n\t\tverticalForms(enabled),\n\t\tverticalAlternatesRotation(enabled),\n\t\tverticalKanaAlternates(enabled),\n\t];\n}\n\n/**\n * Ruby notation forms (ruby)\n */\nexport function ruby(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"ruby\"), enabled };\n}\n\n/**\n * Half-width forms (hwid)\n */\nexport function halfWidthForms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"hwid\"), enabled };\n}\n\n/**\n * Full-width forms (fwid)\n */\nexport function fullWidthForms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"fwid\"), enabled };\n}\n\n/**\n * Proportional-width forms (pwid)\n */\nexport function proportionalWidthForms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"pwid\"), enabled };\n}\n\n/**\n * Quarter-width forms (qwid)\n */\nexport function quarterWidthForms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"qwid\"), enabled };\n}\n\n/**\n * Third-width forms (twid)\n */\nexport function thirdWidthForms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"twid\"), enabled };\n}\n\n/**\n * JIS78 forms (jp78) - Japanese\n */\nexport function jis78Forms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"jp78\"), enabled };\n}\n\n/**\n * JIS83 forms (jp83) - Japanese\n */\nexport function jis83Forms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"jp83\"), enabled };\n}\n\n/**\n * JIS90 forms (jp90) - Japanese\n */\nexport function jis90Forms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"jp90\"), enabled };\n}\n\n/**\n * JIS2004 forms (jp04) - Japanese\n */\nexport function jis2004Forms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"jp04\"), enabled };\n}\n\n/**\n * Simplified forms (smpl) - Chinese\n */\nexport function simplifiedForms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"smpl\"), enabled };\n}\n\n/**\n * Traditional forms (trad) - Chinese\n */\nexport function traditionalForms(enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(\"trad\"), enabled };\n}\n\n/**\n * Create a feature from a 4-character tag string\n */\nexport function feature(tagStr: string, enabled: boolean = true): ShapeFeature {\n\treturn { tag: tag(tagStr), enabled };\n}\n\n/**\n * Create multiple features from tag strings\n */\nexport function features(\n\ttagStrs: string[],\n\tenabled: boolean = true,\n): ShapeFeature[] {\n\treturn tagStrs.map((t) => feature(t, enabled));\n}\n\n/**\n * Combine multiple feature sets\n */\nexport function combineFeatures(\n\t...featureSets: (ShapeFeature | ShapeFeature[])[]\n): ShapeFeature[] {\n\tconst result: ShapeFeature[] = [];\n\tfor (const set of featureSets) {\n\t\tif (Array.isArray(set)) {\n\t\t\tresult.push(...set);\n\t\t} else {\n\t\t\tresult.push(set);\n\t\t}\n\t}\n\treturn result;\n}\n",
65
+ "import type { Font } from \"../font/font.ts\";\nimport type { AnyGposLookup, GposTable } from \"../font/tables/gpos.ts\";\nimport type { AnyGsubLookup, GsubTable } from \"../font/tables/gsub.ts\";\nimport {\n\tfindLangSys,\n\tfindScript,\n\tgetFeature,\n} from \"../layout/structures/layout-common.ts\";\nimport {\n\ttype FeatureVariations,\n\tfindMatchingFeatureVariation,\n} from \"../layout/structures/feature-variations.ts\";\nimport type { Tag, uint16 } from \"../types.ts\";\nimport { tag, tagToString } from \"../types.ts\";\n\n/** Shape plan cache for reusing computed plans */\nconst shapePlanCache = new WeakMap<Font, Map<string, ShapePlan>>();\n\n/** Maximum cache size per font */\nconst MAX_CACHE_SIZE = 64;\n\n/** Feature with optional value */\nexport interface ShapeFeature {\n\ttag: Tag;\n\tenabled: boolean;\n}\n\n/** Collected lookups for shaping */\nexport interface ShapePlan {\n\tscript: Tag;\n\tlanguage: Tag | null;\n\tdirection: \"ltr\" | \"rtl\";\n\n\t/** GSUB lookups to apply, in order */\n\tgsubLookups: Array<{ index: number; lookup: AnyGsubLookup }>;\n\n\t/** GPOS lookups to apply, in order */\n\tgposLookups: Array<{ index: number; lookup: AnyGposLookup }>;\n}\n\n/** Default GSUB features (always enabled) */\nconst DEFAULT_GSUB_FEATURES = [\n\t\"ccmp\", // Glyph composition/decomposition\n\t\"locl\", // Localized forms\n\t\"rlig\", // Required ligatures\n\t\"rclt\", // Required contextual alternates\n\t\"calt\", // Contextual alternates\n\t\"liga\", // Standard ligatures\n];\n\n/** Default GPOS features (always enabled) */\nconst DEFAULT_GPOS_FEATURES = [\n\t\"kern\", // Kerning\n\t\"mark\", // Mark positioning\n\t\"mkmk\", // Mark-to-mark positioning\n];\n\n/** Generate cache key for shape plan */\nfunction getCacheKey(\n\tscript: string,\n\tlanguage: string | null,\n\tdirection: \"ltr\" | \"rtl\",\n\tuserFeatures: ShapeFeature[],\n\taxisCoords: number[] | null,\n): string {\n\tconst featuresKey = userFeatures\n\t\t.map((f) => `${tagToString(f.tag)}:${f.enabled ? \"1\" : \"0\"}`)\n\t\t.sort()\n\t\t.join(\",\");\n\tconst coordsKey = axisCoords ? axisCoords.map(c => c.toFixed(4)).join(\",\") : \"\";\n\treturn `${script}|${language || \"\"}|${direction}|${featuresKey}|${coordsKey}`;\n}\n\n/** Get or create a cached shape plan */\nexport function getOrCreateShapePlan(\n\tfont: Font,\n\tscript: string,\n\tlanguage: string | null,\n\tdirection: \"ltr\" | \"rtl\",\n\tuserFeatures: ShapeFeature[] = [],\n\taxisCoords: number[] | null = null,\n): ShapePlan {\n\tconst cacheKey = getCacheKey(script, language, direction, userFeatures, axisCoords);\n\n\t// Get or create font's cache map\n\tlet fontCache = shapePlanCache.get(font);\n\tif (!fontCache) {\n\t\tfontCache = new Map();\n\t\tshapePlanCache.set(font, fontCache);\n\t}\n\n\t// Check cache\n\tconst cached = fontCache.get(cacheKey);\n\tif (cached) {\n\t\treturn cached;\n\t}\n\n\t// Create new plan\n\tconst plan = createShapePlanInternal(\n\t\tfont,\n\t\tscript,\n\t\tlanguage,\n\t\tdirection,\n\t\tuserFeatures,\n\t\taxisCoords,\n\t);\n\n\t// Evict if cache is too large\n\tif (fontCache.size >= MAX_CACHE_SIZE) {\n\t\tconst firstKey = fontCache.keys().next().value;\n\t\tif (firstKey !== undefined) {\n\t\t\tfontCache.delete(firstKey);\n\t\t}\n\t}\n\n\tfontCache.set(cacheKey, plan);\n\treturn plan;\n}\n\n/** Create a shape plan for the given font and settings */\nexport function createShapePlan(\n\tfont: Font,\n\tscript: string,\n\tlanguage: string | null,\n\tdirection: \"ltr\" | \"rtl\",\n\tuserFeatures: ShapeFeature[] = [],\n\taxisCoords: number[] | null = null,\n): ShapePlan {\n\t// Use caching by default\n\treturn getOrCreateShapePlan(font, script, language, direction, userFeatures, axisCoords);\n}\n\n/** Create a shape plan without caching */\nfunction createShapePlanInternal(\n\tfont: Font,\n\tscript: string,\n\tlanguage: string | null,\n\tdirection: \"ltr\" | \"rtl\",\n\tuserFeatures: ShapeFeature[] = [],\n\taxisCoords: number[] | null = null,\n): ShapePlan {\n\tconst scriptTag = tag(script.padEnd(4, \" \"));\n\tconst languageTag = language ? tag(language.padEnd(4, \" \")) : null;\n\n\t// Collect enabled features\n\tconst enabledFeatures = new Set<Tag>();\n\n\t// Add default features\n\tfor (const feat of DEFAULT_GSUB_FEATURES) {\n\t\tenabledFeatures.add(tag(feat));\n\t}\n\tfor (const feat of DEFAULT_GPOS_FEATURES) {\n\t\tenabledFeatures.add(tag(feat));\n\t}\n\n\t// Apply user features\n\tfor (const feat of userFeatures) {\n\t\tif (feat.enabled) {\n\t\t\tenabledFeatures.add(feat.tag);\n\t\t} else {\n\t\t\tenabledFeatures.delete(feat.tag);\n\t\t}\n\t}\n\n\t// Collect GSUB lookups (with feature variations support)\n\tconst gsubLookups = collectLookups(\n\t\tfont.gsub,\n\t\tscriptTag,\n\t\tlanguageTag,\n\t\tenabledFeatures,\n\t\taxisCoords,\n\t);\n\n\t// Collect GPOS lookups (with feature variations support)\n\tconst gposLookups = collectLookups(\n\t\tfont.gpos,\n\t\tscriptTag,\n\t\tlanguageTag,\n\t\tenabledFeatures,\n\t\taxisCoords,\n\t);\n\n\treturn {\n\t\tscript: scriptTag,\n\t\tlanguage: languageTag,\n\t\tdirection,\n\t\tgsubLookups: gsubLookups as Array<{ index: number; lookup: AnyGsubLookup }>,\n\t\tgposLookups: gposLookups as Array<{ index: number; lookup: AnyGposLookup }>,\n\t};\n}\n\nfunction collectLookups<T extends { lookups: unknown[] }>(\n\ttable: T | null,\n\tscriptTag: Tag,\n\tlanguageTag: Tag | null,\n\tenabledFeatures: Set<Tag>,\n\taxisCoords: number[] | null,\n): Array<{ index: number; lookup: unknown }> {\n\tif (!table) return [];\n\n\tconst gsub = table as unknown as GsubTable | GposTable;\n\tconst lookupIndices = new Set<number>();\n\n\t// Find script\n\tlet script = findScript(gsub.scriptList, scriptTag);\n\tif (!script) {\n\t\t// Try DFLT script\n\t\tscript = findScript(gsub.scriptList, tag(\"DFLT\"));\n\t}\n\tif (!script) {\n\t\t// Try latn as fallback\n\t\tscript = findScript(gsub.scriptList, tag(\"latn\"));\n\t}\n\tif (!script) return [];\n\n\t// Find language system\n\tconst langSys = findLangSys(script, languageTag);\n\tif (!langSys) return [];\n\n\t// Get feature variations substitutions if applicable\n\tconst featureVariations = (gsub as { featureVariations?: FeatureVariations }).featureVariations;\n\tconst matchingVariation = featureVariations && axisCoords\n\t\t? findMatchingFeatureVariation(featureVariations, axisCoords)\n\t\t: null;\n\n\t// Build a map of feature indices to their substituted lookup lists\n\tconst featureSubstitutions = new Map<uint16, uint16[]>();\n\tif (matchingVariation) {\n\t\tfor (const subst of matchingVariation.featureTableSubstitution.substitutions) {\n\t\t\tfeatureSubstitutions.set(subst.featureIndex, subst.alternateFeature.lookupListIndices);\n\t\t}\n\t}\n\n\t// Add required feature\n\tif (langSys.requiredFeatureIndex !== 0xffff) {\n\t\tconst feature = getFeature(gsub.featureList, langSys.requiredFeatureIndex);\n\t\tif (feature) {\n\t\t\t// Check if this feature has a substitution\n\t\t\tconst substitutedLookups = featureSubstitutions.get(langSys.requiredFeatureIndex);\n\t\t\tconst lookups = substitutedLookups ?? feature.feature.lookupListIndices;\n\t\t\tfor (const lookupIndex of lookups) {\n\t\t\t\tlookupIndices.add(lookupIndex);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add enabled features\n\tfor (const featureIndex of langSys.featureIndices) {\n\t\tconst featureRecord = getFeature(gsub.featureList, featureIndex);\n\t\tif (!featureRecord) continue;\n\n\t\tif (enabledFeatures.has(featureRecord.featureTag)) {\n\t\t\t// Check if this feature has a substitution\n\t\t\tconst substitutedLookups = featureSubstitutions.get(featureIndex);\n\t\t\tconst lookups = substitutedLookups ?? featureRecord.feature.lookupListIndices;\n\t\t\tfor (const lookupIndex of lookups) {\n\t\t\t\tlookupIndices.add(lookupIndex);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Convert to sorted array with lookup objects\n\tconst result: Array<{ index: number; lookup: unknown }> = [];\n\tconst sortedIndices = Array.from(lookupIndices).sort((a, b) => a - b);\n\n\tfor (const index of sortedIndices) {\n\t\tconst lookup = gsub.lookups[index];\n\t\tif (lookup) {\n\t\t\tresult.push({ index, lookup });\n\t\t}\n\t}\n\n\treturn result;\n}\n",
66
+ "import type { GlyphInfo } from \"../../types.ts\";\n\n/**\n * Arabic joining types from Unicode\n */\nexport enum ArabicJoiningType {\n\tNonJoining = \"U\", // Non_Joining\n\tRightJoining = \"R\", // Right_Joining (joins on the right)\n\tDualJoining = \"D\", // Dual_Joining (joins on both sides)\n\tJoinCausing = \"C\", // Join_Causing (like TATWEEL)\n\tLeftJoining = \"L\", // Left_Joining (rare)\n\tTransparent = \"T\", // Transparent (marks, etc.)\n}\n\n/**\n * Action to take for each glyph based on context\n */\nexport enum JoiningAction {\n\tNone = 0,\n\tIsol = 1, // Isolated form\n\tFina = 2, // Final form\n\tMedi = 3, // Medial form\n\tInit = 4, // Initial form\n}\n\n/**\n * Arabic joining group for specific shaping behavior\n */\nexport enum ArabicJoiningGroup {\n\tNone = 0,\n\tAlaph = 1,\n\tDalathRish = 2,\n\t// Add more as needed for Syriac, etc.\n}\n\n/**\n * Per-glyph info for Arabic shaping\n */\nexport interface ArabicGlyphData {\n\tjoiningType: ArabicJoiningType;\n\tjoiningGroup: ArabicJoiningGroup;\n\taction: JoiningAction;\n}\n\n// Unicode ranges for Arabic characters\nconst ARABIC_START = 0x0600;\nconst ARABIC_END = 0x06ff;\nconst ARABIC_SUPPLEMENT_START = 0x0750;\nconst ARABIC_SUPPLEMENT_END = 0x077f;\nconst ARABIC_EXTENDED_A_START = 0x08a0;\nconst ARABIC_EXTENDED_A_END = 0x08ff;\nconst ARABIC_PRESENTATION_A_START = 0xfb50;\nconst ARABIC_PRESENTATION_A_END = 0xfdff;\nconst ARABIC_PRESENTATION_B_START = 0xfe70;\nconst ARABIC_PRESENTATION_B_END = 0xfeff;\n\n/**\n * Check if a codepoint is in Arabic script range\n */\nexport function isArabic(cp: number): boolean {\n\treturn (\n\t\t(cp >= ARABIC_START && cp <= ARABIC_END) ||\n\t\t(cp >= ARABIC_SUPPLEMENT_START && cp <= ARABIC_SUPPLEMENT_END) ||\n\t\t(cp >= ARABIC_EXTENDED_A_START && cp <= ARABIC_EXTENDED_A_END) ||\n\t\t(cp >= ARABIC_PRESENTATION_A_START && cp <= ARABIC_PRESENTATION_A_END) ||\n\t\t(cp >= ARABIC_PRESENTATION_B_START && cp <= ARABIC_PRESENTATION_B_END)\n\t);\n}\n\n/**\n * Get the joining type for a codepoint\n * Based on Unicode Arabic Shaping data\n */\nexport function getJoiningType(cp: number): ArabicJoiningType {\n\t// Non-joining: space, numbers, punctuation\n\tif (cp < ARABIC_START) return ArabicJoiningType.NonJoining;\n\n\t// Arabic block (0600-06FF)\n\tif (cp >= 0x0600 && cp <= 0x0605) return ArabicJoiningType.NonJoining; // Number signs\n\tif (cp === 0x0608) return ArabicJoiningType.NonJoining; // Arabic Ray\n\tif (cp === 0x060b) return ArabicJoiningType.NonJoining; // Afghani Sign\n\tif (cp === 0x060d) return ArabicJoiningType.NonJoining; // Date Separator\n\n\t// Dual-joining letters (most common Arabic letters)\n\t// These can connect on both sides\n\tif (cp === 0x0626) return ArabicJoiningType.DualJoining; // YEH WITH HAMZA ABOVE\n\tif (cp === 0x0628) return ArabicJoiningType.DualJoining; // BEH\n\tif (cp === 0x062a) return ArabicJoiningType.DualJoining; // TEH\n\tif (cp === 0x062b) return ArabicJoiningType.DualJoining; // THEH\n\tif (cp === 0x062c) return ArabicJoiningType.DualJoining; // JEEM\n\tif (cp === 0x062d) return ArabicJoiningType.DualJoining; // HAH\n\tif (cp === 0x062e) return ArabicJoiningType.DualJoining; // KHAH\n\tif (cp === 0x0633) return ArabicJoiningType.DualJoining; // SEEN\n\tif (cp === 0x0634) return ArabicJoiningType.DualJoining; // SHEEN\n\tif (cp === 0x0635) return ArabicJoiningType.DualJoining; // SAD\n\tif (cp === 0x0636) return ArabicJoiningType.DualJoining; // DAD\n\tif (cp === 0x0637) return ArabicJoiningType.DualJoining; // TAH\n\tif (cp === 0x0638) return ArabicJoiningType.DualJoining; // ZAH\n\tif (cp === 0x0639) return ArabicJoiningType.DualJoining; // AIN\n\tif (cp === 0x063a) return ArabicJoiningType.DualJoining; // GHAIN\n\tif (cp >= 0x063b && cp <= 0x063f) return ArabicJoiningType.DualJoining; // Extended\n\tif (cp === 0x0641) return ArabicJoiningType.DualJoining; // FEH\n\tif (cp === 0x0642) return ArabicJoiningType.DualJoining; // QAF\n\tif (cp === 0x0643) return ArabicJoiningType.DualJoining; // KAF\n\tif (cp === 0x0644) return ArabicJoiningType.DualJoining; // LAM\n\tif (cp === 0x0645) return ArabicJoiningType.DualJoining; // MEEM\n\tif (cp === 0x0646) return ArabicJoiningType.DualJoining; // NOON\n\tif (cp === 0x0647) return ArabicJoiningType.DualJoining; // HEH\n\tif (cp === 0x0649) return ArabicJoiningType.DualJoining; // ALEF MAKSURA\n\tif (cp === 0x064a) return ArabicJoiningType.DualJoining; // YEH\n\tif (cp >= 0x066e && cp <= 0x066f) return ArabicJoiningType.DualJoining; // DOTLESS BEH/QAF\n\tif (cp >= 0x0678 && cp <= 0x0687) return ArabicJoiningType.DualJoining; // Extended Arabic\n\tif (cp >= 0x069a && cp <= 0x06bf) return ArabicJoiningType.DualJoining; // More extended\n\tif (cp >= 0x06c1 && cp <= 0x06c2) return ArabicJoiningType.DualJoining; // HEH variants\n\tif (cp === 0x06cc) return ArabicJoiningType.DualJoining; // FARSI YEH\n\tif (cp >= 0x06ce && cp <= 0x06d1) return ArabicJoiningType.DualJoining; // YEH variants\n\tif (cp === 0x06d5) return ArabicJoiningType.DualJoining; // AE\n\tif (cp >= 0x06fa && cp <= 0x06fc) return ArabicJoiningType.DualJoining; // More letters\n\tif (cp === 0x06ff) return ArabicJoiningType.DualJoining; // HEH WITH INVERTED V\n\n\t// Right-joining letters (only connect on the right)\n\t// ALEF and its variants, DAL/DHAL, REH/ZAY, WAW\n\tif (cp === 0x0622) return ArabicJoiningType.RightJoining; // ALEF WITH MADDA ABOVE\n\tif (cp === 0x0623) return ArabicJoiningType.RightJoining; // ALEF WITH HAMZA ABOVE\n\tif (cp === 0x0624) return ArabicJoiningType.RightJoining; // WAW WITH HAMZA ABOVE\n\tif (cp === 0x0625) return ArabicJoiningType.RightJoining; // ALEF WITH HAMZA BELOW\n\tif (cp === 0x0627) return ArabicJoiningType.RightJoining; // ALEF\n\tif (cp === 0x0629) return ArabicJoiningType.RightJoining; // TEH MARBUTA\n\tif (cp === 0x062f) return ArabicJoiningType.RightJoining; // DAL\n\tif (cp === 0x0630) return ArabicJoiningType.RightJoining; // THAL\n\tif (cp === 0x0631) return ArabicJoiningType.RightJoining; // REH\n\tif (cp === 0x0632) return ArabicJoiningType.RightJoining; // ZAIN\n\tif (cp === 0x0648) return ArabicJoiningType.RightJoining; // WAW\n\tif (cp === 0x0671) return ArabicJoiningType.RightJoining; // ALEF WASLA\n\tif (cp >= 0x0672 && cp <= 0x0677) return ArabicJoiningType.RightJoining; // ALEF variants\n\tif (cp >= 0x0688 && cp <= 0x0699) return ArabicJoiningType.RightJoining; // DAL/REH extended\n\tif (cp >= 0x06c0 && cp <= 0x06c0) return ArabicJoiningType.RightJoining; // HEH WITH YEH\n\tif (cp === 0x06c3) return ArabicJoiningType.RightJoining; // TEH MARBUTA GOAL\n\tif (cp >= 0x06c4 && cp <= 0x06cb) return ArabicJoiningType.RightJoining; // WAW variants\n\tif (cp === 0x06cd) return ArabicJoiningType.RightJoining; // YEH WITH TAIL\n\tif (cp >= 0x06d2 && cp <= 0x06d3) return ArabicJoiningType.RightJoining; // YEH BARREE\n\n\t// TATWEEL - Join causing\n\tif (cp === 0x0640) return ArabicJoiningType.JoinCausing;\n\n\t// Transparent - combining marks, diacritics\n\tif (cp >= 0x064b && cp <= 0x065f) return ArabicJoiningType.Transparent; // Arabic marks\n\tif (cp === 0x0670) return ArabicJoiningType.Transparent; // SUPERSCRIPT ALEF\n\tif (cp >= 0x06d6 && cp <= 0x06ed) return ArabicJoiningType.Transparent; // Quranic marks\n\tif (cp >= 0x08d3 && cp <= 0x08ff) return ArabicJoiningType.Transparent; // Extended marks\n\n\t// Default for Arabic range: NonJoining\n\tif (isArabic(cp)) return ArabicJoiningType.NonJoining;\n\n\treturn ArabicJoiningType.NonJoining;\n}\n\n/**\n * Analyze joining for a sequence of glyphs.\n * Returns the action to take for each glyph.\n */\nexport function analyzeJoining(infos: GlyphInfo[]): JoiningAction[] {\n\tconst n = infos.length;\n\tconst actions: JoiningAction[] = new Array(n).fill(JoiningAction.None);\n\tconst types: ArabicJoiningType[] = [];\n\n\t// Get joining types for all glyphs\n\tfor (const info of infos) {\n\t\tconst cp = info.codepoint ?? 0;\n\t\ttypes.push(getJoiningType(cp));\n\t}\n\n\t// Analyze each glyph based on neighbors (skipping transparent)\n\tfor (let i = 0; i < n; i++) {\n\t\tconst type = types[i];\n\t\tif (!type) continue;\n\n\t\t// Skip non-Arabic characters\n\t\tif (\n\t\t\ttype === ArabicJoiningType.NonJoining ||\n\t\t\ttype === ArabicJoiningType.Transparent\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Find previous non-transparent glyph\n\t\tlet prevType: ArabicJoiningType | null = null;\n\t\tfor (let j = i - 1; j >= 0; j--) {\n\t\t\tconst jType = types[j];\n\t\t\tif (jType && jType !== ArabicJoiningType.Transparent) {\n\t\t\t\tprevType = jType;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Find next non-transparent glyph\n\t\tlet nextType: ArabicJoiningType | null = null;\n\t\tfor (let j = i + 1; j < n; j++) {\n\t\t\tconst jType = types[j];\n\t\t\tif (jType && jType !== ArabicJoiningType.Transparent) {\n\t\t\t\tnextType = jType;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Determine if we join left/right\n\t\tconst joinsLeft =\n\t\t\tprevType === ArabicJoiningType.DualJoining ||\n\t\t\tprevType === ArabicJoiningType.LeftJoining ||\n\t\t\tprevType === ArabicJoiningType.JoinCausing;\n\n\t\tconst joinsRight =\n\t\t\tnextType === ArabicJoiningType.DualJoining ||\n\t\t\tnextType === ArabicJoiningType.RightJoining ||\n\t\t\tnextType === ArabicJoiningType.JoinCausing;\n\n\t\t// Determine action based on joining type and context\n\t\tif (type === ArabicJoiningType.DualJoining) {\n\t\t\tif (joinsLeft && joinsRight) {\n\t\t\t\tactions[i] = JoiningAction.Medi;\n\t\t\t} else if (joinsLeft) {\n\t\t\t\tactions[i] = JoiningAction.Fina;\n\t\t\t} else if (joinsRight) {\n\t\t\t\tactions[i] = JoiningAction.Init;\n\t\t\t} else {\n\t\t\t\tactions[i] = JoiningAction.Isol;\n\t\t\t}\n\t\t} else if (type === ArabicJoiningType.RightJoining) {\n\t\t\t// Right-joining can only join on the right (to previous glyph in RTL)\n\t\t\tif (joinsLeft) {\n\t\t\t\tactions[i] = JoiningAction.Fina;\n\t\t\t} else {\n\t\t\t\tactions[i] = JoiningAction.Isol;\n\t\t\t}\n\t\t} else if (type === ArabicJoiningType.LeftJoining) {\n\t\t\t// Left-joining (rare)\n\t\t\tif (joinsRight) {\n\t\t\t\tactions[i] = JoiningAction.Init;\n\t\t\t} else {\n\t\t\t\tactions[i] = JoiningAction.Isol;\n\t\t\t}\n\t\t} else if (type === ArabicJoiningType.JoinCausing) {\n\t\t\t// TATWEEL - just connects, no form change\n\t\t\tactions[i] = JoiningAction.None;\n\t\t}\n\t}\n\n\treturn actions;\n}\n\n/**\n * Get the feature tag for a joining action\n */\nexport function getFeatureForAction(action: JoiningAction): string | null {\n\tswitch (action) {\n\t\tcase JoiningAction.Isol:\n\t\t\treturn \"isol\";\n\t\tcase JoiningAction.Fina:\n\t\t\treturn \"fina\";\n\t\tcase JoiningAction.Medi:\n\t\t\treturn \"medi\";\n\t\tcase JoiningAction.Init:\n\t\t\treturn \"init\";\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\n/**\n * Set the feature mask for each glyph based on joining analysis\n */\nexport function setupArabicMasks(infos: GlyphInfo[]): void {\n\tconst actions = analyzeJoining(infos);\n\n\t// Feature tag bits (these should match how ShapePlan assigns masks)\n\t// For now we use a simple scheme where:\n\t// - bit 0: isol\n\t// - bit 1: fina\n\t// - bit 2: medi\n\t// - bit 3: init\n\tfor (const [i, action] of actions.entries()) {\n\t\tconst info = infos[i];\n\t\tif (!info) continue;\n\n\t\t// Set mask based on action\n\t\t// The shaper will need to check these masks when applying features\n\t\tswitch (action) {\n\t\t\tcase JoiningAction.Isol:\n\t\t\t\tinfo.mask = (info.mask & 0xfffffff0) | 0x1;\n\t\t\t\tbreak;\n\t\t\tcase JoiningAction.Fina:\n\t\t\t\tinfo.mask = (info.mask & 0xfffffff0) | 0x2;\n\t\t\t\tbreak;\n\t\t\tcase JoiningAction.Medi:\n\t\t\t\tinfo.mask = (info.mask & 0xfffffff0) | 0x4;\n\t\t\t\tbreak;\n\t\t\tcase JoiningAction.Init:\n\t\t\t\tinfo.mask = (info.mask & 0xfffffff0) | 0x8;\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n",
67
+ "import type { GlyphInfo } from \"../../types.ts\";\n\n/**\n * Hangul shaper for Korean text\n * Handles Jamo composition and syllable block formation\n */\n\n// Hangul Unicode ranges\nconst HANGUL_BASE = 0xac00; // First precomposed syllable (가)\nconst HANGUL_END = 0xd7a3; // Last precomposed syllable (힣)\n\nconst JAMO_L_BASE = 0x1100; // Leading consonant (choseong) base\nconst JAMO_V_BASE = 0x1161; // Vowel (jungseong) base\nconst JAMO_T_BASE = 0x11a7; // Trailing consonant (jongseong) base - 0x11a8 is first real one\n\nconst JAMO_L_COUNT = 19; // Number of leading consonants\nconst JAMO_V_COUNT = 21; // Number of vowels\nconst JAMO_T_COUNT = 28; // Number of trailing consonants (including none)\n\nconst JAMO_VT_COUNT = JAMO_V_COUNT * JAMO_T_COUNT; // 588\nconst _JAMO_LVT_COUNT = JAMO_L_COUNT * JAMO_VT_COUNT; // 11172\n\n// Compatibility Jamo (for conversion)\nconst COMPAT_JAMO_START = 0x3131;\nconst COMPAT_JAMO_END = 0x318e;\n\n// Hangul Jamo Extended-A (old Korean)\nconst JAMO_EXT_A_START = 0xa960;\nconst JAMO_EXT_A_END = 0xa97c;\n\n// Hangul Jamo Extended-B (old Korean)\nconst JAMO_EXT_B_START = 0xd7b0;\nconst JAMO_EXT_B_END = 0xd7fb;\n\n/**\n * Check if codepoint is a Hangul syllable\n */\nexport function isHangulSyllable(cp: number): boolean {\n\treturn cp >= HANGUL_BASE && cp <= HANGUL_END;\n}\n\n/**\n * Check if codepoint is a Hangul Jamo (conjoining)\n */\nexport function isHangulJamo(cp: number): boolean {\n\treturn (\n\t\t(cp >= JAMO_L_BASE && cp <= 0x11ff) ||\n\t\t(cp >= JAMO_EXT_A_START && cp <= JAMO_EXT_A_END) ||\n\t\t(cp >= JAMO_EXT_B_START && cp <= JAMO_EXT_B_END)\n\t);\n}\n\n/**\n * Check if codepoint is a leading consonant (L)\n */\nexport function isJamoL(cp: number): boolean {\n\treturn (\n\t\t(cp >= JAMO_L_BASE && cp < JAMO_L_BASE + JAMO_L_COUNT) ||\n\t\t(cp >= JAMO_EXT_A_START && cp <= JAMO_EXT_A_END)\n\t);\n}\n\n/**\n * Check if codepoint is a vowel (V)\n */\nexport function isJamoV(cp: number): boolean {\n\treturn (\n\t\t(cp >= JAMO_V_BASE && cp < JAMO_V_BASE + JAMO_V_COUNT) ||\n\t\t(cp >= 0xd7b0 && cp <= 0xd7c6)\n\t);\n}\n\n/**\n * Check if codepoint is a trailing consonant (T)\n */\nexport function isJamoT(cp: number): boolean {\n\treturn (\n\t\t(cp > JAMO_T_BASE && cp <= JAMO_T_BASE + JAMO_T_COUNT - 1) ||\n\t\t(cp >= 0xd7cb && cp <= 0xd7fb)\n\t);\n}\n\n/**\n * Decompose a precomposed Hangul syllable into Jamo\n */\nexport function decomposeHangul(cp: number): number[] {\n\tif (!isHangulSyllable(cp)) return [cp];\n\n\tconst syllableIndex = cp - HANGUL_BASE;\n\tconst l = Math.floor(syllableIndex / JAMO_VT_COUNT);\n\tconst v = Math.floor((syllableIndex % JAMO_VT_COUNT) / JAMO_T_COUNT);\n\tconst t = syllableIndex % JAMO_T_COUNT;\n\n\tconst result = [JAMO_L_BASE + l, JAMO_V_BASE + v];\n\tif (t > 0) {\n\t\tresult.push(JAMO_T_BASE + t);\n\t}\n\treturn result;\n}\n\n/**\n * Compose Jamo into a precomposed Hangul syllable\n */\nexport function composeHangul(\n\tl: number,\n\tv: number,\n\tt: number = 0,\n): number | null {\n\t// Normalize indices\n\tconst lIndex = l - JAMO_L_BASE;\n\tconst vIndex = v - JAMO_V_BASE;\n\tconst tIndex = t === 0 ? 0 : t - JAMO_T_BASE;\n\n\tif (lIndex < 0 || lIndex >= JAMO_L_COUNT) return null;\n\tif (vIndex < 0 || vIndex >= JAMO_V_COUNT) return null;\n\tif (tIndex < 0 || tIndex >= JAMO_T_COUNT) return null;\n\n\treturn HANGUL_BASE + lIndex * JAMO_VT_COUNT + vIndex * JAMO_T_COUNT + tIndex;\n}\n\n/**\n * Hangul syllable types\n */\nexport enum HangulSyllableType {\n\tNotApplicable = 0,\n\tLeadingJamo = 1, // L\n\tVowelJamo = 2, // V\n\tTrailingJamo = 3, // T\n\tLVSyllable = 4, // LV (no trailing)\n\tLVTSyllable = 5, // LVT (with trailing)\n}\n\n/**\n * Get the syllable type of a codepoint\n */\nexport function getHangulSyllableType(cp: number): HangulSyllableType {\n\tif (isJamoL(cp)) return HangulSyllableType.LeadingJamo;\n\tif (isJamoV(cp)) return HangulSyllableType.VowelJamo;\n\tif (isJamoT(cp)) return HangulSyllableType.TrailingJamo;\n\n\tif (isHangulSyllable(cp)) {\n\t\tconst syllableIndex = cp - HANGUL_BASE;\n\t\tconst t = syllableIndex % JAMO_T_COUNT;\n\t\treturn t === 0\n\t\t\t? HangulSyllableType.LVSyllable\n\t\t\t: HangulSyllableType.LVTSyllable;\n\t}\n\n\treturn HangulSyllableType.NotApplicable;\n}\n\n/**\n * Feature masks for Hangul\n */\nexport const HangulFeatureMask = {\n\tljmo: 0x0001, // Leading jamo forms\n\tvjmo: 0x0002, // Vowel jamo forms\n\ttjmo: 0x0004, // Trailing jamo forms\n} as const;\n\n/**\n * Setup Hangul masks for feature application\n */\nexport function setupHangulMasks(infos: GlyphInfo[]): void {\n\tfor (const info of infos) {\n\t\tconst type = getHangulSyllableType(info.codepoint);\n\n\t\tswitch (type) {\n\t\t\tcase HangulSyllableType.LeadingJamo:\n\t\t\t\tinfo.mask |= HangulFeatureMask.ljmo;\n\t\t\t\tbreak;\n\t\t\tcase HangulSyllableType.VowelJamo:\n\t\t\t\tinfo.mask |= HangulFeatureMask.vjmo;\n\t\t\t\tbreak;\n\t\t\tcase HangulSyllableType.TrailingJamo:\n\t\t\t\tinfo.mask |= HangulFeatureMask.tjmo;\n\t\t\t\tbreak;\n\t\t\tcase HangulSyllableType.LVSyllable:\n\t\t\tcase HangulSyllableType.LVTSyllable:\n\t\t\t\t// Precomposed syllables don't need special features\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Normalize Hangul - compose Jamo sequences into syllables where possible\n */\nexport function normalizeHangul(infos: GlyphInfo[]): GlyphInfo[] {\n\tconst result: GlyphInfo[] = [];\n\tlet i = 0;\n\n\twhile (i < infos.length) {\n\t\tconst info = infos[i];\n\t\tif (!info) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst type = getHangulSyllableType(info.codepoint);\n\n\t\t// Try to compose L + V [+ T]\n\t\tif (type === HangulSyllableType.LeadingJamo && i + 1 < infos.length) {\n\t\t\tconst nextInfo = infos[i + 1];\n\t\t\tif (!nextInfo) {\n\t\t\t\tresult.push(info);\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst nextType = getHangulSyllableType(nextInfo.codepoint);\n\n\t\t\tif (nextType === HangulSyllableType.VowelJamo) {\n\t\t\t\t// Check for trailing jamo\n\t\t\t\tlet t = 0;\n\t\t\t\tlet consumed = 2;\n\n\t\t\t\tif (i + 2 < infos.length) {\n\t\t\t\t\tconst thirdInfo = infos[i + 2];\n\t\t\t\t\tif (thirdInfo) {\n\t\t\t\t\t\tconst thirdType = getHangulSyllableType(thirdInfo.codepoint);\n\n\t\t\t\t\t\tif (thirdType === HangulSyllableType.TrailingJamo) {\n\t\t\t\t\t\t\tt = thirdInfo.codepoint;\n\t\t\t\t\t\t\tconsumed = 3;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst composed = composeHangul(info.codepoint, nextInfo.codepoint, t);\n\t\t\t\tif (composed !== null) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\tglyphId: info.glyphId, // Will be remapped\n\t\t\t\t\t\tcluster: info.cluster,\n\t\t\t\t\t\tmask: info.mask,\n\t\t\t\t\t\tcodepoint: composed,\n\t\t\t\t\t});\n\t\t\t\t\ti += consumed;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Try to compose LV + T\n\t\tif (type === HangulSyllableType.LVSyllable && i + 1 < infos.length) {\n\t\t\tconst nextInfo = infos[i + 1];\n\t\t\tif (!nextInfo) {\n\t\t\t\tresult.push(info);\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst nextType = getHangulSyllableType(nextInfo.codepoint);\n\n\t\t\tif (nextType === HangulSyllableType.TrailingJamo) {\n\t\t\t\t// Decompose LV, add T, recompose\n\t\t\t\tconst decomposed = decomposeHangul(info.codepoint);\n\t\t\t\tconst [firstJamo, secondJamo] = decomposed;\n\t\t\t\tif (\n\t\t\t\t\tdecomposed.length === 2 &&\n\t\t\t\t\tfirstJamo !== undefined &&\n\t\t\t\t\tsecondJamo !== undefined\n\t\t\t\t) {\n\t\t\t\t\tconst composed = composeHangul(\n\t\t\t\t\t\tfirstJamo,\n\t\t\t\t\t\tsecondJamo,\n\t\t\t\t\t\tnextInfo.codepoint,\n\t\t\t\t\t);\n\t\t\t\t\tif (composed !== null) {\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\tglyphId: info.glyphId,\n\t\t\t\t\t\t\tcluster: info.cluster,\n\t\t\t\t\t\t\tmask: info.mask,\n\t\t\t\t\t\t\tcodepoint: composed,\n\t\t\t\t\t\t});\n\t\t\t\t\t\ti += 2;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// No composition, keep as-is\n\t\tresult.push(info);\n\t\ti++;\n\t}\n\n\treturn result;\n}\n\n/**\n * Check if codepoint is Korean (Hangul or Jamo)\n */\nexport function isKorean(cp: number): boolean {\n\treturn (\n\t\tisHangulSyllable(cp) ||\n\t\tisHangulJamo(cp) ||\n\t\t(cp >= COMPAT_JAMO_START && cp <= COMPAT_JAMO_END)\n\t);\n}\n",
68
+ "import type { GlyphInfo } from \"../../types.ts\";\n\n/**\n * Hebrew character categories\n */\nexport enum HebrewCategory {\n\tOther = 0,\n\tLetter = 1, // Regular letter\n\tPoint = 2, // Niqqud (vowel point)\n\tDagesh = 3, // Dagesh/Mapiq\n\tShin = 4, // Shin/Sin dot\n\tRafe = 5, // Rafe mark\n\tAccent = 6, // Cantillation marks\n\tMaqaf = 7, // Hebrew hyphen\n\tPunctuation = 8, // Punctuation\n}\n\n/**\n * Hebrew Unicode range\n */\nconst HEBREW_START = 0x0590;\nconst HEBREW_END = 0x05ff;\nconst HEBREW_EXTENDED_START = 0xfb1d;\nconst HEBREW_EXTENDED_END = 0xfb4f;\n\n/**\n * Check if codepoint is Hebrew\n */\nexport function isHebrew(cp: number): boolean {\n\treturn (\n\t\t(cp >= HEBREW_START && cp <= HEBREW_END) ||\n\t\t(cp >= HEBREW_EXTENDED_START && cp <= HEBREW_EXTENDED_END)\n\t);\n}\n\n/**\n * Get Hebrew category for a codepoint\n */\nexport function getHebrewCategory(cp: number): HebrewCategory {\n\t// Cantillation marks (0591-05AF)\n\tif (cp >= 0x0591 && cp <= 0x05af) return HebrewCategory.Accent;\n\n\t// Points (05B0-05BD)\n\tif (cp >= 0x05b0 && cp <= 0x05bd) return HebrewCategory.Point;\n\n\t// Maqaf\n\tif (cp === 0x05be) return HebrewCategory.Maqaf;\n\n\t// Rafe\n\tif (cp === 0x05bf) return HebrewCategory.Rafe;\n\n\t// Paseq, Sof Pasuq\n\tif (cp === 0x05c0 || cp === 0x05c3) return HebrewCategory.Punctuation;\n\n\t// Shin/Sin dot\n\tif (cp === 0x05c1 || cp === 0x05c2) return HebrewCategory.Shin;\n\n\t// Dagesh/Mapiq\n\tif (cp === 0x05bc) return HebrewCategory.Dagesh;\n\n\t// Meteg\n\tif (cp === 0x05bd) return HebrewCategory.Point;\n\n\t// Letters (05D0-05EA)\n\tif (cp >= 0x05d0 && cp <= 0x05ea) return HebrewCategory.Letter;\n\n\t// Final letters are handled the same\n\tif (cp >= 0x05f0 && cp <= 0x05f4) return HebrewCategory.Letter;\n\n\t// Extended forms (FB1D-FB4F)\n\tif (cp >= 0xfb1d && cp <= 0xfb4f) return HebrewCategory.Letter;\n\n\tif (isHebrew(cp)) return HebrewCategory.Other;\n\treturn HebrewCategory.Other;\n}\n\n/**\n * Set up masks for Hebrew shaping\n * Hebrew is relatively simple - mainly RTL with marks\n */\nexport function setupHebrewMasks(infos: GlyphInfo[]): void {\n\t// Hebrew shaping primarily relies on:\n\t// 1. Mark positioning (handled by GPOS)\n\t// 2. RTL reordering (handled by main shaper)\n\n\t// Group characters with their base letters\n\tlet baseIndex = 0;\n\n\tfor (let i = 0; i < infos.length; i++) {\n\t\tconst info = infos[i];\n\t\tif (!info) continue;\n\n\t\tconst cat = getHebrewCategory(info.codepoint);\n\n\t\t// Letters start new clusters\n\t\tif (cat === HebrewCategory.Letter) {\n\t\t\tbaseIndex = i;\n\t\t}\n\n\t\t// Store base index for mark attachment\n\t\tinfo.mask = (info.mask & 0xffff0000) | (baseIndex & 0xffff);\n\t}\n}\n",
69
+ "import type { GlyphInfo } from \"../../types.ts\";\n\n/**\n * Indic syllable categories based on Unicode and OpenType spec\n */\nexport enum IndicCategory {\n\tX = 0, // Other/Unknown\n\tC = 1, // Consonant\n\tV = 2, // Independent vowel\n\tN = 3, // Nukta\n\tH = 4, // Halant/Virama\n\tZWNJ = 5, // Zero Width Non-Joiner\n\tZWJ = 6, // Zero Width Joiner\n\tM = 7, // Matra (dependent vowel)\n\tSM = 8, // Syllable modifier (anusvara, visarga)\n\tA = 9, // Accent mark\n\tVD = 10, // Vedic mark\n\tPlaceholder = 11, // Placeholder (dotted circle)\n\tDotted_Circle = 12, // Explicit dotted circle\n\tRS = 13, // Repha form\n\tCoeng = 14, // Coeng (Khmer virama)\n\tRa = 15, // Ra consonant (for repha)\n\tCM = 16, // Consonant modifier\n\tSymbol = 17, // Symbol\n\tCS = 18, // Consonant with stacker\n}\n\n/**\n * Indic syllabic position\n */\nexport enum IndicPosition {\n\tStart = 0,\n\tRaToBecomeReph = 1,\n\tPreM = 2,\n\tPreC = 3,\n\tBaseC = 4,\n\tAfterMain = 5,\n\tAboveC = 6,\n\tBeforeSub = 7,\n\tBelowC = 8,\n\tAfterSub = 9,\n\tBeforePost = 10,\n\tPostC = 11,\n\tAfterPost = 12,\n\tFinalC = 13,\n\tSMVD = 14,\n\tEnd = 15,\n}\n\n/**\n * Per-glyph Indic shaping data\n */\nexport interface IndicGlyphData {\n\tcategory: IndicCategory;\n\tposition: IndicPosition;\n\tsyllableIndex: number;\n}\n\n/**\n * Determine if codepoint is in Devanagari range\n */\nfunction isDevanagari(cp: number): boolean {\n\treturn cp >= 0x0900 && cp <= 0x097f;\n}\n\n/**\n * Determine if codepoint is in Bengali range\n */\nfunction isBengali(cp: number): boolean {\n\treturn cp >= 0x0980 && cp <= 0x09ff;\n}\n\n/**\n * Determine if codepoint is in Gurmukhi range\n */\nfunction isGurmukhi(cp: number): boolean {\n\treturn cp >= 0x0a00 && cp <= 0x0a7f;\n}\n\n/**\n * Determine if codepoint is in Gujarati range\n */\nfunction isGujarati(cp: number): boolean {\n\treturn cp >= 0x0a80 && cp <= 0x0aff;\n}\n\n/**\n * Determine if codepoint is in Oriya range\n */\nfunction isOriya(cp: number): boolean {\n\treturn cp >= 0x0b00 && cp <= 0x0b7f;\n}\n\n/**\n * Determine if codepoint is in Tamil range\n */\nfunction isTamil(cp: number): boolean {\n\treturn cp >= 0x0b80 && cp <= 0x0bff;\n}\n\n/**\n * Determine if codepoint is in Telugu range\n */\nfunction isTelugu(cp: number): boolean {\n\treturn cp >= 0x0c00 && cp <= 0x0c7f;\n}\n\n/**\n * Determine if codepoint is in Kannada range\n */\nfunction isKannada(cp: number): boolean {\n\treturn cp >= 0x0c80 && cp <= 0x0cff;\n}\n\n/**\n * Determine if codepoint is in Malayalam range\n */\nfunction isMalayalam(cp: number): boolean {\n\treturn cp >= 0x0d00 && cp <= 0x0d7f;\n}\n\n/**\n * Check if a codepoint is an Indic script\n */\nexport function isIndic(cp: number): boolean {\n\treturn (\n\t\tisDevanagari(cp) ||\n\t\tisBengali(cp) ||\n\t\tisGurmukhi(cp) ||\n\t\tisGujarati(cp) ||\n\t\tisOriya(cp) ||\n\t\tisTamil(cp) ||\n\t\tisTelugu(cp) ||\n\t\tisKannada(cp) ||\n\t\tisMalayalam(cp)\n\t);\n}\n\n/**\n * Get the Indic category for a codepoint\n */\nexport function getIndicCategory(cp: number): IndicCategory {\n\t// Zero-width characters\n\tif (cp === 0x200c) return IndicCategory.ZWNJ;\n\tif (cp === 0x200d) return IndicCategory.ZWJ;\n\tif (cp === 0x25cc) return IndicCategory.Dotted_Circle;\n\n\t// Devanagari (0900-097F)\n\tif (isDevanagari(cp)) {\n\t\t// Vowel signs (matras)\n\t\tif (\n\t\t\t(cp >= 0x093a && cp <= 0x093b) ||\n\t\t\t(cp >= 0x093e && cp <= 0x094c) ||\n\t\t\t(cp >= 0x094e && cp <= 0x094f) ||\n\t\t\t(cp >= 0x0955 && cp <= 0x0957)\n\t\t) {\n\t\t\treturn IndicCategory.M;\n\t\t}\n\t\t// Virama\n\t\tif (cp === 0x094d) return IndicCategory.H;\n\t\t// Nukta\n\t\tif (cp === 0x093c) return IndicCategory.N;\n\t\t// Anusvara, Visarga, Chandrabindu\n\t\tif (cp >= 0x0901 && cp <= 0x0903) return IndicCategory.SM;\n\t\t// Vedic marks\n\t\tif (cp >= 0x0951 && cp <= 0x0954) return IndicCategory.A;\n\t\t// Independent vowels\n\t\tif (\n\t\t\t(cp >= 0x0904 && cp <= 0x0914) ||\n\t\t\tcp === 0x0960 ||\n\t\t\tcp === 0x0961 ||\n\t\t\tcp === 0x0972 ||\n\t\t\t(cp >= 0x0976 && cp <= 0x0977)\n\t\t) {\n\t\t\treturn IndicCategory.V;\n\t\t}\n\t\t// Consonants\n\t\tif (\n\t\t\t(cp >= 0x0915 && cp <= 0x0939) ||\n\t\t\t(cp >= 0x0958 && cp <= 0x095f) ||\n\t\t\tcp === 0x0978 ||\n\t\t\tcp === 0x0979 ||\n\t\t\tcp === 0x097a ||\n\t\t\t(cp >= 0x097b && cp <= 0x097c) ||\n\t\t\t(cp >= 0x097e && cp <= 0x097f)\n\t\t) {\n\t\t\t// Ra for repha\n\t\t\tif (cp === 0x0930) return IndicCategory.Ra;\n\t\t\treturn IndicCategory.C;\n\t\t}\n\t\t// Digits and symbols\n\t\tif (cp >= 0x0966 && cp <= 0x096f) return IndicCategory.Symbol;\n\t\treturn IndicCategory.X;\n\t}\n\n\t// Bengali (0980-09FF)\n\tif (isBengali(cp)) {\n\t\tif (\n\t\t\t(cp >= 0x09be && cp <= 0x09c4) ||\n\t\t\t(cp >= 0x09c7 && cp <= 0x09c8) ||\n\t\t\t(cp >= 0x09cb && cp <= 0x09cc) ||\n\t\t\tcp === 0x09d7\n\t\t) {\n\t\t\treturn IndicCategory.M;\n\t\t}\n\t\tif (cp === 0x09cd) return IndicCategory.H;\n\t\tif (cp === 0x09bc) return IndicCategory.N;\n\t\tif (cp >= 0x0981 && cp <= 0x0983) return IndicCategory.SM;\n\t\tif (\n\t\t\t(cp >= 0x0985 && cp <= 0x098c) ||\n\t\t\t(cp >= 0x098f && cp <= 0x0990) ||\n\t\t\t(cp >= 0x0993 && cp <= 0x0994) ||\n\t\t\tcp === 0x09e0 ||\n\t\t\tcp === 0x09e1\n\t\t) {\n\t\t\treturn IndicCategory.V;\n\t\t}\n\t\tif (\n\t\t\t(cp >= 0x0995 && cp <= 0x09a8) ||\n\t\t\t(cp >= 0x09aa && cp <= 0x09b0) ||\n\t\t\tcp === 0x09b2 ||\n\t\t\t(cp >= 0x09b6 && cp <= 0x09b9) ||\n\t\t\t(cp >= 0x09dc && cp <= 0x09dd) ||\n\t\t\t(cp >= 0x09df && cp <= 0x09e1)\n\t\t) {\n\t\t\tif (cp === 0x09b0) return IndicCategory.Ra;\n\t\t\treturn IndicCategory.C;\n\t\t}\n\t\treturn IndicCategory.X;\n\t}\n\n\t// Other Indic scripts - simplified handling\n\t// Tamil, Telugu, Kannada, Malayalam, Gurmukhi, Gujarati, Oriya\n\tif (\n\t\tisGurmukhi(cp) ||\n\t\tisGujarati(cp) ||\n\t\tisOriya(cp) ||\n\t\tisTamil(cp) ||\n\t\tisTelugu(cp) ||\n\t\tisKannada(cp) ||\n\t\tisMalayalam(cp)\n\t) {\n\t\tconst offset = cp & 0x7f; // Position within the block\n\t\t// Common patterns for Indic scripts\n\t\tif (offset >= 0x01 && offset <= 0x03) return IndicCategory.SM; // Anusvara etc\n\t\tif (offset >= 0x05 && offset <= 0x14) return IndicCategory.V; // Vowels\n\t\tif (offset >= 0x15 && offset <= 0x39) return IndicCategory.C; // Consonants\n\t\tif (offset === 0x3c) return IndicCategory.N; // Nukta\n\t\tif (offset >= 0x3e && offset <= 0x4c) return IndicCategory.M; // Matras\n\t\tif (offset === 0x4d) return IndicCategory.H; // Virama\n\t\treturn IndicCategory.X;\n\t}\n\n\treturn IndicCategory.X;\n}\n\n/**\n * Syllable structure for Indic scripts\n */\ninterface Syllable {\n\tstart: number;\n\tend: number;\n\thasReph: boolean;\n\tbaseConsonant: number;\n}\n\n/**\n * Find syllable boundaries in the glyph buffer\n */\nexport function findSyllables(infos: GlyphInfo[]): Syllable[] {\n\tconst syllables: Syllable[] = [];\n\tconst n = infos.length;\n\tif (n === 0) return syllables;\n\n\tlet start = 0;\n\n\twhile (start < n) {\n\t\tconst syllable = parseSyllable(infos, start);\n\t\tsyllables.push(syllable);\n\t\tstart = syllable.end;\n\t}\n\n\treturn syllables;\n}\n\n/**\n * Parse a single syllable starting at the given position\n */\nfunction parseSyllable(infos: GlyphInfo[], start: number): Syllable {\n\tconst n = infos.length;\n\tlet pos = start;\n\n\t// Check for initial consonant cluster with halant\n\tlet baseConsonant = -1;\n\tlet hasReph = false;\n\n\t// Look for Ra + H at the start (potential Reph)\n\tif (pos + 1 < n) {\n\t\tconst info1 = infos[pos];\n\t\tconst info2 = infos[pos + 1];\n\t\tif (info1 && info2) {\n\t\t\tconst cat1 = getIndicCategory(info1.codepoint ?? 0);\n\t\t\tconst cat2 = getIndicCategory(info2.codepoint ?? 0);\n\t\t\tif (cat1 === IndicCategory.Ra && cat2 === IndicCategory.H) {\n\t\t\t\thasReph = true;\n\t\t\t\tpos += 2;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Find base consonant (last consonant before matras/end)\n\tlet lastConsonant = -1;\n\twhile (pos < n) {\n\t\tconst info = infos[pos];\n\t\tif (!info) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cp = info.codepoint ?? 0;\n\t\tconst cat = getIndicCategory(cp);\n\n\t\tif (cat === IndicCategory.C || cat === IndicCategory.Ra) {\n\t\t\tlastConsonant = pos;\n\t\t\tpos++;\n\t\t\t// Check for nukta\n\t\t\tif (pos < n) {\n\t\t\t\tconst nextInfo = infos[pos];\n\t\t\t\tif (\n\t\t\t\t\tnextInfo &&\n\t\t\t\t\tgetIndicCategory(nextInfo.codepoint ?? 0) === IndicCategory.N\n\t\t\t\t) {\n\t\t\t\t\tpos++;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Check for halant (may continue consonant cluster)\n\t\t\tif (pos < n) {\n\t\t\t\tconst hInfo = infos[pos];\n\t\t\t\tif (\n\t\t\t\t\thInfo &&\n\t\t\t\t\tgetIndicCategory(hInfo.codepoint ?? 0) === IndicCategory.H\n\t\t\t\t) {\n\t\t\t\t\tpos++;\n\t\t\t\t\t// After halant, might have ZWJ/ZWNJ or another consonant\n\t\t\t\t\tif (pos < n) {\n\t\t\t\t\t\tconst afterH = infos[pos];\n\t\t\t\t\t\tif (afterH) {\n\t\t\t\t\t\t\tconst nextCat = getIndicCategory(afterH.codepoint ?? 0);\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tnextCat === IndicCategory.ZWJ ||\n\t\t\t\t\t\t\t\tnextCat === IndicCategory.ZWNJ\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tpos++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue; // Look for more consonants\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t} else if (cat === IndicCategory.V) {\n\t\t\t// Independent vowel as syllable base\n\t\t\tpos++;\n\t\t\tbreak;\n\t\t} else if (cat === IndicCategory.N) {\n\t\t\t// Standalone nukta - skip\n\t\t\tpos++;\n\t\t} else {\n\t\t\t// Non-syllable character, end here\n\t\t\tif (lastConsonant === -1) {\n\t\t\t\tpos++;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tbaseConsonant = lastConsonant >= 0 ? lastConsonant : start;\n\n\t// Consume matras, anusvara, visarga\n\twhile (pos < n) {\n\t\tconst info = infos[pos];\n\t\tif (!info) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cp = info.codepoint ?? 0;\n\t\tconst cat = getIndicCategory(cp);\n\n\t\tif (\n\t\t\tcat === IndicCategory.M ||\n\t\t\tcat === IndicCategory.SM ||\n\t\t\tcat === IndicCategory.A ||\n\t\t\tcat === IndicCategory.N\n\t\t) {\n\t\t\tpos++;\n\t\t} else if (cat === IndicCategory.H) {\n\t\t\t// Halant at end (final form)\n\t\t\tpos++;\n\t\t\tbreak;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Ensure we advance at least one position\n\tif (pos === start) {\n\t\tpos = start + 1;\n\t}\n\n\treturn {\n\t\tstart,\n\t\tend: pos,\n\t\thasReph,\n\t\tbaseConsonant,\n\t};\n}\n\n/**\n * Indic feature masks for OpenType features\n */\nexport const IndicFeatureMask = {\n\tnukt: 0x0001, // Nukta forms\n\takhn: 0x0002, // Akhand forms\n\trphf: 0x0004, // Reph forms\n\trkrf: 0x0008, // Rakaar forms\n\tpref: 0x0010, // Pre-base forms\n\tblwf: 0x0020, // Below-base forms\n\tabvf: 0x0040, // Above-base forms\n\thalf: 0x0080, // Half forms\n\tpstf: 0x0100, // Post-base forms\n\tvatu: 0x0200, // Vattu variants\n\tcjct: 0x0400, // Conjunct forms\n\tinit: 0x0800, // Initial forms\n\tpres: 0x1000, // Pre-base substitutions\n\tabvs: 0x2000, // Above-base substitutions\n\tblws: 0x4000, // Below-base substitutions\n\tpsts: 0x8000, // Post-base substitutions\n} as const;\n\n/**\n * Matra position in syllable\n */\nexport enum MatraPosition {\n\tPreBase = 0,\n\tAboveBase = 1,\n\tBelowBase = 2,\n\tPostBase = 3,\n}\n\n/**\n * Get matra position based on codepoint\n */\nfunction getMatraPosition(cp: number): MatraPosition {\n\t// Devanagari\n\tif (cp >= 0x0900 && cp <= 0x097f) {\n\t\t// Pre-base: ि (093F)\n\t\tif (cp === 0x093f) return MatraPosition.PreBase;\n\t\t// Above-base: ॅ ॆ े ै (0945-0948)\n\t\tif (cp >= 0x0945 && cp <= 0x0948) return MatraPosition.AboveBase;\n\t\t// Below-base: ु ू ृ ॄ (0941-0944)\n\t\tif (cp >= 0x0941 && cp <= 0x0944) return MatraPosition.BelowBase;\n\t\t// Post-base: everything else\n\t\treturn MatraPosition.PostBase;\n\t}\n\n\t// Bengali\n\tif (cp >= 0x0980 && cp <= 0x09ff) {\n\t\t// Pre-base: ি (09BF)\n\t\tif (cp === 0x09bf) return MatraPosition.PreBase;\n\t\t// Pre-base split vowels: ে ৈ (09C7-09C8) - left part\n\t\tif (cp === 0x09c7 || cp === 0x09c8) return MatraPosition.PreBase;\n\t\t// Below-base: ু ূ ৃ ৄ (09C1-09C4)\n\t\tif (cp >= 0x09c1 && cp <= 0x09c4) return MatraPosition.BelowBase;\n\t\treturn MatraPosition.PostBase;\n\t}\n\n\t// Tamil\n\tif (cp >= 0x0b80 && cp <= 0x0bff) {\n\t\t// Pre-base: ெ ே ை (0BC6-0BC8)\n\t\tif (cp >= 0x0bc6 && cp <= 0x0bc8) return MatraPosition.PreBase;\n\t\t// Above-base: none\n\t\t// Below-base: ு ூ (0BC1-0BC2)\n\t\tif (cp === 0x0bc1 || cp === 0x0bc2) return MatraPosition.BelowBase;\n\t\treturn MatraPosition.PostBase;\n\t}\n\n\t// Telugu\n\tif (cp >= 0x0c00 && cp <= 0x0c7f) {\n\t\t// Above-base: ి ీ ె ే ై (0C3E-0C40, 0C46-0C48)\n\t\tif ((cp >= 0x0c3e && cp <= 0x0c40) || (cp >= 0x0c46 && cp <= 0x0c48)) {\n\t\t\treturn MatraPosition.AboveBase;\n\t\t}\n\t\t// Below-base: ు ూ ృ ౄ (0C41-0C44)\n\t\tif (cp >= 0x0c41 && cp <= 0x0c44) return MatraPosition.BelowBase;\n\t\treturn MatraPosition.PostBase;\n\t}\n\n\t// Kannada\n\tif (cp >= 0x0c80 && cp <= 0x0cff) {\n\t\t// Above-base: similar to Telugu\n\t\tif ((cp >= 0x0cbe && cp <= 0x0cc0) || (cp >= 0x0cc6 && cp <= 0x0cc8)) {\n\t\t\treturn MatraPosition.AboveBase;\n\t\t}\n\t\tif (cp >= 0x0cc1 && cp <= 0x0cc4) return MatraPosition.BelowBase;\n\t\treturn MatraPosition.PostBase;\n\t}\n\n\t// Malayalam\n\tif (cp >= 0x0d00 && cp <= 0x0d7f) {\n\t\t// Pre-base: െ േ ൈ (0D46-0D48)\n\t\tif (cp >= 0x0d46 && cp <= 0x0d48) return MatraPosition.PreBase;\n\t\t// Below-base: ു ൂ ൃ (0D41-0D43)\n\t\tif (cp >= 0x0d41 && cp <= 0x0d43) return MatraPosition.BelowBase;\n\t\treturn MatraPosition.PostBase;\n\t}\n\n\t// Gurmukhi\n\tif (cp >= 0x0a00 && cp <= 0x0a7f) {\n\t\t// Pre-base: ਿ (0A3F)\n\t\tif (cp === 0x0a3f) return MatraPosition.PreBase;\n\t\t// Below-base: ੁ ੂ (0A41-0A42)\n\t\tif (cp === 0x0a41 || cp === 0x0a42) return MatraPosition.BelowBase;\n\t\treturn MatraPosition.PostBase;\n\t}\n\n\t// Gujarati\n\tif (cp >= 0x0a80 && cp <= 0x0aff) {\n\t\t// Pre-base: િ (0ABF)\n\t\tif (cp === 0x0abf) return MatraPosition.PreBase;\n\t\t// Below-base: ુ ૂ ૃ ૄ (0AC1-0AC4)\n\t\tif (cp >= 0x0ac1 && cp <= 0x0ac4) return MatraPosition.BelowBase;\n\t\treturn MatraPosition.PostBase;\n\t}\n\n\t// Oriya\n\tif (cp >= 0x0b00 && cp <= 0x0b7f) {\n\t\t// Pre-base: ି (0B3F)\n\t\tif (cp === 0x0b3f) return MatraPosition.PreBase;\n\t\t// Below-base: ୁ ୂ ୃ (0B41-0B43)\n\t\tif (cp >= 0x0b41 && cp <= 0x0b43) return MatraPosition.BelowBase;\n\t\treturn MatraPosition.PostBase;\n\t}\n\n\treturn MatraPosition.PostBase;\n}\n\n/**\n * Set up masks and syllable indices for Indic shaping\n */\nexport function setupIndicMasks(infos: GlyphInfo[]): void {\n\tconst syllables = findSyllables(infos);\n\n\tfor (const [i, syllable] of syllables.entries()) {\n\t\t// Mark syllable boundaries in mask\n\t\tfor (let j = syllable.start; j < syllable.end; j++) {\n\t\t\tconst info = infos[j];\n\t\t\tif (info) {\n\t\t\t\t// Store syllable index in upper bits\n\t\t\t\tinfo.mask = (info.mask & 0x0000ffff) | ((i & 0xffff) << 16);\n\n\t\t\t\tconst cat = getIndicCategory(info.codepoint);\n\n\t\t\t\t// Nukta - always apply nukt feature\n\t\t\t\tif (cat === IndicCategory.N) {\n\t\t\t\t\tinfo.mask |= IndicFeatureMask.nukt;\n\t\t\t\t}\n\n\t\t\t\t// Halant handling\n\t\t\t\tif (cat === IndicCategory.H) {\n\t\t\t\t\t// Check position relative to base\n\t\t\t\t\tif (j < syllable.baseConsonant) {\n\t\t\t\t\t\t// Pre-base halant - half forms\n\t\t\t\t\t\tinfo.mask |= IndicFeatureMask.half;\n\t\t\t\t\t} else if (j > syllable.baseConsonant) {\n\t\t\t\t\t\t// Post-base halant - below/post forms\n\t\t\t\t\t\tinfo.mask |= IndicFeatureMask.blwf | IndicFeatureMask.pstf;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Consonant handling\n\t\t\t\tif (cat === IndicCategory.C || cat === IndicCategory.Ra) {\n\t\t\t\t\tif (j < syllable.baseConsonant) {\n\t\t\t\t\t\t// Pre-base consonant\n\t\t\t\t\t\tinfo.mask |= IndicFeatureMask.half | IndicFeatureMask.cjct;\n\t\t\t\t\t} else if (j > syllable.baseConsonant) {\n\t\t\t\t\t\t// Post-base consonant\n\t\t\t\t\t\tinfo.mask |=\n\t\t\t\t\t\t\tIndicFeatureMask.blwf |\n\t\t\t\t\t\t\tIndicFeatureMask.pstf |\n\t\t\t\t\t\t\tIndicFeatureMask.vatu;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Reph handling\n\t\t\t\tif (syllable.hasReph && j < syllable.start + 2) {\n\t\t\t\t\tinfo.mask |= IndicFeatureMask.rphf;\n\t\t\t\t}\n\n\t\t\t\t// Matra handling\n\t\t\t\tif (cat === IndicCategory.M) {\n\t\t\t\t\tconst matraPos = getMatraPosition(info.codepoint);\n\t\t\t\t\tswitch (matraPos) {\n\t\t\t\t\t\tcase MatraPosition.PreBase:\n\t\t\t\t\t\t\tinfo.mask |= IndicFeatureMask.pref | IndicFeatureMask.pres;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MatraPosition.AboveBase:\n\t\t\t\t\t\t\tinfo.mask |= IndicFeatureMask.abvf | IndicFeatureMask.abvs;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MatraPosition.BelowBase:\n\t\t\t\t\t\t\tinfo.mask |= IndicFeatureMask.blwf | IndicFeatureMask.blws;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MatraPosition.PostBase:\n\t\t\t\t\t\t\tinfo.mask |= IndicFeatureMask.pstf | IndicFeatureMask.psts;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Syllable modifiers (anusvara, visarga)\n\t\t\t\tif (cat === IndicCategory.SM) {\n\t\t\t\t\tinfo.mask |= IndicFeatureMask.abvs | IndicFeatureMask.psts;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Reorder glyphs within a syllable for correct visual display\n * This handles:\n * - Moving pre-base matras before the base consonant\n * - Moving reph to its final position\n */\nexport function reorderIndic(infos: GlyphInfo[]): void {\n\tconst syllables = findSyllables(infos);\n\n\tfor (const syllable of syllables) {\n\t\treorderSyllable(infos, syllable);\n\t}\n}\n\n/**\n * Reorder a single syllable\n */\nfunction reorderSyllable(infos: GlyphInfo[], syllable: Syllable): void {\n\tconst { start, end, baseConsonant, hasReph } = syllable;\n\n\t// Collect pre-base matras that need to move\n\tconst preBaseMatras: { index: number; info: GlyphInfo }[] = [];\n\n\tfor (let i = baseConsonant + 1; i < end; i++) {\n\t\tconst info = infos[i];\n\t\tif (!info) continue;\n\n\t\tconst cat = getIndicCategory(info.codepoint);\n\t\tif (cat === IndicCategory.M) {\n\t\t\tconst matraPos = getMatraPosition(info.codepoint);\n\t\t\tif (matraPos === MatraPosition.PreBase) {\n\t\t\t\tpreBaseMatras.push({ index: i, info });\n\t\t\t}\n\t\t}\n\t}\n\n\t// Move pre-base matras before the base (or before reph if present)\n\tif (preBaseMatras.length > 0) {\n\t\t// Sort by original index descending to process from right to left\n\t\tpreBaseMatras.sort((a, b) => b.index - a.index);\n\n\t\tfor (const { index, info } of preBaseMatras) {\n\t\t\t// Remove from current position\n\t\t\tinfos.splice(index, 1);\n\n\t\t\t// Insert before base (accounting for reph)\n\t\t\tconst insertPos = hasReph ? start + 2 : start;\n\t\t\tinfos.splice(insertPos, 0, info);\n\t\t}\n\t}\n\n\t// Handle reph movement (Ra + Halant at start moves to end of syllable)\n\t// Note: In many scripts, reph moves to after the matra\n\t// This is a simplified implementation - full implementation would check\n\t// script-specific rules\n\tif (hasReph && end > start + 2) {\n\t\t// Reph is at positions start and start+1 (Ra + Halant)\n\t\t// Move to end of syllable, before final consonant markers\n\t\tconst rephRa = infos[start];\n\t\tconst rephH = infos[start + 1];\n\n\t\tif (rephRa && rephH) {\n\t\t\t// Find insertion point: after matras, before syllable modifiers\n\t\t\tlet rephTarget = end - 1;\n\n\t\t\t// Adjust for any syllable modifiers at the end\n\t\t\twhile (rephTarget > baseConsonant) {\n\t\t\t\tconst targetInfo = infos[rephTarget];\n\t\t\t\tif (!targetInfo) break;\n\n\t\t\t\tconst cat = getIndicCategory(targetInfo.codepoint);\n\t\t\t\tif (cat === IndicCategory.SM || cat === IndicCategory.A) {\n\t\t\t\t\trephTarget--;\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Only move if target is different from current position\n\t\t\tif (rephTarget > start + 1) {\n\t\t\t\t// Remove Ra + Halant from start\n\t\t\t\tinfos.splice(start, 2);\n\n\t\t\t\t// Insert at new position (adjusted for removal)\n\t\t\t\tconst adjustedTarget = rephTarget - 2;\n\t\t\t\tinfos.splice(adjustedTarget + 1, 0, rephRa, rephH);\n\t\t\t}\n\t\t}\n\t}\n}\n",
70
+ "import type { GlyphInfo } from \"../../types.ts\";\n\n/**\n * Khmer shaper\n * Handles Khmer script syllable structure and reordering\n */\n\n// Khmer Unicode range\nconst KHMER_START = 0x1780;\nconst KHMER_END = 0x17ff;\nconst KHMER_SYMBOLS_START = 0x19e0;\nconst KHMER_SYMBOLS_END = 0x19ff;\n\n/**\n * Khmer character categories\n */\nexport enum KhmerCategory {\n\tOther = 0,\n\tConsonant = 1,\n\tIndependentVowel = 2,\n\tDependentVowel = 3,\n\tCoeng = 4, // Subscript sign (្)\n\tRegister = 5, // Register shifters\n\tRobat = 6, // Consonant shifter (៌)\n\tSign = 7,\n\tAnusvara = 8, // Nikahit (ំ)\n\tVisarga = 9, // Reahmuk (ះ)\n}\n\n/**\n * Get Khmer character category\n */\nexport function getKhmerCategory(cp: number): KhmerCategory {\n\tif (cp < KHMER_START || cp > KHMER_END) return KhmerCategory.Other;\n\n\t// Consonants (ក-ស)\n\tif (cp >= 0x1780 && cp <= 0x17a2) return KhmerCategory.Consonant;\n\tif (cp === 0x17a3 || cp === 0x17a4) return KhmerCategory.IndependentVowel;\n\n\t// Independent vowels (ឣ-ឱ)\n\tif (cp >= 0x17a5 && cp <= 0x17b3) return KhmerCategory.IndependentVowel;\n\n\t// Dependent vowels (ា-ៅ)\n\tif (cp >= 0x17b6 && cp <= 0x17c5) return KhmerCategory.DependentVowel;\n\n\t// Signs\n\tif (cp === 0x17c6) return KhmerCategory.Anusvara; // Nikahit\n\tif (cp === 0x17c7) return KhmerCategory.Visarga; // Reahmuk\n\tif (cp === 0x17c8) return KhmerCategory.Sign; // Yuukaleapintu\n\n\t// Register shifters\n\tif (cp === 0x17c9 || cp === 0x17ca) return KhmerCategory.Register;\n\n\t// Coeng (subscript marker)\n\tif (cp === 0x17d2) return KhmerCategory.Coeng;\n\n\t// Robat\n\tif (cp === 0x17cc) return KhmerCategory.Robat;\n\n\t// Other signs\n\tif (cp >= 0x17cb && cp <= 0x17d1) return KhmerCategory.Sign;\n\tif (cp >= 0x17d3 && cp <= 0x17dd) return KhmerCategory.Sign;\n\n\treturn KhmerCategory.Other;\n}\n\n/**\n * Khmer feature masks\n */\nexport const KhmerFeatureMask = {\n\tpref: 0x0001, // Pre-base forms\n\tblwf: 0x0002, // Below-base forms\n\tabvf: 0x0004, // Above-base forms\n\tpstf: 0x0008, // Post-base forms\n\tcfar: 0x0010, // Conjunct form after Ra\n\tpres: 0x0020, // Pre-base substitutions\n\tabvs: 0x0040, // Above-base substitutions\n\tblws: 0x0080, // Below-base substitutions\n\tpsts: 0x0100, // Post-base substitutions\n\tclig: 0x0200, // Contextual ligatures\n} as const;\n\n/**\n * Check if codepoint is Khmer\n */\nexport function isKhmer(cp: number): boolean {\n\treturn (\n\t\t(cp >= KHMER_START && cp <= KHMER_END) ||\n\t\t(cp >= KHMER_SYMBOLS_START && cp <= KHMER_SYMBOLS_END)\n\t);\n}\n\n/**\n * Setup Khmer masks for feature application\n */\nexport function setupKhmerMasks(infos: GlyphInfo[]): void {\n\tlet i = 0;\n\n\twhile (i < infos.length) {\n\t\tconst info = infos[i];\n\t\tif (!info) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cat = getKhmerCategory(info.codepoint);\n\n\t\tif (cat === KhmerCategory.Other) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Find syllable extent\n\t\tconst _syllableStart = i;\n\t\tlet _base = -1;\n\n\t\t// Find base consonant\n\t\tif (cat === KhmerCategory.Consonant) {\n\t\t\t_base = i;\n\t\t}\n\n\t\t// Process syllable\n\t\tlet j = i + 1;\n\t\twhile (j < infos.length) {\n\t\t\tconst nextInfo = infos[j];\n\t\t\tif (!nextInfo) {\n\t\t\t\tj++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst nextCat = getKhmerCategory(nextInfo.codepoint);\n\n\t\t\tif (nextCat === KhmerCategory.Other) break;\n\t\t\tif (nextCat === KhmerCategory.Consonant) {\n\t\t\t\t// Check if followed by coeng\n\t\t\t\tconst prevInfo = infos[j - 1];\n\t\t\t\tif (\n\t\t\t\t\tprevInfo &&\n\t\t\t\t\tgetKhmerCategory(prevInfo.codepoint) !== KhmerCategory.Coeng\n\t\t\t\t) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Coeng + consonant = subscript consonant\n\t\t\tif (nextCat === KhmerCategory.Coeng && j + 1 < infos.length) {\n\t\t\t\tconst afterCoeng = infos[j + 1];\n\t\t\t\tif (\n\t\t\t\t\tafterCoeng &&\n\t\t\t\t\tgetKhmerCategory(afterCoeng.codepoint) === KhmerCategory.Consonant\n\t\t\t\t) {\n\t\t\t\t\t// Mark for below-base forms\n\t\t\t\t\tnextInfo.mask |= KhmerFeatureMask.blwf;\n\t\t\t\t\tafterCoeng.mask |= KhmerFeatureMask.blwf;\n\t\t\t\t\tj += 2;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Dependent vowels\n\t\t\tif (nextCat === KhmerCategory.DependentVowel) {\n\t\t\t\t// Pre-base vowels: ◌េ ◌ែ ◌ៃ\n\t\t\t\tif (nextInfo.codepoint >= 0x17c1 && nextInfo.codepoint <= 0x17c3) {\n\t\t\t\t\tnextInfo.mask |= KhmerFeatureMask.pref;\n\t\t\t\t}\n\t\t\t\t// Above-base vowels\n\t\t\t\telse if (nextInfo.codepoint >= 0x17b7 && nextInfo.codepoint <= 0x17ba) {\n\t\t\t\t\tnextInfo.mask |= KhmerFeatureMask.abvf;\n\t\t\t\t}\n\t\t\t\t// Below-base vowels\n\t\t\t\telse if (\n\t\t\t\t\tnextInfo.codepoint === 0x17bb ||\n\t\t\t\t\tnextInfo.codepoint === 0x17bc ||\n\t\t\t\t\tnextInfo.codepoint === 0x17bd\n\t\t\t\t) {\n\t\t\t\t\tnextInfo.mask |= KhmerFeatureMask.blwf;\n\t\t\t\t}\n\t\t\t\t// Post-base vowels\n\t\t\t\telse {\n\t\t\t\t\tnextInfo.mask |= KhmerFeatureMask.pstf;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Register shifters (above)\n\t\t\tif (nextCat === KhmerCategory.Register) {\n\t\t\t\tnextInfo.mask |= KhmerFeatureMask.abvs;\n\t\t\t}\n\n\t\t\t// Robat (above)\n\t\t\tif (nextCat === KhmerCategory.Robat) {\n\t\t\t\tnextInfo.mask |= KhmerFeatureMask.abvs;\n\t\t\t}\n\n\t\t\tj++;\n\t\t}\n\n\t\ti = j;\n\t}\n}\n\n/**\n * Reorder Khmer pre-base vowels\n * Pre-base vowels (◌េ ◌ែ ◌ៃ) should visually appear before the base\n */\nexport function reorderKhmer(infos: GlyphInfo[]): void {\n\tlet i = 0;\n\n\twhile (i < infos.length) {\n\t\tconst info = infos[i];\n\t\tif (!info) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cat = getKhmerCategory(info.codepoint);\n\n\t\tif (cat !== KhmerCategory.Consonant) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Found base consonant, look for pre-base vowels after it\n\t\tconst base = i;\n\t\tlet j = i + 1;\n\n\t\t// Skip coeng sequences\n\t\twhile (j < infos.length) {\n\t\t\tconst jInfo = infos[j];\n\t\t\tif (!jInfo) break;\n\t\t\tconst jCat = getKhmerCategory(jInfo.codepoint);\n\t\t\tif (jCat === KhmerCategory.Coeng && j + 1 < infos.length) {\n\t\t\t\tj += 2; // Skip coeng + consonant\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Check for pre-base vowel\n\t\tif (j < infos.length) {\n\t\t\tconst jInfo = infos[j];\n\t\t\tif (jInfo) {\n\t\t\t\tconst cp = jInfo.codepoint;\n\t\t\t\tif (cp >= 0x17c1 && cp <= 0x17c3) {\n\t\t\t\t\t// Move pre-base vowel before base\n\t\t\t\t\tconst vowel = jInfo;\n\t\t\t\t\tfor (let k = j; k > base; k--) {\n\t\t\t\t\t\tconst prevInfo = infos[k - 1];\n\t\t\t\t\t\tif (prevInfo) {\n\t\t\t\t\t\t\tinfos[k] = prevInfo;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tinfos[base] = vowel;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ti = j + 1;\n\t}\n}\n",
71
+ "import type { GlyphInfo } from \"../../types.ts\";\n\n/**\n * Myanmar shaper\n * Handles Myanmar script syllable structure and reordering\n */\n\n// Myanmar Unicode ranges\nconst MYANMAR_START = 0x1000;\nconst MYANMAR_END = 0x109f;\nconst MYANMAR_EXT_A_START = 0xaa60;\nconst MYANMAR_EXT_A_END = 0xaa7f;\nconst MYANMAR_EXT_B_START = 0xa9e0;\nconst MYANMAR_EXT_B_END = 0xa9ff;\n\n/**\n * Myanmar character categories\n */\nexport enum MyanmarCategory {\n\tOther = 0,\n\tConsonant = 1,\n\tIndependentVowel = 2,\n\tDependentVowel = 3,\n\tMedial = 4,\n\tAsat = 5, // Killer (္)\n\tAnusvara = 6, // Dot below\n\tVisarga = 7, // Visarga\n\tSign = 8,\n\tNumber = 9,\n\tPlaceholder = 10, // Placeholder for visible virama\n}\n\n/**\n * Get Myanmar character category\n */\nexport function getMyanmarCategory(cp: number): MyanmarCategory {\n\t// Main Myanmar block\n\tif (cp >= MYANMAR_START && cp <= MYANMAR_END) {\n\t\t// Consonants (က-အ)\n\t\tif (cp >= 0x1000 && cp <= 0x1021) return MyanmarCategory.Consonant;\n\t\tif (cp >= 0x1023 && cp <= 0x1027) return MyanmarCategory.IndependentVowel;\n\t\tif (cp >= 0x1029 && cp <= 0x102a) return MyanmarCategory.IndependentVowel;\n\n\t\t// Dependent vowels\n\t\tif (cp >= 0x102b && cp <= 0x1035) return MyanmarCategory.DependentVowel;\n\n\t\t// Anusvara\n\t\tif (cp === 0x1036) return MyanmarCategory.Anusvara;\n\n\t\t// Dot below (asat indicator)\n\t\tif (cp === 0x1037) return MyanmarCategory.Sign;\n\n\t\t// Visarga\n\t\tif (cp === 0x1038) return MyanmarCategory.Visarga;\n\n\t\t// Asat (killer/virama)\n\t\tif (cp === 0x1039) return MyanmarCategory.Asat;\n\t\tif (cp === 0x103a) return MyanmarCategory.Asat;\n\n\t\t// Medials (ျ ြ ွ ှ)\n\t\tif (cp >= 0x103b && cp <= 0x103e) return MyanmarCategory.Medial;\n\n\t\t// More consonants (ဿ, etc.)\n\t\tif (cp >= 0x103f && cp <= 0x1049) {\n\t\t\tif (cp === 0x103f) return MyanmarCategory.Consonant;\n\t\t\treturn MyanmarCategory.Number;\n\t\t}\n\n\t\t// Signs and digits\n\t\tif (cp >= 0x104a && cp <= 0x104f) return MyanmarCategory.Sign;\n\t\tif (cp >= 0x1050 && cp <= 0x1059) return MyanmarCategory.Consonant;\n\n\t\t// Extended consonants\n\t\tif (cp >= 0x105a && cp <= 0x105d) return MyanmarCategory.Consonant;\n\t\tif (cp >= 0x1060 && cp <= 0x1061) return MyanmarCategory.Consonant;\n\t\tif (cp >= 0x1062 && cp <= 0x1064) return MyanmarCategory.DependentVowel;\n\t\tif (cp >= 0x1065 && cp <= 0x1066) return MyanmarCategory.Consonant;\n\t\tif (cp >= 0x1067 && cp <= 0x106d) return MyanmarCategory.DependentVowel;\n\t\tif (cp >= 0x106e && cp <= 0x1070) return MyanmarCategory.Consonant;\n\t\tif (cp >= 0x1071 && cp <= 0x1074) return MyanmarCategory.DependentVowel;\n\t\tif (cp >= 0x1075 && cp <= 0x1081) return MyanmarCategory.Consonant;\n\t\tif (cp >= 0x1082 && cp <= 0x1082) return MyanmarCategory.Medial;\n\t\tif (cp >= 0x1083 && cp <= 0x108c) return MyanmarCategory.DependentVowel;\n\t\tif (cp === 0x108d) return MyanmarCategory.Sign;\n\t\tif (cp === 0x108e) return MyanmarCategory.Consonant;\n\t\tif (cp === 0x108f) return MyanmarCategory.Sign;\n\t\tif (cp >= 0x1090 && cp <= 0x1099) return MyanmarCategory.Number;\n\t}\n\n\t// Myanmar Extended-A\n\tif (cp >= MYANMAR_EXT_A_START && cp <= MYANMAR_EXT_A_END) {\n\t\tif (cp >= 0xaa60 && cp <= 0xaa76) return MyanmarCategory.Consonant;\n\t\tif (cp >= 0xaa77 && cp <= 0xaa79) return MyanmarCategory.Sign;\n\t\tif (cp === 0xaa7a) return MyanmarCategory.Consonant;\n\t\tif (cp === 0xaa7b) return MyanmarCategory.Sign;\n\t\tif (cp === 0xaa7c) return MyanmarCategory.Sign;\n\t\tif (cp === 0xaa7d) return MyanmarCategory.Sign;\n\t\tif (cp >= 0xaa7e && cp <= 0xaa7f) return MyanmarCategory.Consonant;\n\t}\n\n\t// Myanmar Extended-B\n\tif (cp >= MYANMAR_EXT_B_START && cp <= MYANMAR_EXT_B_END) {\n\t\tif (cp >= 0xa9e0 && cp <= 0xa9e4) return MyanmarCategory.Consonant;\n\t\tif (cp === 0xa9e5) return MyanmarCategory.DependentVowel;\n\t\tif (cp >= 0xa9e6 && cp <= 0xa9ef) return MyanmarCategory.Consonant;\n\t\tif (cp >= 0xa9f0 && cp <= 0xa9f9) return MyanmarCategory.Number;\n\t\tif (cp >= 0xa9fa && cp <= 0xa9fe) return MyanmarCategory.Consonant;\n\t}\n\n\treturn MyanmarCategory.Other;\n}\n\n/**\n * Myanmar feature masks\n */\nexport const MyanmarFeatureMask = {\n\trphf: 0x0001, // Reph forms\n\tpref: 0x0002, // Pre-base forms\n\tblwf: 0x0004, // Below-base forms\n\tpstf: 0x0008, // Post-base forms\n\tpres: 0x0010, // Pre-base substitutions\n\tabvs: 0x0020, // Above-base substitutions\n\tblws: 0x0040, // Below-base substitutions\n\tpsts: 0x0080, // Post-base substitutions\n} as const;\n\n/**\n * Check if codepoint is Myanmar\n */\nexport function isMyanmar(cp: number): boolean {\n\treturn (\n\t\t(cp >= MYANMAR_START && cp <= MYANMAR_END) ||\n\t\t(cp >= MYANMAR_EXT_A_START && cp <= MYANMAR_EXT_A_END) ||\n\t\t(cp >= MYANMAR_EXT_B_START && cp <= MYANMAR_EXT_B_END)\n\t);\n}\n\n/**\n * Setup Myanmar masks for feature application\n */\nexport function setupMyanmarMasks(infos: GlyphInfo[]): void {\n\tlet i = 0;\n\n\twhile (i < infos.length) {\n\t\tconst info = infos[i];\n\t\tif (!info) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cat = getMyanmarCategory(info.codepoint);\n\n\t\tif (cat === MyanmarCategory.Other) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Find syllable extent\n\t\tlet _base = -1;\n\t\tlet hasAsat = false;\n\n\t\tif (cat === MyanmarCategory.Consonant) {\n\t\t\t_base = i;\n\t\t}\n\n\t\tlet j = i + 1;\n\t\twhile (j < infos.length) {\n\t\t\tconst nextInfo = infos[j];\n\t\t\tif (!nextInfo) {\n\t\t\t\tj++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst nextCat = getMyanmarCategory(nextInfo.codepoint);\n\n\t\t\tif (nextCat === MyanmarCategory.Other) break;\n\n\t\t\t// Asat (killer) marks a stacked consonant\n\t\t\tif (nextCat === MyanmarCategory.Asat) {\n\t\t\t\thasAsat = true;\n\t\t\t\tnextInfo.mask |= MyanmarFeatureMask.blwf;\n\n\t\t\t\t// Check for following consonant (stacking)\n\t\t\t\tif (j + 1 < infos.length) {\n\t\t\t\t\tconst afterAsat = infos[j + 1];\n\t\t\t\t\tif (\n\t\t\t\t\t\tafterAsat &&\n\t\t\t\t\t\tgetMyanmarCategory(afterAsat.codepoint) ===\n\t\t\t\t\t\t\tMyanmarCategory.Consonant\n\t\t\t\t\t) {\n\t\t\t\t\t\tafterAsat.mask |= MyanmarFeatureMask.blwf;\n\t\t\t\t\t\tj += 2;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Medials\n\t\t\tif (nextCat === MyanmarCategory.Medial) {\n\t\t\t\tconst cp = nextInfo.codepoint;\n\t\t\t\t// ျ (ya) - pre-base\n\t\t\t\tif (cp === 0x103b) {\n\t\t\t\t\tnextInfo.mask |= MyanmarFeatureMask.pref;\n\t\t\t\t}\n\t\t\t\t// ြ (ra) - pre-base\n\t\t\t\telse if (cp === 0x103c) {\n\t\t\t\t\tnextInfo.mask |= MyanmarFeatureMask.pref;\n\t\t\t\t}\n\t\t\t\t// ွ (wa) - below-base\n\t\t\t\telse if (cp === 0x103d) {\n\t\t\t\t\tnextInfo.mask |= MyanmarFeatureMask.blwf;\n\t\t\t\t}\n\t\t\t\t// ှ (ha) - below-base\n\t\t\t\telse if (cp === 0x103e) {\n\t\t\t\t\tnextInfo.mask |= MyanmarFeatureMask.blwf;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Dependent vowels\n\t\t\tif (nextCat === MyanmarCategory.DependentVowel) {\n\t\t\t\tconst cp = nextInfo.codepoint;\n\t\t\t\t// Pre-base vowels: ေ\n\t\t\t\tif (cp === 0x1031) {\n\t\t\t\t\tnextInfo.mask |= MyanmarFeatureMask.pref;\n\t\t\t\t}\n\t\t\t\t// Above-base vowels\n\t\t\t\telse if (cp === 0x102d || cp === 0x102e || cp === 0x1032) {\n\t\t\t\t\tnextInfo.mask |= MyanmarFeatureMask.abvs;\n\t\t\t\t}\n\t\t\t\t// Below-base vowels\n\t\t\t\telse if (cp === 0x102f || cp === 0x1030) {\n\t\t\t\t\tnextInfo.mask |= MyanmarFeatureMask.blws;\n\t\t\t\t}\n\t\t\t\t// Post-base vowels\n\t\t\t\telse {\n\t\t\t\t\tnextInfo.mask |= MyanmarFeatureMask.psts;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Signs above\n\t\t\tif (\n\t\t\t\tnextCat === MyanmarCategory.Anusvara ||\n\t\t\t\tnextCat === MyanmarCategory.Sign\n\t\t\t) {\n\t\t\t\tnextInfo.mask |= MyanmarFeatureMask.abvs;\n\t\t\t}\n\n\t\t\t// New syllable on consonant without asat\n\t\t\tif (nextCat === MyanmarCategory.Consonant && !hasAsat) {\n\t\t\t\t// Check if previous was asat\n\t\t\t\tif (j > 0) {\n\t\t\t\t\tconst prevInfo = infos[j - 1];\n\t\t\t\t\tif (prevInfo) {\n\t\t\t\t\t\tconst prevCat = getMyanmarCategory(prevInfo.codepoint);\n\t\t\t\t\t\tif (prevCat !== MyanmarCategory.Asat) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\thasAsat = false;\n\t\t\tj++;\n\t\t}\n\n\t\ti = j;\n\t}\n}\n\n/**\n * Reorder Myanmar pre-base vowels and medials\n * ေ and ြ should visually appear before the base consonant\n */\nexport function reorderMyanmar(infos: GlyphInfo[]): void {\n\tlet i = 0;\n\n\twhile (i < infos.length) {\n\t\tconst info = infos[i];\n\t\tif (!info) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cat = getMyanmarCategory(info.codepoint);\n\n\t\tif (cat !== MyanmarCategory.Consonant) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Found base consonant\n\t\tconst base = i;\n\t\tconst preBase: GlyphInfo[] = [];\n\n\t\t// Collect pre-base elements that follow base\n\t\tlet j = i + 1;\n\t\twhile (j < infos.length) {\n\t\t\tconst jInfo = infos[j];\n\t\t\tif (!jInfo) {\n\t\t\t\tj++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst jCat = getMyanmarCategory(jInfo.codepoint);\n\n\t\t\t// Pre-base vowel (ေ)\n\t\t\tif (jInfo.codepoint === 0x1031) {\n\t\t\t\tpreBase.push(jInfo);\n\t\t\t\tinfos.splice(j, 1);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Pre-base medial (ြ ra)\n\t\t\tif (jInfo.codepoint === 0x103c) {\n\t\t\t\tpreBase.push(jInfo);\n\t\t\t\tinfos.splice(j, 1);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Stop at next syllable\n\t\t\tif (\n\t\t\t\tjCat === MyanmarCategory.Consonant ||\n\t\t\t\tjCat === MyanmarCategory.Other\n\t\t\t) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tj++;\n\t\t}\n\n\t\t// Insert pre-base elements before base\n\t\tif (preBase.length > 0) {\n\t\t\tinfos.splice(base, 0, ...preBase);\n\t\t\ti += preBase.length;\n\t\t}\n\n\t\ti++;\n\t}\n}\n",
72
+ "import type { GlyphInfo } from \"../../types.ts\";\n\n/**\n * Thai/Lao character categories\n */\nexport enum ThaiLaoCategory {\n\tOther = 0,\n\tConsonant = 1,\n\tLeadingVowel = 2, // Vowels that appear before consonant\n\tAboveVowel = 3, // Vowels above consonant\n\tBelowVowel = 4, // Vowels below consonant\n\tFollowingVowel = 5, // Vowels after consonant\n\tTone = 6, // Tone marks\n\tNikhahitMaiEk = 7, // Special combining marks\n\tSaraAm = 8, // Thai Sara Am (combines anusvara + aa)\n\tSymbol = 9,\n}\n\n/**\n * Check if codepoint is Thai\n */\nexport function isThai(cp: number): boolean {\n\treturn cp >= 0x0e00 && cp <= 0x0e7f;\n}\n\n/**\n * Check if codepoint is Lao\n */\nexport function isLao(cp: number): boolean {\n\treturn cp >= 0x0e80 && cp <= 0x0eff;\n}\n\n/**\n * Get Thai/Lao category for a codepoint\n */\nexport function getThaiLaoCategory(cp: number): ThaiLaoCategory {\n\t// Thai (0E00-0E7F)\n\tif (isThai(cp)) {\n\t\t// Consonants\n\t\tif (cp >= 0x0e01 && cp <= 0x0e2e) return ThaiLaoCategory.Consonant;\n\t\t// Additional consonants\n\t\tif (cp === 0x0e2f) return ThaiLaoCategory.Consonant; // Paiyannoi\n\n\t\t// Leading vowels (displayed before consonant)\n\t\tif (cp >= 0x0e40 && cp <= 0x0e44) return ThaiLaoCategory.LeadingVowel;\n\n\t\t// Above vowels\n\t\tif (cp === 0x0e31) return ThaiLaoCategory.AboveVowel; // Mai Han-Akat\n\t\tif (cp >= 0x0e34 && cp <= 0x0e37) return ThaiLaoCategory.AboveVowel;\n\t\tif (cp === 0x0e47) return ThaiLaoCategory.AboveVowel; // Maitaikhu\n\n\t\t// Below vowels\n\t\tif (cp >= 0x0e38 && cp <= 0x0e3a) return ThaiLaoCategory.BelowVowel;\n\n\t\t// Following vowels\n\t\tif (cp === 0x0e30) return ThaiLaoCategory.FollowingVowel; // Sara A\n\t\tif (cp === 0x0e32 || cp === 0x0e33) return ThaiLaoCategory.FollowingVowel; // Sara Aa, Sara Am\n\t\tif (cp === 0x0e45) return ThaiLaoCategory.FollowingVowel; // Lakkhangyao\n\n\t\t// Sara Am (special - decomposes to nikhahit + sara aa)\n\t\tif (cp === 0x0e33) return ThaiLaoCategory.SaraAm;\n\n\t\t// Tone marks\n\t\tif (cp >= 0x0e48 && cp <= 0x0e4b) return ThaiLaoCategory.Tone;\n\n\t\t// Thanthakhat (cancellation mark)\n\t\tif (cp === 0x0e4c) return ThaiLaoCategory.Tone;\n\n\t\t// Nikhahit (anusvara)\n\t\tif (cp === 0x0e4d) return ThaiLaoCategory.NikhahitMaiEk;\n\n\t\t// Yamakkan\n\t\tif (cp === 0x0e4e) return ThaiLaoCategory.NikhahitMaiEk;\n\n\t\t// Digits and symbols\n\t\tif (cp >= 0x0e50 && cp <= 0x0e5b) return ThaiLaoCategory.Symbol;\n\n\t\treturn ThaiLaoCategory.Other;\n\t}\n\n\t// Lao (0E80-0EFF)\n\tif (isLao(cp)) {\n\t\t// Consonants\n\t\tif (cp >= 0x0e81 && cp <= 0x0eae) return ThaiLaoCategory.Consonant;\n\n\t\t// Leading vowels\n\t\tif (cp >= 0x0ec0 && cp <= 0x0ec4) return ThaiLaoCategory.LeadingVowel;\n\n\t\t// Above vowels\n\t\tif (cp === 0x0eb1) return ThaiLaoCategory.AboveVowel;\n\t\tif (cp >= 0x0eb4 && cp <= 0x0eb7) return ThaiLaoCategory.AboveVowel;\n\t\tif (cp === 0x0ebb) return ThaiLaoCategory.AboveVowel;\n\n\t\t// Below vowels\n\t\tif (cp >= 0x0eb8 && cp <= 0x0eb9) return ThaiLaoCategory.BelowVowel;\n\t\tif (cp === 0x0ebc) return ThaiLaoCategory.BelowVowel;\n\n\t\t// Following vowels\n\t\tif (cp === 0x0eb0) return ThaiLaoCategory.FollowingVowel;\n\t\tif (cp === 0x0eb2 || cp === 0x0eb3) return ThaiLaoCategory.FollowingVowel;\n\n\t\t// Tone marks\n\t\tif (cp >= 0x0ec8 && cp <= 0x0ecd) return ThaiLaoCategory.Tone;\n\n\t\t// Digits\n\t\tif (cp >= 0x0ed0 && cp <= 0x0ed9) return ThaiLaoCategory.Symbol;\n\n\t\treturn ThaiLaoCategory.Other;\n\t}\n\n\treturn ThaiLaoCategory.Other;\n}\n\n/**\n * Set up masks for Thai/Lao shaping\n *\n * Thai/Lao require:\n * 1. Reordering of pre-base vowels (they appear before consonant visually but after in Unicode)\n * 2. Proper stacking of above/below vowels and tone marks\n */\nexport function setupThaiLaoMasks(infos: GlyphInfo[]): void {\n\t// Group characters into syllable-like clusters\n\t// Each cluster starts with a consonant\n\n\tlet clusterIndex = 0;\n\tlet _consonantIndex = -1;\n\n\tfor (let i = 0; i < infos.length; i++) {\n\t\tconst info = infos[i];\n\t\tif (!info) continue;\n\n\t\tconst cat = getThaiLaoCategory(info.codepoint);\n\n\t\t// Consonants start new clusters\n\t\tif (cat === ThaiLaoCategory.Consonant) {\n\t\t\tclusterIndex++;\n\t\t\t_consonantIndex = i;\n\t\t}\n\n\t\t// Store cluster info in mask\n\t\t// Upper bits: cluster index\n\t\t// Lower bits: category for reordering\n\t\tinfo.mask = (info.mask & 0xffffff00) | (cat & 0xff);\n\t\tinfo.mask = (info.mask & 0x0000ffff) | ((clusterIndex & 0xffff) << 16);\n\n\t\t// Mark leading vowels for reordering\n\t\tif (cat === ThaiLaoCategory.LeadingVowel) {\n\t\t\t// These need to be moved before the consonant during shaping\n\t\t\t// The GSUB pref feature handles this\n\t\t\tinfo.mask |= 0x100; // Mark for pre-base processing\n\t\t}\n\t}\n}\n\n/**\n * Reorder Thai/Lao clusters\n * Leading vowels (Sara E, Sara Ae, Sara O, Sara Ai Mai Muan, Sara Ai Mai Malai)\n * are stored after consonant in Unicode but displayed before\n */\nexport function reorderThaiLao(infos: GlyphInfo[]): void {\n\tlet i = 0;\n\twhile (i < infos.length) {\n\t\tconst info = infos[i];\n\t\tif (!info) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst cat = getThaiLaoCategory(info.codepoint);\n\n\t\t// If we find a leading vowel, move it before its consonant\n\t\tif (cat === ThaiLaoCategory.LeadingVowel) {\n\t\t\t// Find the following consonant\n\t\t\tlet j = i + 1;\n\t\t\twhile (j < infos.length) {\n\t\t\t\tconst nextInfo = infos[j];\n\t\t\t\tif (!nextInfo) {\n\t\t\t\t\tj++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst nextCat = getThaiLaoCategory(nextInfo.codepoint ?? 0);\n\t\t\t\tif (nextCat === ThaiLaoCategory.Consonant) {\n\t\t\t\t\t// Swap vowel and consonant\n\t\t\t\t\tconst temp = info;\n\t\t\t\t\tinfos[i] = nextInfo;\n\t\t\t\t\tinfos[j] = temp;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (nextCat !== ThaiLaoCategory.LeadingVowel) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tj++;\n\t\t\t}\n\t\t}\n\t\ti++;\n\t}\n}\n",
73
+ "import type { GlyphInfo } from \"../../types.ts\";\n\n/**\n * Universal Shaping Engine (USE) categories\n * Based on Unicode USE specification\n */\nexport enum UseCategory {\n\tO = 0, // Other\n\tB = 1, // Base\n\tCGJ = 2, // Combining Grapheme Joiner\n\tCM = 3, // Consonant modifier\n\tCS = 4, // Consonant with stacker\n\tF = 5, // Final\n\tFM = 6, // Final modifier\n\tGB = 7, // Generic base\n\tH = 8, // Halant/Virama\n\tHN = 9, // Halant or Nukta\n\tIND = 10, // Independent\n\tJ = 11, // Joiner\n\tN = 12, // Nukta\n\tR = 13, // Repha\n\tS = 14, // Symbol\n\tSB = 15, // Symbol modifier\n\tSE = 16, // Syllable ending\n\tSUB = 17, // Subjoined\n\tVS = 18, // Variation selector\n\tWJ = 19, // Word joiner\n\tZWJ = 20, // Zero Width Joiner\n\tZWNJ = 21, // Zero Width Non-Joiner\n\tV = 22, // Vowel (independent)\n\tVD = 23, // Vowel dependent\n\tVMAbv = 24, // Vowel modifier above\n\tVMBlw = 25, // Vowel modifier below\n\tVMPre = 26, // Vowel modifier pre\n\tVMPst = 27, // Vowel modifier post\n\tVAbv = 28, // Vowel above\n\tVBlw = 29, // Vowel below\n\tVPre = 30, // Vowel pre\n\tVPst = 31, // Vowel post\n\tSMAbv = 32, // Syllable modifier above\n\tSMBlw = 33, // Syllable modifier below\n\tFAbv = 34, // Final above\n\tFBlw = 35, // Final below\n\tFPst = 36, // Final post\n\tMAbv = 37, // Medial above\n\tMBlw = 38, // Medial below\n\tMPre = 39, // Medial pre\n\tMPst = 40, // Medial post\n}\n\n/**\n * Check if a script uses USE\n */\nexport function usesUSE(script: string): boolean {\n\t// Scripts that use Universal Shaping Engine\n\tconst useScripts = [\n\t\t\"bali\", // Balinese\n\t\t\"batk\", // Batak\n\t\t\"brah\", // Brahmi\n\t\t\"bugi\", // Buginese\n\t\t\"buhd\", // Buhid\n\t\t\"cakm\", // Chakma\n\t\t\"cham\", // Cham\n\t\t\"dupl\", // Duployan\n\t\t\"egyp\", // Egyptian Hieroglyphs\n\t\t\"gran\", // Grantha\n\t\t\"hano\", // Hanunoo\n\t\t\"java\", // Javanese\n\t\t\"kthi\", // Kaithi\n\t\t\"khar\", // Kharoshthi\n\t\t\"khmr\", // Khmer\n\t\t\"khoj\", // Khojki\n\t\t\"lana\", // Tai Tham\n\t\t\"lepc\", // Lepcha\n\t\t\"limb\", // Limbu\n\t\t\"mahj\", // Mahajani\n\t\t\"modi\", // Modi\n\t\t\"mtei\", // Meetei Mayek\n\t\t\"mymr\", // Myanmar\n\t\t\"newa\", // Newa\n\t\t\"phlp\", // Psalter Pahlavi\n\t\t\"rjng\", // Rejang\n\t\t\"saur\", // Saurashtra\n\t\t\"shrd\", // Sharada\n\t\t\"sidd\", // Siddham\n\t\t\"sind\", // Sindhi (Khudawadi)\n\t\t\"sinh\", // Sinhala\n\t\t\"sund\", // Sundanese\n\t\t\"sylo\", // Syloti Nagri\n\t\t\"tagb\", // Tagbanwa\n\t\t\"takr\", // Takri\n\t\t\"tale\", // Tai Le\n\t\t\"talu\", // New Tai Lue\n\t\t\"tavt\", // Tai Viet\n\t\t\"tibt\", // Tibetan\n\t\t\"tirh\", // Tirhuta\n\t];\n\treturn useScripts.includes(script);\n}\n\n/**\n * Get USE category for a codepoint\n */\nexport function getUseCategory(cp: number): UseCategory {\n\t// Zero-width characters\n\tif (cp === 0x200c) return UseCategory.ZWNJ;\n\tif (cp === 0x200d) return UseCategory.ZWJ;\n\tif (cp === 0x034f) return UseCategory.CGJ; // Combining Grapheme Joiner\n\tif (cp === 0x2060) return UseCategory.WJ; // Word Joiner\n\tif (cp >= 0xfe00 && cp <= 0xfe0f) return UseCategory.VS; // Variation Selectors\n\tif (cp >= 0xe0100 && cp <= 0xe01ef) return UseCategory.VS; // VS 17-256\n\n\t// Myanmar (1000-109F)\n\tif (cp >= 0x1000 && cp <= 0x109f) {\n\t\t// Consonants\n\t\tif (cp >= 0x1000 && cp <= 0x1020) return UseCategory.B;\n\t\t// Independent vowels\n\t\tif (cp >= 0x1021 && cp <= 0x102a) return UseCategory.IND;\n\t\t// Dependent vowels\n\t\tif (cp >= 0x102b && cp <= 0x1032) return UseCategory.VPst;\n\t\t// Anusvara etc\n\t\tif (cp >= 0x1036 && cp <= 0x1037) return UseCategory.SMAbv;\n\t\t// Virama\n\t\tif (cp === 0x1039) return UseCategory.H;\n\t\t// Asat (visible virama)\n\t\tif (cp === 0x103a) return UseCategory.H;\n\t\t// Medial consonants\n\t\tif (cp >= 0x103b && cp <= 0x103e) return UseCategory.MBlw;\n\t\t// Digits\n\t\tif (cp >= 0x1040 && cp <= 0x1049) return UseCategory.GB;\n\t\treturn UseCategory.O;\n\t}\n\n\t// Khmer (1780-17FF)\n\tif (cp >= 0x1780 && cp <= 0x17ff) {\n\t\t// Consonants\n\t\tif (cp >= 0x1780 && cp <= 0x17a2) return UseCategory.B;\n\t\t// Independent vowels\n\t\tif (cp >= 0x17a3 && cp <= 0x17b3) return UseCategory.IND;\n\t\t// Dependent vowels\n\t\tif (cp >= 0x17b6 && cp <= 0x17c5) return UseCategory.VPst;\n\t\t// Coeng (stacking virama)\n\t\tif (cp === 0x17d2) return UseCategory.H;\n\t\t// Anusvara, Visarga\n\t\tif (cp >= 0x17c6 && cp <= 0x17c8) return UseCategory.SMAbv;\n\t\treturn UseCategory.O;\n\t}\n\n\t// Tibetan (0F00-0FFF)\n\tif (cp >= 0x0f00 && cp <= 0x0fff) {\n\t\t// Syllable markers\n\t\tif (cp >= 0x0f00 && cp <= 0x0f17) return UseCategory.S;\n\t\t// Vowel signs\n\t\tif (cp >= 0x0f71 && cp <= 0x0f7d) return UseCategory.VAbv;\n\t\t// Subjoined consonants\n\t\tif (cp >= 0x0f90 && cp <= 0x0fbc) return UseCategory.SUB;\n\t\t// Base consonants\n\t\tif (cp >= 0x0f40 && cp <= 0x0f6c) return UseCategory.B;\n\t\treturn UseCategory.O;\n\t}\n\n\t// Thai (0E00-0E7F)\n\tif (cp >= 0x0e00 && cp <= 0x0e7f) {\n\t\t// Consonants\n\t\tif (cp >= 0x0e01 && cp <= 0x0e2e) return UseCategory.B;\n\t\t// Vowels\n\t\tif (cp >= 0x0e30 && cp <= 0x0e3a) return UseCategory.VPst;\n\t\tif (cp >= 0x0e40 && cp <= 0x0e44) return UseCategory.VPre;\n\t\t// Tone marks\n\t\tif (cp >= 0x0e48 && cp <= 0x0e4b) return UseCategory.SMAbv;\n\t\treturn UseCategory.O;\n\t}\n\n\t// Lao (0E80-0EFF)\n\tif (cp >= 0x0e80 && cp <= 0x0eff) {\n\t\t// Consonants\n\t\tif (cp >= 0x0e81 && cp <= 0x0ea3) return UseCategory.B;\n\t\t// Vowels\n\t\tif (cp >= 0x0eb0 && cp <= 0x0ebc) return UseCategory.VPst;\n\t\tif (cp >= 0x0ec0 && cp <= 0x0ec4) return UseCategory.VPre;\n\t\t// Tone marks\n\t\tif (cp >= 0x0ec8 && cp <= 0x0ecd) return UseCategory.SMAbv;\n\t\treturn UseCategory.O;\n\t}\n\n\treturn UseCategory.O;\n}\n\n/** USE feature masks */\nexport const UseFeatureMask = {\n\trphf: 0x0001, // Reph forms\n\tpref: 0x0002, // Pre-base forms\n\tblwf: 0x0004, // Below-base forms\n\tabvf: 0x0008, // Above-base forms\n\tpstf: 0x0010, // Post-base forms\n\thalf: 0x0020, // Half forms\n\tcjct: 0x0040, // Conjunct forms\n\tvatu: 0x0080, // Vattu variants\n\tpres: 0x0100, // Pre-base substitutions\n\tabvs: 0x0200, // Above-base substitutions\n\tblws: 0x0400, // Below-base substitutions\n\tpsts: 0x0800, // Post-base substitutions\n\thaln: 0x1000, // Halant forms\n} as const;\n\n/**\n * USE syllable structure\n */\ninterface UseSyllable {\n\tstart: number;\n\tend: number;\n\tbase: number;\n\thasReph: boolean;\n}\n\n/**\n * Find syllable boundaries in USE text\n */\nfunction findUseSyllables(infos: GlyphInfo[]): UseSyllable[] {\n\tconst syllables: UseSyllable[] = [];\n\tconst n = infos.length;\n\tif (n === 0) return syllables;\n\n\tlet start = 0;\n\n\twhile (start < n) {\n\t\tconst syllable = parseUseSyllable(infos, start);\n\t\tsyllables.push(syllable);\n\t\tstart = syllable.end;\n\t}\n\n\treturn syllables;\n}\n\n/**\n * Parse a single USE syllable\n */\nfunction parseUseSyllable(infos: GlyphInfo[], start: number): UseSyllable {\n\tconst n = infos.length;\n\tlet pos = start;\n\tlet base = -1;\n\tlet hasReph = false;\n\n\t// Check for Repha (R + H at start)\n\tif (pos + 1 < n) {\n\t\tconst info1 = infos[pos];\n\t\tconst info2 = infos[pos + 1];\n\t\tif (info1 && info2) {\n\t\t\tconst cat1 = getUseCategory(info1.codepoint ?? 0);\n\t\t\tconst cat2 = getUseCategory(info2.codepoint ?? 0);\n\t\t\tif (cat1 === UseCategory.R && cat2 === UseCategory.H) {\n\t\t\t\thasReph = true;\n\t\t\t\tpos += 2;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Find base character\n\twhile (pos < n) {\n\t\tconst info = infos[pos];\n\t\tif (!info) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cat = getUseCategory(info.codepoint ?? 0);\n\n\t\t// Base characters\n\t\tif (\n\t\t\tcat === UseCategory.B ||\n\t\t\tcat === UseCategory.IND ||\n\t\t\tcat === UseCategory.GB ||\n\t\t\tcat === UseCategory.V\n\t\t) {\n\t\t\tbase = pos;\n\t\t\tpos++;\n\t\t\tbreak;\n\t\t}\n\n\t\t// Non-base starters - continue looking\n\t\tif (\n\t\t\tcat === UseCategory.VMPre ||\n\t\t\tcat === UseCategory.VPre ||\n\t\t\tcat === UseCategory.MPre\n\t\t) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// End of valid cluster start\n\t\tif (base === -1) {\n\t\t\tpos++;\n\t\t}\n\t\tbreak;\n\t}\n\n\tif (base === -1) base = start;\n\n\t// Consume consonant cluster\n\twhile (pos < n) {\n\t\tconst posInfo = infos[pos];\n\t\tif (!posInfo) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cat = getUseCategory(posInfo.codepoint ?? 0);\n\n\t\t// Halant + Consonant continues cluster\n\t\tif (cat === UseCategory.H) {\n\t\t\tpos++;\n\t\t\tif (pos < n) {\n\t\t\t\tconst nextInfo = infos[pos];\n\t\t\t\tif (nextInfo) {\n\t\t\t\t\tconst nextCat = getUseCategory(nextInfo.codepoint ?? 0);\n\t\t\t\t\tif (\n\t\t\t\t\t\tnextCat === UseCategory.B ||\n\t\t\t\t\t\tnextCat === UseCategory.CS ||\n\t\t\t\t\t\tnextCat === UseCategory.SUB\n\t\t\t\t\t) {\n\t\t\t\t\t\tpos++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t// ZWJ/ZWNJ after halant\n\t\t\t\t\tif (nextCat === UseCategory.ZWJ || nextCat === UseCategory.ZWNJ) {\n\t\t\t\t\t\tpos++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Subjoined consonants\n\t\tif (cat === UseCategory.SUB || cat === UseCategory.CS) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Nukta\n\t\tif (cat === UseCategory.N || cat === UseCategory.HN) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tbreak;\n\t}\n\n\t// Consume matras and modifiers\n\twhile (pos < n) {\n\t\tconst posInfo = infos[pos];\n\t\tif (!posInfo) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\t\tconst cat = getUseCategory(posInfo.codepoint ?? 0);\n\n\t\t// Vowel signs\n\t\tif (\n\t\t\tcat === UseCategory.VAbv ||\n\t\t\tcat === UseCategory.VBlw ||\n\t\t\tcat === UseCategory.VPre ||\n\t\t\tcat === UseCategory.VPst ||\n\t\t\tcat === UseCategory.VD\n\t\t) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Medials\n\t\tif (\n\t\t\tcat === UseCategory.MAbv ||\n\t\t\tcat === UseCategory.MBlw ||\n\t\t\tcat === UseCategory.MPre ||\n\t\t\tcat === UseCategory.MPst\n\t\t) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Vowel modifiers\n\t\tif (\n\t\t\tcat === UseCategory.VMAbv ||\n\t\t\tcat === UseCategory.VMBlw ||\n\t\t\tcat === UseCategory.VMPre ||\n\t\t\tcat === UseCategory.VMPst\n\t\t) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Syllable modifiers\n\t\tif (cat === UseCategory.SMAbv || cat === UseCategory.SMBlw) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Finals\n\t\tif (\n\t\t\tcat === UseCategory.FAbv ||\n\t\t\tcat === UseCategory.FBlw ||\n\t\t\tcat === UseCategory.FPst ||\n\t\t\tcat === UseCategory.F ||\n\t\t\tcat === UseCategory.FM\n\t\t) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// CGJ, VS\n\t\tif (cat === UseCategory.CGJ || cat === UseCategory.VS) {\n\t\t\tpos++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tbreak;\n\t}\n\n\t// Ensure we advance at least one position\n\tif (pos === start) {\n\t\tpos = start + 1;\n\t}\n\n\treturn { start, end: pos, base, hasReph };\n}\n\n/**\n * Set up masks for USE shaping\n */\nexport function setupUseMasks(infos: GlyphInfo[]): void {\n\tconst syllables = findUseSyllables(infos);\n\n\tfor (const [i, syllable] of syllables.entries()) {\n\t\tfor (let j = syllable.start; j < syllable.end; j++) {\n\t\t\tconst info = infos[j];\n\t\t\tif (!info) continue;\n\n\t\t\t// Store syllable index in upper mask bits\n\t\t\tinfo.mask = (info.mask & 0x0000ffff) | ((i & 0xffff) << 16);\n\n\t\t\tconst cat = getUseCategory(info.codepoint);\n\n\t\t\t// Reph handling\n\t\t\tif (syllable.hasReph && j < syllable.start + 2) {\n\t\t\t\tinfo.mask |= UseFeatureMask.rphf;\n\t\t\t}\n\n\t\t\t// Pre-base handling\n\t\t\tif (j < syllable.base) {\n\t\t\t\tif (\n\t\t\t\t\tcat === UseCategory.B ||\n\t\t\t\t\tcat === UseCategory.CS ||\n\t\t\t\t\tcat === UseCategory.SUB\n\t\t\t\t) {\n\t\t\t\t\tinfo.mask |= UseFeatureMask.half | UseFeatureMask.cjct;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Post-base handling\n\t\t\tif (j > syllable.base) {\n\t\t\t\tif (\n\t\t\t\t\tcat === UseCategory.B ||\n\t\t\t\t\tcat === UseCategory.CS ||\n\t\t\t\t\tcat === UseCategory.SUB\n\t\t\t\t) {\n\t\t\t\t\tinfo.mask |=\n\t\t\t\t\t\tUseFeatureMask.blwf | UseFeatureMask.pstf | UseFeatureMask.vatu;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Halant\n\t\t\tif (cat === UseCategory.H || cat === UseCategory.HN) {\n\t\t\t\tif (j < syllable.base) {\n\t\t\t\t\tinfo.mask |= UseFeatureMask.half;\n\t\t\t\t} else {\n\t\t\t\t\tinfo.mask |= UseFeatureMask.haln;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Vowel signs\n\t\t\tif (cat === UseCategory.VPre) {\n\t\t\t\tinfo.mask |= UseFeatureMask.pref | UseFeatureMask.pres;\n\t\t\t} else if (cat === UseCategory.VAbv) {\n\t\t\t\tinfo.mask |= UseFeatureMask.abvf | UseFeatureMask.abvs;\n\t\t\t} else if (cat === UseCategory.VBlw) {\n\t\t\t\tinfo.mask |= UseFeatureMask.blwf | UseFeatureMask.blws;\n\t\t\t} else if (cat === UseCategory.VPst || cat === UseCategory.VD) {\n\t\t\t\tinfo.mask |= UseFeatureMask.pstf | UseFeatureMask.psts;\n\t\t\t}\n\n\t\t\t// Medials\n\t\t\tif (cat === UseCategory.MAbv) {\n\t\t\t\tinfo.mask |= UseFeatureMask.abvs;\n\t\t\t} else if (cat === UseCategory.MBlw) {\n\t\t\t\tinfo.mask |= UseFeatureMask.blws;\n\t\t\t} else if (cat === UseCategory.MPre) {\n\t\t\t\tinfo.mask |= UseFeatureMask.pres;\n\t\t\t} else if (cat === UseCategory.MPst) {\n\t\t\t\tinfo.mask |= UseFeatureMask.psts;\n\t\t\t}\n\n\t\t\t// Syllable modifiers\n\t\t\tif (cat === UseCategory.SMAbv) {\n\t\t\t\tinfo.mask |= UseFeatureMask.abvs;\n\t\t\t} else if (cat === UseCategory.SMBlw) {\n\t\t\t\tinfo.mask |= UseFeatureMask.blws;\n\t\t\t}\n\n\t\t\t// Finals\n\t\t\tif (cat === UseCategory.FAbv) {\n\t\t\t\tinfo.mask |= UseFeatureMask.abvs;\n\t\t\t} else if (cat === UseCategory.FBlw) {\n\t\t\t\tinfo.mask |= UseFeatureMask.blws;\n\t\t\t} else if (\n\t\t\t\tcat === UseCategory.FPst ||\n\t\t\t\tcat === UseCategory.F ||\n\t\t\t\tcat === UseCategory.FM\n\t\t\t) {\n\t\t\t\tinfo.mask |= UseFeatureMask.psts;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Reorder USE syllables (pre-base vowels, reph)\n */\nexport function reorderUSE(infos: GlyphInfo[]): void {\n\tconst syllables = findUseSyllables(infos);\n\n\tfor (const syllable of syllables) {\n\t\treorderUseSyllable(infos, syllable);\n\t}\n}\n\n/**\n * Reorder a single USE syllable\n */\nfunction reorderUseSyllable(infos: GlyphInfo[], syllable: UseSyllable): void {\n\tconst { start, end, base, hasReph } = syllable;\n\n\t// Collect pre-base vowels that need to move\n\tconst preBaseVowels: { index: number; info: GlyphInfo }[] = [];\n\n\tfor (let i = base + 1; i < end; i++) {\n\t\tconst info = infos[i];\n\t\tif (!info) continue;\n\n\t\tconst cat = getUseCategory(info.codepoint);\n\t\tif (cat === UseCategory.VPre || cat === UseCategory.MPre) {\n\t\t\tpreBaseVowels.push({ index: i, info });\n\t\t}\n\t}\n\n\t// Move pre-base vowels before the base\n\tif (preBaseVowels.length > 0) {\n\t\tpreBaseVowels.sort((a, b) => b.index - a.index);\n\n\t\tfor (const { index, info } of preBaseVowels) {\n\t\t\tinfos.splice(index, 1);\n\t\t\tconst insertPos = hasReph ? start + 2 : start;\n\t\t\tinfos.splice(insertPos, 0, info);\n\t\t}\n\t}\n\n\t// Move reph to end (if present)\n\tif (hasReph && end > start + 2) {\n\t\tconst rephStart = infos[start];\n\t\tconst rephH = infos[start + 1];\n\n\t\tif (rephStart && rephH) {\n\t\t\t// Find target position: after matras, before finals\n\t\t\tlet rephTarget = end - 1;\n\n\t\t\twhile (rephTarget > base) {\n\t\t\t\tconst targetInfo = infos[rephTarget];\n\t\t\t\tif (!targetInfo) break;\n\n\t\t\t\tconst cat = getUseCategory(targetInfo.codepoint);\n\t\t\t\tif (\n\t\t\t\t\tcat === UseCategory.SMAbv ||\n\t\t\t\t\tcat === UseCategory.SMBlw ||\n\t\t\t\t\tcat === UseCategory.FAbv ||\n\t\t\t\t\tcat === UseCategory.FBlw ||\n\t\t\t\t\tcat === UseCategory.FPst ||\n\t\t\t\t\tcat === UseCategory.F ||\n\t\t\t\t\tcat === UseCategory.FM\n\t\t\t\t) {\n\t\t\t\t\trephTarget--;\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (rephTarget > start + 1) {\n\t\t\t\tinfos.splice(start, 2);\n\t\t\t\tconst adjustedTarget = rephTarget - 2;\n\t\t\t\tinfos.splice(adjustedTarget + 1, 0, rephStart, rephH);\n\t\t\t}\n\t\t}\n\t}\n}\n",
74
+ "import {\n\tprocessContextual,\n\tprocessInsertion,\n\tprocessLigature,\n\tprocessRearrangement,\n} from \"../aat/state-machine.ts\";\nimport { GlyphBuffer } from \"../buffer/glyph-buffer.ts\";\nimport type { UnicodeBuffer } from \"../buffer/unicode-buffer.ts\";\nimport { Face } from \"../font/face.ts\";\nimport type { Font } from \"../font/font.ts\";\nimport { getGlyphClass } from \"../font/tables/gdef.ts\";\nimport {\n\ttype AnyGposLookup,\n\ttype CursivePosLookup,\n\tGposLookupType,\n\tgetKerning,\n\ttype MarkBasePosLookup,\n\ttype MarkLigaturePosLookup,\n\ttype MarkMarkPosLookup,\n\ttype PairPosLookup,\n\ttype SinglePosLookup,\n} from \"../font/tables/gpos.ts\";\nimport type {\n\tChainingContextPosFormat1,\n\tChainingContextPosFormat2,\n\tChainingContextPosFormat3,\n\tChainingContextPosLookup,\n\tContextPosFormat1,\n\tContextPosFormat2,\n\tContextPosFormat3,\n\tContextPosLookup,\n\tPosLookupRecord,\n} from \"../font/tables/gpos-contextual.ts\";\nimport {\n\ttype AlternateSubstLookup,\n\ttype AnyGsubLookup,\n\tapplyLigatureSubst,\n\tapplySingleSubst,\n\ttype ChainingContextSubstLookup,\n\ttype ContextSubstLookup,\n\tGsubLookupType,\n\ttype LigatureSubstLookup,\n\ttype MultipleSubstLookup,\n\ttype ReverseChainingSingleSubstLookup,\n\ttype SingleSubstLookup,\n} from \"../font/tables/gsub.ts\";\nimport type {\n\tChainingContextFormat1,\n\tChainingContextFormat2,\n\tChainingContextFormat3,\n\tContextSubstFormat1,\n\tContextSubstFormat2,\n\tContextSubstFormat3,\n\tSequenceLookupRecord,\n} from \"../font/tables/gsub-contextual.ts\";\nimport {\n\tapplyNonContextual,\n\ttype MorxContextualSubtable,\n\ttype MorxInsertionSubtable,\n\ttype MorxLigatureSubtable,\n\ttype MorxNonContextualSubtable,\n\ttype MorxRearrangementSubtable,\n\tMorxSubtableType,\n} from \"../font/tables/morx.ts\";\nimport type { ClassDef } from \"../layout/structures/class-def.ts\";\nimport {\n\tgetMarkAttachmentType,\n\tLookupFlag,\n} from \"../layout/structures/layout-common.ts\";\nimport type { GlyphId, GlyphInfo, GlyphPosition } from \"../types.ts\";\nimport { GlyphClass } from \"../types.ts\";\nimport { setupArabicMasks } from \"./complex/arabic.ts\";\nimport {\n\tisKorean,\n\tnormalizeHangul,\n\tsetupHangulMasks,\n} from \"./complex/hangul.ts\";\nimport { setupHebrewMasks } from \"./complex/hebrew.ts\";\nimport { isIndic, reorderIndic, setupIndicMasks } from \"./complex/indic.ts\";\nimport { isKhmer, reorderKhmer, setupKhmerMasks } from \"./complex/khmer.ts\";\nimport {\n\tisMyanmar,\n\treorderMyanmar,\n\tsetupMyanmarMasks,\n} from \"./complex/myanmar.ts\";\nimport {\n\tisLao,\n\tisThai,\n\treorderThaiLao,\n\tsetupThaiLaoMasks,\n} from \"./complex/thai-lao.ts\";\nimport { reorderUSE, setupUseMasks, usesUSE } from \"./complex/use.ts\";\nimport {\n\tapplyFallbackKerning,\n\tapplyFallbackMarkPositioning,\n} from \"./fallback.ts\";\nimport {\n\tcreateShapePlan,\n\ttype ShapeFeature,\n\ttype ShapePlan,\n} from \"./shape-plan.ts\";\n\nexport interface ShapeOptions {\n\tscript?: string;\n\tlanguage?: string | null;\n\tdirection?: \"ltr\" | \"rtl\";\n\tfeatures?: ShapeFeature[];\n}\n\n/** Font or Face - accepted by shape function */\nexport type FontLike = Font | Face;\n\n/** Get the underlying Font from a FontLike */\nfunction getFont(fontLike: FontLike): Font {\n\treturn fontLike instanceof Face ? fontLike.font : fontLike;\n}\n\n/** Get Face (create if needed) */\nfunction getFace(fontLike: FontLike): Face {\n\treturn fontLike instanceof Face ? fontLike : new Face(fontLike);\n}\n\n/**\n * Shape text using OpenType features.\n * Accepts Font or Face (for variable fonts).\n */\nexport function shape(\n\tfontLike: FontLike,\n\tbuffer: UnicodeBuffer,\n\toptions: ShapeOptions = {},\n): GlyphBuffer {\n\tconst font = getFont(fontLike);\n\tconst face = getFace(fontLike);\n\n\tconst script = options.script ?? buffer.script ?? \"latn\";\n\tconst language = options.language ?? buffer.language ?? null;\n\tconst direction = options.direction ?? \"ltr\";\n\tconst features = options.features ?? [];\n\n\t// Get axis coordinates from face for feature variations\n\tconst axisCoords = face.normalizedCoords.length > 0 ? face.normalizedCoords : null;\n\tconst plan = createShapePlan(font, script, language, direction, features, axisCoords);\n\n\tconst glyphBuffer = new GlyphBuffer();\n\tglyphBuffer.direction = buffer.direction;\n\tglyphBuffer.script = script;\n\tglyphBuffer.language = language;\n\n\t// Convert codepoints to initial glyph infos\n\tconst infos: GlyphInfo[] = [];\n\tfor (const [i, codepoint] of buffer.codepoints.entries()) {\n\t\tconst cluster = buffer.clusters[i];\n\t\tif (cluster === undefined) continue;\n\t\tconst glyphId = font.glyphId(codepoint);\n\n\t\tinfos.push({\n\t\t\tglyphId,\n\t\t\tcluster,\n\t\t\tmask: 0xffffffff,\n\t\t\tcodepoint,\n\t\t});\n\t}\n\n\tglyphBuffer.initFromInfos(infos);\n\n\t// Pre-shaping: Apply complex script analysis\n\tpreShape(glyphBuffer, script);\n\n\t// Apply GSUB\n\tapplyGsub(font, glyphBuffer, plan);\n\n\t// Initialize positions (using Face for variable font metrics)\n\tinitializePositions(face, glyphBuffer);\n\n\t// Apply GPOS or fallback positioning\n\tconst hasGpos = font.gpos !== null && plan.gposLookups.length > 0;\n\tif (hasGpos) {\n\t\tapplyGpos(font, glyphBuffer, plan);\n\t} else {\n\t\t// Fallback kerning using kern table\n\t\tapplyFallbackKerning(font, glyphBuffer.infos, glyphBuffer.positions);\n\t\t// Fallback mark positioning using combining classes\n\t\tapplyFallbackMarkPositioning(\n\t\t\tfont,\n\t\t\tglyphBuffer.infos,\n\t\t\tglyphBuffer.positions,\n\t\t);\n\t}\n\n\t// Apply AAT morx substitutions if no GSUB\n\tif (!font.gsub && font.morx) {\n\t\tapplyMorx(font, glyphBuffer);\n\t}\n\n\t// Reverse for RTL\n\tif (direction === \"rtl\") {\n\t\tglyphBuffer.reverse();\n\t}\n\n\treturn glyphBuffer;\n}\n\n// Pre-shaping for complex scripts\n\nfunction preShape(buffer: GlyphBuffer, script: string): void {\n\t// Arabic joining analysis\n\tif (\n\t\tscript === \"arab\" ||\n\t\tscript === \"syrc\" ||\n\t\tscript === \"mand\" ||\n\t\tscript === \"nko \"\n\t) {\n\t\tsetupArabicMasks(buffer.infos);\n\t\treturn;\n\t}\n\n\t// Hebrew (RTL with marks)\n\tif (script === \"hebr\") {\n\t\tsetupHebrewMasks(buffer.infos);\n\t\treturn;\n\t}\n\n\t// Hangul (Korean)\n\tif (script === \"hang\" || script === \"kore\") {\n\t\t// Normalize Jamo sequences into precomposed syllables\n\t\tconst normalized = normalizeHangul(buffer.infos);\n\t\tif (normalized.length !== buffer.infos.length) {\n\t\t\tbuffer.initFromInfos(normalized);\n\t\t}\n\t\tsetupHangulMasks(buffer.infos);\n\t\treturn;\n\t}\n\n\t// Indic scripts (syllable-based)\n\tif (\n\t\tscript === \"deva\" ||\n\t\tscript === \"beng\" ||\n\t\tscript === \"guru\" ||\n\t\tscript === \"gujr\" ||\n\t\tscript === \"orya\" ||\n\t\tscript === \"taml\" ||\n\t\tscript === \"telu\" ||\n\t\tscript === \"knda\" ||\n\t\tscript === \"mlym\"\n\t) {\n\t\tsetupIndicMasks(buffer.infos);\n\t\treorderIndic(buffer.infos);\n\t\treturn;\n\t}\n\n\t// Thai and Lao (leading vowel reordering)\n\tif (script === \"thai\" || script === \"lao \") {\n\t\tsetupThaiLaoMasks(buffer.infos);\n\t\treorderThaiLao(buffer.infos);\n\t\treturn;\n\t}\n\n\t// Khmer (subscript consonants, pre-base vowels)\n\tif (script === \"khmr\") {\n\t\tsetupKhmerMasks(buffer.infos);\n\t\treorderKhmer(buffer.infos);\n\t\treturn;\n\t}\n\n\t// Myanmar (medials, pre-base vowels, stacking)\n\tif (script === \"mymr\") {\n\t\tsetupMyanmarMasks(buffer.infos);\n\t\treorderMyanmar(buffer.infos);\n\t\treturn;\n\t}\n\n\t// Universal Shaping Engine (many other complex scripts)\n\tif (usesUSE(script)) {\n\t\tsetupUseMasks(buffer.infos);\n\t\treorderUSE(buffer.infos);\n\t\treturn;\n\t}\n\n\t// Auto-detect based on content if script is unknown\n\tif (script === \"Zyyy\" || script === \"Zinh\" || script === \"Zzzz\") {\n\t\tdetectAndApplyComplexShaping(buffer.infos);\n\t}\n}\n\n// Auto-detect complex script from content\nfunction detectAndApplyComplexShaping(infos: GlyphInfo[]): void {\n\tif (infos.length === 0) return;\n\n\t// Sample first few codepoints to detect script\n\tconst sample = infos.slice(0, Math.min(10, infos.length));\n\n\tfor (const info of sample) {\n\t\tconst cp = info.codepoint;\n\n\t\t// Arabic range\n\t\tif (\n\t\t\t(cp >= 0x0600 && cp <= 0x06ff) ||\n\t\t\t(cp >= 0x0750 && cp <= 0x077f) ||\n\t\t\t(cp >= 0x08a0 && cp <= 0x08ff)\n\t\t) {\n\t\t\tsetupArabicMasks(infos);\n\t\t\treturn;\n\t\t}\n\n\t\t// Hebrew range\n\t\tif (cp >= 0x0590 && cp <= 0x05ff) {\n\t\t\tsetupHebrewMasks(infos);\n\t\t\treturn;\n\t\t}\n\n\t\t// Korean/Hangul\n\t\tif (isKorean(cp)) {\n\t\t\tconst normalized = normalizeHangul(infos);\n\t\t\tif (normalized.length !== infos.length) {\n\t\t\t\t// Replace infos in place\n\t\t\t\tinfos.length = 0;\n\t\t\t\tinfos.push(...normalized);\n\t\t\t}\n\t\t\tsetupHangulMasks(infos);\n\t\t\treturn;\n\t\t}\n\n\t\t// Devanagari and other Indic\n\t\tif (isIndic(cp)) {\n\t\t\tsetupIndicMasks(infos);\n\t\t\treorderIndic(infos);\n\t\t\treturn;\n\t\t}\n\n\t\t// Thai\n\t\tif (isThai(cp)) {\n\t\t\tsetupThaiLaoMasks(infos);\n\t\t\treorderThaiLao(infos);\n\t\t\treturn;\n\t\t}\n\n\t\t// Lao\n\t\tif (isLao(cp)) {\n\t\t\tsetupThaiLaoMasks(infos);\n\t\t\treorderThaiLao(infos);\n\t\t\treturn;\n\t\t}\n\n\t\t// Khmer\n\t\tif (isKhmer(cp)) {\n\t\t\tsetupKhmerMasks(infos);\n\t\t\treorderKhmer(infos);\n\t\t\treturn;\n\t\t}\n\n\t\t// Myanmar\n\t\tif (isMyanmar(cp)) {\n\t\t\tsetupMyanmarMasks(infos);\n\t\t\treorderMyanmar(infos);\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n// GSUB application\n\nfunction applyGsub(font: Font, buffer: GlyphBuffer, plan: ShapePlan): void {\n\tfor (const { lookup } of plan.gsubLookups) {\n\t\tapplyGsubLookup(font, buffer, lookup, plan);\n\t}\n}\n\nfunction applyGsubLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: AnyGsubLookup,\n\tplan: ShapePlan,\n): void {\n\tswitch (lookup.type) {\n\t\tcase GsubLookupType.Single:\n\t\t\tapplySingleSubstLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t\tcase GsubLookupType.Multiple:\n\t\t\tapplyMultipleSubstLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t\tcase GsubLookupType.Alternate:\n\t\t\t// Alternate requires user selection - use first alternate as default\n\t\t\tapplyAlternateSubstLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t\tcase GsubLookupType.Ligature:\n\t\t\tapplyLigatureSubstLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t\tcase GsubLookupType.Context:\n\t\t\tapplyContextSubstLookup(font, buffer, lookup, plan);\n\t\t\tbreak;\n\t\tcase GsubLookupType.ChainingContext:\n\t\t\tapplyChainingContextSubstLookup(font, buffer, lookup, plan);\n\t\t\tbreak;\n\t\t// Note: Extension lookups (Type 7) are unwrapped during parsing\n\t\t// and converted to their actual lookup types, so no case needed here\n\t\tcase GsubLookupType.ReverseChainingSingle:\n\t\t\tapplyReverseChainingSingleSubstLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t}\n}\n\nfunction applySingleSubstLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: SingleSubstLookup,\n): void {\n\tfor (const info of buffer.infos) {\n\t\tif (shouldSkipGlyph(font, info.glyphId, lookup.flag)) continue;\n\n\t\tconst replacement = applySingleSubst(lookup, info.glyphId);\n\t\tif (replacement !== null) {\n\t\t\tinfo.glyphId = replacement;\n\t\t}\n\t}\n}\n\nfunction applyMultipleSubstLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: MultipleSubstLookup,\n): void {\n\tlet i = 0;\n\twhile (i < buffer.infos.length) {\n\t\tconst info = buffer.infos[i];\n\t\tif (!info) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (shouldSkipGlyph(font, info.glyphId, lookup.flag)) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tlet applied = false;\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tconst coverageIndex = subtable.coverage.get(info.glyphId);\n\t\t\tif (coverageIndex === null) continue;\n\n\t\t\tconst sequence = subtable.sequences[coverageIndex];\n\t\t\tif (!sequence || sequence.length === 0) continue;\n\n\t\t\tconst [firstGlyph, ...restGlyphs] = sequence;\n\t\t\tif (firstGlyph === undefined) continue;\n\n\t\t\t// Replace with sequence\n\t\t\tinfo.glyphId = firstGlyph;\n\n\t\t\t// Insert remaining glyphs\n\t\t\tfor (const [j, glyphId] of restGlyphs.entries()) {\n\t\t\t\tconst newInfo: GlyphInfo = {\n\t\t\t\t\tglyphId,\n\t\t\t\t\tcluster: info.cluster,\n\t\t\t\t\tmask: info.mask,\n\t\t\t\t\tcodepoint: info.codepoint,\n\t\t\t\t};\n\t\t\t\tconst newPos: GlyphPosition = {\n\t\t\t\t\txAdvance: 0,\n\t\t\t\t\tyAdvance: 0,\n\t\t\t\t\txOffset: 0,\n\t\t\t\t\tyOffset: 0,\n\t\t\t\t};\n\t\t\t\tbuffer.insertGlyph(i + j + 1, newInfo, newPos);\n\t\t\t}\n\n\t\t\ti += sequence.length;\n\t\t\tapplied = true;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (!applied) i++;\n\t}\n}\n\nfunction applyAlternateSubstLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: AlternateSubstLookup,\n): void {\n\t// Alternate substitution allows selecting from multiple alternates\n\t// By default, use the first alternate (index 0)\n\tfor (const info of buffer.infos) {\n\t\tif (shouldSkipGlyph(font, info.glyphId, lookup.flag)) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tconst coverageIndex = subtable.coverage.get(info.glyphId);\n\t\t\tif (coverageIndex === null) continue;\n\n\t\t\tconst alternateSet = subtable.alternateSets[coverageIndex];\n\t\t\tif (!alternateSet || alternateSet.length === 0) continue;\n\n\t\t\tconst [firstAlternate] = alternateSet;\n\t\t\tif (firstAlternate === undefined) continue;\n\n\t\t\t// Use first alternate by default\n\t\t\tinfo.glyphId = firstAlternate;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction applyLigatureSubstLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: LigatureSubstLookup,\n): void {\n\tlet i = 0;\n\twhile (i < buffer.infos.length) {\n\t\tconst info = buffer.infos[i];\n\t\tif (!info) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (shouldSkipGlyph(font, info.glyphId, lookup.flag)) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Collect matchable glyphs (skipping ignored ones)\n\t\tconst matchIndices: number[] = [i];\n\t\tconst matchGlyphs: GlyphId[] = [info.glyphId];\n\n\t\tfor (\n\t\t\tlet j = i + 1;\n\t\t\tj < buffer.infos.length && matchGlyphs.length < 16;\n\t\t\tj++\n\t\t) {\n\t\t\tconst nextInfo = buffer.infos[j];\n\t\t\tif (!nextInfo) continue;\n\t\t\tif (shouldSkipGlyph(font, nextInfo.glyphId, lookup.flag)) continue;\n\t\t\tmatchIndices.push(j);\n\t\t\tmatchGlyphs.push(nextInfo.glyphId);\n\t\t}\n\n\t\tconst result = applyLigatureSubst(lookup, matchGlyphs, 0);\n\t\tif (result) {\n\t\t\t// Replace first glyph with ligature\n\t\t\tinfo.glyphId = result.ligatureGlyph;\n\n\t\t\t// Merge clusters and remove consumed glyphs\n\t\t\tconst indicesToRemove: number[] = [];\n\t\t\tfor (let k = 1; k < result.consumed; k++) {\n\t\t\t\tconst idx = matchIndices[k];\n\t\t\t\tif (idx !== undefined) {\n\t\t\t\t\tconst targetInfo = buffer.infos[idx];\n\t\t\t\t\tif (targetInfo) {\n\t\t\t\t\t\tinfo.cluster = Math.min(info.cluster, targetInfo.cluster);\n\t\t\t\t\t}\n\t\t\t\t\tindicesToRemove.push(idx);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove in reverse order to maintain indices\n\t\t\tfor (const idx of indicesToRemove.reverse()) {\n\t\t\t\tbuffer.removeRange(idx, idx + 1);\n\t\t\t}\n\t\t}\n\n\t\ti++;\n\t}\n}\n\nfunction applyContextSubstLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: ContextSubstLookup,\n\tplan: ShapePlan,\n): void {\n\t// Context substitution - matches input sequence and applies nested lookups\n\tfor (let i = 0; i < buffer.infos.length; i++) {\n\t\tconst info = buffer.infos[i];\n\t\tif (!info) continue;\n\t\tif (shouldSkipGlyph(font, info.glyphId, lookup.flag)) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tlet matched = false;\n\t\t\tlet lookupRecords: SequenceLookupRecord[] = [];\n\n\t\t\tif (subtable.format === 1) {\n\t\t\t\tconst result = matchContextFormat1(\n\t\t\t\t\tfont,\n\t\t\t\t\tbuffer,\n\t\t\t\t\ti,\n\t\t\t\t\tsubtable,\n\t\t\t\t\tlookup.flag,\n\t\t\t\t);\n\t\t\t\tif (result) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = result;\n\t\t\t\t}\n\t\t\t} else if (subtable.format === 2) {\n\t\t\t\tconst result = matchContextFormat2(\n\t\t\t\t\tfont,\n\t\t\t\t\tbuffer,\n\t\t\t\t\ti,\n\t\t\t\t\tsubtable,\n\t\t\t\t\tlookup.flag,\n\t\t\t\t);\n\t\t\t\tif (result) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = result;\n\t\t\t\t}\n\t\t\t} else if (subtable.format === 3) {\n\t\t\t\tif (matchContextFormat3(font, buffer, i, subtable, lookup.flag)) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = subtable.lookupRecords;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matched) {\n\t\t\t\tapplyNestedLookups(font, buffer, i, lookupRecords, plan);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction applyChainingContextSubstLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: ChainingContextSubstLookup,\n\tplan: ShapePlan,\n): void {\n\tfor (let i = 0; i < buffer.infos.length; i++) {\n\t\tconst info = buffer.infos[i];\n\t\tif (!info) continue;\n\t\tif (shouldSkipGlyph(font, info.glyphId, lookup.flag)) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tlet matched = false;\n\t\t\tlet lookupRecords: SequenceLookupRecord[] = [];\n\n\t\t\tif (subtable.format === 1) {\n\t\t\t\tconst result = matchChainingFormat1(\n\t\t\t\t\tfont,\n\t\t\t\t\tbuffer,\n\t\t\t\t\ti,\n\t\t\t\t\tsubtable,\n\t\t\t\t\tlookup.flag,\n\t\t\t\t);\n\t\t\t\tif (result) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = result;\n\t\t\t\t}\n\t\t\t} else if (subtable.format === 2) {\n\t\t\t\tconst result = matchChainingFormat2(\n\t\t\t\t\tfont,\n\t\t\t\t\tbuffer,\n\t\t\t\t\ti,\n\t\t\t\t\tsubtable,\n\t\t\t\t\tlookup.flag,\n\t\t\t\t);\n\t\t\t\tif (result) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = result;\n\t\t\t\t}\n\t\t\t} else if (subtable.format === 3) {\n\t\t\t\tif (matchChainingFormat3(font, buffer, i, subtable, lookup.flag)) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = subtable.lookupRecords;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matched) {\n\t\t\t\tapplyNestedLookups(font, buffer, i, lookupRecords, plan);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction applyReverseChainingSingleSubstLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: ReverseChainingSingleSubstLookup,\n): void {\n\t// Process in reverse order\n\tfor (let i = buffer.infos.length - 1; i >= 0; i--) {\n\t\tconst info = buffer.infos[i];\n\t\tif (!info) continue;\n\t\tif (shouldSkipGlyph(font, info.glyphId, lookup.flag)) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tconst coverageIndex = subtable.coverage.get(info.glyphId);\n\t\t\tif (coverageIndex === null) continue;\n\n\t\t\t// Check backtrack (glyphs after current in reverse order)\n\t\t\tlet backtrackMatch = true;\n\t\t\tlet backtrackPos = i + 1;\n\t\t\tfor (const backCov of subtable.backtrackCoverages) {\n\t\t\t\twhile (\n\t\t\t\t\tbacktrackPos < buffer.infos.length &&\n\t\t\t\t\tshouldSkipGlyph(\n\t\t\t\t\t\tfont,\n\t\t\t\t\t\tbuffer.infos[backtrackPos]?.glyphId,\n\t\t\t\t\t\tlookup.flag,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tbacktrackPos++;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tbacktrackPos >= buffer.infos.length ||\n\t\t\t\t\tbackCov.get(buffer.infos[backtrackPos]?.glyphId) === null\n\t\t\t\t) {\n\t\t\t\t\tbacktrackMatch = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbacktrackPos++;\n\t\t\t}\n\t\t\tif (!backtrackMatch) continue;\n\n\t\t\t// Check lookahead (glyphs before current)\n\t\t\tlet lookaheadMatch = true;\n\t\t\tlet lookaheadPos = i - 1;\n\t\t\tfor (const lookCov of subtable.lookaheadCoverages) {\n\t\t\t\twhile (\n\t\t\t\t\tlookaheadPos >= 0 &&\n\t\t\t\t\tshouldSkipGlyph(\n\t\t\t\t\t\tfont,\n\t\t\t\t\t\tbuffer.infos[lookaheadPos]?.glyphId,\n\t\t\t\t\t\tlookup.flag,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tlookaheadPos--;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tlookaheadPos < 0 ||\n\t\t\t\t\tlookCov.get(buffer.infos[lookaheadPos]?.glyphId) === null\n\t\t\t\t) {\n\t\t\t\t\tlookaheadMatch = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlookaheadPos--;\n\t\t\t}\n\t\t\tif (!lookaheadMatch) continue;\n\n\t\t\t// Apply substitution\n\t\t\tconst substitute = subtable.substituteGlyphIds[coverageIndex];\n\t\t\tif (substitute !== undefined) {\n\t\t\t\tinfo.glyphId = substitute;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n// Note: Extension lookups (Type 7) are unwrapped during parsing,\n// so no applyExtensionGsubLookup function is needed at runtime.\n\n/** Match Context Format 1 - glyph-based rules */\nfunction matchContextFormat1(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ContextSubstFormat1,\n\tlookupFlag: number,\n): SequenceLookupRecord[] | null {\n\tconst firstGlyph = buffer.infos[startIndex]?.glyphId;\n\tconst coverageIndex = subtable.coverage.get(firstGlyph);\n\tif (coverageIndex === null) return null;\n\n\tconst ruleSet = subtable.ruleSets[coverageIndex];\n\tif (!ruleSet) return null;\n\n\tfor (const rule of ruleSet) {\n\t\tif (\n\t\t\tmatchGlyphSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex + 1,\n\t\t\t\trule.inputSequence,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\treturn rule.lookupRecords;\n\t\t}\n\t}\n\treturn null;\n}\n\n/** Match Context Format 2 - class-based rules */\nfunction matchContextFormat2(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ContextSubstFormat2,\n\tlookupFlag: number,\n): SequenceLookupRecord[] | null {\n\tconst firstGlyph = buffer.infos[startIndex]?.glyphId;\n\tconst coverageIndex = subtable.coverage.get(firstGlyph);\n\tif (coverageIndex === null) return null;\n\n\tconst firstClass = subtable.classDef.get(firstGlyph);\n\tconst classRuleSet = subtable.classRuleSets[firstClass];\n\tif (!classRuleSet) return null;\n\n\tfor (const rule of classRuleSet) {\n\t\tif (\n\t\t\tmatchClassSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex + 1,\n\t\t\t\trule.inputClasses,\n\t\t\t\tsubtable.classDef,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\treturn rule.lookupRecords;\n\t\t}\n\t}\n\treturn null;\n}\n\n/** Match Context Format 3 - coverage-based */\nfunction matchContextFormat3(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ContextSubstFormat3,\n\tlookupFlag: number,\n): boolean {\n\tlet pos = startIndex;\n\tfor (const coverage of subtable.coverages) {\n\t\twhile (\n\t\t\tpos < buffer.infos.length &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[pos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tpos++;\n\t\t}\n\t\tif (pos >= buffer.infos.length) return false;\n\t\tif (coverage.get(buffer.infos[pos]?.glyphId) === null) return false;\n\t\tpos++;\n\t}\n\treturn true;\n}\n\n/** Match Chaining Context Format 1 - glyph-based rules */\nfunction matchChainingFormat1(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ChainingContextFormat1,\n\tlookupFlag: number,\n): SequenceLookupRecord[] | null {\n\tconst firstGlyph = buffer.infos[startIndex]?.glyphId;\n\tconst coverageIndex = subtable.coverage.get(firstGlyph);\n\tif (coverageIndex === null) return null;\n\n\tconst chainRuleSet = subtable.chainRuleSets[coverageIndex];\n\tif (!chainRuleSet) return null;\n\n\tfor (const rule of chainRuleSet) {\n\t\t// Check backtrack (reversed order, before startIndex)\n\t\tif (\n\t\t\t!matchGlyphSequenceBackward(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex - 1,\n\t\t\t\trule.backtrackSequence,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check input (excluding first glyph which is in coverage)\n\t\tif (\n\t\t\t!matchGlyphSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex + 1,\n\t\t\t\trule.inputSequence,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Find where input sequence ends\n\t\tlet inputEnd = startIndex + 1;\n\t\tfor (let i = 0; i < rule.inputSequence.length; i++) {\n\t\t\twhile (\n\t\t\t\tinputEnd < buffer.infos.length &&\n\t\t\t\tshouldSkipGlyph(font, buffer.infos[inputEnd]?.glyphId, lookupFlag)\n\t\t\t) {\n\t\t\t\tinputEnd++;\n\t\t\t}\n\t\t\tinputEnd++;\n\t\t}\n\n\t\t// Check lookahead\n\t\tif (\n\t\t\t!matchGlyphSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tinputEnd,\n\t\t\t\trule.lookaheadSequence,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn rule.lookupRecords;\n\t}\n\treturn null;\n}\n\n/** Match Chaining Context Format 2 - class-based rules */\nfunction matchChainingFormat2(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ChainingContextFormat2,\n\tlookupFlag: number,\n): SequenceLookupRecord[] | null {\n\tconst firstGlyph = buffer.infos[startIndex]?.glyphId;\n\tconst coverageIndex = subtable.coverage.get(firstGlyph);\n\tif (coverageIndex === null) return null;\n\n\tconst firstClass = subtable.inputClassDef.get(firstGlyph);\n\tconst chainClassRuleSet = subtable.chainClassRuleSets[firstClass];\n\tif (!chainClassRuleSet) return null;\n\n\tfor (const rule of chainClassRuleSet) {\n\t\t// Check backtrack classes (reversed order)\n\t\tif (\n\t\t\t!matchClassSequenceBackward(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex - 1,\n\t\t\t\trule.backtrackClasses,\n\t\t\t\tsubtable.backtrackClassDef,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check input classes (excluding first)\n\t\tif (\n\t\t\t!matchClassSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex + 1,\n\t\t\t\trule.inputClasses,\n\t\t\t\tsubtable.inputClassDef,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Find where input ends\n\t\tlet inputEnd = startIndex + 1;\n\t\tfor (let i = 0; i < rule.inputClasses.length; i++) {\n\t\t\twhile (\n\t\t\t\tinputEnd < buffer.infos.length &&\n\t\t\t\tshouldSkipGlyph(font, buffer.infos[inputEnd]?.glyphId, lookupFlag)\n\t\t\t) {\n\t\t\t\tinputEnd++;\n\t\t\t}\n\t\t\tinputEnd++;\n\t\t}\n\n\t\t// Check lookahead classes\n\t\tif (\n\t\t\t!matchClassSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tinputEnd,\n\t\t\t\trule.lookaheadClasses,\n\t\t\t\tsubtable.lookaheadClassDef,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn rule.lookupRecords;\n\t}\n\treturn null;\n}\n\n/** Match Chaining Context Format 3 - coverage-based */\nfunction matchChainingFormat3(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ChainingContextFormat3,\n\tlookupFlag: number,\n): boolean {\n\t// Check backtrack (in reverse order, before startIndex)\n\tlet backtrackPos = startIndex - 1;\n\tfor (const coverage of subtable.backtrackCoverages) {\n\t\twhile (\n\t\t\tbacktrackPos >= 0 &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[backtrackPos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tbacktrackPos--;\n\t\t}\n\t\tif (backtrackPos < 0) return false;\n\t\tif (coverage.get(buffer.infos[backtrackPos]?.glyphId) === null)\n\t\t\treturn false;\n\t\tbacktrackPos--;\n\t}\n\n\t// Check input sequence\n\tlet inputPos = startIndex;\n\tfor (const coverage of subtable.inputCoverages) {\n\t\twhile (\n\t\t\tinputPos < buffer.infos.length &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[inputPos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tinputPos++;\n\t\t}\n\t\tif (inputPos >= buffer.infos.length) return false;\n\t\tif (coverage.get(buffer.infos[inputPos]?.glyphId) === null) return false;\n\t\tinputPos++;\n\t}\n\n\t// Check lookahead\n\tlet lookaheadPos = inputPos;\n\tfor (const coverage of subtable.lookaheadCoverages) {\n\t\twhile (\n\t\t\tlookaheadPos < buffer.infos.length &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[lookaheadPos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tlookaheadPos++;\n\t\t}\n\t\tif (lookaheadPos >= buffer.infos.length) return false;\n\t\tif (coverage.get(buffer.infos[lookaheadPos]?.glyphId) === null)\n\t\t\treturn false;\n\t\tlookaheadPos++;\n\t}\n\n\treturn true;\n}\n\nfunction applyNestedLookups(\n\t_font: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tlookupRecords: Array<{ sequenceIndex: number; lookupListIndex: number }>,\n\tplan: ShapePlan,\n): void {\n\t// Sort by sequence index descending to apply from end to start\n\tconst sorted = [...lookupRecords].sort(\n\t\t(a, b) => b.sequenceIndex - a.sequenceIndex,\n\t);\n\n\tfor (const record of sorted) {\n\t\tconst lookupEntry = plan.gsubLookups.find(\n\t\t\t(l) => l.index === record.lookupListIndex,\n\t\t);\n\t\tif (!lookupEntry) continue;\n\n\t\t// Apply at the specific position\n\t\tconst pos = startIndex + record.sequenceIndex;\n\t\tif (pos >= buffer.infos.length) continue;\n\n\t\tconst targetInfo = buffer.infos[pos];\n\t\tif (!targetInfo) continue;\n\n\t\t// For single subst, apply directly\n\t\tif (lookupEntry.lookup.type === GsubLookupType.Single) {\n\t\t\tconst replacement = applySingleSubst(\n\t\t\t\tlookupEntry.lookup as SingleSubstLookup,\n\t\t\t\ttargetInfo.glyphId,\n\t\t\t);\n\t\t\tif (replacement !== null) {\n\t\t\t\ttargetInfo.glyphId = replacement;\n\t\t\t}\n\t\t}\n\t}\n}\n\n// GPOS application\n\nfunction initializePositions(face: Face, buffer: GlyphBuffer): void {\n\tfor (const [i, info] of buffer.infos.entries()) {\n\t\t// Use Face.advanceWidth to include variable font deltas\n\t\tconst advance = face.advanceWidth(info.glyphId);\n\t\tbuffer.setAdvance(i, advance, 0);\n\t}\n}\n\nfunction applyGpos(font: Font, buffer: GlyphBuffer, plan: ShapePlan): void {\n\tfor (const { lookup } of plan.gposLookups) {\n\t\tapplyGposLookup(font, buffer, lookup, plan);\n\t}\n}\n\nfunction applyGposLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: AnyGposLookup,\n\tplan: ShapePlan,\n): void {\n\tswitch (lookup.type) {\n\t\tcase GposLookupType.Single:\n\t\t\tapplySinglePosLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t\tcase GposLookupType.Pair:\n\t\t\tapplyPairPosLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t\tcase GposLookupType.Cursive:\n\t\t\tapplyCursivePosLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t\tcase GposLookupType.MarkToBase:\n\t\t\tapplyMarkBasePosLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t\tcase GposLookupType.MarkToLigature:\n\t\t\tapplyMarkLigaturePosLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t\tcase GposLookupType.MarkToMark:\n\t\t\tapplyMarkMarkPosLookup(font, buffer, lookup);\n\t\t\tbreak;\n\t\tcase GposLookupType.Context:\n\t\t\tapplyContextPosLookup(font, buffer, lookup as ContextPosLookup, plan);\n\t\t\tbreak;\n\t\tcase GposLookupType.ChainingContext:\n\t\t\tapplyChainingContextPosLookup(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tlookup as ChainingContextPosLookup,\n\t\t\t\tplan,\n\t\t\t);\n\t\t\tbreak;\n\t\t// Extension (type 9) is unwrapped during parsing - no runtime case needed\n\t}\n}\n\nfunction applySinglePosLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: SinglePosLookup,\n): void {\n\tfor (const [i, info] of buffer.infos.entries()) {\n\t\tconst pos = buffer.positions[i];\n\t\tif (!pos) continue;\n\t\tif (shouldSkipGlyph(font, info.glyphId, lookup.flag)) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tconst coverageIndex = subtable.coverage.get(info.glyphId);\n\t\t\tif (coverageIndex === null) continue;\n\n\t\t\tconst value =\n\t\t\t\tsubtable.format === 1\n\t\t\t\t\t? subtable.value\n\t\t\t\t\t: subtable.values?.[coverageIndex];\n\t\t\tif (value) {\n\t\t\t\tif (value.xPlacement) pos.xOffset += value.xPlacement;\n\t\t\t\tif (value.yPlacement) pos.yOffset += value.yPlacement;\n\t\t\t\tif (value.xAdvance) pos.xAdvance += value.xAdvance;\n\t\t\t\tif (value.yAdvance) pos.yAdvance += value.yAdvance;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction applyPairPosLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: PairPosLookup,\n): void {\n\tfor (let i = 0; i < buffer.infos.length - 1; i++) {\n\t\tconst info1 = buffer.infos[i];\n\t\tif (!info1) continue;\n\t\tif (shouldSkipGlyph(font, info1.glyphId, lookup.flag)) continue;\n\n\t\t// Find next non-skipped glyph\n\t\tlet j = i + 1;\n\t\twhile (j < buffer.infos.length) {\n\t\t\tconst nextInfo = buffer.infos[j];\n\t\t\tif (nextInfo && !shouldSkipGlyph(font, nextInfo.glyphId, lookup.flag)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tj++;\n\t\t}\n\t\tif (j >= buffer.infos.length) break;\n\n\t\tconst info2 = buffer.infos[j];\n\t\tif (!info2) continue;\n\n\t\tconst kern = getKerning(lookup, info1.glyphId, info2.glyphId);\n\t\tif (kern) {\n\t\t\tconst pos1 = buffer.positions[i];\n\t\t\tconst pos2 = buffer.positions[j];\n\t\t\tif (pos1) pos1.xAdvance += kern.xAdvance1;\n\t\t\tif (pos2) pos2.xAdvance += kern.xAdvance2;\n\t\t}\n\t}\n}\n\nfunction applyCursivePosLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: CursivePosLookup,\n): void {\n\t// Cursive attachment - connect exit anchor of one glyph to entry anchor of next\n\tfor (let i = 0; i < buffer.infos.length - 1; i++) {\n\t\tconst info1 = buffer.infos[i];\n\t\tif (!info1) continue;\n\t\tif (shouldSkipGlyph(font, info1.glyphId, lookup.flag)) continue;\n\n\t\t// Find next non-skipped glyph\n\t\tlet j = i + 1;\n\t\twhile (j < buffer.infos.length) {\n\t\t\tconst nextInfo = buffer.infos[j];\n\t\t\tif (nextInfo && !shouldSkipGlyph(font, nextInfo.glyphId, lookup.flag)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tj++;\n\t\t}\n\t\tif (j >= buffer.infos.length) break;\n\n\t\tconst info2 = buffer.infos[j];\n\t\tif (!info2) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tconst exitIndex = subtable.coverage.get(info1.glyphId);\n\t\t\tconst entryIndex = subtable.coverage.get(info2.glyphId);\n\n\t\t\tif (exitIndex === null || entryIndex === null) continue;\n\n\t\t\tconst exitRecord = subtable.entryExitRecords[exitIndex];\n\t\t\tconst entryRecord = subtable.entryExitRecords[entryIndex];\n\n\t\t\tif (!exitRecord?.exitAnchor || !entryRecord?.entryAnchor) continue;\n\n\t\t\t// Calculate offset to align anchors\n\t\t\tconst exitAnchor = exitRecord.exitAnchor;\n\t\t\tconst entryAnchor = entryRecord.entryAnchor;\n\n\t\t\t// Adjust position of second glyph\n\t\t\tconst pos2 = buffer.positions[j];\n\t\t\tif (pos2) {\n\t\t\t\tpos2.yOffset = exitAnchor.yCoordinate - entryAnchor.yCoordinate;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction applyMarkBasePosLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: MarkBasePosLookup,\n): void {\n\tfor (let i = 0; i < buffer.infos.length; i++) {\n\t\tconst markInfo = buffer.infos[i];\n\t\tif (!markInfo) continue;\n\n\t\t// Must be a mark glyph\n\t\tif (getGlyphClass(font.gdef, markInfo.glyphId) !== GlyphClass.Mark)\n\t\t\tcontinue;\n\n\t\t// Find preceding base glyph\n\t\tlet baseIndex = -1;\n\t\tfor (let j = i - 1; j >= 0; j--) {\n\t\t\tconst prevInfo = buffer.infos[j];\n\t\t\tif (!prevInfo) continue;\n\t\t\tconst prevClass = getGlyphClass(font.gdef, prevInfo.glyphId);\n\t\t\tif (prevClass === GlyphClass.Base || prevClass === 0) {\n\t\t\t\tbaseIndex = j;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// Skip marks\n\t\t\tif (prevClass === GlyphClass.Mark) continue;\n\t\t\t// Stop at ligature\n\t\t\tif (prevClass === GlyphClass.Ligature) {\n\t\t\t\tbaseIndex = j;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (baseIndex < 0) continue;\n\t\tconst baseInfo = buffer.infos[baseIndex];\n\t\tif (!baseInfo) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tconst markCoverageIndex = subtable.markCoverage.get(markInfo.glyphId);\n\t\t\tconst baseCoverageIndex = subtable.baseCoverage.get(baseInfo.glyphId);\n\n\t\t\tif (markCoverageIndex === null || baseCoverageIndex === null) continue;\n\n\t\t\tconst markRecord = subtable.markArray.markRecords[markCoverageIndex];\n\t\t\tconst baseRecord = subtable.baseArray[baseCoverageIndex];\n\n\t\t\tif (!markRecord || !baseRecord) continue;\n\n\t\t\tconst baseAnchor = baseRecord.baseAnchors[markRecord.markClass];\n\t\t\tif (!baseAnchor) continue;\n\n\t\t\tconst markAnchor = markRecord.markAnchor;\n\n\t\t\t// Position mark relative to base\n\t\t\tconst markPos = buffer.positions[i];\n\t\t\tconst basePos = buffer.positions[baseIndex];\n\t\t\tif (!markPos || !basePos) continue;\n\n\t\t\tmarkPos.xOffset =\n\t\t\t\tbaseAnchor.xCoordinate - markAnchor.xCoordinate + basePos.xOffset;\n\t\t\tmarkPos.yOffset =\n\t\t\t\tbaseAnchor.yCoordinate - markAnchor.yCoordinate + basePos.yOffset;\n\n\t\t\t// Mark doesn't advance cursor\n\t\t\tmarkPos.xAdvance = 0;\n\t\t\tmarkPos.yAdvance = 0;\n\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction applyMarkLigaturePosLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: MarkLigaturePosLookup,\n): void {\n\tfor (let i = 0; i < buffer.infos.length; i++) {\n\t\tconst markInfo = buffer.infos[i];\n\t\tif (!markInfo) continue;\n\n\t\tif (getGlyphClass(font.gdef, markInfo.glyphId) !== GlyphClass.Mark)\n\t\t\tcontinue;\n\n\t\t// Find preceding ligature\n\t\tlet ligIndex = -1;\n\t\tlet componentIndex = 0; // Which component of the ligature\n\n\t\tfor (let j = i - 1; j >= 0; j--) {\n\t\t\tconst prevInfo = buffer.infos[j];\n\t\t\tif (!prevInfo) continue;\n\t\t\tconst prevClass = getGlyphClass(font.gdef, prevInfo.glyphId);\n\t\t\tif (prevClass === GlyphClass.Ligature) {\n\t\t\t\tligIndex = j;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (prevClass === GlyphClass.Mark) {\n\t\t\t\tcomponentIndex++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tif (ligIndex < 0) continue;\n\t\tconst ligInfo = buffer.infos[ligIndex];\n\t\tif (!ligInfo) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tconst markCoverageIndex = subtable.markCoverage.get(markInfo.glyphId);\n\t\t\tconst ligCoverageIndex = subtable.ligatureCoverage.get(ligInfo.glyphId);\n\n\t\t\tif (markCoverageIndex === null || ligCoverageIndex === null) continue;\n\n\t\t\tconst markRecord = subtable.markArray.markRecords[markCoverageIndex];\n\t\t\tconst ligAttach = subtable.ligatureArray[ligCoverageIndex];\n\n\t\t\tif (!markRecord || !ligAttach) continue;\n\n\t\t\t// Clamp component index\n\t\t\tconst compIdx = Math.min(\n\t\t\t\tcomponentIndex,\n\t\t\t\tligAttach.componentRecords.length - 1,\n\t\t\t);\n\t\t\tconst component = ligAttach.componentRecords[compIdx];\n\t\t\tif (!component) continue;\n\n\t\t\tconst ligAnchor = component.ligatureAnchors[markRecord.markClass];\n\t\t\tif (!ligAnchor) continue;\n\n\t\t\tconst markAnchor = markRecord.markAnchor;\n\t\t\tconst markPos = buffer.positions[i];\n\t\t\tconst ligPos = buffer.positions[ligIndex];\n\t\t\tif (!markPos || !ligPos) continue;\n\n\t\t\tmarkPos.xOffset =\n\t\t\t\tligAnchor.xCoordinate - markAnchor.xCoordinate + ligPos.xOffset;\n\t\t\tmarkPos.yOffset =\n\t\t\t\tligAnchor.yCoordinate - markAnchor.yCoordinate + ligPos.yOffset;\n\t\t\tmarkPos.xAdvance = 0;\n\t\t\tmarkPos.yAdvance = 0;\n\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction applyMarkMarkPosLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: MarkMarkPosLookup,\n): void {\n\tfor (let i = 0; i < buffer.infos.length; i++) {\n\t\tconst mark1Info = buffer.infos[i];\n\t\tif (!mark1Info) continue;\n\n\t\tif (getGlyphClass(font.gdef, mark1Info.glyphId) !== GlyphClass.Mark)\n\t\t\tcontinue;\n\n\t\t// Find preceding mark (mark2) - must be immediately preceding\n\t\tlet mark2Index = -1;\n\t\tif (i > 0) {\n\t\t\tconst prevInfo = buffer.infos[i - 1];\n\t\t\tif (prevInfo) {\n\t\t\t\tconst prevClass = getGlyphClass(font.gdef, prevInfo.glyphId);\n\t\t\t\tif (prevClass === GlyphClass.Mark) {\n\t\t\t\t\tmark2Index = i - 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (mark2Index < 0) continue;\n\t\tconst mark2Info = buffer.infos[mark2Index];\n\t\tif (!mark2Info) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tconst mark1CoverageIndex = subtable.mark1Coverage.get(mark1Info.glyphId);\n\t\t\tconst mark2CoverageIndex = subtable.mark2Coverage.get(mark2Info.glyphId);\n\n\t\t\tif (mark1CoverageIndex === null || mark2CoverageIndex === null) continue;\n\n\t\t\tconst mark1Record = subtable.mark1Array.markRecords[mark1CoverageIndex];\n\t\t\tconst mark2Record = subtable.mark2Array[mark2CoverageIndex];\n\n\t\t\tif (!mark1Record || !mark2Record) continue;\n\n\t\t\tconst mark2Anchor = mark2Record.mark2Anchors[mark1Record.markClass];\n\t\t\tif (!mark2Anchor) continue;\n\n\t\t\tconst mark1Anchor = mark1Record.markAnchor;\n\t\t\tconst mark1Pos = buffer.positions[i];\n\t\t\tconst mark2Pos = buffer.positions[mark2Index];\n\t\t\tif (!mark1Pos || !mark2Pos) continue;\n\n\t\t\tmark1Pos.xOffset =\n\t\t\t\tmark2Anchor.xCoordinate - mark1Anchor.xCoordinate + mark2Pos.xOffset;\n\t\t\tmark1Pos.yOffset =\n\t\t\t\tmark2Anchor.yCoordinate - mark1Anchor.yCoordinate + mark2Pos.yOffset;\n\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n// GPOS Context positioning\n\nfunction applyContextPosLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: ContextPosLookup,\n\tplan: ShapePlan,\n): void {\n\tfor (let i = 0; i < buffer.infos.length; i++) {\n\t\tconst info = buffer.infos[i];\n\t\tif (!info) continue;\n\t\tif (shouldSkipGlyph(font, info.glyphId, lookup.flag)) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tlet matched = false;\n\t\t\tlet lookupRecords: PosLookupRecord[] = [];\n\n\t\t\tif (subtable.format === 1) {\n\t\t\t\tconst result = matchContextPosFormat1(\n\t\t\t\t\tfont,\n\t\t\t\t\tbuffer,\n\t\t\t\t\ti,\n\t\t\t\t\tsubtable,\n\t\t\t\t\tlookup.flag,\n\t\t\t\t);\n\t\t\t\tif (result) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = result;\n\t\t\t\t}\n\t\t\t} else if (subtable.format === 2) {\n\t\t\t\tconst result = matchContextPosFormat2(\n\t\t\t\t\tfont,\n\t\t\t\t\tbuffer,\n\t\t\t\t\ti,\n\t\t\t\t\tsubtable,\n\t\t\t\t\tlookup.flag,\n\t\t\t\t);\n\t\t\t\tif (result) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = result;\n\t\t\t\t}\n\t\t\t} else if (subtable.format === 3) {\n\t\t\t\tif (matchContextPosFormat3(font, buffer, i, subtable, lookup.flag)) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = subtable.lookupRecords;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matched) {\n\t\t\t\tapplyNestedPosLookups(font, buffer, i, lookupRecords, plan);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction applyChainingContextPosLookup(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tlookup: ChainingContextPosLookup,\n\tplan: ShapePlan,\n): void {\n\tfor (let i = 0; i < buffer.infos.length; i++) {\n\t\tconst info = buffer.infos[i];\n\t\tif (!info) continue;\n\t\tif (shouldSkipGlyph(font, info.glyphId, lookup.flag)) continue;\n\n\t\tfor (const subtable of lookup.subtables) {\n\t\t\tlet matched = false;\n\t\t\tlet lookupRecords: PosLookupRecord[] = [];\n\n\t\t\tif (subtable.format === 1) {\n\t\t\t\tconst result = matchChainingContextPosFormat1(\n\t\t\t\t\tfont,\n\t\t\t\t\tbuffer,\n\t\t\t\t\ti,\n\t\t\t\t\tsubtable,\n\t\t\t\t\tlookup.flag,\n\t\t\t\t);\n\t\t\t\tif (result) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = result;\n\t\t\t\t}\n\t\t\t} else if (subtable.format === 2) {\n\t\t\t\tconst result = matchChainingContextPosFormat2(\n\t\t\t\t\tfont,\n\t\t\t\t\tbuffer,\n\t\t\t\t\ti,\n\t\t\t\t\tsubtable,\n\t\t\t\t\tlookup.flag,\n\t\t\t\t);\n\t\t\t\tif (result) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = result;\n\t\t\t\t}\n\t\t\t} else if (subtable.format === 3) {\n\t\t\t\tif (\n\t\t\t\t\tmatchChainingContextPosFormat3(font, buffer, i, subtable, lookup.flag)\n\t\t\t\t) {\n\t\t\t\t\tmatched = true;\n\t\t\t\t\tlookupRecords = subtable.lookupRecords;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matched) {\n\t\t\t\tapplyNestedPosLookups(font, buffer, i, lookupRecords, plan);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Match Context Pos Format 1 - glyph-based rules */\nfunction matchContextPosFormat1(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ContextPosFormat1,\n\tlookupFlag: number,\n): PosLookupRecord[] | null {\n\tconst firstGlyph = buffer.infos[startIndex]?.glyphId;\n\tconst coverageIndex = subtable.coverage.get(firstGlyph);\n\tif (coverageIndex === null) return null;\n\n\tconst ruleSet = subtable.ruleSets[coverageIndex];\n\tif (!ruleSet) return null;\n\n\tfor (const rule of ruleSet) {\n\t\tif (\n\t\t\tmatchGlyphSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex + 1,\n\t\t\t\trule.inputSequence,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\treturn rule.lookupRecords;\n\t\t}\n\t}\n\treturn null;\n}\n\n/** Match Context Pos Format 2 - class-based rules */\nfunction matchContextPosFormat2(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ContextPosFormat2,\n\tlookupFlag: number,\n): PosLookupRecord[] | null {\n\tconst firstGlyph = buffer.infos[startIndex]?.glyphId;\n\tconst coverageIndex = subtable.coverage.get(firstGlyph);\n\tif (coverageIndex === null) return null;\n\n\tconst firstClass = subtable.classDef.get(firstGlyph);\n\tconst classRuleSet = subtable.classRuleSets[firstClass];\n\tif (!classRuleSet) return null;\n\n\tfor (const rule of classRuleSet) {\n\t\tif (\n\t\t\tmatchClassSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex + 1,\n\t\t\t\trule.inputClasses,\n\t\t\t\tsubtable.classDef,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\treturn rule.lookupRecords;\n\t\t}\n\t}\n\treturn null;\n}\n\n/** Match Context Pos Format 3 - coverage-based */\nfunction matchContextPosFormat3(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ContextPosFormat3,\n\tlookupFlag: number,\n): boolean {\n\tlet pos = startIndex;\n\tfor (const coverage of subtable.coverages) {\n\t\twhile (\n\t\t\tpos < buffer.infos.length &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[pos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tpos++;\n\t\t}\n\t\tif (pos >= buffer.infos.length) return false;\n\t\tif (coverage.get(buffer.infos[pos]?.glyphId) === null) return false;\n\t\tpos++;\n\t}\n\treturn true;\n}\n\n/** Match Chaining Context Pos Format 1 - glyph-based rules */\nfunction matchChainingContextPosFormat1(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ChainingContextPosFormat1,\n\tlookupFlag: number,\n): PosLookupRecord[] | null {\n\tconst firstGlyph = buffer.infos[startIndex]?.glyphId;\n\tconst coverageIndex = subtable.coverage.get(firstGlyph);\n\tif (coverageIndex === null) return null;\n\n\tconst chainRuleSet = subtable.chainRuleSets[coverageIndex];\n\tif (!chainRuleSet) return null;\n\n\tfor (const rule of chainRuleSet) {\n\t\t// Check backtrack (reversed order, before startIndex)\n\t\tif (\n\t\t\t!matchGlyphSequenceBackward(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex - 1,\n\t\t\t\trule.backtrackSequence,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check input (excluding first glyph which is in coverage)\n\t\tif (\n\t\t\t!matchGlyphSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex + 1,\n\t\t\t\trule.inputSequence,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Find where input sequence ends\n\t\tlet inputEnd = startIndex + 1;\n\t\tfor (let i = 0; i < rule.inputSequence.length; i++) {\n\t\t\twhile (\n\t\t\t\tinputEnd < buffer.infos.length &&\n\t\t\t\tshouldSkipGlyph(font, buffer.infos[inputEnd]?.glyphId, lookupFlag)\n\t\t\t) {\n\t\t\t\tinputEnd++;\n\t\t\t}\n\t\t\tinputEnd++;\n\t\t}\n\n\t\t// Check lookahead\n\t\tif (\n\t\t\t!matchGlyphSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tinputEnd,\n\t\t\t\trule.lookaheadSequence,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn rule.lookupRecords;\n\t}\n\treturn null;\n}\n\n/** Match Chaining Context Pos Format 2 - class-based rules */\nfunction matchChainingContextPosFormat2(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ChainingContextPosFormat2,\n\tlookupFlag: number,\n): PosLookupRecord[] | null {\n\tconst firstGlyph = buffer.infos[startIndex]?.glyphId;\n\tconst coverageIndex = subtable.coverage.get(firstGlyph);\n\tif (coverageIndex === null) return null;\n\n\tconst firstClass = subtable.inputClassDef.get(firstGlyph);\n\tconst chainClassRuleSet = subtable.chainClassRuleSets[firstClass];\n\tif (!chainClassRuleSet) return null;\n\n\tfor (const rule of chainClassRuleSet) {\n\t\t// Check backtrack classes (reversed order)\n\t\tif (\n\t\t\t!matchClassSequenceBackward(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex - 1,\n\t\t\t\trule.backtrackClasses,\n\t\t\t\tsubtable.backtrackClassDef,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check input classes (excluding first)\n\t\tif (\n\t\t\t!matchClassSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tstartIndex + 1,\n\t\t\t\trule.inputClasses,\n\t\t\t\tsubtable.inputClassDef,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Find where input ends\n\t\tlet inputEnd = startIndex + 1;\n\t\tfor (let i = 0; i < rule.inputClasses.length; i++) {\n\t\t\twhile (\n\t\t\t\tinputEnd < buffer.infos.length &&\n\t\t\t\tshouldSkipGlyph(font, buffer.infos[inputEnd]?.glyphId, lookupFlag)\n\t\t\t) {\n\t\t\t\tinputEnd++;\n\t\t\t}\n\t\t\tinputEnd++;\n\t\t}\n\n\t\t// Check lookahead classes\n\t\tif (\n\t\t\t!matchClassSequence(\n\t\t\t\tfont,\n\t\t\t\tbuffer,\n\t\t\t\tinputEnd,\n\t\t\t\trule.lookaheadClasses,\n\t\t\t\tsubtable.lookaheadClassDef,\n\t\t\t\tlookupFlag,\n\t\t\t)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn rule.lookupRecords;\n\t}\n\treturn null;\n}\n\n/** Match Chaining Context Pos Format 3 - coverage-based */\nfunction matchChainingContextPosFormat3(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tsubtable: ChainingContextPosFormat3,\n\tlookupFlag: number,\n): boolean {\n\t// Check backtrack (in reverse order, before startIndex)\n\tlet backtrackPos = startIndex - 1;\n\tfor (const coverage of subtable.backtrackCoverages) {\n\t\twhile (\n\t\t\tbacktrackPos >= 0 &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[backtrackPos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tbacktrackPos--;\n\t\t}\n\t\tif (backtrackPos < 0) return false;\n\t\tif (coverage.get(buffer.infos[backtrackPos]?.glyphId) === null)\n\t\t\treturn false;\n\t\tbacktrackPos--;\n\t}\n\n\t// Check input sequence\n\tlet inputPos = startIndex;\n\tfor (const coverage of subtable.inputCoverages) {\n\t\twhile (\n\t\t\tinputPos < buffer.infos.length &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[inputPos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tinputPos++;\n\t\t}\n\t\tif (inputPos >= buffer.infos.length) return false;\n\t\tif (coverage.get(buffer.infos[inputPos]?.glyphId) === null) return false;\n\t\tinputPos++;\n\t}\n\n\t// Check lookahead\n\tlet lookaheadPos = inputPos;\n\tfor (const coverage of subtable.lookaheadCoverages) {\n\t\twhile (\n\t\t\tlookaheadPos < buffer.infos.length &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[lookaheadPos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tlookaheadPos++;\n\t\t}\n\t\tif (lookaheadPos >= buffer.infos.length) return false;\n\t\tif (coverage.get(buffer.infos[lookaheadPos]?.glyphId) === null)\n\t\t\treturn false;\n\t\tlookaheadPos++;\n\t}\n\n\treturn true;\n}\n\n/** Apply nested positioning lookups at specific positions */\nfunction applyNestedPosLookups(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartIndex: number,\n\tlookupRecords: PosLookupRecord[],\n\tplan: ShapePlan,\n): void {\n\t// Sort by sequence index descending to apply from end to start\n\tconst sorted = [...lookupRecords].sort(\n\t\t(a, b) => b.sequenceIndex - a.sequenceIndex,\n\t);\n\n\tfor (const record of sorted) {\n\t\tconst lookupEntry = plan.gposLookups.find(\n\t\t\t(l) => l.index === record.lookupListIndex,\n\t\t);\n\t\tif (!lookupEntry) continue;\n\n\t\t// Apply at the specific position\n\t\tconst pos = startIndex + record.sequenceIndex;\n\t\tif (pos >= buffer.infos.length) continue;\n\n\t\t// Apply the lookup directly\n\t\tapplyGposLookup(font, buffer, lookupEntry.lookup, plan);\n\t}\n}\n\n// Sequence matching helpers\n\n/** Match a sequence of specific glyphs forward */\nfunction matchGlyphSequence(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartPos: number,\n\tglyphs: GlyphId[],\n\tlookupFlag: number,\n): boolean {\n\tlet pos = startPos;\n\tfor (const glyph of glyphs) {\n\t\twhile (\n\t\t\tpos < buffer.infos.length &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[pos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tpos++;\n\t\t}\n\t\tif (pos >= buffer.infos.length) return false;\n\t\tif (buffer.infos[pos]?.glyphId !== glyph) return false;\n\t\tpos++;\n\t}\n\treturn true;\n}\n\n/** Match a sequence of specific glyphs backward */\nfunction matchGlyphSequenceBackward(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartPos: number,\n\tglyphs: GlyphId[],\n\tlookupFlag: number,\n): boolean {\n\tlet pos = startPos;\n\tfor (const glyph of glyphs) {\n\t\twhile (\n\t\t\tpos >= 0 &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[pos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tpos--;\n\t\t}\n\t\tif (pos < 0) return false;\n\t\tif (buffer.infos[pos]?.glyphId !== glyph) return false;\n\t\tpos--;\n\t}\n\treturn true;\n}\n\n/** Match a sequence of classes forward */\nfunction matchClassSequence(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartPos: number,\n\tclasses: number[],\n\tclassDef: ClassDef,\n\tlookupFlag: number,\n): boolean {\n\tlet pos = startPos;\n\tfor (const cls of classes) {\n\t\twhile (\n\t\t\tpos < buffer.infos.length &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[pos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tpos++;\n\t\t}\n\t\tif (pos >= buffer.infos.length) return false;\n\t\tif (classDef.get(buffer.infos[pos]?.glyphId) !== cls) return false;\n\t\tpos++;\n\t}\n\treturn true;\n}\n\n/** Match a sequence of classes backward */\nfunction matchClassSequenceBackward(\n\tfont: Font,\n\tbuffer: GlyphBuffer,\n\tstartPos: number,\n\tclasses: number[],\n\tclassDef: ClassDef,\n\tlookupFlag: number,\n): boolean {\n\tlet pos = startPos;\n\tfor (const cls of classes) {\n\t\twhile (\n\t\t\tpos >= 0 &&\n\t\t\tshouldSkipGlyph(font, buffer.infos[pos]?.glyphId, lookupFlag)\n\t\t) {\n\t\t\tpos--;\n\t\t}\n\t\tif (pos < 0) return false;\n\t\tif (classDef.get(buffer.infos[pos]?.glyphId) !== cls) return false;\n\t\tpos--;\n\t}\n\treturn true;\n}\n\n// Utility\n\nfunction shouldSkipGlyph(\n\tfont: Font,\n\tglyphId: GlyphId,\n\tlookupFlag: number,\n): boolean {\n\tconst gdef = font.gdef;\n\tif (!gdef) return false;\n\n\tconst glyphClass = getGlyphClass(gdef, glyphId);\n\n\tif (\n\t\tlookupFlag & LookupFlag.IgnoreBaseGlyphs &&\n\t\tglyphClass === GlyphClass.Base\n\t)\n\t\treturn true;\n\tif (\n\t\tlookupFlag & LookupFlag.IgnoreLigatures &&\n\t\tglyphClass === GlyphClass.Ligature\n\t)\n\t\treturn true;\n\tif (lookupFlag & LookupFlag.IgnoreMarks && glyphClass === GlyphClass.Mark)\n\t\treturn true;\n\n\tconst markAttachmentType = getMarkAttachmentType(lookupFlag);\n\tif (markAttachmentType !== 0 && glyphClass === GlyphClass.Mark) {\n\t\tconst glyphMarkClass = gdef.markAttachClassDef.get(glyphId);\n\t\tif (glyphMarkClass !== markAttachmentType) return true;\n\t}\n\n\treturn false;\n}\n\n// AAT morx substitution\n\nfunction applyMorx(font: Font, buffer: GlyphBuffer): void {\n\tconst morx = font.morx;\n\tif (!morx) return;\n\n\tfor (const chain of morx.chains) {\n\t\tfor (const subtable of chain.subtables) {\n\t\t\t// Apply if subFeatureFlags match (default: all enabled)\n\t\t\tif ((chain.defaultFlags & subtable.subFeatureFlags) === 0) continue;\n\n\t\t\tswitch (subtable.type) {\n\t\t\t\tcase MorxSubtableType.NonContextual:\n\t\t\t\t\t// Simple substitution (Type 4)\n\t\t\t\t\tfor (const info of buffer.infos) {\n\t\t\t\t\t\tconst replacement = applyNonContextual(\n\t\t\t\t\t\t\tsubtable as MorxNonContextualSubtable,\n\t\t\t\t\t\t\tinfo.glyphId,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (replacement !== null) {\n\t\t\t\t\t\t\tinfo.glyphId = replacement;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MorxSubtableType.Rearrangement:\n\t\t\t\t\t// Rearrangement (Type 0) - reorder glyphs\n\t\t\t\t\tprocessRearrangement(\n\t\t\t\t\t\tsubtable as MorxRearrangementSubtable,\n\t\t\t\t\t\tbuffer.infos,\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MorxSubtableType.Contextual:\n\t\t\t\t\t// Contextual substitution (Type 1)\n\t\t\t\t\tprocessContextual(subtable as MorxContextualSubtable, buffer.infos);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MorxSubtableType.Ligature: {\n\t\t\t\t\t// Ligature (Type 2)\n\t\t\t\t\tconst newInfos = processLigature(\n\t\t\t\t\t\tsubtable as MorxLigatureSubtable,\n\t\t\t\t\t\tbuffer.infos,\n\t\t\t\t\t);\n\t\t\t\t\t// Update buffer with new infos (may be shorter due to ligatures)\n\t\t\t\t\tif (newInfos.length !== buffer.infos.length) {\n\t\t\t\t\t\tbuffer.initFromInfos(newInfos);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase MorxSubtableType.Insertion: {\n\t\t\t\t\t// Insertion (Type 5)\n\t\t\t\t\tconst newInfos = processInsertion(\n\t\t\t\t\t\tsubtable as MorxInsertionSubtable,\n\t\t\t\t\t\tbuffer.infos,\n\t\t\t\t\t);\n\t\t\t\t\t// Update buffer with new infos (may be longer due to insertions)\n\t\t\t\t\tif (newInfos.length !== buffer.infos.length) {\n\t\t\t\t\t\tbuffer.initFromInfos(newInfos);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n",
75
+ "// Bidi bracket pairs data, auto generated\nexport default {\n\tpairs:\n\t\t\"14>1,1e>2,u>2,2wt>1,1>1,1ge>1,1wp>1,1j>1,f>1,hm>1,1>1,u>1,u6>1,1>1,+5,28>1,w>1,1>1,+3,b8>1,1>1,+3,1>3,-1>-1,3>1,1>1,+2,1s>1,1>1,x>1,th>1,1>1,+2,db>1,1>1,+3,3>1,1>1,+2,14qm>1,1>1,+1,4q>1,1e>2,u>2,2>1,+1\",\n\tcanonical:\n\t\t\"6f1>-6dx,6dy>-6dx,6ec>-6ed,6ee>-6ed,6ww>2jj,-2ji>2jj,14r4>-1e7l,1e7m>-1e7l,1e7m>-1e5c,1e5d>-1e5b,1e5c>-14qx,14qy>-14qx,14vn>-1ecg,1ech>-1ecg,1edu>-1ecg,1eci>-1ecg,1eda>-1ecg,1eci>-1ecg,1eci>-168q,168r>-168q,168s>-14ye,14yf>-14ye\",\n};\n",
76
+ "/**\n * Parses an string that holds encoded codepoint mappings, e.g. for bracket pairs or\n * mirroring characters. Returns an object holding the `map`, and optionally a `reverseMap`.\n */\nexport function parseCharacterMap(\n\tencodedString: string,\n\tincludeReverse: boolean,\n): { map: Map<string, string>; reverseMap: Map<string, string> | null } {\n\tconst radix = 36;\n\tlet lastCode = 0;\n\tconst map = new Map<string, string>();\n\tconst reverseMap = includeReverse ? new Map<string, string>() : null;\n\tlet prevPair = \"\";\n\n\tfunction visit(entry: string): void {\n\t\tif (entry.indexOf(\"+\") !== -1) {\n\t\t\tfor (let i = +entry; i--; ) {\n\t\t\t\tvisit(prevPair);\n\t\t\t}\n\t\t} else {\n\t\t\tprevPair = entry;\n\t\t\tconst parts = entry.split(\">\");\n\t\t\tconst aStr = parts[0] ?? \"\";\n\t\t\tconst bStr = parts[1] ?? \"\";\n\t\t\tlastCode += parseInt(aStr, radix);\n\t\t\tconst a = String.fromCodePoint(lastCode);\n\t\t\tlastCode += parseInt(bStr, radix);\n\t\t\tconst b = String.fromCodePoint(lastCode);\n\t\t\tmap.set(a, b);\n\t\t\tif (reverseMap) {\n\t\t\t\treverseMap.set(b, a);\n\t\t\t}\n\t\t}\n\t}\n\n\tencodedString.split(\",\").forEach(visit);\n\treturn { map, reverseMap };\n}\n",
77
+ "/**\n * Bidi bracket pair functions\n * Port of bidi-js brackets.js\n */\n\nimport data from \"./brackets.data.ts\";\nimport { parseCharacterMap } from \"./parse-character-map.ts\";\n\nlet openToClose: Map<string, string> | null = null;\nlet closeToOpen: Map<string, string> | null = null;\nlet canonical: Map<string, string> | null = null;\n\nfunction parse(): void {\n\tif (!openToClose) {\n\t\tconst { map, reverseMap } = parseCharacterMap(data.pairs, true);\n\t\topenToClose = map;\n\t\tcloseToOpen = reverseMap;\n\t\tcanonical = parseCharacterMap(data.canonical, false).map;\n\t}\n}\n\nexport function openingToClosingBracket(char: string): string | null {\n\tparse();\n\treturn openToClose?.get(char) || null;\n}\n\nexport function closingToOpeningBracket(char: string): string | null {\n\tparse();\n\treturn closeToOpen?.get(char) || null;\n}\n\nexport function getCanonicalBracket(char: string): string | null {\n\tparse();\n\treturn canonical?.get(char) || null;\n}\n",
78
+ "// Bidi character types data, auto generated\nexport default {\n\tR: \"13k,1a,2,3,3,2+1j,ch+16,a+1,5+2,2+n,5,a,4,6+16,4+3,h+1b,4mo,179q,2+9,2+11,2i9+7y,2+68,4,3+4,5+13,4+3,2+4k,3+29,8+cf,1t+7z,w+17,3+3m,1t+3z,16o1+5r,8+30,8+mc,29+1r,29+4v,75+73\",\n\tEN: \"1c+9,3d+1,6,187+9,513,4+5,7+9,sf+j,175h+9,qw+q,161f+1d,4xt+a,25i+9\",\n\tES: \"17,2,6dp+1,f+1,av,16vr,mx+1,4o,2\",\n\tET: \"z+2,3h+3,b+1,ym,3e+1,2o,p4+1,8,6u,7c,g6,1wc,1n9+4,30+1b,2n,6d,qhx+1,h0m,a+1,49+2,63+1,4+1,6bb+3,12jj\",\n\tAN: \"16o+5,2j+9,2+1,35,ed,1ff2+9,87+u\",\n\tCS: \"18,2+1,b,2u,12k,55v,l,17v0,2,3,53,2+1,b\",\n\tB: \"a,3,f+2,2v,690\",\n\tS: \"9,2,k\",\n\tWS: \"c,k,4f4,1vk+a,u,1j,335\",\n\tON: \"x+1,4+4,h+5,r+5,r+3,z,5+3,2+1,2+1,5,2+2,3+4,o,w,ci+1,8+d,3+d,6+8,2+g,39+1,9,6+1,2,33,b8,3+1,3c+1,7+1,5r,b,7h+3,sa+5,2,3i+6,jg+3,ur+9,2v,ij+1,9g+9,7+a,8m,4+1,49+x,14u,2+2,c+2,e+2,e+2,e+1,i+n,e+e,2+p,u+2,e+2,36+1,2+3,2+1,b,2+2,6+5,2,2,2,h+1,5+4,6+3,3+f,16+2,5+3l,3+81,1y+p,2+40,q+a,m+13,2r+ch,2+9e,75+hf,3+v,2+2w,6e+5,f+6,75+2a,1a+p,2+2g,d+5x,r+b,6+3,4+o,g,6+1,6+2,2k+1,4,2j,5h+z,1m+1,1e+f,t+2,1f+e,d+3,4o+3,2s+1,w,535+1r,h3l+1i,93+2,2s,b+1,3l+x,2v,4g+3,21+3,kz+1,g5v+1,5a,j+9,n+v,2,3,2+8,2+1,3+2,2,3,46+1,4+4,h+5,r+5,r+a,3h+2,4+6,b+4,78,1r+24,4+c,4,1hb,ey+6,103+j,16j+c,1ux+7,5+g,fsh,jdq+1t,4,57+2e,p1,1m,1m,1m,1m,4kt+1,7j+17,5+2r,d+e,3+e,2+e,2+10,m+4,w,1n+5,1q,4z+5,4b+rb,9+c,4+c,4+37,d+2g,8+b,l+b,5+1j,9+9,7+13,9+t,3+1,27+3c,2+29,2+3q,d+d,3+4,4+2,6+6,a+o,8+6,a+2,e+6,16+42,2+1i\",\n\tBN: \"0+8,6+d,2s+5,2+p,e,4m9,1kt+2,2b+5,5+5,17q9+v,7k,6p+8,6+1,119d+3,440+7,96s+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+1,1ekf+75,6p+2rz,1ben+1,1ekf+1,1ekf+1\",\n\tNSM: \"lc+33,7o+6,7c+18,2,2+1,2+1,2,21+a,1d+k,h,2u+6,3+5,3+1,2+3,10,v+q,2k+a,1n+8,a,p+3,2+8,2+2,2+4,18+2,3c+e,2+v,1k,2,5+7,5,4+6,b+1,u,1n,5+3,9,l+1,r,3+1,1m,5+1,5+1,3+2,4,v+1,4,c+1,1m,5+4,2+1,5,l+1,n+5,2,1n,3,2+3,9,8+1,c+1,v,1q,d,1f,4,1m+2,6+2,2+3,8+1,c+1,u,1n,g+1,l+1,t+1,1m+1,5+3,9,l+1,u,21,8+2,2,2j,3+6,d+7,2r,3+8,c+5,23+1,s,2,2,1k+d,2+4,2+1,6+a,2+z,a,2v+3,2+5,2+1,3+1,q+1,5+2,h+3,e,3+1,7,g,jk+2,qb+2,u+2,u+1,v+1,1t+1,2+6,9,3+a,a,1a+2,3c+1,z,3b+2,5+1,a,7+2,64+1,3,1n,2+6,2,2,3+7,7+9,3,1d+g,1s+3,1d,2+4,2,6,15+8,d+1,x+3,3+1,2+2,1l,2+1,4,2+2,1n+7,3+1,49+2,2+c,2+6,5,7,4+1,5j+1l,2+4,k1+w,2db+2,3y,2p+v,ff+3,30+1,n9x+3,2+9,x+1,29+1,7l,4,5,q+1,6,48+1,r+h,e,13+7,q+a,1b+2,1d,3+3,3+1,14,1w+5,3+1,3+1,d,9,1c,1g,2+2,3+1,6+1,2,17+1,9,6n,3,5,fn5,ki+f,h+f,r2,6b,46+4,1af+2,2+1,6+3,15+2,5,4m+1,fy+3,as+1,4a+a,4x,1j+e,1l+2,1e+3,3+1,1y+2,11+4,2+7,1r,d+1,1h+8,b+3,3,2o+2,3,2+1,7,4h,4+7,m+1,1m+1,4,12+6,4+4,5g+7,3+2,2,o,2d+5,2,5+1,2+1,6n+3,7+1,2+1,s+1,2e+7,3,2+1,2z,2,3+5,2,2u+2,3+3,2+4,78+8,2+1,75+1,2,5,41+3,3+1,5,x+5,3+1,15+5,3+3,9,a+5,3+2,1b+c,2+1,bb+6,2+5,2d+l,3+6,2+1,2+1,3f+5,4,2+1,2+6,2,21+1,4,2,9o+1,f0c+4,1o+6,t5,1s+3,2a,f5l+1,43t+2,i+7,3+6,v+3,45+2,1j0+1i,5+1d,9,f,n+4,2+e,11t+6,2+g,3+6,2+1,2+4,7a+6,c6+3,15t+6,32+6,gzhy+6n\",\n\tAL: \"16w,3,2,e+1b,z+2,2+2s,g+1,8+1,b+m,2+t,s+2i,c+e,4h+f,1d+1e,1bwe+dp,3+3z,x+c,2+1,35+3y,2rm+z,5+7,b+5,dt+l,c+u,17nl+27,1t+27,4x+6n,3+d\",\n\tLRO: \"6ct\",\n\tRLO: \"6cu\",\n\tLRE: \"6cq\",\n\tRLE: \"6cr\",\n\tPDF: \"6cs\",\n\tLRI: \"6ee\",\n\tRLI: \"6ef\",\n\tFSI: \"6eg\",\n\tPDI: \"6eh\",\n};\n",
79
+ "/**\n * Bidi character type detection\n * Port of bidi-js charTypes.js\n */\n\nimport DATA from \"./char-types.data.ts\";\n\nexport const TYPES: Record<string, number> = {};\nexport const TYPES_TO_NAMES: Record<number, string> = {};\nTYPES.L = 1; // L is the default\nTYPES_TO_NAMES[1] = \"L\";\n\nObject.keys(DATA).forEach((type, i) => {\n\tTYPES[type] = 1 << (i + 1);\n\tconst typeVal = TYPES[type];\n\tif (typeVal !== undefined) {\n\t\tTYPES_TO_NAMES[typeVal] = type;\n\t}\n});\n\nObject.freeze(TYPES);\n\n// Helper to get type value with fallback\nfunction getType(name: string): number {\n\treturn TYPES[name] ?? 0;\n}\n\nexport const ISOLATE_INIT_TYPES =\n\tgetType(\"LRI\") | getType(\"RLI\") | getType(\"FSI\");\nexport const STRONG_TYPES = getType(\"L\") | getType(\"R\") | getType(\"AL\");\nexport const NEUTRAL_ISOLATE_TYPES =\n\tgetType(\"B\") |\n\tgetType(\"S\") |\n\tgetType(\"WS\") |\n\tgetType(\"ON\") |\n\tgetType(\"FSI\") |\n\tgetType(\"LRI\") |\n\tgetType(\"RLI\") |\n\tgetType(\"PDI\");\nexport const BN_LIKE_TYPES =\n\tgetType(\"BN\") |\n\tgetType(\"RLE\") |\n\tgetType(\"LRE\") |\n\tgetType(\"RLO\") |\n\tgetType(\"LRO\") |\n\tgetType(\"PDF\");\nexport const TRAILING_TYPES =\n\tgetType(\"S\") |\n\tgetType(\"WS\") |\n\tgetType(\"B\") |\n\tISOLATE_INIT_TYPES |\n\tgetType(\"PDI\") |\n\tBN_LIKE_TYPES;\n\nlet map: Map<number, number> | null = null;\n\nfunction parseData(): void {\n\tif (!map) {\n\t\tmap = new Map();\n\t\tlet lastCode = 0;\n\t\tfor (const type in DATA) {\n\t\t\tif (Object.hasOwn(DATA, type)) {\n\t\t\t\tconst segments = DATA[type as keyof typeof DATA];\n\t\t\t\tlet temp = \"\";\n\t\t\t\tlet start = 0;\n\t\t\t\tlet end = 0;\n\t\t\t\tlet state = false;\n\t\t\t\tfor (let i = 0; i <= segments.length + 1; i += 1) {\n\t\t\t\t\tconst char = segments[i];\n\t\t\t\t\tif (char !== \",\" && i !== segments.length) {\n\t\t\t\t\t\tif (char === \"+\") {\n\t\t\t\t\t\t\tstate = true;\n\t\t\t\t\t\t\tlastCode = start = lastCode + parseInt(temp, 36);\n\t\t\t\t\t\t\ttemp = \"\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttemp += char;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!state) {\n\t\t\t\t\t\t\tlastCode = start = lastCode + parseInt(temp, 36);\n\t\t\t\t\t\t\tend = start;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tend = start + parseInt(temp, 36);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate = false;\n\t\t\t\t\t\ttemp = \"\";\n\t\t\t\t\t\tlastCode = end;\n\t\t\t\t\t\tconst typeVal = getType(type);\n\t\t\t\t\t\tfor (let j = start; j < end + 1; j += 1) {\n\t\t\t\t\t\t\tmap.set(j, typeVal);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Get the bidi character type for a character\n */\nexport function getBidiCharType(char: string): number {\n\tparseData();\n\tconst codepoint = char.codePointAt(0);\n\tif (codepoint === undefined) return getType(\"L\");\n\treturn map?.get(codepoint) ?? getType(\"L\");\n}\n\n/**\n * Get the name of a bidi character type\n */\nexport function getBidiCharTypeName(char: string): string {\n\treturn TYPES_TO_NAMES[getBidiCharType(char)] ?? \"L\";\n}\n",
80
+ "/**\n * Bidi embedding levels calculation (UAX #9)\n * Port of bidi-js embeddingLevels.js\n */\n\nimport {\n\tclosingToOpeningBracket,\n\tgetCanonicalBracket,\n\topeningToClosingBracket,\n} from \"./brackets.ts\";\nimport {\n\tBN_LIKE_TYPES,\n\tgetBidiCharType,\n\tISOLATE_INIT_TYPES,\n\tNEUTRAL_ISOLATE_TYPES,\n\tSTRONG_TYPES,\n\tTRAILING_TYPES,\n\tTYPES,\n} from \"./char-types.ts\";\n\n// Local type aliases\nconst TYPE_L = TYPES.L ?? 1;\nconst TYPE_R = TYPES.R ?? 2;\nconst TYPE_EN = TYPES.EN ?? 4;\nconst TYPE_ES = TYPES.ES ?? 8;\nconst TYPE_ET = TYPES.ET ?? 16;\nconst TYPE_AN = TYPES.AN ?? 32;\nconst TYPE_CS = TYPES.CS ?? 64;\nconst TYPE_B = TYPES.B ?? 128;\nconst TYPE_S = TYPES.S ?? 256;\nconst TYPE_ON = TYPES.ON ?? 512;\nconst TYPE_BN = TYPES.BN ?? 1024;\nconst TYPE_NSM = TYPES.NSM ?? 2048;\nconst TYPE_AL = TYPES.AL ?? 4096;\nconst TYPE_LRO = TYPES.LRO ?? 8192;\nconst TYPE_RLO = TYPES.RLO ?? 16384;\nconst TYPE_LRE = TYPES.LRE ?? 32768;\nconst TYPE_RLE = TYPES.RLE ?? 65536;\nconst TYPE_PDF = TYPES.PDF ?? 131072;\nconst TYPE_LRI = TYPES.LRI ?? 262144;\nconst TYPE_RLI = TYPES.RLI ?? 524288;\nconst TYPE_FSI = TYPES.FSI ?? 1048576;\nconst TYPE_PDI = TYPES.PDI ?? 2097152;\n\nexport interface EmbeddingLevelsResult {\n\tparagraphs: Array<{ start: number; end: number; level: number }>;\n\tlevels: Uint8Array;\n}\n\ninterface StatusStackEntry {\n\t_level: number;\n\t_override: number;\n\t_isolate: number;\n\t_isolInitIndex?: number;\n}\n\ninterface LevelRun {\n\t_start: number;\n\t_end: number;\n\t_level: number;\n\t_startsWithPDI: boolean;\n\t_endsWithIsolInit: boolean;\n}\n\ninterface IsolatingRunSeq {\n\t_seqIndices: number[];\n\t_sosType: number;\n\t_eosType: number;\n}\n\nfunction getCharType(charTypes: Uint32Array, i: number): number {\n\treturn charTypes[i] ?? 0;\n}\n\nfunction getSeqIndex(seqIndices: number[], i: number): number {\n\treturn seqIndices[i] ?? 0;\n}\n\nfunction getCharAt(s: string, i: number): string {\n\treturn s[i] ?? \"\";\n}\n\n/**\n * This function applies the Bidirectional Algorithm to a string, returning the resolved embedding levels\n * in a single Uint8Array plus a list of objects holding each paragraph's start and end indices and resolved\n * base embedding level.\n */\nexport function getEmbeddingLevels(\n\tstring: string,\n\tbaseDirection?: \"ltr\" | \"rtl\" | \"auto\",\n): EmbeddingLevelsResult {\n\tconst MAX_DEPTH = 125;\n\n\t// Start by mapping all characters to their unicode type, as a bitmask integer\n\tconst charTypes = new Uint32Array(string.length);\n\tfor (let i = 0; i < string.length; i++) {\n\t\tcharTypes[i] = getBidiCharType(getCharAt(string, i));\n\t}\n\n\tconst charTypeCounts = new Map<number, number>();\n\n\tfunction changeCharType(i: number, type: number): void {\n\t\tconst oldType = getCharType(charTypes, i);\n\t\tcharTypes[i] = type;\n\t\tcharTypeCounts.set(oldType, (charTypeCounts.get(oldType) ?? 0) - 1);\n\t\tif (oldType & NEUTRAL_ISOLATE_TYPES) {\n\t\t\tcharTypeCounts.set(\n\t\t\t\tNEUTRAL_ISOLATE_TYPES,\n\t\t\t\t(charTypeCounts.get(NEUTRAL_ISOLATE_TYPES) ?? 0) - 1,\n\t\t\t);\n\t\t}\n\t\tcharTypeCounts.set(type, (charTypeCounts.get(type) ?? 0) + 1);\n\t\tif (type & NEUTRAL_ISOLATE_TYPES) {\n\t\t\tcharTypeCounts.set(\n\t\t\t\tNEUTRAL_ISOLATE_TYPES,\n\t\t\t\t(charTypeCounts.get(NEUTRAL_ISOLATE_TYPES) ?? 0) + 1,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst embedLevels = new Uint8Array(string.length);\n\tconst isolationPairs = new Map<number, number>();\n\n\tconst paragraphs: Array<{ start: number; end: number; level: number }> = [];\n\tlet paragraph: { start: number; end: number; level: number } | null = null;\n\n\tfunction determineAutoEmbedLevel(start: number, isFSI: boolean): number {\n\t\tfor (let i = start; i < string.length; i++) {\n\t\t\tconst charType = getCharType(charTypes, i);\n\t\t\tif (charType & (TYPE_R | TYPE_AL)) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tif (charType & (TYPE_B | TYPE_L) || (isFSI && charType === TYPE_PDI)) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (charType & ISOLATE_INIT_TYPES) {\n\t\t\t\tconst pdi = indexOfMatchingPDI(i);\n\t\t\t\ti = pdi === -1 ? string.length : pdi;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\n\tfunction indexOfMatchingPDI(isolateStart: number): number {\n\t\tlet isolationLevel = 1;\n\t\tfor (let i = isolateStart + 1; i < string.length; i++) {\n\t\t\tconst charType = getCharType(charTypes, i);\n\t\t\tif (charType & TYPE_B) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (charType & TYPE_PDI) {\n\t\t\t\tif (--isolationLevel === 0) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t} else if (charType & ISOLATE_INIT_TYPES) {\n\t\t\t\tisolationLevel++;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t}\n\n\tfor (let i = 0; i < string.length; i++) {\n\t\tif (!paragraph) {\n\t\t\tparagraph = {\n\t\t\t\tstart: i,\n\t\t\t\tend: string.length - 1,\n\t\t\t\tlevel:\n\t\t\t\t\tbaseDirection === \"rtl\"\n\t\t\t\t\t\t? 1\n\t\t\t\t\t\t: baseDirection === \"ltr\"\n\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t: determineAutoEmbedLevel(i, false),\n\t\t\t};\n\t\t\tparagraphs.push(paragraph);\n\t\t}\n\t\tif (getCharType(charTypes, i) & TYPE_B) {\n\t\t\tparagraph.end = i;\n\t\t\tparagraph = null;\n\t\t}\n\t}\n\n\tconst FORMATTING_TYPES =\n\t\tTYPE_RLE |\n\t\tTYPE_LRE |\n\t\tTYPE_RLO |\n\t\tTYPE_LRO |\n\t\tISOLATE_INIT_TYPES |\n\t\tTYPE_PDI |\n\t\tTYPE_PDF |\n\t\tTYPE_B;\n\tconst nextEven = (n: number): number => n + (n & 1 ? 1 : 2);\n\tconst nextOdd = (n: number): number => n + (n & 1 ? 2 : 1);\n\n\tfor (let paraIdx = 0; paraIdx < paragraphs.length; paraIdx++) {\n\t\tconst para = paragraphs[paraIdx];\n\t\tif (!para) continue;\n\t\tparagraph = para;\n\n\t\tconst statusStack: StatusStackEntry[] = [\n\t\t\t{\n\t\t\t\t_level: paragraph.level,\n\t\t\t\t_override: 0,\n\t\t\t\t_isolate: 0,\n\t\t\t},\n\t\t];\n\n\t\tlet overflowIsolateCount = 0;\n\t\tlet overflowEmbeddingCount = 0;\n\t\tlet validIsolateCount = 0;\n\t\tcharTypeCounts.clear();\n\n\t\tfor (let i = paragraph.start; i <= paragraph.end; i++) {\n\t\t\tlet charType = getCharType(charTypes, i);\n\t\t\tlet stackTop = statusStack[statusStack.length - 1];\n\t\t\tif (!stackTop) continue;\n\n\t\t\tcharTypeCounts.set(charType, (charTypeCounts.get(charType) ?? 0) + 1);\n\t\t\tif (charType & NEUTRAL_ISOLATE_TYPES) {\n\t\t\t\tcharTypeCounts.set(\n\t\t\t\t\tNEUTRAL_ISOLATE_TYPES,\n\t\t\t\t\t(charTypeCounts.get(NEUTRAL_ISOLATE_TYPES) ?? 0) + 1,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (charType & FORMATTING_TYPES) {\n\t\t\t\tif (charType & (TYPE_RLE | TYPE_LRE)) {\n\t\t\t\t\tembedLevels[i] = stackTop._level;\n\t\t\t\t\tconst level = (charType === TYPE_RLE ? nextOdd : nextEven)(\n\t\t\t\t\t\tstackTop._level,\n\t\t\t\t\t);\n\t\t\t\t\tif (\n\t\t\t\t\t\tlevel <= MAX_DEPTH &&\n\t\t\t\t\t\t!overflowIsolateCount &&\n\t\t\t\t\t\t!overflowEmbeddingCount\n\t\t\t\t\t) {\n\t\t\t\t\t\tstatusStack.push({\n\t\t\t\t\t\t\t_level: level,\n\t\t\t\t\t\t\t_override: 0,\n\t\t\t\t\t\t\t_isolate: 0,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (!overflowIsolateCount) {\n\t\t\t\t\t\toverflowEmbeddingCount++;\n\t\t\t\t\t}\n\t\t\t\t} else if (charType & (TYPE_RLO | TYPE_LRO)) {\n\t\t\t\t\tembedLevels[i] = stackTop._level;\n\t\t\t\t\tconst level = (charType === TYPE_RLO ? nextOdd : nextEven)(\n\t\t\t\t\t\tstackTop._level,\n\t\t\t\t\t);\n\t\t\t\t\tif (\n\t\t\t\t\t\tlevel <= MAX_DEPTH &&\n\t\t\t\t\t\t!overflowIsolateCount &&\n\t\t\t\t\t\t!overflowEmbeddingCount\n\t\t\t\t\t) {\n\t\t\t\t\t\tstatusStack.push({\n\t\t\t\t\t\t\t_level: level,\n\t\t\t\t\t\t\t_override: charType & TYPE_RLO ? TYPE_R : TYPE_L,\n\t\t\t\t\t\t\t_isolate: 0,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (!overflowIsolateCount) {\n\t\t\t\t\t\toverflowEmbeddingCount++;\n\t\t\t\t\t}\n\t\t\t\t} else if (charType & ISOLATE_INIT_TYPES) {\n\t\t\t\t\tif (charType & TYPE_FSI) {\n\t\t\t\t\t\tcharType =\n\t\t\t\t\t\t\tdetermineAutoEmbedLevel(i + 1, true) === 1 ? TYPE_RLI : TYPE_LRI;\n\t\t\t\t\t}\n\n\t\t\t\t\tembedLevels[i] = stackTop._level;\n\t\t\t\t\tif (stackTop._override) {\n\t\t\t\t\t\tchangeCharType(i, stackTop._override);\n\t\t\t\t\t}\n\t\t\t\t\tconst level = (charType === TYPE_RLI ? nextOdd : nextEven)(\n\t\t\t\t\t\tstackTop._level,\n\t\t\t\t\t);\n\t\t\t\t\tif (\n\t\t\t\t\t\tlevel <= MAX_DEPTH &&\n\t\t\t\t\t\toverflowIsolateCount === 0 &&\n\t\t\t\t\t\toverflowEmbeddingCount === 0\n\t\t\t\t\t) {\n\t\t\t\t\t\tvalidIsolateCount++;\n\t\t\t\t\t\tstatusStack.push({\n\t\t\t\t\t\t\t_level: level,\n\t\t\t\t\t\t\t_override: 0,\n\t\t\t\t\t\t\t_isolate: 1,\n\t\t\t\t\t\t\t_isolInitIndex: i,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\toverflowIsolateCount++;\n\t\t\t\t\t}\n\t\t\t\t} else if (charType & TYPE_PDI) {\n\t\t\t\t\tif (overflowIsolateCount > 0) {\n\t\t\t\t\t\toverflowIsolateCount--;\n\t\t\t\t\t} else if (validIsolateCount > 0) {\n\t\t\t\t\t\toverflowEmbeddingCount = 0;\n\t\t\t\t\t\twhile (statusStack.length > 0) {\n\t\t\t\t\t\t\tconst top = statusStack[statusStack.length - 1];\n\t\t\t\t\t\t\tif (top?._isolate) break;\n\t\t\t\t\t\t\tstatusStack.pop();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst top = statusStack[statusStack.length - 1];\n\t\t\t\t\t\tconst isolInitIndex = top?._isolInitIndex;\n\t\t\t\t\t\tif (isolInitIndex != null) {\n\t\t\t\t\t\t\tisolationPairs.set(isolInitIndex, i);\n\t\t\t\t\t\t\tisolationPairs.set(i, isolInitIndex);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstatusStack.pop();\n\t\t\t\t\t\tvalidIsolateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tstackTop = statusStack[statusStack.length - 1];\n\t\t\t\t\tif (!stackTop) continue;\n\t\t\t\t\tembedLevels[i] = stackTop._level;\n\t\t\t\t\tif (stackTop._override) {\n\t\t\t\t\t\tchangeCharType(i, stackTop._override);\n\t\t\t\t\t}\n\t\t\t\t} else if (charType & TYPE_PDF) {\n\t\t\t\t\tif (overflowIsolateCount === 0) {\n\t\t\t\t\t\tif (overflowEmbeddingCount > 0) {\n\t\t\t\t\t\t\toverflowEmbeddingCount--;\n\t\t\t\t\t\t} else if (!stackTop._isolate && statusStack.length > 1) {\n\t\t\t\t\t\t\tstatusStack.pop();\n\t\t\t\t\t\t\tstackTop = statusStack[statusStack.length - 1];\n\t\t\t\t\t\t\tif (!stackTop) continue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tembedLevels[i] = stackTop._level;\n\t\t\t\t} else if (charType & TYPE_B) {\n\t\t\t\t\tembedLevels[i] = paragraph.level;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tembedLevels[i] = stackTop._level;\n\t\t\t\tif (stackTop._override && charType !== TYPE_BN) {\n\t\t\t\t\tchangeCharType(i, stackTop._override);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst levelRuns: LevelRun[] = [];\n\t\tlet currentRun: LevelRun | null = null;\n\t\tfor (let i = paragraph.start; i <= paragraph.end; i++) {\n\t\t\tconst charType = getCharType(charTypes, i);\n\t\t\tif (!(charType & BN_LIKE_TYPES)) {\n\t\t\t\tconst lvl = embedLevels[i] ?? 0;\n\t\t\t\tconst isIsolInit = !!(charType & ISOLATE_INIT_TYPES);\n\t\t\t\tconst isPDI = charType === TYPE_PDI;\n\t\t\t\tif (currentRun && lvl === currentRun._level) {\n\t\t\t\t\tcurrentRun._end = i;\n\t\t\t\t\tcurrentRun._endsWithIsolInit = isIsolInit;\n\t\t\t\t} else {\n\t\t\t\t\tcurrentRun = {\n\t\t\t\t\t\t_start: i,\n\t\t\t\t\t\t_end: i,\n\t\t\t\t\t\t_level: lvl,\n\t\t\t\t\t\t_startsWithPDI: isPDI,\n\t\t\t\t\t\t_endsWithIsolInit: isIsolInit,\n\t\t\t\t\t};\n\t\t\t\t\tlevelRuns.push(currentRun);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst isolatingRunSeqs: IsolatingRunSeq[] = [];\n\n\t\tfor (let runIdx = 0; runIdx < levelRuns.length; runIdx++) {\n\t\t\tconst run = levelRuns[runIdx];\n\t\t\tif (!run) continue;\n\t\t\tif (\n\t\t\t\t!run._startsWithPDI ||\n\t\t\t\t(run._startsWithPDI && !isolationPairs.has(run._start))\n\t\t\t) {\n\t\t\t\tcurrentRun = run;\n\t\t\t\tconst seqRuns: LevelRun[] = [run];\n\n\t\t\t\twhile (currentRun?._endsWithIsolInit) {\n\t\t\t\t\tconst pdiIndex = isolationPairs.get(currentRun._end);\n\t\t\t\t\tif (pdiIndex == null) break;\n\t\t\t\t\tlet found = false;\n\t\t\t\t\tfor (let i = runIdx + 1; i < levelRuns.length; i++) {\n\t\t\t\t\t\tconst nextRun = levelRuns[i];\n\t\t\t\t\t\tif (nextRun?._start === pdiIndex) {\n\t\t\t\t\t\t\tcurrentRun = nextRun;\n\t\t\t\t\t\t\tseqRuns.push(nextRun);\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!found) break;\n\t\t\t\t}\n\n\t\t\t\tconst seqIndices: number[] = [];\n\t\t\t\tfor (const seqRun of seqRuns) {\n\t\t\t\t\tfor (let j = seqRun._start; j <= seqRun._end; j++) {\n\t\t\t\t\t\tseqIndices.push(j);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst firstIdx = seqIndices[0] ?? 0;\n\t\t\t\tconst firstLevel = embedLevels[firstIdx] ?? 0;\n\t\t\t\tlet prevLevel = paragraph.level;\n\t\t\t\tfor (let i = firstIdx - 1; i >= 0; i--) {\n\t\t\t\t\tif (!(getCharType(charTypes, i) & BN_LIKE_TYPES)) {\n\t\t\t\t\t\tprevLevel = embedLevels[i] ?? 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst lastIndex = seqIndices[seqIndices.length - 1] ?? 0;\n\t\t\t\tconst lastLevel = embedLevels[lastIndex] ?? 0;\n\t\t\t\tlet nextLevel = paragraph.level;\n\t\t\t\tif (!(getCharType(charTypes, lastIndex) & ISOLATE_INIT_TYPES)) {\n\t\t\t\t\tfor (let i = lastIndex + 1; i <= paragraph.end; i++) {\n\t\t\t\t\t\tif (!(getCharType(charTypes, i) & BN_LIKE_TYPES)) {\n\t\t\t\t\t\t\tnextLevel = embedLevels[i] ?? 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tisolatingRunSeqs.push({\n\t\t\t\t\t_seqIndices: seqIndices,\n\t\t\t\t\t_sosType: Math.max(prevLevel, firstLevel) % 2 ? TYPE_R : TYPE_L,\n\t\t\t\t\t_eosType: Math.max(nextLevel, lastLevel) % 2 ? TYPE_R : TYPE_L,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfor (const seq of isolatingRunSeqs) {\n\t\t\tconst {\n\t\t\t\t_seqIndices: seqIndices,\n\t\t\t\t_sosType: sosType,\n\t\t\t\t_eosType: eosType,\n\t\t\t} = seq;\n\t\t\tconst firstSeqIdx = seqIndices[0] ?? 0;\n\t\t\tconst embedDirection =\n\t\t\t\t(embedLevels[firstSeqIdx] ?? 0) & 1 ? TYPE_R : TYPE_L;\n\n\t\t\t// W1\n\t\t\tif (charTypeCounts.get(TYPE_NSM)) {\n\t\t\t\tfor (let si = 0; si < seqIndices.length; si++) {\n\t\t\t\t\tconst i = getSeqIndex(seqIndices, si);\n\t\t\t\t\tif (getCharType(charTypes, i) & TYPE_NSM) {\n\t\t\t\t\t\tlet prevType = sosType;\n\t\t\t\t\t\tfor (let sj = si - 1; sj >= 0; sj--) {\n\t\t\t\t\t\t\tconst sjIdx = getSeqIndex(seqIndices, sj);\n\t\t\t\t\t\t\tif (!(getCharType(charTypes, sjIdx) & BN_LIKE_TYPES)) {\n\t\t\t\t\t\t\t\tprevType = getCharType(charTypes, sjIdx);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tchangeCharType(\n\t\t\t\t\t\t\ti,\n\t\t\t\t\t\t\tprevType & (ISOLATE_INIT_TYPES | TYPE_PDI) ? TYPE_ON : prevType,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// W2\n\t\t\tif (charTypeCounts.get(TYPE_EN)) {\n\t\t\t\tfor (let si = 0; si < seqIndices.length; si++) {\n\t\t\t\t\tconst i = getSeqIndex(seqIndices, si);\n\t\t\t\t\tif (getCharType(charTypes, i) & TYPE_EN) {\n\t\t\t\t\t\tfor (let sj = si - 1; sj >= -1; sj--) {\n\t\t\t\t\t\t\tconst prevCharType =\n\t\t\t\t\t\t\t\tsj === -1\n\t\t\t\t\t\t\t\t\t? sosType\n\t\t\t\t\t\t\t\t\t: getCharType(charTypes, getSeqIndex(seqIndices, sj));\n\t\t\t\t\t\t\tif (prevCharType & STRONG_TYPES) {\n\t\t\t\t\t\t\t\tif (prevCharType === TYPE_AL) {\n\t\t\t\t\t\t\t\t\tchangeCharType(i, TYPE_AN);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// W3\n\t\t\tif (charTypeCounts.get(TYPE_AL)) {\n\t\t\t\tfor (let si = 0; si < seqIndices.length; si++) {\n\t\t\t\t\tconst i = getSeqIndex(seqIndices, si);\n\t\t\t\t\tif (getCharType(charTypes, i) & TYPE_AL) {\n\t\t\t\t\t\tchangeCharType(i, TYPE_R);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// W4\n\t\t\tif (charTypeCounts.get(TYPE_ES) || charTypeCounts.get(TYPE_CS)) {\n\t\t\t\tfor (let si = 1; si < seqIndices.length - 1; si++) {\n\t\t\t\t\tconst i = getSeqIndex(seqIndices, si);\n\t\t\t\t\tif (getCharType(charTypes, i) & (TYPE_ES | TYPE_CS)) {\n\t\t\t\t\t\tlet prevType = 0;\n\t\t\t\t\t\tlet nextType = 0;\n\t\t\t\t\t\tfor (let sj = si - 1; sj >= 0; sj--) {\n\t\t\t\t\t\t\tprevType = getCharType(charTypes, getSeqIndex(seqIndices, sj));\n\t\t\t\t\t\t\tif (!(prevType & BN_LIKE_TYPES)) break;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (let sj = si + 1; sj < seqIndices.length; sj++) {\n\t\t\t\t\t\t\tnextType = getCharType(charTypes, getSeqIndex(seqIndices, sj));\n\t\t\t\t\t\t\tif (!(nextType & BN_LIKE_TYPES)) break;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tprevType === nextType &&\n\t\t\t\t\t\t\t(getCharType(charTypes, i) === TYPE_ES\n\t\t\t\t\t\t\t\t? prevType === TYPE_EN\n\t\t\t\t\t\t\t\t: prevType & (TYPE_EN | TYPE_AN))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tchangeCharType(i, prevType);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// W5\n\t\t\tif (charTypeCounts.get(TYPE_EN)) {\n\t\t\t\tfor (let si = 0; si < seqIndices.length; si++) {\n\t\t\t\t\tconst i = getSeqIndex(seqIndices, si);\n\t\t\t\t\tif (getCharType(charTypes, i) & TYPE_EN) {\n\t\t\t\t\t\tfor (let sj = si - 1; sj >= 0; sj--) {\n\t\t\t\t\t\t\tconst sjIdx = getSeqIndex(seqIndices, sj);\n\t\t\t\t\t\t\tif (!(getCharType(charTypes, sjIdx) & (TYPE_ET | BN_LIKE_TYPES)))\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tchangeCharType(sjIdx, TYPE_EN);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (si++; si < seqIndices.length; si++) {\n\t\t\t\t\t\t\tconst siIdx = getSeqIndex(seqIndices, si);\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\tgetCharType(charTypes, siIdx) &\n\t\t\t\t\t\t\t\t\t(TYPE_ET | BN_LIKE_TYPES | TYPE_EN)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tif (getCharType(charTypes, siIdx) !== TYPE_EN) {\n\t\t\t\t\t\t\t\tchangeCharType(siIdx, TYPE_EN);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// W6\n\t\t\tif (\n\t\t\t\tcharTypeCounts.get(TYPE_ET) ||\n\t\t\t\tcharTypeCounts.get(TYPE_ES) ||\n\t\t\t\tcharTypeCounts.get(TYPE_CS)\n\t\t\t) {\n\t\t\t\tfor (let si = 0; si < seqIndices.length; si++) {\n\t\t\t\t\tconst i = getSeqIndex(seqIndices, si);\n\t\t\t\t\tif (getCharType(charTypes, i) & (TYPE_ET | TYPE_ES | TYPE_CS)) {\n\t\t\t\t\t\tchangeCharType(i, TYPE_ON);\n\t\t\t\t\t\tfor (let sj = si - 1; sj >= 0; sj--) {\n\t\t\t\t\t\t\tconst sjIdx = getSeqIndex(seqIndices, sj);\n\t\t\t\t\t\t\tif (!(getCharType(charTypes, sjIdx) & BN_LIKE_TYPES)) break;\n\t\t\t\t\t\t\tchangeCharType(sjIdx, TYPE_ON);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (let sj = si + 1; sj < seqIndices.length; sj++) {\n\t\t\t\t\t\t\tconst sjIdx = getSeqIndex(seqIndices, sj);\n\t\t\t\t\t\t\tif (!(getCharType(charTypes, sjIdx) & BN_LIKE_TYPES)) break;\n\t\t\t\t\t\t\tchangeCharType(sjIdx, TYPE_ON);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// W7\n\t\t\tif (charTypeCounts.get(TYPE_EN)) {\n\t\t\t\tlet prevStrongType = sosType;\n\t\t\t\tfor (let si = 0; si < seqIndices.length; si++) {\n\t\t\t\t\tconst i = getSeqIndex(seqIndices, si);\n\t\t\t\t\tconst type = getCharType(charTypes, i);\n\t\t\t\t\tif (type & TYPE_EN) {\n\t\t\t\t\t\tif (prevStrongType === TYPE_L) {\n\t\t\t\t\t\t\tchangeCharType(i, TYPE_L);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (type & STRONG_TYPES) {\n\t\t\t\t\t\tprevStrongType = type;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// N0-N2\n\t\t\tif (charTypeCounts.get(NEUTRAL_ISOLATE_TYPES)) {\n\t\t\t\tconst R_TYPES_FOR_N_STEPS = TYPE_R | TYPE_EN | TYPE_AN;\n\t\t\t\tconst STRONG_TYPES_FOR_N_STEPS = R_TYPES_FOR_N_STEPS | TYPE_L;\n\n\t\t\t\tconst bracketPairs: Array<[number, number]> = [];\n\t\t\t\tconst openerStack: Array<{ char: string; seqIndex: number }> = [];\n\n\t\t\t\tfor (let si = 0; si < seqIndices.length; si++) {\n\t\t\t\t\tconst siIdx = getSeqIndex(seqIndices, si);\n\t\t\t\t\tif (getCharType(charTypes, siIdx) & NEUTRAL_ISOLATE_TYPES) {\n\t\t\t\t\t\tconst char = getCharAt(string, siIdx);\n\t\t\t\t\t\tconst closingBracket = openingToClosingBracket(char);\n\t\t\t\t\t\tif (closingBracket !== null) {\n\t\t\t\t\t\t\tif (openerStack.length < 63) {\n\t\t\t\t\t\t\t\topenerStack.push({ char, seqIndex: si });\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst oppositeBracket = closingToOpeningBracket(char);\n\t\t\t\t\t\t\tif (oppositeBracket !== null) {\n\t\t\t\t\t\t\t\tfor (\n\t\t\t\t\t\t\t\t\tlet stackIdx = openerStack.length - 1;\n\t\t\t\t\t\t\t\t\tstackIdx >= 0;\n\t\t\t\t\t\t\t\t\tstackIdx--\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\tconst opener = openerStack[stackIdx];\n\t\t\t\t\t\t\t\t\tif (!opener) continue;\n\t\t\t\t\t\t\t\t\tconst stackChar = opener.char;\n\t\t\t\t\t\t\t\t\tconst canonicalChar = getCanonicalBracket(char);\n\t\t\t\t\t\t\t\t\tconst canonicalStack = getCanonicalBracket(stackChar);\n\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\tstackChar === oppositeBracket ||\n\t\t\t\t\t\t\t\t\t\t(canonicalChar &&\n\t\t\t\t\t\t\t\t\t\t\tstackChar === closingToOpeningBracket(canonicalChar)) ||\n\t\t\t\t\t\t\t\t\t\t(canonicalStack &&\n\t\t\t\t\t\t\t\t\t\t\topeningToClosingBracket(canonicalStack) === char)\n\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\tbracketPairs.push([opener.seqIndex, si]);\n\t\t\t\t\t\t\t\t\t\topenerStack.length = stackIdx;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbracketPairs.sort((a, b) => a[0] - b[0]);\n\n\t\t\t\tfor (const pair of bracketPairs) {\n\t\t\t\t\tconst [openSeqIdx, closeSeqIdx] = pair;\n\t\t\t\t\tlet foundStrongType = false;\n\t\t\t\t\tlet useStrongType = 0;\n\n\t\t\t\t\tfor (let si = openSeqIdx + 1; si < closeSeqIdx; si++) {\n\t\t\t\t\t\tconst i = getSeqIndex(seqIndices, si);\n\t\t\t\t\t\tconst ct = getCharType(charTypes, i);\n\t\t\t\t\t\tif (ct & STRONG_TYPES_FOR_N_STEPS) {\n\t\t\t\t\t\t\tfoundStrongType = true;\n\t\t\t\t\t\t\tconst lr = ct & R_TYPES_FOR_N_STEPS ? TYPE_R : TYPE_L;\n\t\t\t\t\t\t\tif (lr === embedDirection) {\n\t\t\t\t\t\t\t\tuseStrongType = lr;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (foundStrongType && !useStrongType) {\n\t\t\t\t\t\tuseStrongType = sosType;\n\t\t\t\t\t\tfor (let si = openSeqIdx - 1; si >= 0; si--) {\n\t\t\t\t\t\t\tconst i = getSeqIndex(seqIndices, si);\n\t\t\t\t\t\t\tconst ct = getCharType(charTypes, i);\n\t\t\t\t\t\t\tif (ct & STRONG_TYPES_FOR_N_STEPS) {\n\t\t\t\t\t\t\t\tconst lr = ct & R_TYPES_FOR_N_STEPS ? TYPE_R : TYPE_L;\n\t\t\t\t\t\t\t\tuseStrongType = lr !== embedDirection ? lr : embedDirection;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (useStrongType) {\n\t\t\t\t\t\tcharTypes[getSeqIndex(seqIndices, openSeqIdx)] = useStrongType;\n\t\t\t\t\t\tcharTypes[getSeqIndex(seqIndices, closeSeqIdx)] = useStrongType;\n\n\t\t\t\t\t\tif (useStrongType !== embedDirection) {\n\t\t\t\t\t\t\tfor (let si = openSeqIdx + 1; si < seqIndices.length; si++) {\n\t\t\t\t\t\t\t\tconst siIdx = getSeqIndex(seqIndices, si);\n\t\t\t\t\t\t\t\tif (!(getCharType(charTypes, siIdx) & BN_LIKE_TYPES)) {\n\t\t\t\t\t\t\t\t\tif (getBidiCharType(getCharAt(string, siIdx)) & TYPE_NSM) {\n\t\t\t\t\t\t\t\t\t\tcharTypes[siIdx] = useStrongType;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor (let si = closeSeqIdx + 1; si < seqIndices.length; si++) {\n\t\t\t\t\t\t\t\tconst siIdx = getSeqIndex(seqIndices, si);\n\t\t\t\t\t\t\t\tif (!(getCharType(charTypes, siIdx) & BN_LIKE_TYPES)) {\n\t\t\t\t\t\t\t\t\tif (getBidiCharType(getCharAt(string, siIdx)) & TYPE_NSM) {\n\t\t\t\t\t\t\t\t\t\tcharTypes[siIdx] = useStrongType;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// N1/N2\n\t\t\t\tfor (let si = 0; si < seqIndices.length; si++) {\n\t\t\t\t\tconst siIdx = getSeqIndex(seqIndices, si);\n\t\t\t\t\tif (getCharType(charTypes, siIdx) & NEUTRAL_ISOLATE_TYPES) {\n\t\t\t\t\t\tlet niRunStart = si;\n\t\t\t\t\t\tlet niRunEnd = si;\n\t\t\t\t\t\tlet prevType = sosType;\n\n\t\t\t\t\t\tfor (let si2 = si - 1; si2 >= 0; si2--) {\n\t\t\t\t\t\t\tconst si2Idx = getSeqIndex(seqIndices, si2);\n\t\t\t\t\t\t\tif (getCharType(charTypes, si2Idx) & BN_LIKE_TYPES) {\n\t\t\t\t\t\t\t\tniRunStart = si2;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tprevType =\n\t\t\t\t\t\t\t\t\tgetCharType(charTypes, si2Idx) & R_TYPES_FOR_N_STEPS\n\t\t\t\t\t\t\t\t\t\t? TYPE_R\n\t\t\t\t\t\t\t\t\t\t: TYPE_L;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet nextType = eosType;\n\t\t\t\t\t\tfor (let si2 = si + 1; si2 < seqIndices.length; si2++) {\n\t\t\t\t\t\t\tconst si2Idx = getSeqIndex(seqIndices, si2);\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tgetCharType(charTypes, si2Idx) &\n\t\t\t\t\t\t\t\t(NEUTRAL_ISOLATE_TYPES | BN_LIKE_TYPES)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tniRunEnd = si2;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnextType =\n\t\t\t\t\t\t\t\t\tgetCharType(charTypes, si2Idx) & R_TYPES_FOR_N_STEPS\n\t\t\t\t\t\t\t\t\t\t? TYPE_R\n\t\t\t\t\t\t\t\t\t\t: TYPE_L;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor (let sj = niRunStart; sj <= niRunEnd; sj++) {\n\t\t\t\t\t\t\tcharTypes[getSeqIndex(seqIndices, sj)] =\n\t\t\t\t\t\t\t\tprevType === nextType ? prevType : embedDirection;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsi = niRunEnd;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Resolving Implicit Levels\n\t\tfor (let i = paragraph.start; i <= paragraph.end; i++) {\n\t\t\tconst level = embedLevels[i] ?? 0;\n\t\t\tconst type = getCharType(charTypes, i);\n\n\t\t\tif (level & 1) {\n\t\t\t\tif (type & (TYPE_L | TYPE_EN | TYPE_AN)) {\n\t\t\t\t\tembedLevels[i]++;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (type & TYPE_R) {\n\t\t\t\t\tembedLevels[i]++;\n\t\t\t\t} else if (type & (TYPE_AN | TYPE_EN)) {\n\t\t\t\t\tembedLevels[i] += 2;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (type & BN_LIKE_TYPES) {\n\t\t\t\tembedLevels[i] =\n\t\t\t\t\ti === 0 ? paragraph.level : (embedLevels[i - 1] ?? paragraph.level);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\ti === paragraph.end ||\n\t\t\t\tgetBidiCharType(getCharAt(string, i)) & (TYPE_S | TYPE_B)\n\t\t\t) {\n\t\t\t\tfor (\n\t\t\t\t\tlet j = i;\n\t\t\t\t\tj >= 0 && getBidiCharType(getCharAt(string, j)) & TRAILING_TYPES;\n\t\t\t\t\tj--\n\t\t\t\t) {\n\t\t\t\t\tembedLevels[j] = paragraph.level;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tlevels: embedLevels,\n\t\tparagraphs,\n\t};\n}\n",
81
+ "// Bidi mirrored chars data, auto generated\nexport default \"14>1,j>2,t>2,u>2,1a>g,2v3>1,1>1,1ge>1,1wd>1,b>1,1j>1,f>1,ai>3,-2>3,+1,8>1k0,-1jq>1y7,-1y6>1hf,-1he>1h6,-1h5>1ha,-1h8>1qi,-1pu>1,6>3u,-3s>7,6>1,1>1,f>1,1>1,+2,3>1,1>1,+13,4>1,1>1,6>1eo,-1ee>1,3>1mg,-1me>1mk,-1mj>1mi,-1mg>1mi,-1md>1,1>1,+2,1>10k,-103>1,1>1,4>1,5>1,1>1,+10,3>1,1>8,-7>8,+1,-6>7,+1,a>1,1>1,u>1,u6>1,1>1,+5,26>1,1>1,2>1,2>2,8>1,7>1,4>1,1>1,+5,b8>1,1>1,+3,1>3,-2>1,2>1,1>1,+2,c>1,3>1,1>1,+2,h>1,3>1,a>1,1>1,2>1,3>1,1>1,d>1,f>1,3>1,1a>1,1>1,6>1,7>1,13>1,k>1,1>1,+19,4>1,1>1,+2,2>1,1>1,+18,m>1,a>1,1>1,lk>1,1>1,4>1,2>1,f>1,3>1,1>1,+3,db>1,1>1,+3,3>1,1>1,+2,14qm>1,1>1,+1,6>1,4j>1,j>2,t>2,u>2,2>1,+1\";\n",
82
+ "/**\n * Bidi character mirroring\n * Port of bidi-js mirroring.js\n */\n\nimport data from \"./mirroring.data.ts\";\nimport { parseCharacterMap } from \"./parse-character-map.ts\";\n\nlet mirrorMap: Map<string, string> | null = null;\n\nfunction parse(): void {\n\tif (!mirrorMap) {\n\t\tconst { map, reverseMap } = parseCharacterMap(data, true);\n\t\t// Combine both maps into one\n\t\tif (reverseMap) {\n\t\t\treverseMap.forEach((value, key) => {\n\t\t\t\tmap.set(key, value);\n\t\t\t});\n\t\t}\n\t\tmirrorMap = map;\n\t}\n}\n\nexport function getMirroredCharacter(char: string): string | null {\n\tparse();\n\treturn mirrorMap?.get(char) || null;\n}\n\n/**\n * Given a string and its resolved embedding levels, build a map of indices to replacement chars\n * for any characters in right-to-left segments that have defined mirrored characters.\n */\nexport function getMirroredCharactersMap(\n\tstring: string,\n\tembeddingLevels: Uint8Array,\n\tstart?: number,\n\tend?: number,\n): Map<number, string> {\n\tconst strLen = string.length;\n\tstart = Math.max(0, start == null ? 0 : +start);\n\tend = Math.min(strLen - 1, end == null ? strLen - 1 : +end);\n\n\tconst map = new Map<number, string>();\n\tfor (let i = start; i <= end; i++) {\n\t\tif (embeddingLevels[i]! & 1) {\n\t\t\t// only odd (rtl) levels\n\t\t\tconst mirror = getMirroredCharacter(string[i]!);\n\t\t\tif (mirror !== null) {\n\t\t\t\tmap.set(i, mirror);\n\t\t\t}\n\t\t}\n\t}\n\treturn map;\n}\n",
83
+ "/**\n * Bidi reordering\n * Port of bidi-js reordering.js\n */\n\nimport { getBidiCharType, TRAILING_TYPES } from \"./char-types.ts\";\nimport type { EmbeddingLevelsResult } from \"./embedding-levels.ts\";\nimport { getMirroredCharacter } from \"./mirroring.ts\";\n\n/**\n * Given a start and end denoting a single line within a string, and a set of precalculated\n * bidi embedding levels, produce a list of segments whose ordering should be flipped, in sequence.\n */\nexport function getReorderSegments(\n\tstring: string,\n\tembeddingLevelsResult: EmbeddingLevelsResult,\n\tstart?: number,\n\tend?: number,\n): Array<[number, number]> {\n\tconst strLen = string.length;\n\tconst startPos = Math.max(0, start == null ? 0 : +start);\n\tconst endPos = Math.min(strLen - 1, end == null ? strLen - 1 : +end);\n\n\tconst segments: Array<[number, number]> = [];\n\tfor (const paragraph of embeddingLevelsResult.paragraphs) {\n\t\tconst lineStart = Math.max(startPos, paragraph.start);\n\t\tconst lineEnd = Math.min(endPos, paragraph.end);\n\t\tif (lineStart < lineEnd) {\n\t\t\t// Local slice for mutation\n\t\t\tconst lineLevels = embeddingLevelsResult.levels.slice(\n\t\t\t\tlineStart,\n\t\t\t\tlineEnd + 1,\n\t\t\t);\n\n\t\t\t// 3.4 L1.4: Reset any sequence of whitespace characters and/or isolate formatting characters at the\n\t\t\t// end of the line to the paragraph level.\n\t\t\tfor (let i = lineEnd; i >= lineStart; i--) {\n\t\t\t\tconst char = string[i];\n\t\t\t\tif (char === undefined) break;\n\t\t\t\tif (!(getBidiCharType(char) & TRAILING_TYPES)) break;\n\t\t\t\tlineLevels[i - lineStart] = paragraph.level;\n\t\t\t}\n\n\t\t\t// L2. From the highest level found in the text to the lowest odd level on each line, including intermediate levels\n\t\t\t// not actually present in the text, reverse any contiguous sequence of characters that are at that level or higher.\n\t\t\tlet maxLevel = paragraph.level;\n\t\t\tlet minOddLevel = Infinity;\n\t\t\tfor (let i = 0; i < lineLevels.length; i++) {\n\t\t\t\tconst level = lineLevels[i] ?? 0;\n\t\t\t\tif (level > maxLevel) maxLevel = level;\n\t\t\t\tif (level < minOddLevel) minOddLevel = level | 1;\n\t\t\t}\n\t\t\tfor (let lvl = maxLevel; lvl >= minOddLevel; lvl--) {\n\t\t\t\tfor (let i = 0; i < lineLevels.length; i++) {\n\t\t\t\t\tconst level = lineLevels[i] ?? 0;\n\t\t\t\t\tif (level >= lvl) {\n\t\t\t\t\t\tconst segStart = i;\n\t\t\t\t\t\twhile (i + 1 < lineLevels.length) {\n\t\t\t\t\t\t\tconst nextLevel = lineLevels[i + 1] ?? 0;\n\t\t\t\t\t\t\tif (nextLevel < lvl) break;\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (i > segStart) {\n\t\t\t\t\t\t\tsegments.push([segStart + lineStart, i + lineStart]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn segments;\n}\n\n/**\n * Get the reordered string with bidi segments reversed\n */\nexport function getReorderedString(\n\tstring: string,\n\tembedLevelsResult: EmbeddingLevelsResult,\n\tstart?: number,\n\tend?: number,\n): string {\n\tconst indices = getReorderedIndices(string, embedLevelsResult, start, end);\n\tconst chars = [...string];\n\tfor (let i = 0; i < indices.length; i++) {\n\t\tconst charIndex = indices[i] ?? 0;\n\t\tconst level = embedLevelsResult.levels[charIndex] ?? 0;\n\t\tconst originalChar = string[charIndex] ?? \"\";\n\t\tif (level & 1) {\n\t\t\tconst mirrored = getMirroredCharacter(originalChar);\n\t\t\tchars[i] = mirrored ?? originalChar;\n\t\t} else {\n\t\t\tchars[i] = originalChar;\n\t\t}\n\t}\n\treturn chars.join(\"\");\n}\n\n/**\n * Get an array with character indices in their new bidi order\n */\nexport function getReorderedIndices(\n\tstring: string,\n\tembedLevelsResult: EmbeddingLevelsResult,\n\tstart?: number,\n\tend?: number,\n): number[] {\n\tconst segments = getReorderSegments(string, embedLevelsResult, start, end);\n\t// Fill an array with indices\n\tconst indices: number[] = [];\n\tfor (let i = 0; i < string.length; i++) {\n\t\tindices[i] = i;\n\t}\n\t// Reverse each segment in order\n\tfor (const [segStart, segEnd] of segments) {\n\t\tconst slice = indices.slice(segStart, segEnd + 1);\n\t\tfor (let i = slice.length; i--; ) {\n\t\t\tconst val = slice[i];\n\t\t\tif (val !== undefined) {\n\t\t\t\tindices[segEnd - i] = val;\n\t\t\t}\n\t\t}\n\t}\n\treturn indices;\n}\n",
84
+ "/**\n * Bidirectional text processing (UAX #9)\n */\n\nimport type { GlyphInfo } from \"../types.ts\";\nimport { Direction } from \"../types.ts\";\nimport {\n\tgetBidiCharType,\n\tgetEmbeddingLevels,\n\tgetMirroredCharacter,\n\tgetReorderedIndices,\n} from \"./bidi/index.ts\";\n\n/**\n * Result of BiDi processing\n */\nexport interface BidiResult {\n\t/** Embedding levels per character */\n\tlevels: Uint8Array;\n\t/** Paragraph information */\n\tparagraphs: BidiParagraph[];\n}\n\n/**\n * Paragraph info from BiDi algorithm\n */\nexport interface BidiParagraph {\n\tstart: number;\n\tend: number;\n\tlevel: number;\n}\n\n/**\n * Get embedding levels for a string\n */\nexport function getEmbeddings(\n\ttext: string,\n\tbaseDirection: Direction = Direction.LTR,\n): BidiResult {\n\tconst dir =\n\t\tbaseDirection === Direction.RTL\n\t\t\t? \"rtl\"\n\t\t\t: baseDirection === Direction.LTR\n\t\t\t\t? \"ltr\"\n\t\t\t\t: \"auto\";\n\n\tconst result = getEmbeddingLevels(text, dir);\n\n\treturn {\n\t\tlevels: result.levels,\n\t\tparagraphs: result.paragraphs,\n\t};\n}\n\n/**\n * Get reordered indices for visual display\n */\nexport function getVisualOrder(\n\ttext: string,\n\tresult: BidiResult,\n\tstart: number = 0,\n\tend: number = text.length,\n): number[] {\n\treturn Array.from(getReorderedIndices(text, result, start, end));\n}\n\n/**\n * Apply BiDi reordering to glyph infos\n */\nexport function reorderGlyphs(\n\tinfos: GlyphInfo[],\n\tresult: BidiResult,\n): GlyphInfo[] {\n\tif (infos.length === 0) return infos;\n\n\t// Get reordered indices\n\tconst dummyString = \"x\".repeat(infos.length);\n\tconst indices = getReorderedIndices(dummyString, result, 0, infos.length);\n\n\t// Reorder glyphs according to visual order\n\tconst reordered: GlyphInfo[] = [];\n\tfor (const idx of indices) {\n\t\tif (idx < infos.length) {\n\t\t\tconst info = infos[idx];\n\t\t\tif (info) {\n\t\t\t\treordered.push(info);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn reordered;\n}\n\n/**\n * Get mirrored character for RTL contexts\n */\nexport function getMirror(codepoint: number): number {\n\tconst char = String.fromCodePoint(codepoint);\n\tconst mirrored = getMirroredCharacter(char);\n\treturn mirrored ? (mirrored.codePointAt(0) ?? codepoint) : codepoint;\n}\n\n/**\n * Apply character mirroring for RTL runs\n */\nexport function applyMirroring(infos: GlyphInfo[], levels: Uint8Array): void {\n\tfor (const [i, info] of infos.entries()) {\n\t\tconst level = levels[i];\n\t\tif (level === undefined) continue;\n\n\t\t// Odd levels are RTL\n\t\tif (level & 1) {\n\t\t\tconst mirrored = getMirror(info.codepoint);\n\t\t\tif (mirrored !== info.codepoint) {\n\t\t\t\t// Store mirrored codepoint - glyph ID will be remapped later\n\t\t\t\tinfo.codepoint = mirrored;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * BiDi character type constants\n */\nexport const BidiType = {\n\tL: 0x0001, // Left-to-Right\n\tR: 0x0002, // Right-to-Left\n\tEN: 0x0004, // European Number\n\tES: 0x0008, // European Separator\n\tET: 0x0010, // European Terminator\n\tAN: 0x0020, // Arabic Number\n\tCS: 0x0040, // Common Separator\n\tB: 0x0080, // Paragraph Separator\n\tS: 0x0100, // Segment Separator\n\tWS: 0x0200, // Whitespace\n\tON: 0x0400, // Other Neutral\n\tBN: 0x0800, // Boundary Neutral\n\tNSM: 0x1000, // Non-Spacing Mark\n\tAL: 0x2000, // Arabic Letter\n\tLRO: 0x4000, // Left-to-Right Override\n\tRLO: 0x8000, // Right-to-Left Override\n\tLRE: 0x10000, // Left-to-Right Embedding\n\tRLE: 0x20000, // Right-to-Left Embedding\n\tPDF: 0x40000, // Pop Directional Format\n\tLRI: 0x80000, // Left-to-Right Isolate\n\tRLI: 0x100000, // Right-to-Left Isolate\n\tFSI: 0x200000, // First Strong Isolate\n\tPDI: 0x400000, // Pop Directional Isolate\n} as const;\n\n/**\n * Get BiDi character type for a character\n */\nexport function getCharType(char: string): number {\n\treturn getBidiCharType(char);\n}\n\n/**\n * Check if a character is strongly RTL\n */\nexport function isRTL(codepoint: number): boolean {\n\tconst char = String.fromCodePoint(codepoint);\n\tconst type = getBidiCharType(char);\n\treturn (type & (BidiType.R | BidiType.AL)) !== 0;\n}\n\n/**\n * Check if a character is strongly LTR\n */\nexport function isLTR(codepoint: number): boolean {\n\tconst char = String.fromCodePoint(codepoint);\n\tconst type = getBidiCharType(char);\n\treturn (type & BidiType.L) !== 0;\n}\n\n/**\n * Detect base direction from text content\n */\nexport function detectDirection(text: string): Direction {\n\tfor (const char of text) {\n\t\tconst type = getBidiCharType(char);\n\t\tif (type & BidiType.L) return Direction.LTR;\n\t\tif (type & (BidiType.R | BidiType.AL)) return Direction.RTL;\n\t}\n\treturn Direction.LTR; // Default\n}\n\n/**\n * Full BiDi processing for shaping\n */\nexport function processBidi(\n\tinfos: GlyphInfo[],\n\tbaseDirection: Direction = Direction.LTR,\n): { infos: GlyphInfo[]; levels: Uint8Array } {\n\tif (infos.length === 0) {\n\t\treturn { infos, levels: new Uint8Array(0) };\n\t}\n\n\t// Build string from codepoints\n\tconst text = infos.map((i) => String.fromCodePoint(i.codepoint)).join(\"\");\n\n\t// Get embedding levels\n\tconst result = getEmbeddings(text, baseDirection);\n\n\t// Apply character mirroring\n\tapplyMirroring(infos, result.levels);\n\n\t// Reorder glyphs for visual order\n\tconst reordered = reorderGlyphs(infos, result);\n\n\treturn { infos: reordered, levels: result.levels };\n}\n",
85
+ "/**\n * Unicode Line Breaking Algorithm (UAX #14)\n * Determines line break opportunities in text\n */\n\nimport type { GlyphInfo } from \"../types.ts\";\n\n/**\n * Line break class from UAX #14\n */\nexport enum LineBreakClass {\n\t// Non-tailorable Line Breaking Classes\n\tBK = 0, // Mandatory Break\n\tCR = 1, // Carriage Return\n\tLF = 2, // Line Feed\n\tCM = 3, // Combining Mark\n\tNL = 4, // Next Line\n\tSG = 5, // Surrogate (not used)\n\tWJ = 6, // Word Joiner\n\tZW = 7, // Zero Width Space\n\tGL = 8, // Non-breaking (\"Glue\")\n\tSP = 9, // Space\n\tZWJ = 10, // Zero Width Joiner\n\n\t// Break Opportunities\n\tB2 = 11, // Break Opportunity Before and After\n\tBA = 12, // Break After\n\tBB = 13, // Break Before\n\tHY = 14, // Hyphen\n\tCB = 15, // Contingent Break Opportunity\n\n\t// Characters Prohibiting Certain Breaks\n\tCL = 16, // Close Punctuation\n\tCP = 17, // Close Parenthesis\n\tEX = 18, // Exclamation/Interrogation\n\tIN = 19, // Inseparable\n\tNS = 20, // Nonstarter\n\tOP = 21, // Open Punctuation\n\tQU = 22, // Quotation\n\n\t// Numeric Context\n\tIS = 23, // Infix Numeric Separator\n\tNU = 24, // Numeric\n\tPO = 25, // Postfix Numeric\n\tPR = 26, // Prefix Numeric\n\tSY = 27, // Symbols Allowing Break After\n\n\t// Other Characters\n\tAI = 28, // Ambiguous (Alphabetic or Ideographic)\n\tAL = 29, // Alphabetic\n\tCJ = 30, // Conditional Japanese Starter\n\tEB = 31, // Emoji Base\n\tEM = 32, // Emoji Modifier\n\tH2 = 33, // Hangul LV Syllable\n\tH3 = 34, // Hangul LVT Syllable\n\tHL = 35, // Hebrew Letter\n\tID = 36, // Ideographic\n\tJL = 37, // Hangul L Jamo\n\tJV = 38, // Hangul V Jamo\n\tJT = 39, // Hangul T Jamo\n\tRI = 40, // Regional Indicator\n\tSA = 41, // Complex Context Dependent (South East Asian)\n\tXX = 42, // Unknown\n}\n\n/**\n * Break action\n */\nexport enum BreakAction {\n\tDirect = 0, // Direct break opportunity (after space)\n\tIndirect = 1, // Indirect break (only if spaces intervene)\n\tCombiningIndirect = 2, // Indirect break for combining marks\n\tCombiningProhibited = 3, // Prohibited break for combining marks\n\tProhibited = 4, // No break allowed\n\tExplicit = 5, // Explicit break (BK, CR, LF, NL)\n}\n\n/**\n * Line break opportunity\n */\nexport enum BreakOpportunity {\n\tNoBreak = 0,\n\tOptional = 1,\n\tMandatory = 2,\n}\n\n/**\n * Get line break class for a codepoint\n */\nexport function getLineBreakClass(cp: number): LineBreakClass {\n\t// Mandatory breaks\n\tif (cp === 0x000a) return LineBreakClass.LF;\n\tif (cp === 0x000d) return LineBreakClass.CR;\n\tif (cp === 0x0085) return LineBreakClass.NL;\n\tif (cp === 0x000b || cp === 0x000c) return LineBreakClass.BK;\n\tif (cp === 0x2028) return LineBreakClass.BK; // Line Separator\n\tif (cp === 0x2029) return LineBreakClass.BK; // Paragraph Separator\n\n\t// Zero-width characters\n\tif (cp === 0x200b) return LineBreakClass.ZW; // Zero Width Space\n\tif (cp === 0x200d) return LineBreakClass.ZWJ; // Zero Width Joiner\n\tif (cp === 0x2060) return LineBreakClass.WJ; // Word Joiner\n\tif (cp === 0xfeff) return LineBreakClass.WJ; // BOM / ZWNBSP\n\n\t// Spaces\n\tif (cp === 0x0020) return LineBreakClass.SP;\n\tif (cp === 0x00a0) return LineBreakClass.GL; // No-Break Space\n\tif (cp === 0x202f) return LineBreakClass.GL; // Narrow No-Break Space\n\tif (cp === 0x2007) return LineBreakClass.GL; // Figure Space\n\tif (cp === 0x2011) return LineBreakClass.GL; // Non-Breaking Hyphen\n\n\t// Tabs and other whitespace\n\tif (cp === 0x0009) return LineBreakClass.BA; // Tab\n\tif (cp >= 0x2000 && cp <= 0x200a) return LineBreakClass.BA; // Various spaces\n\n\t// Combining marks\n\tif (cp >= 0x0300 && cp <= 0x036f) return LineBreakClass.CM; // Combining Diacritical Marks\n\tif (cp >= 0x0483 && cp <= 0x0489) return LineBreakClass.CM; // Cyrillic combining\n\tif (cp >= 0x0591 && cp <= 0x05bd) return LineBreakClass.CM; // Hebrew points\n\tif (cp >= 0x05bf && cp <= 0x05c7) return LineBreakClass.CM;\n\tif (cp >= 0x0610 && cp <= 0x061a) return LineBreakClass.CM; // Arabic marks\n\tif (cp >= 0x064b && cp <= 0x065f) return LineBreakClass.CM;\n\tif (cp >= 0x0670 && cp <= 0x0670) return LineBreakClass.CM;\n\tif (cp >= 0x06d6 && cp <= 0x06ed) return LineBreakClass.CM;\n\tif (cp >= 0x0711 && cp <= 0x0711) return LineBreakClass.CM; // Syriac\n\tif (cp >= 0x0730 && cp <= 0x074a) return LineBreakClass.CM;\n\tif (cp >= 0x07a6 && cp <= 0x07b0) return LineBreakClass.CM; // Thaana\n\tif (cp >= 0x0816 && cp <= 0x0823) return LineBreakClass.CM; // Samaritan\n\tif (cp >= 0x0825 && cp <= 0x082d) return LineBreakClass.CM;\n\tif (cp >= 0x0859 && cp <= 0x085b) return LineBreakClass.CM; // Mandaic\n\tif (cp >= 0x08d3 && cp <= 0x08e1) return LineBreakClass.CM; // Arabic extended\n\tif (cp >= 0x08e3 && cp <= 0x0903) return LineBreakClass.CM;\n\tif (cp >= 0x093a && cp <= 0x093c) return LineBreakClass.CM; // Devanagari\n\tif (cp >= 0x093e && cp <= 0x094f) return LineBreakClass.CM;\n\tif (cp >= 0x0951 && cp <= 0x0957) return LineBreakClass.CM;\n\tif (cp >= 0x0962 && cp <= 0x0963) return LineBreakClass.CM;\n\tif (cp >= 0x0981 && cp <= 0x0983) return LineBreakClass.CM; // Bengali\n\tif (cp === 0x09bc) return LineBreakClass.CM;\n\tif (cp >= 0x09be && cp <= 0x09cd) return LineBreakClass.CM;\n\tif (cp >= 0x09d7 && cp <= 0x09d7) return LineBreakClass.CM;\n\tif (cp >= 0x09e2 && cp <= 0x09e3) return LineBreakClass.CM;\n\tif (cp >= 0x09fe && cp <= 0x09fe) return LineBreakClass.CM;\n\tif (cp >= 0x0a01 && cp <= 0x0a03) return LineBreakClass.CM; // Gurmukhi\n\tif (cp >= 0x0a3c && cp <= 0x0a51) return LineBreakClass.CM;\n\tif (cp >= 0x0a70 && cp <= 0x0a71) return LineBreakClass.CM;\n\tif (cp >= 0x0a75 && cp <= 0x0a75) return LineBreakClass.CM;\n\tif (cp >= 0x0a81 && cp <= 0x0a83) return LineBreakClass.CM; // Gujarati\n\tif (cp >= 0x0abc && cp <= 0x0acd) return LineBreakClass.CM;\n\tif (cp >= 0x0ae2 && cp <= 0x0ae3) return LineBreakClass.CM;\n\tif (cp >= 0x0afa && cp <= 0x0aff) return LineBreakClass.CM;\n\tif (cp >= 0x0b01 && cp <= 0x0b03) return LineBreakClass.CM; // Oriya\n\tif (cp >= 0x0b3c && cp <= 0x0b57) return LineBreakClass.CM;\n\tif (cp >= 0x0b62 && cp <= 0x0b63) return LineBreakClass.CM;\n\tif (cp >= 0x0b82 && cp <= 0x0b82) return LineBreakClass.CM; // Tamil\n\tif (cp >= 0x0bbe && cp <= 0x0bcd) return LineBreakClass.CM;\n\tif (cp >= 0x0bd7 && cp <= 0x0bd7) return LineBreakClass.CM;\n\tif (cp >= 0x0c00 && cp <= 0x0c04) return LineBreakClass.CM; // Telugu\n\tif (cp >= 0x0c3e && cp <= 0x0c56) return LineBreakClass.CM;\n\tif (cp >= 0x0c62 && cp <= 0x0c63) return LineBreakClass.CM;\n\tif (cp >= 0x0c81 && cp <= 0x0c83) return LineBreakClass.CM; // Kannada\n\tif (cp >= 0x0cbc && cp <= 0x0cd6) return LineBreakClass.CM;\n\tif (cp >= 0x0ce2 && cp <= 0x0ce3) return LineBreakClass.CM;\n\tif (cp >= 0x0d00 && cp <= 0x0d03) return LineBreakClass.CM; // Malayalam\n\tif (cp >= 0x0d3b && cp <= 0x0d4d) return LineBreakClass.CM;\n\tif (cp >= 0x0d57 && cp <= 0x0d57) return LineBreakClass.CM;\n\tif (cp >= 0x0d62 && cp <= 0x0d63) return LineBreakClass.CM;\n\tif (cp >= 0x0d81 && cp <= 0x0d83) return LineBreakClass.CM; // Sinhala\n\tif (cp >= 0x0dca && cp <= 0x0df3) return LineBreakClass.CM;\n\tif (cp >= 0x0f18 && cp <= 0x0f19) return LineBreakClass.CM; // Tibetan\n\tif (cp >= 0x0f35 && cp <= 0x0f39) return LineBreakClass.CM;\n\tif (cp >= 0x0f3e && cp <= 0x0f3f) return LineBreakClass.CM;\n\tif (cp >= 0x0f71 && cp <= 0x0f84) return LineBreakClass.CM;\n\tif (cp >= 0x0f86 && cp <= 0x0f87) return LineBreakClass.CM;\n\tif (cp >= 0x0f8d && cp <= 0x0fbc) return LineBreakClass.CM;\n\tif (cp === 0x0fc6) return LineBreakClass.CM;\n\tif (cp >= 0x1712 && cp <= 0x1714) return LineBreakClass.CM; // Tagalog\n\tif (cp >= 0x1732 && cp <= 0x1734) return LineBreakClass.CM; // Hanunoo\n\tif (cp >= 0x1752 && cp <= 0x1753) return LineBreakClass.CM; // Buhid\n\tif (cp >= 0x1772 && cp <= 0x1773) return LineBreakClass.CM; // Tagbanwa\n\tif (cp >= 0x17b4 && cp <= 0x17d3) return LineBreakClass.CM; // Khmer\n\tif (cp === 0x17dd) return LineBreakClass.CM;\n\tif (cp >= 0x180b && cp <= 0x180d) return LineBreakClass.CM; // Mongolian\n\tif (cp === 0x180f) return LineBreakClass.CM;\n\tif (cp >= 0x1885 && cp <= 0x1886) return LineBreakClass.CM;\n\tif (cp === 0x18a9) return LineBreakClass.CM;\n\tif (cp >= 0x1920 && cp <= 0x193b) return LineBreakClass.CM; // Limbu, Buginese\n\tif (cp >= 0x1a17 && cp <= 0x1a1b) return LineBreakClass.CM;\n\tif (cp >= 0x1a55 && cp <= 0x1a7f) return LineBreakClass.CM; // Tai Tham\n\tif (cp >= 0x1ab0 && cp <= 0x1ace) return LineBreakClass.CM; // Combining Diacritical Marks Extended\n\tif (cp >= 0x1b00 && cp <= 0x1b04) return LineBreakClass.CM; // Balinese\n\tif (cp >= 0x1b34 && cp <= 0x1b44) return LineBreakClass.CM;\n\tif (cp >= 0x1b6b && cp <= 0x1b73) return LineBreakClass.CM;\n\tif (cp >= 0x1b80 && cp <= 0x1b82) return LineBreakClass.CM; // Sundanese\n\tif (cp >= 0x1ba1 && cp <= 0x1bad) return LineBreakClass.CM;\n\tif (cp >= 0x1be6 && cp <= 0x1bf3) return LineBreakClass.CM; // Batak\n\tif (cp >= 0x1c24 && cp <= 0x1c37) return LineBreakClass.CM; // Lepcha\n\tif (cp >= 0x1cd0 && cp <= 0x1cf9) return LineBreakClass.CM; // Vedic Extensions\n\tif (cp >= 0x1dc0 && cp <= 0x1dff) return LineBreakClass.CM; // Combining Diacritical Marks Supplement\n\tif (cp >= 0x20d0 && cp <= 0x20f0) return LineBreakClass.CM; // Combining Diacritical Marks for Symbols\n\tif (cp >= 0x2cef && cp <= 0x2cf1) return LineBreakClass.CM; // Coptic\n\tif (cp === 0x2d7f) return LineBreakClass.CM; // Tifinagh\n\tif (cp >= 0x2de0 && cp <= 0x2dff) return LineBreakClass.CM; // Cyrillic Extended-A\n\tif (cp >= 0x302a && cp <= 0x302f) return LineBreakClass.CM; // Ideographic Description\n\tif (cp >= 0x3099 && cp <= 0x309a) return LineBreakClass.CM; // Hiragana/Katakana voicing\n\tif (cp >= 0xa66f && cp <= 0xa672) return LineBreakClass.CM; // Combining Cyrillic\n\tif (cp >= 0xa674 && cp <= 0xa67d) return LineBreakClass.CM;\n\tif (cp >= 0xa69e && cp <= 0xa69f) return LineBreakClass.CM;\n\tif (cp >= 0xa6f0 && cp <= 0xa6f1) return LineBreakClass.CM; // Bamum\n\tif (cp >= 0xa802 && cp <= 0xa827) return LineBreakClass.CM; // Syloti Nagri\n\tif (cp >= 0xa82c && cp <= 0xa82c) return LineBreakClass.CM;\n\tif (cp >= 0xa880 && cp <= 0xa881) return LineBreakClass.CM; // Saurashtra\n\tif (cp >= 0xa8b4 && cp <= 0xa8c5) return LineBreakClass.CM;\n\tif (cp >= 0xa8e0 && cp <= 0xa8f1) return LineBreakClass.CM; // Devanagari Extended\n\tif (cp === 0xa8ff) return LineBreakClass.CM;\n\tif (cp >= 0xa926 && cp <= 0xa92d) return LineBreakClass.CM; // Kayah Li\n\tif (cp >= 0xa947 && cp <= 0xa953) return LineBreakClass.CM; // Rejang\n\tif (cp >= 0xa980 && cp <= 0xa983) return LineBreakClass.CM; // Javanese\n\tif (cp >= 0xa9b3 && cp <= 0xa9cd) return LineBreakClass.CM;\n\tif (cp === 0xa9e5) return LineBreakClass.CM; // Myanmar Extended-B\n\tif (cp >= 0xaa29 && cp <= 0xaa36) return LineBreakClass.CM; // Cham\n\tif (cp >= 0xaa43 && cp <= 0xaa43) return LineBreakClass.CM;\n\tif (cp >= 0xaa4c && cp <= 0xaa4d) return LineBreakClass.CM;\n\tif (cp >= 0xaa7b && cp <= 0xaa7d) return LineBreakClass.CM; // Myanmar Extended-A\n\tif (cp >= 0xaab0 && cp <= 0xaac2) return LineBreakClass.CM; // Tai Viet\n\tif (cp >= 0xaaeb && cp <= 0xaaef) return LineBreakClass.CM; // Meetei Mayek Extensions\n\tif (cp >= 0xaaf5 && cp <= 0xaaf6) return LineBreakClass.CM;\n\tif (cp >= 0xabe3 && cp <= 0xabea) return LineBreakClass.CM; // Meetei Mayek\n\tif (cp >= 0xabec && cp <= 0xabed) return LineBreakClass.CM;\n\tif (cp === 0xfb1e) return LineBreakClass.CM; // Hebrew\n\tif (cp >= 0xfe00 && cp <= 0xfe0f) return LineBreakClass.CM; // Variation Selectors\n\tif (cp >= 0xfe20 && cp <= 0xfe2f) return LineBreakClass.CM; // Combining Half Marks\n\tif (cp >= 0x101fd && cp <= 0x101fd) return LineBreakClass.CM; // Phaistos\n\tif (cp >= 0x102e0 && cp <= 0x102e0) return LineBreakClass.CM; // Coptic Epact\n\tif (cp >= 0x10376 && cp <= 0x1037a) return LineBreakClass.CM; // Old Permic\n\tif (cp >= 0x10a01 && cp <= 0x10a0f) return LineBreakClass.CM; // Kharoshthi\n\tif (cp >= 0x10a38 && cp <= 0x10a3f) return LineBreakClass.CM;\n\tif (cp >= 0x10ae5 && cp <= 0x10ae6) return LineBreakClass.CM; // Manichaean\n\tif (cp >= 0x10d24 && cp <= 0x10d27) return LineBreakClass.CM; // Hanifi Rohingya\n\tif (cp >= 0x10eab && cp <= 0x10eac) return LineBreakClass.CM; // Yezidi\n\tif (cp >= 0x10f46 && cp <= 0x10f50) return LineBreakClass.CM; // Sogdian\n\tif (cp >= 0x10f82 && cp <= 0x10f85) return LineBreakClass.CM; // Old Uyghur\n\tif (cp >= 0x11000 && cp <= 0x11002) return LineBreakClass.CM; // Brahmi\n\tif (cp >= 0x11038 && cp <= 0x11046) return LineBreakClass.CM;\n\tif (cp >= 0x11070 && cp <= 0x11070) return LineBreakClass.CM;\n\tif (cp >= 0x11073 && cp <= 0x11074) return LineBreakClass.CM;\n\tif (cp >= 0x1107f && cp <= 0x11082) return LineBreakClass.CM;\n\tif (cp >= 0x110b0 && cp <= 0x110c2) return LineBreakClass.CM; // Kaithi\n\tif (cp >= 0x11100 && cp <= 0x11102) return LineBreakClass.CM; // Chakma\n\tif (cp >= 0x11127 && cp <= 0x11134) return LineBreakClass.CM;\n\tif (cp === 0x11145) return LineBreakClass.CM;\n\tif (cp === 0x11146) return LineBreakClass.CM;\n\tif (cp >= 0x11173 && cp <= 0x11173) return LineBreakClass.CM; // Mahajani\n\tif (cp >= 0x11180 && cp <= 0x11182) return LineBreakClass.CM; // Sharada\n\tif (cp >= 0x111b3 && cp <= 0x111c0) return LineBreakClass.CM;\n\tif (cp >= 0x111c9 && cp <= 0x111cc) return LineBreakClass.CM;\n\tif (cp === 0x111ce) return LineBreakClass.CM;\n\tif (cp === 0x111cf) return LineBreakClass.CM;\n\tif (cp >= 0x1122c && cp <= 0x11237) return LineBreakClass.CM; // Khojki\n\tif (cp === 0x1123e) return LineBreakClass.CM;\n\tif (cp >= 0x112df && cp <= 0x112ea) return LineBreakClass.CM; // Khudawadi\n\tif (cp >= 0x11300 && cp <= 0x11303) return LineBreakClass.CM; // Grantha\n\tif (cp >= 0x1133b && cp <= 0x1133c) return LineBreakClass.CM;\n\tif (cp >= 0x1133e && cp <= 0x1134d) return LineBreakClass.CM;\n\tif (cp >= 0x11357 && cp <= 0x11357) return LineBreakClass.CM;\n\tif (cp >= 0x11362 && cp <= 0x11374) return LineBreakClass.CM;\n\tif (cp >= 0x11435 && cp <= 0x11446) return LineBreakClass.CM; // Newa\n\tif (cp === 0x1145e) return LineBreakClass.CM;\n\tif (cp >= 0x114b0 && cp <= 0x114c3) return LineBreakClass.CM; // Tirhuta\n\tif (cp >= 0x115af && cp <= 0x115c0) return LineBreakClass.CM; // Siddham\n\tif (cp >= 0x115dc && cp <= 0x115dd) return LineBreakClass.CM;\n\tif (cp >= 0x11630 && cp <= 0x11640) return LineBreakClass.CM; // Modi\n\tif (cp >= 0x116ab && cp <= 0x116b7) return LineBreakClass.CM; // Takri\n\tif (cp >= 0x1171d && cp <= 0x1172b) return LineBreakClass.CM; // Ahom\n\tif (cp >= 0x1182c && cp <= 0x1183a) return LineBreakClass.CM; // Dogra\n\tif (cp >= 0x11930 && cp <= 0x11935) return LineBreakClass.CM; // Dives Akuru\n\tif (cp >= 0x11937 && cp <= 0x11938) return LineBreakClass.CM;\n\tif (cp >= 0x1193b && cp <= 0x1193e) return LineBreakClass.CM;\n\tif (cp === 0x11940) return LineBreakClass.CM;\n\tif (cp >= 0x11942 && cp <= 0x11943) return LineBreakClass.CM;\n\tif (cp >= 0x119d1 && cp <= 0x119d7) return LineBreakClass.CM; // Nandinagari\n\tif (cp >= 0x119da && cp <= 0x119e0) return LineBreakClass.CM;\n\tif (cp === 0x119e4) return LineBreakClass.CM;\n\tif (cp >= 0x11a01 && cp <= 0x11a0a) return LineBreakClass.CM; // Zanabazar Square\n\tif (cp >= 0x11a33 && cp <= 0x11a39) return LineBreakClass.CM;\n\tif (cp >= 0x11a3b && cp <= 0x11a3e) return LineBreakClass.CM;\n\tif (cp === 0x11a47) return LineBreakClass.CM;\n\tif (cp >= 0x11a51 && cp <= 0x11a5b) return LineBreakClass.CM; // Soyombo\n\tif (cp >= 0x11a8a && cp <= 0x11a99) return LineBreakClass.CM;\n\tif (cp >= 0x11c2f && cp <= 0x11c36) return LineBreakClass.CM; // Bhaiksuki\n\tif (cp >= 0x11c38 && cp <= 0x11c3f) return LineBreakClass.CM;\n\tif (cp >= 0x11c92 && cp <= 0x11ca7) return LineBreakClass.CM; // Marchen\n\tif (cp >= 0x11ca9 && cp <= 0x11cb6) return LineBreakClass.CM;\n\tif (cp >= 0x11d31 && cp <= 0x11d45) return LineBreakClass.CM; // Masaram Gondi\n\tif (cp === 0x11d47) return LineBreakClass.CM;\n\tif (cp >= 0x11d8a && cp <= 0x11d97) return LineBreakClass.CM; // Gunjala Gondi\n\tif (cp >= 0x11ef3 && cp <= 0x11ef6) return LineBreakClass.CM; // Makasar\n\tif (cp >= 0x16af0 && cp <= 0x16af4) return LineBreakClass.CM; // Bassa Vah\n\tif (cp >= 0x16b30 && cp <= 0x16b36) return LineBreakClass.CM; // Pahawh Hmong\n\tif (cp === 0x16f4f) return LineBreakClass.CM; // Miao\n\tif (cp >= 0x16f51 && cp <= 0x16f87) return LineBreakClass.CM;\n\tif (cp >= 0x16f8f && cp <= 0x16f92) return LineBreakClass.CM;\n\tif (cp >= 0x16fe4 && cp <= 0x16fe4) return LineBreakClass.CM; // Khitan Small Script\n\tif (cp >= 0x16ff0 && cp <= 0x16ff1) return LineBreakClass.CM;\n\tif (cp >= 0x1bc9d && cp <= 0x1bc9e) return LineBreakClass.CM; // Duployan\n\tif (cp >= 0x1cf00 && cp <= 0x1cf46) return LineBreakClass.CM; // Znamenny Musical Notation\n\tif (cp >= 0x1d165 && cp <= 0x1d169) return LineBreakClass.CM; // Musical Symbols\n\tif (cp >= 0x1d16d && cp <= 0x1d172) return LineBreakClass.CM;\n\tif (cp >= 0x1d17b && cp <= 0x1d182) return LineBreakClass.CM;\n\tif (cp >= 0x1d185 && cp <= 0x1d18b) return LineBreakClass.CM;\n\tif (cp >= 0x1d1aa && cp <= 0x1d1ad) return LineBreakClass.CM;\n\tif (cp >= 0x1d242 && cp <= 0x1d244) return LineBreakClass.CM;\n\tif (cp >= 0x1da00 && cp <= 0x1da36) return LineBreakClass.CM; // Sutton SignWriting\n\tif (cp >= 0x1da3b && cp <= 0x1da6c) return LineBreakClass.CM;\n\tif (cp === 0x1da75) return LineBreakClass.CM;\n\tif (cp === 0x1da84) return LineBreakClass.CM;\n\tif (cp >= 0x1da9b && cp <= 0x1daaf) return LineBreakClass.CM;\n\tif (cp >= 0x1e000 && cp <= 0x1e02a) return LineBreakClass.CM; // Glagolitic Supplement\n\tif (cp >= 0x1e130 && cp <= 0x1e136) return LineBreakClass.CM; // Nyiakeng Puachue Hmong\n\tif (cp >= 0x1e2ae && cp <= 0x1e2ae) return LineBreakClass.CM; // Toto\n\tif (cp >= 0x1e2ec && cp <= 0x1e2ef) return LineBreakClass.CM; // Wancho\n\tif (cp >= 0x1e8d0 && cp <= 0x1e8d6) return LineBreakClass.CM; // Mende Kikakui\n\tif (cp >= 0x1e944 && cp <= 0x1e94a) return LineBreakClass.CM; // Adlam\n\tif (cp >= 0xe0100 && cp <= 0xe01ef) return LineBreakClass.CM; // Variation Selectors Supplement\n\n\t// Punctuation\n\tif (cp === 0x0021) return LineBreakClass.EX; // !\n\tif (cp === 0x003f) return LineBreakClass.EX; // ?\n\tif (cp === 0x0022) return LineBreakClass.QU; // \"\n\tif (cp === 0x0027) return LineBreakClass.QU; // '\n\tif (cp === 0x0028) return LineBreakClass.OP; // (\n\tif (cp === 0x0029) return LineBreakClass.CP; // )\n\tif (cp === 0x005b) return LineBreakClass.OP; // [\n\tif (cp === 0x005d) return LineBreakClass.CP; // ]\n\tif (cp === 0x007b) return LineBreakClass.OP; // {\n\tif (cp === 0x007d) return LineBreakClass.CL; // }\n\tif (cp === 0x002c) return LineBreakClass.IS; // ,\n\tif (cp === 0x002e) return LineBreakClass.IS; // .\n\tif (cp === 0x003a) return LineBreakClass.IS; // :\n\tif (cp === 0x003b) return LineBreakClass.IS; // ;\n\tif (cp === 0x002d) return LineBreakClass.HY; // -\n\tif (cp === 0x2010) return LineBreakClass.BA; // Hyphen\n\tif (cp === 0x2013) return LineBreakClass.BA; // En Dash\n\tif (cp === 0x2014) return LineBreakClass.B2; // Em Dash\n\tif (cp === 0x2018 || cp === 0x2019) return LineBreakClass.QU; // Single quotes\n\tif (cp === 0x201c || cp === 0x201d) return LineBreakClass.QU; // Double quotes\n\tif (cp === 0x2026) return LineBreakClass.IN; // Ellipsis\n\n\t// CJK punctuation\n\tif (cp === 0x3001 || cp === 0x3002) return LineBreakClass.CL; // Ideographic comma, period\n\tif (cp === 0x3008) return LineBreakClass.OP;\n\tif (cp === 0x3009) return LineBreakClass.CL;\n\tif (cp === 0x300a) return LineBreakClass.OP;\n\tif (cp === 0x300b) return LineBreakClass.CL;\n\tif (cp === 0x300c) return LineBreakClass.OP;\n\tif (cp === 0x300d) return LineBreakClass.CL;\n\tif (cp === 0x300e) return LineBreakClass.OP;\n\tif (cp === 0x300f) return LineBreakClass.CL;\n\tif (cp === 0x3010) return LineBreakClass.OP;\n\tif (cp === 0x3011) return LineBreakClass.CL;\n\tif (cp === 0x3014) return LineBreakClass.OP;\n\tif (cp === 0x3015) return LineBreakClass.CL;\n\tif (cp === 0x3016) return LineBreakClass.OP;\n\tif (cp === 0x3017) return LineBreakClass.CL;\n\tif (cp >= 0x3018 && cp <= 0x301b)\n\t\treturn cp % 2 === 0 ? LineBreakClass.OP : LineBreakClass.CL;\n\tif (cp === 0xff08) return LineBreakClass.OP; // Fullwidth (\n\tif (cp === 0xff09) return LineBreakClass.CL; // Fullwidth )\n\tif (cp === 0xff0c) return LineBreakClass.CL; // Fullwidth ,\n\tif (cp === 0xff0e) return LineBreakClass.CL; // Fullwidth .\n\tif (cp === 0xff1a) return LineBreakClass.NS; // Fullwidth :\n\tif (cp === 0xff1b) return LineBreakClass.NS; // Fullwidth ;\n\tif (cp === 0xff1f) return LineBreakClass.EX; // Fullwidth ?\n\tif (cp === 0xff01) return LineBreakClass.EX; // Fullwidth !\n\n\t// Small Kana\n\tif (cp >= 0x3041 && cp <= 0x3096) {\n\t\t// Check for small kana\n\t\tif (\n\t\t\tcp === 0x3041 ||\n\t\t\tcp === 0x3043 ||\n\t\t\tcp === 0x3045 ||\n\t\t\tcp === 0x3047 ||\n\t\t\tcp === 0x3049 ||\n\t\t\tcp === 0x3063 ||\n\t\t\tcp === 0x3083 ||\n\t\t\tcp === 0x3085 ||\n\t\t\tcp === 0x3087 ||\n\t\t\tcp === 0x308e ||\n\t\t\tcp === 0x3095 ||\n\t\t\tcp === 0x3096\n\t\t)\n\t\t\treturn LineBreakClass.CJ;\n\t\treturn LineBreakClass.ID;\n\t}\n\tif (cp >= 0x30a1 && cp <= 0x30fa) {\n\t\t// Check for small katakana\n\t\tif (\n\t\t\tcp === 0x30a1 ||\n\t\t\tcp === 0x30a3 ||\n\t\t\tcp === 0x30a5 ||\n\t\t\tcp === 0x30a7 ||\n\t\t\tcp === 0x30a9 ||\n\t\t\tcp === 0x30c3 ||\n\t\t\tcp === 0x30e3 ||\n\t\t\tcp === 0x30e5 ||\n\t\t\tcp === 0x30e7 ||\n\t\t\tcp === 0x30ee ||\n\t\t\tcp === 0x30f5 ||\n\t\t\tcp === 0x30f6\n\t\t)\n\t\t\treturn LineBreakClass.CJ;\n\t\treturn LineBreakClass.ID;\n\t}\n\n\t// Hiragana/Katakana prolonged sound mark\n\tif (cp === 0x30fc) return LineBreakClass.CJ;\n\n\t// Hangul\n\tif (cp >= 0x1100 && cp <= 0x115f) return LineBreakClass.JL;\n\tif (cp >= 0xa960 && cp <= 0xa97c) return LineBreakClass.JL;\n\tif (cp >= 0x1160 && cp <= 0x11a7) return LineBreakClass.JV;\n\tif (cp >= 0xd7b0 && cp <= 0xd7c6) return LineBreakClass.JV;\n\tif (cp >= 0x11a8 && cp <= 0x11ff) return LineBreakClass.JT;\n\tif (cp >= 0xd7cb && cp <= 0xd7fb) return LineBreakClass.JT;\n\t// Hangul syllables\n\tif (cp >= 0xac00 && cp <= 0xd7a3) {\n\t\tconst sIndex = cp - 0xac00;\n\t\tif (sIndex % 28 === 0) return LineBreakClass.H2;\n\t\treturn LineBreakClass.H3;\n\t}\n\n\t// Numbers\n\tif (cp >= 0x0030 && cp <= 0x0039) return LineBreakClass.NU;\n\tif (cp >= 0x0660 && cp <= 0x0669) return LineBreakClass.NU; // Arabic-Indic\n\tif (cp >= 0x06f0 && cp <= 0x06f9) return LineBreakClass.NU; // Extended Arabic-Indic\n\tif (cp >= 0x0966 && cp <= 0x096f) return LineBreakClass.NU; // Devanagari\n\tif (cp >= 0xff10 && cp <= 0xff19) return LineBreakClass.NU; // Fullwidth\n\n\t// Currency symbols\n\tif (cp === 0x0024) return LineBreakClass.PR; // $\n\tif (cp === 0x00a3) return LineBreakClass.PR; // £\n\tif (cp === 0x00a5) return LineBreakClass.PR; // ¥\n\tif (cp === 0x20ac) return LineBreakClass.PR; // €\n\tif (cp === 0x0025) return LineBreakClass.PO; // %\n\n\t// Hebrew\n\tif (cp >= 0x05d0 && cp <= 0x05ea) return LineBreakClass.HL;\n\tif (cp >= 0xfb1d && cp <= 0xfb4f) return LineBreakClass.HL;\n\n\t// CJK Ideographs\n\tif (cp >= 0x4e00 && cp <= 0x9fff) return LineBreakClass.ID;\n\tif (cp >= 0x3400 && cp <= 0x4dbf) return LineBreakClass.ID;\n\tif (cp >= 0x20000 && cp <= 0x2a6df) return LineBreakClass.ID;\n\tif (cp >= 0x2a700 && cp <= 0x2b73f) return LineBreakClass.ID;\n\tif (cp >= 0x2b740 && cp <= 0x2b81f) return LineBreakClass.ID;\n\tif (cp >= 0x2b820 && cp <= 0x2ceaf) return LineBreakClass.ID;\n\tif (cp >= 0x2ceb0 && cp <= 0x2ebef) return LineBreakClass.ID;\n\tif (cp >= 0x30000 && cp <= 0x3134f) return LineBreakClass.ID;\n\tif (cp >= 0xf900 && cp <= 0xfaff) return LineBreakClass.ID;\n\tif (cp >= 0x2f800 && cp <= 0x2fa1f) return LineBreakClass.ID;\n\n\t// Emoji\n\tif (cp >= 0x1f300 && cp <= 0x1f9ff) return LineBreakClass.ID;\n\tif (cp >= 0x1fa00 && cp <= 0x1faff) return LineBreakClass.ID;\n\tif (cp >= 0x2600 && cp <= 0x26ff) return LineBreakClass.ID;\n\tif (cp >= 0x2700 && cp <= 0x27bf) return LineBreakClass.ID;\n\n\t// Regional indicators\n\tif (cp >= 0x1f1e0 && cp <= 0x1f1ff) return LineBreakClass.RI;\n\n\t// Emoji modifiers\n\tif (cp >= 0x1f3fb && cp <= 0x1f3ff) return LineBreakClass.EM;\n\n\t// Thai\n\tif (cp >= 0x0e00 && cp <= 0x0e7f) return LineBreakClass.SA;\n\n\t// Lao\n\tif (cp >= 0x0e80 && cp <= 0x0eff) return LineBreakClass.SA;\n\n\t// Myanmar\n\tif (cp >= 0x1000 && cp <= 0x109f) return LineBreakClass.SA;\n\tif (cp >= 0xa9e0 && cp <= 0xa9ff) return LineBreakClass.SA;\n\tif (cp >= 0xaa60 && cp <= 0xaa7f) return LineBreakClass.SA;\n\n\t// Khmer\n\tif (cp >= 0x1780 && cp <= 0x17ff) return LineBreakClass.SA;\n\tif (cp >= 0x19e0 && cp <= 0x19ff) return LineBreakClass.SA;\n\n\t// Default: treat as alphabetic\n\tif (cp >= 0x0041 && cp <= 0x005a) return LineBreakClass.AL; // A-Z\n\tif (cp >= 0x0061 && cp <= 0x007a) return LineBreakClass.AL; // a-z\n\tif (cp >= 0x00c0 && cp <= 0x024f) return LineBreakClass.AL; // Latin Extended\n\n\t// Arabic\n\tif (cp >= 0x0600 && cp <= 0x06ff) return LineBreakClass.AL;\n\tif (cp >= 0x0750 && cp <= 0x077f) return LineBreakClass.AL;\n\tif (cp >= 0x08a0 && cp <= 0x08ff) return LineBreakClass.AL;\n\n\t// Devanagari and other Indic\n\tif (cp >= 0x0900 && cp <= 0x097f) return LineBreakClass.AL;\n\tif (cp >= 0x0980 && cp <= 0x09ff) return LineBreakClass.AL;\n\tif (cp >= 0x0a00 && cp <= 0x0a7f) return LineBreakClass.AL;\n\tif (cp >= 0x0a80 && cp <= 0x0aff) return LineBreakClass.AL;\n\tif (cp >= 0x0b00 && cp <= 0x0b7f) return LineBreakClass.AL;\n\tif (cp >= 0x0b80 && cp <= 0x0bff) return LineBreakClass.AL;\n\tif (cp >= 0x0c00 && cp <= 0x0c7f) return LineBreakClass.AL;\n\tif (cp >= 0x0c80 && cp <= 0x0cff) return LineBreakClass.AL;\n\tif (cp >= 0x0d00 && cp <= 0x0d7f) return LineBreakClass.AL;\n\n\t// Cyrillic\n\tif (cp >= 0x0400 && cp <= 0x04ff) return LineBreakClass.AL;\n\tif (cp >= 0x0500 && cp <= 0x052f) return LineBreakClass.AL;\n\n\t// Greek\n\tif (cp >= 0x0370 && cp <= 0x03ff) return LineBreakClass.AL;\n\n\treturn LineBreakClass.XX;\n}\n\n/**\n * Pair table for line break classes\n * Returns whether a break is allowed between two classes\n */\nfunction getPairAction(\n\tbefore: LineBreakClass,\n\tafter: LineBreakClass,\n): BreakAction {\n\t// LB1: Resolve AI, CB, CJ, SA, SG, XX -> AL (simplified)\n\tif (before === LineBreakClass.AI) before = LineBreakClass.AL;\n\tif (before === LineBreakClass.SA) before = LineBreakClass.AL;\n\tif (before === LineBreakClass.SG) before = LineBreakClass.AL;\n\tif (before === LineBreakClass.XX) before = LineBreakClass.AL;\n\tif (before === LineBreakClass.CJ) before = LineBreakClass.NS;\n\n\tif (after === LineBreakClass.AI) after = LineBreakClass.AL;\n\tif (after === LineBreakClass.SA) after = LineBreakClass.AL;\n\tif (after === LineBreakClass.SG) after = LineBreakClass.AL;\n\tif (after === LineBreakClass.XX) after = LineBreakClass.AL;\n\tif (after === LineBreakClass.CJ) after = LineBreakClass.NS;\n\n\t// LB4: Always break after hard line breaks\n\tif (before === LineBreakClass.BK) return BreakAction.Explicit;\n\n\t// LB5: Treat CR followed by LF, as well as CR, LF, and NL as hard line breaks\n\tif (before === LineBreakClass.CR && after === LineBreakClass.LF)\n\t\treturn BreakAction.Prohibited;\n\tif (\n\t\tbefore === LineBreakClass.CR ||\n\t\tbefore === LineBreakClass.LF ||\n\t\tbefore === LineBreakClass.NL\n\t)\n\t\treturn BreakAction.Explicit;\n\n\t// LB6: Do not break before hard line breaks\n\tif (\n\t\tafter === LineBreakClass.BK ||\n\t\tafter === LineBreakClass.CR ||\n\t\tafter === LineBreakClass.LF ||\n\t\tafter === LineBreakClass.NL\n\t)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB7: Do not break before spaces or zero width space\n\tif (after === LineBreakClass.SP || after === LineBreakClass.ZW)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB8: Break before any character following a zero-width space\n\tif (before === LineBreakClass.ZW) return BreakAction.Direct;\n\n\t// LB8a: Do not break after a zero width joiner\n\tif (before === LineBreakClass.ZWJ) return BreakAction.Prohibited;\n\n\t// LB9: Do not break a combining character sequence\n\t// Note: BK, CR, LF, NL, ZW are already handled by early returns above\n\tif (after === LineBreakClass.CM || after === LineBreakClass.ZWJ) {\n\t\tif (before !== LineBreakClass.SP) return BreakAction.Prohibited;\n\t}\n\n\t// LB10: Treat any remaining combining mark or ZWJ as AL\n\t// Use type assertion since we know these could be CM/ZWJ from above\n\tlet beforeResolved: LineBreakClass = before;\n\tlet afterResolved: LineBreakClass = after;\n\tif (before === LineBreakClass.CM || (before as number) === LineBreakClass.ZWJ)\n\t\tbeforeResolved = LineBreakClass.AL;\n\tif (after === LineBreakClass.CM || after === LineBreakClass.ZWJ)\n\t\tafterResolved = LineBreakClass.AL;\n\tbefore = beforeResolved;\n\tafter = afterResolved;\n\n\t// LB11: Do not break before or after Word Joiner\n\tif (before === LineBreakClass.WJ || after === LineBreakClass.WJ)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB12: Do not break after NBSP and related characters\n\tif (before === LineBreakClass.GL) return BreakAction.Prohibited;\n\n\t// LB12a: Do not break before NBSP and related characters, except after spaces and hyphens\n\tif (after === LineBreakClass.GL) {\n\t\tif (\n\t\t\tbefore !== LineBreakClass.SP &&\n\t\t\tbefore !== LineBreakClass.BA &&\n\t\t\tbefore !== LineBreakClass.HY\n\t\t)\n\t\t\treturn BreakAction.Prohibited;\n\t}\n\n\t// LB13: Do not break before ']' or '!' or ';' or '/', even after spaces\n\tif (\n\t\tafter === LineBreakClass.CL ||\n\t\tafter === LineBreakClass.CP ||\n\t\tafter === LineBreakClass.EX ||\n\t\tafter === LineBreakClass.IS ||\n\t\tafter === LineBreakClass.SY\n\t)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB14: Do not break after '[', even after spaces\n\tif (before === LineBreakClass.OP) return BreakAction.Prohibited;\n\n\t// LB15: Do not break within '\"[', even with intervening spaces\n\tif (before === LineBreakClass.QU && after === LineBreakClass.OP)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB16: Do not break between closing punctuation and nonstarter\n\tif (\n\t\t(before === LineBreakClass.CL || before === LineBreakClass.CP) &&\n\t\tafter === LineBreakClass.NS\n\t)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB17: Do not break within '——', even with intervening spaces\n\tif (before === LineBreakClass.B2 && after === LineBreakClass.B2)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB18: Break after spaces\n\tif (before === LineBreakClass.SP) return BreakAction.Direct;\n\n\t// LB19: Do not break before or after quotation marks\n\tif (before === LineBreakClass.QU || after === LineBreakClass.QU)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB20: Break before and after unresolved CB\n\tif (before === LineBreakClass.CB || after === LineBreakClass.CB)\n\t\treturn BreakAction.Direct;\n\n\t// LB21: Do not break before hyphen-minus, etc.\n\t// Note: LB21a (Hebrew + Hyphen) is subsumed by this rule\n\tif (\n\t\tafter === LineBreakClass.BA ||\n\t\tafter === LineBreakClass.HY ||\n\t\tafter === LineBreakClass.NS\n\t)\n\t\treturn BreakAction.Prohibited;\n\tif (before === LineBreakClass.BB) return BreakAction.Prohibited;\n\n\t// LB21b: Don't break between Solidus and Hebrew letters\n\tif (before === LineBreakClass.SY && after === LineBreakClass.HL)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB22: Do not break before ellipses\n\tif (after === LineBreakClass.IN) return BreakAction.Prohibited;\n\n\t// LB23: Do not break between digits and letters\n\tif (\n\t\t(before === LineBreakClass.AL || before === LineBreakClass.HL) &&\n\t\tafter === LineBreakClass.NU\n\t)\n\t\treturn BreakAction.Prohibited;\n\tif (\n\t\tbefore === LineBreakClass.NU &&\n\t\t(after === LineBreakClass.AL || after === LineBreakClass.HL)\n\t)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB23a: Do not break between numeric prefixes/postfixes and ideographs\n\tif (before === LineBreakClass.PR && after === LineBreakClass.ID)\n\t\treturn BreakAction.Prohibited;\n\tif (before === LineBreakClass.ID && after === LineBreakClass.PO)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB24: Do not break between numeric prefix/postfix and letters\n\tif (\n\t\t(before === LineBreakClass.PR || before === LineBreakClass.PO) &&\n\t\t(after === LineBreakClass.AL || after === LineBreakClass.HL)\n\t)\n\t\treturn BreakAction.Prohibited;\n\tif (\n\t\t(before === LineBreakClass.AL || before === LineBreakClass.HL) &&\n\t\t(after === LineBreakClass.PR || after === LineBreakClass.PO)\n\t)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB25: Do not break between numbers\n\tif (\n\t\t(before === LineBreakClass.CL || before === LineBreakClass.CP) &&\n\t\tafter === LineBreakClass.NU\n\t)\n\t\treturn BreakAction.Prohibited;\n\tif (\n\t\tbefore === LineBreakClass.NU &&\n\t\t(after === LineBreakClass.PO || after === LineBreakClass.PR)\n\t)\n\t\treturn BreakAction.Prohibited;\n\tif (\n\t\t(before === LineBreakClass.PO ||\n\t\t\tbefore === LineBreakClass.PR ||\n\t\t\tbefore === LineBreakClass.HY ||\n\t\t\tbefore === LineBreakClass.IS ||\n\t\t\tbefore === LineBreakClass.NU ||\n\t\t\tbefore === LineBreakClass.SY) &&\n\t\tafter === LineBreakClass.NU\n\t)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB26: Do not break a Korean syllable\n\tif (before === LineBreakClass.JL) {\n\t\tif (\n\t\t\tafter === LineBreakClass.JL ||\n\t\t\tafter === LineBreakClass.JV ||\n\t\t\tafter === LineBreakClass.H2 ||\n\t\t\tafter === LineBreakClass.H3\n\t\t)\n\t\t\treturn BreakAction.Prohibited;\n\t}\n\tif (before === LineBreakClass.JV || before === LineBreakClass.H2) {\n\t\tif (after === LineBreakClass.JV || after === LineBreakClass.JT)\n\t\t\treturn BreakAction.Prohibited;\n\t}\n\tif (before === LineBreakClass.JT || before === LineBreakClass.H3) {\n\t\tif (after === LineBreakClass.JT) return BreakAction.Prohibited;\n\t}\n\n\t// LB27: Treat Korean syllables as ID\n\tif (\n\t\tbefore === LineBreakClass.JL ||\n\t\tbefore === LineBreakClass.JV ||\n\t\tbefore === LineBreakClass.JT ||\n\t\tbefore === LineBreakClass.H2 ||\n\t\tbefore === LineBreakClass.H3\n\t) {\n\t\tif (after === LineBreakClass.PO) return BreakAction.Prohibited;\n\t}\n\tif (\n\t\tafter === LineBreakClass.JL ||\n\t\tafter === LineBreakClass.JV ||\n\t\tafter === LineBreakClass.JT ||\n\t\tafter === LineBreakClass.H2 ||\n\t\tafter === LineBreakClass.H3\n\t) {\n\t\tif (before === LineBreakClass.PR) return BreakAction.Prohibited;\n\t}\n\n\t// LB28: Do not break between alphabetics\n\tif (\n\t\t(before === LineBreakClass.AL || before === LineBreakClass.HL) &&\n\t\t(after === LineBreakClass.AL || after === LineBreakClass.HL)\n\t)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB29: Do not break between numeric punctuation and alphabetics\n\tif (\n\t\tbefore === LineBreakClass.IS &&\n\t\t(after === LineBreakClass.AL || after === LineBreakClass.HL)\n\t)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB30: Do not break between letters/numbers and opening/closing\n\tif (\n\t\t(before === LineBreakClass.AL ||\n\t\t\tbefore === LineBreakClass.HL ||\n\t\t\tbefore === LineBreakClass.NU) &&\n\t\tafter === LineBreakClass.OP\n\t)\n\t\treturn BreakAction.Prohibited;\n\tif (\n\t\tbefore === LineBreakClass.CP &&\n\t\t(after === LineBreakClass.AL ||\n\t\t\tafter === LineBreakClass.HL ||\n\t\t\tafter === LineBreakClass.NU)\n\t)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB30a: Break between pairs of regional indicator symbols\n\tif (before === LineBreakClass.RI && after === LineBreakClass.RI)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB30b: Do not break between an emoji base and an emoji modifier\n\tif (before === LineBreakClass.EB && after === LineBreakClass.EM)\n\t\treturn BreakAction.Prohibited;\n\n\t// LB31: Break everywhere else\n\treturn BreakAction.Direct;\n}\n\n/**\n * Result of line break analysis\n */\nexport interface LineBreakAnalysis {\n\t/** Break opportunities (one per character boundary) */\n\tbreaks: BreakOpportunity[];\n\t/** Line break classes for each character */\n\tclasses: LineBreakClass[];\n}\n\n/**\n * Analyze line break opportunities in text\n */\nexport function analyzeLineBreaks(text: string): LineBreakAnalysis {\n\tconst codepoints: number[] = [];\n\tfor (const char of text) {\n\t\tcodepoints.push(char.codePointAt(0) ?? 0);\n\t}\n\n\treturn analyzeLineBreaksFromCodepoints(codepoints);\n}\n\n/**\n * Analyze line break opportunities from codepoints\n */\nexport function analyzeLineBreaksFromCodepoints(\n\tcodepoints: number[],\n): LineBreakAnalysis {\n\tconst len = codepoints.length;\n\tconst classes: LineBreakClass[] = [];\n\tconst breaks: BreakOpportunity[] = [];\n\n\t// Get classes for all codepoints\n\tfor (const cp of codepoints) {\n\t\tclasses.push(getLineBreakClass(cp));\n\t}\n\n\t// LB1: Assign a line breaking class - done in getLineBreakClass\n\n\t// LB2: Never break at the start of text\n\tbreaks.push(BreakOpportunity.NoBreak);\n\n\t// Process each boundary\n\tfor (let i = 1; i < len; i++) {\n\t\tconst before = classes[i - 1]!;\n\t\tconst after = classes[i]!;\n\n\t\tconst action = getPairAction(before, after);\n\n\t\tswitch (action) {\n\t\t\tcase BreakAction.Explicit:\n\t\t\t\tbreaks.push(BreakOpportunity.Mandatory);\n\t\t\t\tbreak;\n\t\t\tcase BreakAction.Direct:\n\t\t\t\tbreaks.push(BreakOpportunity.Optional);\n\t\t\t\tbreak;\n\t\t\tcase BreakAction.Indirect:\n\t\t\t\t// Look for intervening space\n\t\t\t\tif (before === LineBreakClass.SP) {\n\t\t\t\t\tbreaks.push(BreakOpportunity.Optional);\n\t\t\t\t} else {\n\t\t\t\t\tbreaks.push(BreakOpportunity.NoBreak);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreaks.push(BreakOpportunity.NoBreak);\n\t\t}\n\t}\n\n\t// LB3: Always break at the end of text\n\tbreaks.push(BreakOpportunity.Mandatory);\n\n\treturn { breaks, classes };\n}\n\n/**\n * Analyze line breaks for glyph infos\n */\nexport function analyzeLineBreaksForGlyphs(\n\tinfos: GlyphInfo[],\n): LineBreakAnalysis {\n\tconst codepoints = infos.map((info) => info.codepoint);\n\treturn analyzeLineBreaksFromCodepoints(codepoints);\n}\n\n/**\n * Find next line break opportunity\n */\nexport function findNextBreak(\n\tanalysis: LineBreakAnalysis,\n\tstartIndex: number,\n): number {\n\tfor (let i = startIndex + 1; i < analysis.breaks.length; i++) {\n\t\tif (analysis.breaks[i] !== BreakOpportunity.NoBreak) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn analysis.breaks.length - 1;\n}\n\n/**\n * Check if break is allowed at position\n */\nexport function canBreakAt(\n\tanalysis: LineBreakAnalysis,\n\tindex: number,\n): boolean {\n\tif (index < 0 || index >= analysis.breaks.length) return false;\n\treturn analysis.breaks[index] !== BreakOpportunity.NoBreak;\n}\n\n/**\n * Check if break is mandatory at position\n */\nexport function mustBreakAt(\n\tanalysis: LineBreakAnalysis,\n\tindex: number,\n): boolean {\n\tif (index < 0 || index >= analysis.breaks.length) return false;\n\treturn analysis.breaks[index] === BreakOpportunity.Mandatory;\n}\n\n/**\n * Get all break opportunities\n */\nexport function getAllBreakOpportunities(\n\tanalysis: LineBreakAnalysis,\n): number[] {\n\tconst opportunities: number[] = [];\n\tfor (let i = 0; i < analysis.breaks.length; i++) {\n\t\tif (analysis.breaks[i] !== BreakOpportunity.NoBreak) {\n\t\t\topportunities.push(i);\n\t\t}\n\t}\n\treturn opportunities;\n}\n",
86
+ "/**\n * Unicode Text Segmentation (UAX #29)\n * Grapheme cluster and word boundaries\n */\n\nimport type { GlyphInfo } from \"../types.ts\";\n\n/**\n * Grapheme cluster break property\n */\nexport enum GraphemeBreakProperty {\n\tOther = 0,\n\tCR = 1,\n\tLF = 2,\n\tControl = 3,\n\tExtend = 4,\n\tZWJ = 5,\n\tRegional_Indicator = 6,\n\tPrepend = 7,\n\tSpacingMark = 8,\n\tL = 9, // Hangul L\n\tV = 10, // Hangul V\n\tT = 11, // Hangul T\n\tLV = 12, // Hangul LV\n\tLVT = 13, // Hangul LVT\n\tExtended_Pictographic = 14,\n}\n\n/**\n * Word break property\n */\nexport enum WordBreakProperty {\n\tOther = 0,\n\tCR = 1,\n\tLF = 2,\n\tNewline = 3,\n\tExtend = 4,\n\tZWJ = 5,\n\tRegional_Indicator = 6,\n\tFormat = 7,\n\tKatakana = 8,\n\tHebrew_Letter = 9,\n\tALetter = 10,\n\tSingle_Quote = 11,\n\tDouble_Quote = 12,\n\tMidNumLet = 13,\n\tMidLetter = 14,\n\tMidNum = 15,\n\tNumeric = 16,\n\tExtendNumLet = 17,\n\tWSegSpace = 18,\n\tExtended_Pictographic = 19,\n}\n\n/**\n * Get grapheme break property for codepoint\n */\nexport function getGraphemeBreakProperty(cp: number): GraphemeBreakProperty {\n\t// CR, LF\n\tif (cp === 0x000d) return GraphemeBreakProperty.CR;\n\tif (cp === 0x000a) return GraphemeBreakProperty.LF;\n\n\t// Control characters\n\tif (cp >= 0x0000 && cp <= 0x001f && cp !== 0x000a && cp !== 0x000d)\n\t\treturn GraphemeBreakProperty.Control;\n\tif (cp >= 0x007f && cp <= 0x009f) return GraphemeBreakProperty.Control;\n\tif (cp === 0x00ad) return GraphemeBreakProperty.Control; // Soft hyphen\n\tif (cp === 0x061c) return GraphemeBreakProperty.Control; // ALM\n\tif (cp === 0x180e) return GraphemeBreakProperty.Control;\n\tif (cp === 0x200b) return GraphemeBreakProperty.Control; // ZWSP\n\tif (cp >= 0x200e && cp <= 0x200f) return GraphemeBreakProperty.Control; // LRM, RLM\n\tif (cp >= 0x2028 && cp <= 0x202e) return GraphemeBreakProperty.Control;\n\tif (cp >= 0x2060 && cp <= 0x206f) return GraphemeBreakProperty.Control;\n\tif (cp === 0xfeff) return GraphemeBreakProperty.Control; // BOM\n\tif (cp >= 0xfff0 && cp <= 0xfffb) return GraphemeBreakProperty.Control;\n\n\t// ZWJ\n\tif (cp === 0x200d) return GraphemeBreakProperty.ZWJ;\n\n\t// Regional Indicator\n\tif (cp >= 0x1f1e0 && cp <= 0x1f1ff) return GraphemeBreakProperty.Regional_Indicator;\n\n\t// Prepend\n\tif (cp === 0x0600 || cp === 0x0601 || cp === 0x0602 || cp === 0x0603 ||\n\t\tcp === 0x0604 || cp === 0x0605 || cp === 0x06dd || cp === 0x070f ||\n\t\tcp === 0x0890 || cp === 0x0891 || cp === 0x08e2 || cp === 0x110bd ||\n\t\tcp === 0x110cd)\n\t\treturn GraphemeBreakProperty.Prepend;\n\n\t// Hangul L (Leading consonants)\n\tif (cp >= 0x1100 && cp <= 0x115f) return GraphemeBreakProperty.L;\n\tif (cp >= 0xa960 && cp <= 0xa97c) return GraphemeBreakProperty.L;\n\n\t// Hangul V (Vowels)\n\tif (cp >= 0x1160 && cp <= 0x11a7) return GraphemeBreakProperty.V;\n\tif (cp >= 0xd7b0 && cp <= 0xd7c6) return GraphemeBreakProperty.V;\n\n\t// Hangul T (Trailing consonants)\n\tif (cp >= 0x11a8 && cp <= 0x11ff) return GraphemeBreakProperty.T;\n\tif (cp >= 0xd7cb && cp <= 0xd7fb) return GraphemeBreakProperty.T;\n\n\t// Hangul syllables\n\tif (cp >= 0xac00 && cp <= 0xd7a3) {\n\t\tconst sIndex = cp - 0xac00;\n\t\tif (sIndex % 28 === 0) return GraphemeBreakProperty.LV;\n\t\treturn GraphemeBreakProperty.LVT;\n\t}\n\n\t// Extended Pictographic (Emoji)\n\tif (cp >= 0x1f300 && cp <= 0x1f9ff) return GraphemeBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x1fa00 && cp <= 0x1faff) return GraphemeBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x2600 && cp <= 0x26ff) return GraphemeBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x2700 && cp <= 0x27bf) return GraphemeBreakProperty.Extended_Pictographic;\n\tif (cp === 0x00a9 || cp === 0x00ae) return GraphemeBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x2300 && cp <= 0x23ff) return GraphemeBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x1f000 && cp <= 0x1f02f) return GraphemeBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x1f0a0 && cp <= 0x1f0ff) return GraphemeBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x1f100 && cp <= 0x1f1ff) return GraphemeBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x1f200 && cp <= 0x1f2ff) return GraphemeBreakProperty.Extended_Pictographic;\n\n\t// Spacing Mark\n\tif (cp >= 0x0903 && cp <= 0x0903) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x093b && cp <= 0x093b) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x093e && cp <= 0x0940) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0949 && cp <= 0x094c) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x094e && cp <= 0x094f) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0982 && cp <= 0x0983) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x09be && cp <= 0x09c0) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x09c7 && cp <= 0x09cc) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x09d7) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0a03 && cp <= 0x0a03) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0a3e && cp <= 0x0a40) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0a83 && cp <= 0x0a83) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0abe && cp <= 0x0ac0) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x0ac9) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0acb && cp <= 0x0acc) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0b02 && cp <= 0x0b03) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x0b3e) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x0b40) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0b47 && cp <= 0x0b4c) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x0b57) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0bbe && cp <= 0x0bbf) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0bc1 && cp <= 0x0bcc) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x0bd7) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0c01 && cp <= 0x0c03) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0c41 && cp <= 0x0c44) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0c82 && cp <= 0x0c83) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x0cbe) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0cc0 && cp <= 0x0cc4) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0cc7 && cp <= 0x0ccb) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0cd5 && cp <= 0x0cd6) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0d02 && cp <= 0x0d03) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0d3e && cp <= 0x0d40) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0d46 && cp <= 0x0d4c) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x0d57) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0d82 && cp <= 0x0d83) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0dcf && cp <= 0x0dd1) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0dd8 && cp <= 0x0ddf) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x0df2 && cp <= 0x0df3) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x0f3e || cp === 0x0f3f) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x0f7f) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x102b && cp <= 0x102c) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x1031) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x1038) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x103b && cp <= 0x103c) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x1056 && cp <= 0x1057) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x1062) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x1067 && cp <= 0x1068) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x1083 && cp <= 0x1084) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x1087 && cp <= 0x108c) return GraphemeBreakProperty.SpacingMark;\n\tif (cp === 0x108f) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x109a && cp <= 0x109c) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x17b6 && cp <= 0x17b6) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x17be && cp <= 0x17c5) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x17c7 && cp <= 0x17c8) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x1923 && cp <= 0x1926) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x1929 && cp <= 0x192b) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x1930 && cp <= 0x1931) return GraphemeBreakProperty.SpacingMark;\n\tif (cp >= 0x1933 && cp <= 0x1938) return GraphemeBreakProperty.SpacingMark;\n\n\t// Extend (combining marks, etc.)\n\tif (cp >= 0x0300 && cp <= 0x036f) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0483 && cp <= 0x0489) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0591 && cp <= 0x05bd) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x05bf) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x05c1 && cp <= 0x05c2) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x05c4 && cp <= 0x05c5) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x05c7) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0610 && cp <= 0x061a) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x064b && cp <= 0x065f) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0670) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x06d6 && cp <= 0x06dc) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x06df && cp <= 0x06e4) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x06e7 && cp <= 0x06e8) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x06ea && cp <= 0x06ed) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0711) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0730 && cp <= 0x074a) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x07a6 && cp <= 0x07b0) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x07eb && cp <= 0x07f3) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x07fd) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0816 && cp <= 0x0819) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x081b && cp <= 0x0823) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0825 && cp <= 0x0827) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0829 && cp <= 0x082d) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0859 && cp <= 0x085b) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x08d3 && cp <= 0x08e1) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x08e3 && cp <= 0x0902) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x093a) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x093c) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0941 && cp <= 0x0948) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x094d) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0951 && cp <= 0x0957) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0962 && cp <= 0x0963) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0981) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x09bc) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x09c1 && cp <= 0x09c4) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x09cd) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x09e2 && cp <= 0x09e3) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x09fe) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0a01 && cp <= 0x0a02) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0a3c) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0a41 && cp <= 0x0a42) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0a47 && cp <= 0x0a48) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0a4b && cp <= 0x0a4d) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0a51) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0a70 && cp <= 0x0a71) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0a75) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0a81 && cp <= 0x0a82) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0abc) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0ac1 && cp <= 0x0ac5) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0ac7 && cp <= 0x0ac8) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0acd) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0ae2 && cp <= 0x0ae3) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0afa && cp <= 0x0aff) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0b01) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0b3c) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0b3f) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0b41 && cp <= 0x0b44) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0b4d) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0b55 && cp <= 0x0b56) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0b62 && cp <= 0x0b63) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0b82) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0bc0) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0bcd) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0c00) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0c04) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0c3e && cp <= 0x0c40) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0c46 && cp <= 0x0c48) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0c4a && cp <= 0x0c4d) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0c55 && cp <= 0x0c56) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0c62 && cp <= 0x0c63) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0c81) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0cbc) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0cbf) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0cc6) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0ccc && cp <= 0x0ccd) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0ce2 && cp <= 0x0ce3) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0d00 && cp <= 0x0d01) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0d3b && cp <= 0x0d3c) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0d41 && cp <= 0x0d44) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0d4d) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0d62 && cp <= 0x0d63) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0d81) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0dca) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0dd2 && cp <= 0x0dd4) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0dd6) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0e31) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0e34 && cp <= 0x0e3a) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0e47 && cp <= 0x0e4e) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0eb1) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0eb4 && cp <= 0x0ebc) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0ec8 && cp <= 0x0ecd) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0f18 && cp <= 0x0f19) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0f35) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0f37) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0f39) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0f71 && cp <= 0x0f7e) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0f80 && cp <= 0x0f84) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0f86 && cp <= 0x0f87) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0f8d && cp <= 0x0f97) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x0f99 && cp <= 0x0fbc) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x0fc6) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x102d && cp <= 0x1030) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1032 && cp <= 0x1037) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1039 && cp <= 0x103a) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x103d && cp <= 0x103e) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1058 && cp <= 0x1059) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x105e && cp <= 0x1060) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1071 && cp <= 0x1074) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1082) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1085 && cp <= 0x1086) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x108d) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x109d) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x135d && cp <= 0x135f) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1712 && cp <= 0x1714) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1732 && cp <= 0x1734) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1752 && cp <= 0x1753) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1772 && cp <= 0x1773) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x17b4 && cp <= 0x17b5) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x17b7 && cp <= 0x17bd) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x17c6) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x17c9 && cp <= 0x17d3) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x17dd) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x180b && cp <= 0x180d) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x180f) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1885 && cp <= 0x1886) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x18a9) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1920 && cp <= 0x1922) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1927 && cp <= 0x1928) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1932) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1939 && cp <= 0x193b) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1a17 && cp <= 0x1a18) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1a1b) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1a56) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1a58 && cp <= 0x1a5e) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1a60) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1a62) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1a65 && cp <= 0x1a6c) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1a73 && cp <= 0x1a7c) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1a7f) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1ab0 && cp <= 0x1ace) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1b00 && cp <= 0x1b03) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1b34) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1b36 && cp <= 0x1b3a) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1b3c) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1b42) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1b6b && cp <= 0x1b73) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1b80 && cp <= 0x1b81) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1ba2 && cp <= 0x1ba5) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1ba8 && cp <= 0x1ba9) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1bab && cp <= 0x1bad) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1be6) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1be8 && cp <= 0x1be9) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1bed) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1bef && cp <= 0x1bf1) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1c2c && cp <= 0x1c33) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1c36 && cp <= 0x1c37) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1cd0 && cp <= 0x1cd2) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1cd4 && cp <= 0x1ce0) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1ce2 && cp <= 0x1ce8) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1ced) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x1cf4) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1cf8 && cp <= 0x1cf9) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1dc0 && cp <= 0x1dff) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x20d0 && cp <= 0x20f0) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x2cef && cp <= 0x2cf1) return GraphemeBreakProperty.Extend;\n\tif (cp === 0x2d7f) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x2de0 && cp <= 0x2dff) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x302a && cp <= 0x302f) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x3099 && cp <= 0x309a) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa66f && cp <= 0xa672) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa674 && cp <= 0xa67d) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa69e && cp <= 0xa69f) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa6f0 && cp <= 0xa6f1) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xa802) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xa806) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xa80b) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa825 && cp <= 0xa826) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xa82c) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa8c4 && cp <= 0xa8c5) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa8e0 && cp <= 0xa8f1) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xa8ff) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa926 && cp <= 0xa92d) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa947 && cp <= 0xa951) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa980 && cp <= 0xa982) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xa9b3) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa9b6 && cp <= 0xa9b9) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xa9bc && cp <= 0xa9bd) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xa9e5) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xaa29 && cp <= 0xaa2e) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xaa31 && cp <= 0xaa32) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xaa35 && cp <= 0xaa36) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xaa43) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xaa4c) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xaa7c) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xaab0) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xaab2 && cp <= 0xaab4) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xaab7 && cp <= 0xaab8) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xaabe && cp <= 0xaabf) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xaac1) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xaaec && cp <= 0xaaed) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xaaf6) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xabe5) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xabe8) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xabed) return GraphemeBreakProperty.Extend;\n\tif (cp === 0xfb1e) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xfe00 && cp <= 0xfe0f) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0xfe20 && cp <= 0xfe2f) return GraphemeBreakProperty.Extend;\n\tif (cp >= 0x1f3fb && cp <= 0x1f3ff) return GraphemeBreakProperty.Extend; // Emoji modifiers\n\tif (cp >= 0xe0100 && cp <= 0xe01ef) return GraphemeBreakProperty.Extend; // Variation selectors\n\n\treturn GraphemeBreakProperty.Other;\n}\n\n/**\n * Get word break property for codepoint\n */\nexport function getWordBreakProperty(cp: number): WordBreakProperty {\n\t// CR, LF, Newline\n\tif (cp === 0x000d) return WordBreakProperty.CR;\n\tif (cp === 0x000a) return WordBreakProperty.LF;\n\tif (cp === 0x000b || cp === 0x000c || cp === 0x0085 || cp === 0x2028 || cp === 0x2029)\n\t\treturn WordBreakProperty.Newline;\n\n\t// ZWJ\n\tif (cp === 0x200d) return WordBreakProperty.ZWJ;\n\n\t// Format characters\n\tif (cp === 0x00ad) return WordBreakProperty.Format;\n\tif (cp === 0x061c) return WordBreakProperty.Format;\n\tif (cp === 0x200b) return WordBreakProperty.Format;\n\tif (cp >= 0x200e && cp <= 0x200f) return WordBreakProperty.Format;\n\tif (cp >= 0x2060 && cp <= 0x206f) return WordBreakProperty.Format;\n\tif (cp === 0xfeff) return WordBreakProperty.Format;\n\n\t// Regional Indicator\n\tif (cp >= 0x1f1e0 && cp <= 0x1f1ff) return WordBreakProperty.Regional_Indicator;\n\n\t// Extended Pictographic\n\tif (cp >= 0x1f300 && cp <= 0x1f9ff) return WordBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x1fa00 && cp <= 0x1faff) return WordBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x2600 && cp <= 0x26ff) return WordBreakProperty.Extended_Pictographic;\n\tif (cp >= 0x2700 && cp <= 0x27bf) return WordBreakProperty.Extended_Pictographic;\n\n\t// Hebrew Letter\n\tif (cp >= 0x05d0 && cp <= 0x05ea) return WordBreakProperty.Hebrew_Letter;\n\tif (cp >= 0xfb1d && cp <= 0xfb4f) return WordBreakProperty.Hebrew_Letter;\n\n\t// Katakana\n\tif (cp >= 0x30a0 && cp <= 0x30ff) return WordBreakProperty.Katakana;\n\tif (cp === 0x3031 || cp === 0x3032 || cp === 0x3033 || cp === 0x3034 || cp === 0x3035)\n\t\treturn WordBreakProperty.Katakana;\n\tif (cp === 0x309b || cp === 0x309c) return WordBreakProperty.Katakana;\n\tif (cp >= 0x31f0 && cp <= 0x31ff) return WordBreakProperty.Katakana;\n\tif (cp >= 0x32d0 && cp <= 0x32fe) return WordBreakProperty.Katakana;\n\tif (cp >= 0x3300 && cp <= 0x3357) return WordBreakProperty.Katakana;\n\tif (cp >= 0xff66 && cp <= 0xff9d) return WordBreakProperty.Katakana;\n\n\t// Single Quote\n\tif (cp === 0x0027) return WordBreakProperty.Single_Quote;\n\n\t// Double Quote\n\tif (cp === 0x0022) return WordBreakProperty.Double_Quote;\n\n\t// MidNumLet\n\tif (cp === 0x002e) return WordBreakProperty.MidNumLet; // .\n\tif (cp === 0x2018 || cp === 0x2019) return WordBreakProperty.MidNumLet;\n\tif (cp === 0x2024) return WordBreakProperty.MidNumLet;\n\tif (cp === 0xfe52) return WordBreakProperty.MidNumLet;\n\tif (cp === 0xff07) return WordBreakProperty.MidNumLet;\n\tif (cp === 0xff0e) return WordBreakProperty.MidNumLet;\n\n\t// MidLetter\n\tif (cp === 0x003a) return WordBreakProperty.MidLetter; // :\n\tif (cp === 0x00b7) return WordBreakProperty.MidLetter;\n\tif (cp === 0x0387) return WordBreakProperty.MidLetter;\n\tif (cp === 0x05f4) return WordBreakProperty.MidLetter;\n\tif (cp === 0x2027) return WordBreakProperty.MidLetter;\n\tif (cp === 0xfe13) return WordBreakProperty.MidLetter;\n\tif (cp === 0xfe55) return WordBreakProperty.MidLetter;\n\tif (cp === 0xff1a) return WordBreakProperty.MidLetter;\n\n\t// MidNum\n\tif (cp === 0x002c) return WordBreakProperty.MidNum; // ,\n\tif (cp === 0x003b) return WordBreakProperty.MidNum; // ;\n\tif (cp === 0x037e) return WordBreakProperty.MidNum;\n\tif (cp === 0x0589) return WordBreakProperty.MidNum;\n\tif (cp === 0x060c || cp === 0x060d) return WordBreakProperty.MidNum;\n\tif (cp === 0x066c) return WordBreakProperty.MidNum;\n\tif (cp === 0x07f8) return WordBreakProperty.MidNum;\n\tif (cp === 0x2044) return WordBreakProperty.MidNum;\n\tif (cp === 0xfe10) return WordBreakProperty.MidNum;\n\tif (cp === 0xfe14) return WordBreakProperty.MidNum;\n\tif (cp === 0xfe50) return WordBreakProperty.MidNum;\n\tif (cp === 0xfe54) return WordBreakProperty.MidNum;\n\tif (cp === 0xff0c) return WordBreakProperty.MidNum;\n\tif (cp === 0xff1b) return WordBreakProperty.MidNum;\n\n\t// Numeric\n\tif (cp >= 0x0030 && cp <= 0x0039) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0660 && cp <= 0x0669) return WordBreakProperty.Numeric;\n\tif (cp >= 0x06f0 && cp <= 0x06f9) return WordBreakProperty.Numeric;\n\tif (cp >= 0x07c0 && cp <= 0x07c9) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0966 && cp <= 0x096f) return WordBreakProperty.Numeric;\n\tif (cp >= 0x09e6 && cp <= 0x09ef) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0a66 && cp <= 0x0a6f) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0ae6 && cp <= 0x0aef) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0b66 && cp <= 0x0b6f) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0be6 && cp <= 0x0bef) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0c66 && cp <= 0x0c6f) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0ce6 && cp <= 0x0cef) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0d66 && cp <= 0x0d6f) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0de6 && cp <= 0x0def) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0e50 && cp <= 0x0e59) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0ed0 && cp <= 0x0ed9) return WordBreakProperty.Numeric;\n\tif (cp >= 0x0f20 && cp <= 0x0f29) return WordBreakProperty.Numeric;\n\tif (cp >= 0x1040 && cp <= 0x1049) return WordBreakProperty.Numeric;\n\tif (cp >= 0x1090 && cp <= 0x1099) return WordBreakProperty.Numeric;\n\tif (cp >= 0x17e0 && cp <= 0x17e9) return WordBreakProperty.Numeric;\n\tif (cp >= 0x1810 && cp <= 0x1819) return WordBreakProperty.Numeric;\n\tif (cp >= 0x1946 && cp <= 0x194f) return WordBreakProperty.Numeric;\n\tif (cp >= 0x19d0 && cp <= 0x19d9) return WordBreakProperty.Numeric;\n\tif (cp >= 0x1a80 && cp <= 0x1a89) return WordBreakProperty.Numeric;\n\tif (cp >= 0x1a90 && cp <= 0x1a99) return WordBreakProperty.Numeric;\n\tif (cp >= 0x1b50 && cp <= 0x1b59) return WordBreakProperty.Numeric;\n\tif (cp >= 0x1bb0 && cp <= 0x1bb9) return WordBreakProperty.Numeric;\n\tif (cp >= 0x1c40 && cp <= 0x1c49) return WordBreakProperty.Numeric;\n\tif (cp >= 0x1c50 && cp <= 0x1c59) return WordBreakProperty.Numeric;\n\tif (cp >= 0xa620 && cp <= 0xa629) return WordBreakProperty.Numeric;\n\tif (cp >= 0xa8d0 && cp <= 0xa8d9) return WordBreakProperty.Numeric;\n\tif (cp >= 0xa900 && cp <= 0xa909) return WordBreakProperty.Numeric;\n\tif (cp >= 0xa9d0 && cp <= 0xa9d9) return WordBreakProperty.Numeric;\n\tif (cp >= 0xa9f0 && cp <= 0xa9f9) return WordBreakProperty.Numeric;\n\tif (cp >= 0xaa50 && cp <= 0xaa59) return WordBreakProperty.Numeric;\n\tif (cp >= 0xabf0 && cp <= 0xabf9) return WordBreakProperty.Numeric;\n\tif (cp >= 0xff10 && cp <= 0xff19) return WordBreakProperty.Numeric;\n\n\t// ExtendNumLet\n\tif (cp === 0x005f) return WordBreakProperty.ExtendNumLet; // _\n\tif (cp === 0x202f) return WordBreakProperty.ExtendNumLet;\n\tif (cp === 0x2040) return WordBreakProperty.ExtendNumLet;\n\tif (cp === 0x2054) return WordBreakProperty.ExtendNumLet;\n\tif (cp === 0xfe33 || cp === 0xfe34) return WordBreakProperty.ExtendNumLet;\n\tif (cp >= 0xfe4d && cp <= 0xfe4f) return WordBreakProperty.ExtendNumLet;\n\tif (cp === 0xff3f) return WordBreakProperty.ExtendNumLet;\n\n\t// WSegSpace\n\tif (cp === 0x0020) return WordBreakProperty.WSegSpace;\n\tif (cp === 0x1680) return WordBreakProperty.WSegSpace;\n\tif (cp >= 0x2000 && cp <= 0x200a && cp !== 0x2007) return WordBreakProperty.WSegSpace;\n\tif (cp === 0x205f) return WordBreakProperty.WSegSpace;\n\tif (cp === 0x3000) return WordBreakProperty.WSegSpace;\n\n\t// Extend (same as grapheme extend)\n\tconst gbp = getGraphemeBreakProperty(cp);\n\tif (gbp === GraphemeBreakProperty.Extend) return WordBreakProperty.Extend;\n\n\t// ALetter (alphabetic)\n\tif (cp >= 0x0041 && cp <= 0x005a) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0061 && cp <= 0x007a) return WordBreakProperty.ALetter;\n\tif (cp >= 0x00c0 && cp <= 0x00d6) return WordBreakProperty.ALetter;\n\tif (cp >= 0x00d8 && cp <= 0x00f6) return WordBreakProperty.ALetter;\n\tif (cp >= 0x00f8 && cp <= 0x024f) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0250 && cp <= 0x02af) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0370 && cp <= 0x03ff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0400 && cp <= 0x04ff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0500 && cp <= 0x052f) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0531 && cp <= 0x0556) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0560 && cp <= 0x0588) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0600 && cp <= 0x06ff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0900 && cp <= 0x097f) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0980 && cp <= 0x09ff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0a00 && cp <= 0x0a7f) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0a80 && cp <= 0x0aff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0b00 && cp <= 0x0b7f) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0b80 && cp <= 0x0bff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0c00 && cp <= 0x0c7f) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0c80 && cp <= 0x0cff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0d00 && cp <= 0x0d7f) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0e00 && cp <= 0x0e7f) return WordBreakProperty.ALetter;\n\tif (cp >= 0x0e80 && cp <= 0x0eff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x1000 && cp <= 0x109f) return WordBreakProperty.ALetter;\n\tif (cp >= 0x10a0 && cp <= 0x10ff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x1100 && cp <= 0x11ff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x1780 && cp <= 0x17ff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x3040 && cp <= 0x309f) return WordBreakProperty.ALetter; // Hiragana\n\tif (cp >= 0x1f00 && cp <= 0x1fff) return WordBreakProperty.ALetter;\n\tif (cp >= 0x2c00 && cp <= 0x2c5f) return WordBreakProperty.ALetter;\n\tif (cp >= 0xa000 && cp <= 0xa48f) return WordBreakProperty.ALetter;\n\tif (cp >= 0xa4d0 && cp <= 0xa4ff) return WordBreakProperty.ALetter;\n\tif (cp >= 0xa500 && cp <= 0xa63f) return WordBreakProperty.ALetter;\n\tif (cp >= 0xa640 && cp <= 0xa69f) return WordBreakProperty.ALetter;\n\tif (cp >= 0xa720 && cp <= 0xa7ff) return WordBreakProperty.ALetter;\n\tif (cp >= 0xab00 && cp <= 0xab6f) return WordBreakProperty.ALetter;\n\tif (cp >= 0xac00 && cp <= 0xd7af) return WordBreakProperty.ALetter; // Hangul\n\tif (cp >= 0xfb00 && cp <= 0xfb06) return WordBreakProperty.ALetter;\n\tif (cp >= 0xff21 && cp <= 0xff3a) return WordBreakProperty.ALetter;\n\tif (cp >= 0xff41 && cp <= 0xff5a) return WordBreakProperty.ALetter;\n\n\treturn WordBreakProperty.Other;\n}\n\n/**\n * Grapheme cluster boundary result\n */\nexport interface GraphemeBoundaries {\n\t/** Boundary positions (indices where clusters end) */\n\tboundaries: number[];\n\t/** Grapheme break properties */\n\tproperties: GraphemeBreakProperty[];\n}\n\n/**\n * Find grapheme cluster boundaries in codepoints\n */\nexport function findGraphemeBoundaries(codepoints: number[]): GraphemeBoundaries {\n\tconst len = codepoints.length;\n\tconst properties: GraphemeBreakProperty[] = [];\n\tconst boundaries: number[] = [];\n\n\tfor (const cp of codepoints) {\n\t\tproperties.push(getGraphemeBreakProperty(cp));\n\t}\n\n\tif (len === 0) return { boundaries, properties };\n\n\t// GB1: Break at the start of text\n\t// (implicitly handled)\n\n\t// Track state for RI pairs\n\tlet riCount = 0;\n\tlet inExtendedPictographicSequence = false;\n\n\tfor (let i = 1; i < len; i++) {\n\t\tconst prev = properties[i - 1]!;\n\t\tconst curr = properties[i]!;\n\n\t\tlet shouldBreak = true;\n\n\t\t// GB3: Do not break between a CR and LF\n\t\tif (prev === GraphemeBreakProperty.CR && curr === GraphemeBreakProperty.LF) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// GB4: Break after controls\n\t\telse if (\n\t\t\tprev === GraphemeBreakProperty.Control ||\n\t\t\tprev === GraphemeBreakProperty.CR ||\n\t\t\tprev === GraphemeBreakProperty.LF\n\t\t) {\n\t\t\tshouldBreak = true;\n\t\t}\n\t\t// GB5: Break before controls\n\t\telse if (\n\t\t\tcurr === GraphemeBreakProperty.Control ||\n\t\t\tcurr === GraphemeBreakProperty.CR ||\n\t\t\tcurr === GraphemeBreakProperty.LF\n\t\t) {\n\t\t\tshouldBreak = true;\n\t\t}\n\t\t// GB6: Do not break Hangul syllable sequences\n\t\telse if (\n\t\t\tprev === GraphemeBreakProperty.L &&\n\t\t\t(curr === GraphemeBreakProperty.L ||\n\t\t\t\tcurr === GraphemeBreakProperty.V ||\n\t\t\t\tcurr === GraphemeBreakProperty.LV ||\n\t\t\t\tcurr === GraphemeBreakProperty.LVT)\n\t\t) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// GB7\n\t\telse if (\n\t\t\t(prev === GraphemeBreakProperty.LV || prev === GraphemeBreakProperty.V) &&\n\t\t\t(curr === GraphemeBreakProperty.V || curr === GraphemeBreakProperty.T)\n\t\t) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// GB8\n\t\telse if (\n\t\t\t(prev === GraphemeBreakProperty.LVT || prev === GraphemeBreakProperty.T) &&\n\t\t\tcurr === GraphemeBreakProperty.T\n\t\t) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// GB9: Do not break before extending characters or ZWJ\n\t\telse if (curr === GraphemeBreakProperty.Extend || curr === GraphemeBreakProperty.ZWJ) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// GB9a: Do not break before SpacingMarks\n\t\telse if (curr === GraphemeBreakProperty.SpacingMark) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// GB9b: Do not break after Prepend characters\n\t\telse if (prev === GraphemeBreakProperty.Prepend) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// GB11: Do not break within emoji modifier sequences or emoji ZWJ sequences\n\t\telse if (inExtendedPictographicSequence && prev === GraphemeBreakProperty.ZWJ &&\n\t\t\tcurr === GraphemeBreakProperty.Extended_Pictographic) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// GB12-13: Do not break within emoji flag sequences\n\t\telse if (prev === GraphemeBreakProperty.Regional_Indicator &&\n\t\t\tcurr === GraphemeBreakProperty.Regional_Indicator) {\n\t\t\t// Only break after even number of RIs\n\t\t\tif (riCount % 2 === 1) {\n\t\t\t\tshouldBreak = false;\n\t\t\t}\n\t\t}\n\n\t\t// Track extended pictographic state\n\t\tif (curr === GraphemeBreakProperty.Extended_Pictographic) {\n\t\t\tinExtendedPictographicSequence = true;\n\t\t} else if (curr !== GraphemeBreakProperty.Extend && curr !== GraphemeBreakProperty.ZWJ) {\n\t\t\tinExtendedPictographicSequence = false;\n\t\t}\n\n\t\t// Track RI count\n\t\tif (curr === GraphemeBreakProperty.Regional_Indicator) {\n\t\t\triCount++;\n\t\t} else {\n\t\t\triCount = 0;\n\t\t}\n\n\t\tif (shouldBreak) {\n\t\t\tboundaries.push(i);\n\t\t}\n\t}\n\n\t// GB2: Break at the end of text\n\tboundaries.push(len);\n\n\treturn { boundaries, properties };\n}\n\n/**\n * Word boundary result\n */\nexport interface WordBoundaries {\n\t/** Boundary positions */\n\tboundaries: number[];\n\t/** Word break properties */\n\tproperties: WordBreakProperty[];\n}\n\n/**\n * Find word boundaries in codepoints\n */\nexport function findWordBoundaries(codepoints: number[]): WordBoundaries {\n\tconst len = codepoints.length;\n\tconst properties: WordBreakProperty[] = [];\n\tconst boundaries: number[] = [];\n\n\tfor (const cp of codepoints) {\n\t\tproperties.push(getWordBreakProperty(cp));\n\t}\n\n\tif (len === 0) return { boundaries, properties };\n\n\t// WB1: Break at the start\n\tboundaries.push(0);\n\n\tlet riCount = 0;\n\n\tfor (let i = 1; i < len; i++) {\n\t\tconst prev = properties[i - 1]!;\n\t\tconst curr = properties[i]!;\n\n\t\tlet shouldBreak = true;\n\n\t\t// WB3: Do not break within CRLF\n\t\tif (prev === WordBreakProperty.CR && curr === WordBreakProperty.LF) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// WB3a-b: Break before and after Newlines\n\t\telse if (\n\t\t\tprev === WordBreakProperty.Newline ||\n\t\t\tprev === WordBreakProperty.CR ||\n\t\t\tprev === WordBreakProperty.LF\n\t\t) {\n\t\t\tshouldBreak = true;\n\t\t} else if (\n\t\t\tcurr === WordBreakProperty.Newline ||\n\t\t\tcurr === WordBreakProperty.CR ||\n\t\t\tcurr === WordBreakProperty.LF\n\t\t) {\n\t\t\tshouldBreak = true;\n\t\t}\n\t\t// WB3c: Do not break within emoji ZWJ sequences\n\t\telse if (prev === WordBreakProperty.ZWJ &&\n\t\t\tcurr === WordBreakProperty.Extended_Pictographic) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// WB3d: Keep horizontal whitespace together\n\t\telse if (prev === WordBreakProperty.WSegSpace &&\n\t\t\tcurr === WordBreakProperty.WSegSpace) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// WB4: Ignore Format and Extend characters\n\t\telse if (curr === WordBreakProperty.Format ||\n\t\t\tcurr === WordBreakProperty.Extend ||\n\t\t\tcurr === WordBreakProperty.ZWJ) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// WB5: Do not break between most letters\n\t\telse if (\n\t\t\t(prev === WordBreakProperty.ALetter || prev === WordBreakProperty.Hebrew_Letter) &&\n\t\t\t(curr === WordBreakProperty.ALetter || curr === WordBreakProperty.Hebrew_Letter)\n\t\t) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// WB6-7: Do not break letters across certain punctuation\n\t\telse if (\n\t\t\t(prev === WordBreakProperty.ALetter || prev === WordBreakProperty.Hebrew_Letter) &&\n\t\t\t(curr === WordBreakProperty.MidLetter || curr === WordBreakProperty.MidNumLet || curr === WordBreakProperty.Single_Quote)\n\t\t) {\n\t\t\t// Look ahead\n\t\t\tif (i + 1 < len) {\n\t\t\t\tconst next = properties[i + 1]!;\n\t\t\t\tif (next === WordBreakProperty.ALetter || next === WordBreakProperty.Hebrew_Letter) {\n\t\t\t\t\tshouldBreak = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// WB8-10: Do not break within sequences of digits\n\t\telse if (prev === WordBreakProperty.Numeric && curr === WordBreakProperty.Numeric) {\n\t\t\tshouldBreak = false;\n\t\t} else if (\n\t\t\t(prev === WordBreakProperty.ALetter || prev === WordBreakProperty.Hebrew_Letter) &&\n\t\t\tcurr === WordBreakProperty.Numeric\n\t\t) {\n\t\t\tshouldBreak = false;\n\t\t} else if (\n\t\t\tprev === WordBreakProperty.Numeric &&\n\t\t\t(curr === WordBreakProperty.ALetter || curr === WordBreakProperty.Hebrew_Letter)\n\t\t) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// WB11-12: Do not break within sequences with numeric separators\n\t\telse if (\n\t\t\tprev === WordBreakProperty.Numeric &&\n\t\t\t(curr === WordBreakProperty.MidNum || curr === WordBreakProperty.MidNumLet || curr === WordBreakProperty.Single_Quote)\n\t\t) {\n\t\t\tif (i + 1 < len && properties[i + 1] === WordBreakProperty.Numeric) {\n\t\t\t\tshouldBreak = false;\n\t\t\t}\n\t\t}\n\t\t// WB13: Do not break between Katakana\n\t\telse if (prev === WordBreakProperty.Katakana && curr === WordBreakProperty.Katakana) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// WB13a-b: ExtendNumLet binding\n\t\telse if (\n\t\t\t(prev === WordBreakProperty.ALetter ||\n\t\t\t\tprev === WordBreakProperty.Hebrew_Letter ||\n\t\t\t\tprev === WordBreakProperty.Numeric ||\n\t\t\t\tprev === WordBreakProperty.Katakana ||\n\t\t\t\tprev === WordBreakProperty.ExtendNumLet) &&\n\t\t\tcurr === WordBreakProperty.ExtendNumLet\n\t\t) {\n\t\t\tshouldBreak = false;\n\t\t} else if (\n\t\t\tprev === WordBreakProperty.ExtendNumLet &&\n\t\t\t(curr === WordBreakProperty.ALetter ||\n\t\t\t\tcurr === WordBreakProperty.Hebrew_Letter ||\n\t\t\t\tcurr === WordBreakProperty.Numeric ||\n\t\t\t\tcurr === WordBreakProperty.Katakana)\n\t\t) {\n\t\t\tshouldBreak = false;\n\t\t}\n\t\t// WB15-16: Do not break within emoji flag sequences\n\t\telse if (prev === WordBreakProperty.Regional_Indicator &&\n\t\t\tcurr === WordBreakProperty.Regional_Indicator) {\n\t\t\tif (riCount % 2 === 1) {\n\t\t\t\tshouldBreak = false;\n\t\t\t}\n\t\t}\n\n\t\t// Track RI count\n\t\tif (curr === WordBreakProperty.Regional_Indicator) {\n\t\t\triCount++;\n\t\t} else {\n\t\t\triCount = 0;\n\t\t}\n\n\t\tif (shouldBreak) {\n\t\t\tboundaries.push(i);\n\t\t}\n\t}\n\n\t// WB2: Break at the end\n\tboundaries.push(len);\n\n\treturn { boundaries, properties };\n}\n\n/**\n * Split text into grapheme clusters\n */\nexport function splitGraphemes(text: string): string[] {\n\tconst codepoints: number[] = [];\n\tconst chars: string[] = [];\n\n\tfor (const char of text) {\n\t\tcodepoints.push(char.codePointAt(0) ?? 0);\n\t\tchars.push(char);\n\t}\n\n\tconst { boundaries } = findGraphemeBoundaries(codepoints);\n\tconst graphemes: string[] = [];\n\n\tlet start = 0;\n\tfor (const end of boundaries) {\n\t\tif (end > start) {\n\t\t\tgraphemes.push(chars.slice(start, end).join(\"\"));\n\t\t}\n\t\tstart = end;\n\t}\n\n\treturn graphemes;\n}\n\n/**\n * Split text into words\n */\nexport function splitWords(text: string): string[] {\n\tconst codepoints: number[] = [];\n\tconst chars: string[] = [];\n\n\tfor (const char of text) {\n\t\tcodepoints.push(char.codePointAt(0) ?? 0);\n\t\tchars.push(char);\n\t}\n\n\tconst { boundaries, properties } = findWordBoundaries(codepoints);\n\tconst words: string[] = [];\n\n\tfor (let i = 0; i < boundaries.length - 1; i++) {\n\t\tconst start = boundaries[i]!;\n\t\tconst end = boundaries[i + 1]!;\n\n\t\t// Skip whitespace-only segments\n\t\tlet hasContent = false;\n\t\tfor (let j = start; j < end; j++) {\n\t\t\tconst prop = properties[j]!;\n\t\t\tif (prop !== WordBreakProperty.WSegSpace &&\n\t\t\t\tprop !== WordBreakProperty.CR &&\n\t\t\t\tprop !== WordBreakProperty.LF &&\n\t\t\t\tprop !== WordBreakProperty.Newline) {\n\t\t\t\thasContent = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (hasContent) {\n\t\t\twords.push(chars.slice(start, end).join(\"\"));\n\t\t}\n\t}\n\n\treturn words;\n}\n\n/**\n * Count grapheme clusters in text\n */\nexport function countGraphemes(text: string): number {\n\tconst codepoints: number[] = [];\n\tfor (const char of text) {\n\t\tcodepoints.push(char.codePointAt(0) ?? 0);\n\t}\n\tconst { boundaries } = findGraphemeBoundaries(codepoints);\n\treturn boundaries.length;\n}\n\n/**\n * Analyze grapheme boundaries for glyph infos\n */\nexport function analyzeGraphemesForGlyphs(infos: GlyphInfo[]): GraphemeBoundaries {\n\tconst codepoints = infos.map((info) => info.codepoint);\n\treturn findGraphemeBoundaries(codepoints);\n}\n\n/**\n * Analyze word boundaries for glyph infos\n */\nexport function analyzeWordsForGlyphs(infos: GlyphInfo[]): WordBoundaries {\n\tconst codepoints = infos.map((info) => info.codepoint);\n\treturn findWordBoundaries(codepoints);\n}\n",
87
+ "/**\n * Unicode Script Detection\n * Detects the script of text based on codepoints\n */\n\n/**\n * Unicode script values (ISO 15924)\n */\nexport enum Script {\n\tCommon = \"Zyyy\",\n\tInherited = \"Zinh\",\n\tUnknown = \"Zzzz\",\n\n\t// Major scripts\n\tLatin = \"Latn\",\n\tGreek = \"Grek\",\n\tCyrillic = \"Cyrl\",\n\tArmenian = \"Armn\",\n\tHebrew = \"Hebr\",\n\tArabic = \"Arab\",\n\tSyriac = \"Syrc\",\n\tThaana = \"Thaa\",\n\tDevanagari = \"Deva\",\n\tBengali = \"Beng\",\n\tGurmukhi = \"Guru\",\n\tGujarati = \"Gujr\",\n\tOriya = \"Orya\",\n\tTamil = \"Taml\",\n\tTelugu = \"Telu\",\n\tKannada = \"Knda\",\n\tMalayalam = \"Mlym\",\n\tSinhala = \"Sinh\",\n\tThai = \"Thai\",\n\tLao = \"Laoo\",\n\tTibetan = \"Tibt\",\n\tMyanmar = \"Mymr\",\n\tGeorgian = \"Geor\",\n\tHangul = \"Hang\",\n\tEthiopic = \"Ethi\",\n\tCherokee = \"Cher\",\n\tCanadianAboriginal = \"Cans\",\n\tOgham = \"Ogam\",\n\tRunic = \"Runr\",\n\tKhmer = \"Khmr\",\n\tMongolian = \"Mong\",\n\tHiragana = \"Hira\",\n\tKatakana = \"Kana\",\n\tBopomofo = \"Bopo\",\n\tHan = \"Hani\",\n\tYi = \"Yiii\",\n\tOldItalic = \"Ital\",\n\tGothic = \"Goth\",\n\tDeseret = \"Dsrt\",\n\tTagalog = \"Tglg\",\n\tHanunoo = \"Hano\",\n\tBuhid = \"Buhd\",\n\tTagbanwa = \"Tagb\",\n\tLimbu = \"Limb\",\n\tTaiLe = \"Tale\",\n\tLinearB = \"Linb\",\n\tUgaritic = \"Ugar\",\n\tShavian = \"Shaw\",\n\tOsmanya = \"Osma\",\n\tCypriot = \"Cprt\",\n\tBraille = \"Brai\",\n\tBuginese = \"Bugi\",\n\tCoptic = \"Copt\",\n\tNewTaiLue = \"Talu\",\n\tGlagolitic = \"Glag\",\n\tTifinagh = \"Tfng\",\n\tSylotiNagri = \"Sylo\",\n\tOldPersian = \"Xpeo\",\n\tKharoshthi = \"Khar\",\n\tBalinese = \"Bali\",\n\tCuneiform = \"Xsux\",\n\tPhoenician = \"Phnx\",\n\tPhagsPa = \"Phag\",\n\tNko = \"Nkoo\",\n\tSundanese = \"Sund\",\n\tLepcha = \"Lepc\",\n\tOlChiki = \"Olck\",\n\tVai = \"Vaii\",\n\tSaurashtra = \"Saur\",\n\tKayahLi = \"Kali\",\n\tRejang = \"Rjng\",\n\tLycian = \"Lyci\",\n\tCarian = \"Cari\",\n\tLydian = \"Lydi\",\n\tCham = \"Cham\",\n\tTaiTham = \"Lana\",\n\tTaiViet = \"Tavt\",\n\tAvestan = \"Avst\",\n\tEgyptianHieroglyphs = \"Egyp\",\n\tSamaritan = \"Samr\",\n\tLisu = \"Lisu\",\n\tBamum = \"Bamu\",\n\tJavanese = \"Java\",\n\tMeeteiMayek = \"Mtei\",\n\tImperialAramaic = \"Armi\",\n\tOldSouthArabian = \"Sarb\",\n\tInscriptionalParthian = \"Prti\",\n\tInscriptionalPahlavi = \"Phli\",\n\tOldTurkic = \"Orkh\",\n\tKaithi = \"Kthi\",\n\tBatak = \"Batk\",\n\tBrahmi = \"Brah\",\n\tMandaic = \"Mand\",\n\tChakma = \"Cakm\",\n\tMeroiticCursive = \"Merc\",\n\tMeroiticHieroglyphs = \"Mero\",\n\tMiao = \"Plrd\",\n\tSharada = \"Shrd\",\n\tSoraSompeng = \"Sora\",\n\tTakri = \"Takr\",\n\tCaucasianAlbanian = \"Aghb\",\n\tBassaVah = \"Bass\",\n\tDuployan = \"Dupl\",\n\tElbasan = \"Elba\",\n\tGrantha = \"Gran\",\n\tPahawhHmong = \"Hmng\",\n\tKhojki = \"Khoj\",\n\tLinearA = \"Lina\",\n\tMahajani = \"Mahj\",\n\tManichaean = \"Mani\",\n\tMendeKikakui = \"Mend\",\n\tModi = \"Modi\",\n\tMro = \"Mroo\",\n\tOldNorthArabian = \"Narb\",\n\tNabataean = \"Nbat\",\n\tPalmyrene = \"Palm\",\n\tPauCinHau = \"Pauc\",\n\tOldPermic = \"Perm\",\n\tPsalterPahlavi = \"Phlp\",\n\tSiddham = \"Sidd\",\n\tKhudawadi = \"Sind\",\n\tTirhuta = \"Tirh\",\n\tWarangCiti = \"Wara\",\n\tAhom = \"Ahom\",\n\tAnatolianHieroglyphs = \"Hluw\",\n\tHatran = \"Hatr\",\n\tMultani = \"Mult\",\n\tOldHungarian = \"Hung\",\n\tSignWriting = \"Sgnw\",\n\tAdlam = \"Adlm\",\n\tBhaiksuki = \"Bhks\",\n\tMarchen = \"Marc\",\n\tNewa = \"Newa\",\n\tOsage = \"Osge\",\n\tTangut = \"Tang\",\n\tMasaramGondi = \"Gonm\",\n\tNushu = \"Nshu\",\n\tSoyombo = \"Soyo\",\n\tZanabazarSquare = \"Zanb\",\n\tDogra = \"Dogr\",\n\tGunjalaGondi = \"Gong\",\n\tMakasar = \"Maka\",\n\tMedefaidrin = \"Medf\",\n\tHanifiRohingya = \"Rohg\",\n\tSogdian = \"Sogd\",\n\tOldSogdian = \"Sogo\",\n\tElymaic = \"Elym\",\n\tNandinagari = \"Nand\",\n\tNyiakengPuachueHmong = \"Hmnp\",\n\tWancho = \"Wcho\",\n\tYezidi = \"Yezi\",\n\tChorasmian = \"Chrs\",\n\tDivesAkuru = \"Diak\",\n\tKhitanSmallScript = \"Kits\",\n\tVithkuqi = \"Vith\",\n\tOldUyghur = \"Ougr\",\n\tCypro_Minoan = \"Cpmn\",\n\tTangsa = \"Tnsa\",\n\tToto = \"Toto\",\n\tKawi = \"Kawi\",\n\tNagMundari = \"Nagm\",\n}\n\n/**\n * Script range entry\n */\ninterface ScriptRange {\n\tstart: number;\n\tend: number;\n\tscript: Script;\n}\n\n/**\n * Script ranges (sorted by start codepoint)\n */\nconst SCRIPT_RANGES: ScriptRange[] = [\n\t// Basic Latin\n\t{ start: 0x0000, end: 0x007f, script: Script.Common },\n\t// Latin-1 Supplement\n\t{ start: 0x0080, end: 0x00ff, script: Script.Latin },\n\t// Latin Extended-A\n\t{ start: 0x0100, end: 0x017f, script: Script.Latin },\n\t// Latin Extended-B\n\t{ start: 0x0180, end: 0x024f, script: Script.Latin },\n\t// IPA Extensions\n\t{ start: 0x0250, end: 0x02af, script: Script.Latin },\n\t// Spacing Modifier Letters\n\t{ start: 0x02b0, end: 0x02ff, script: Script.Common },\n\t// Combining Diacritical Marks\n\t{ start: 0x0300, end: 0x036f, script: Script.Inherited },\n\t// Greek and Coptic\n\t{ start: 0x0370, end: 0x03ff, script: Script.Greek },\n\t// Cyrillic\n\t{ start: 0x0400, end: 0x04ff, script: Script.Cyrillic },\n\t// Cyrillic Supplement\n\t{ start: 0x0500, end: 0x052f, script: Script.Cyrillic },\n\t// Armenian\n\t{ start: 0x0530, end: 0x058f, script: Script.Armenian },\n\t// Hebrew\n\t{ start: 0x0590, end: 0x05ff, script: Script.Hebrew },\n\t// Arabic\n\t{ start: 0x0600, end: 0x06ff, script: Script.Arabic },\n\t// Syriac\n\t{ start: 0x0700, end: 0x074f, script: Script.Syriac },\n\t// Arabic Supplement\n\t{ start: 0x0750, end: 0x077f, script: Script.Arabic },\n\t// Thaana\n\t{ start: 0x0780, end: 0x07bf, script: Script.Thaana },\n\t// NKo\n\t{ start: 0x07c0, end: 0x07ff, script: Script.Nko },\n\t// Samaritan\n\t{ start: 0x0800, end: 0x083f, script: Script.Samaritan },\n\t// Mandaic\n\t{ start: 0x0840, end: 0x085f, script: Script.Mandaic },\n\t// Syriac Supplement\n\t{ start: 0x0860, end: 0x086f, script: Script.Syriac },\n\t// Arabic Extended-B\n\t{ start: 0x0870, end: 0x089f, script: Script.Arabic },\n\t// Arabic Extended-A\n\t{ start: 0x08a0, end: 0x08ff, script: Script.Arabic },\n\t// Devanagari\n\t{ start: 0x0900, end: 0x097f, script: Script.Devanagari },\n\t// Bengali\n\t{ start: 0x0980, end: 0x09ff, script: Script.Bengali },\n\t// Gurmukhi\n\t{ start: 0x0a00, end: 0x0a7f, script: Script.Gurmukhi },\n\t// Gujarati\n\t{ start: 0x0a80, end: 0x0aff, script: Script.Gujarati },\n\t// Oriya\n\t{ start: 0x0b00, end: 0x0b7f, script: Script.Oriya },\n\t// Tamil\n\t{ start: 0x0b80, end: 0x0bff, script: Script.Tamil },\n\t// Telugu\n\t{ start: 0x0c00, end: 0x0c7f, script: Script.Telugu },\n\t// Kannada\n\t{ start: 0x0c80, end: 0x0cff, script: Script.Kannada },\n\t// Malayalam\n\t{ start: 0x0d00, end: 0x0d7f, script: Script.Malayalam },\n\t// Sinhala\n\t{ start: 0x0d80, end: 0x0dff, script: Script.Sinhala },\n\t// Thai\n\t{ start: 0x0e00, end: 0x0e7f, script: Script.Thai },\n\t// Lao\n\t{ start: 0x0e80, end: 0x0eff, script: Script.Lao },\n\t// Tibetan\n\t{ start: 0x0f00, end: 0x0fff, script: Script.Tibetan },\n\t// Myanmar\n\t{ start: 0x1000, end: 0x109f, script: Script.Myanmar },\n\t// Georgian\n\t{ start: 0x10a0, end: 0x10ff, script: Script.Georgian },\n\t// Hangul Jamo\n\t{ start: 0x1100, end: 0x11ff, script: Script.Hangul },\n\t// Ethiopic\n\t{ start: 0x1200, end: 0x137f, script: Script.Ethiopic },\n\t// Ethiopic Supplement\n\t{ start: 0x1380, end: 0x139f, script: Script.Ethiopic },\n\t// Cherokee\n\t{ start: 0x13a0, end: 0x13ff, script: Script.Cherokee },\n\t// Unified Canadian Aboriginal Syllabics\n\t{ start: 0x1400, end: 0x167f, script: Script.CanadianAboriginal },\n\t// Ogham\n\t{ start: 0x1680, end: 0x169f, script: Script.Ogham },\n\t// Runic\n\t{ start: 0x16a0, end: 0x16ff, script: Script.Runic },\n\t// Tagalog\n\t{ start: 0x1700, end: 0x171f, script: Script.Tagalog },\n\t// Hanunoo\n\t{ start: 0x1720, end: 0x173f, script: Script.Hanunoo },\n\t// Buhid\n\t{ start: 0x1740, end: 0x175f, script: Script.Buhid },\n\t// Tagbanwa\n\t{ start: 0x1760, end: 0x177f, script: Script.Tagbanwa },\n\t// Khmer\n\t{ start: 0x1780, end: 0x17ff, script: Script.Khmer },\n\t// Mongolian\n\t{ start: 0x1800, end: 0x18af, script: Script.Mongolian },\n\t// Unified Canadian Aboriginal Syllabics Extended\n\t{ start: 0x18b0, end: 0x18ff, script: Script.CanadianAboriginal },\n\t// Limbu\n\t{ start: 0x1900, end: 0x194f, script: Script.Limbu },\n\t// Tai Le\n\t{ start: 0x1950, end: 0x197f, script: Script.TaiLe },\n\t// New Tai Lue\n\t{ start: 0x1980, end: 0x19df, script: Script.NewTaiLue },\n\t// Khmer Symbols\n\t{ start: 0x19e0, end: 0x19ff, script: Script.Khmer },\n\t// Buginese\n\t{ start: 0x1a00, end: 0x1a1f, script: Script.Buginese },\n\t// Tai Tham\n\t{ start: 0x1a20, end: 0x1aaf, script: Script.TaiTham },\n\t// Combining Diacritical Marks Extended\n\t{ start: 0x1ab0, end: 0x1aff, script: Script.Inherited },\n\t// Balinese\n\t{ start: 0x1b00, end: 0x1b7f, script: Script.Balinese },\n\t// Sundanese\n\t{ start: 0x1b80, end: 0x1bbf, script: Script.Sundanese },\n\t// Batak\n\t{ start: 0x1bc0, end: 0x1bff, script: Script.Batak },\n\t// Lepcha\n\t{ start: 0x1c00, end: 0x1c4f, script: Script.Lepcha },\n\t// Ol Chiki\n\t{ start: 0x1c50, end: 0x1c7f, script: Script.OlChiki },\n\t// Cyrillic Extended-C\n\t{ start: 0x1c80, end: 0x1c8f, script: Script.Cyrillic },\n\t// Georgian Extended\n\t{ start: 0x1c90, end: 0x1cbf, script: Script.Georgian },\n\t// Sundanese Supplement\n\t{ start: 0x1cc0, end: 0x1ccf, script: Script.Sundanese },\n\t// Vedic Extensions\n\t{ start: 0x1cd0, end: 0x1cff, script: Script.Inherited },\n\t// Phonetic Extensions\n\t{ start: 0x1d00, end: 0x1d7f, script: Script.Latin },\n\t// Phonetic Extensions Supplement\n\t{ start: 0x1d80, end: 0x1dbf, script: Script.Latin },\n\t// Combining Diacritical Marks Supplement\n\t{ start: 0x1dc0, end: 0x1dff, script: Script.Inherited },\n\t// Latin Extended Additional\n\t{ start: 0x1e00, end: 0x1eff, script: Script.Latin },\n\t// Greek Extended\n\t{ start: 0x1f00, end: 0x1fff, script: Script.Greek },\n\t// General Punctuation\n\t{ start: 0x2000, end: 0x206f, script: Script.Common },\n\t// Superscripts and Subscripts\n\t{ start: 0x2070, end: 0x209f, script: Script.Common },\n\t// Currency Symbols\n\t{ start: 0x20a0, end: 0x20cf, script: Script.Common },\n\t// Combining Diacritical Marks for Symbols\n\t{ start: 0x20d0, end: 0x20ff, script: Script.Inherited },\n\t// Letterlike Symbols\n\t{ start: 0x2100, end: 0x214f, script: Script.Common },\n\t// Number Forms\n\t{ start: 0x2150, end: 0x218f, script: Script.Common },\n\t// Arrows\n\t{ start: 0x2190, end: 0x21ff, script: Script.Common },\n\t// Mathematical Operators\n\t{ start: 0x2200, end: 0x22ff, script: Script.Common },\n\t// Miscellaneous Technical\n\t{ start: 0x2300, end: 0x23ff, script: Script.Common },\n\t// Control Pictures\n\t{ start: 0x2400, end: 0x243f, script: Script.Common },\n\t// OCR\n\t{ start: 0x2440, end: 0x245f, script: Script.Common },\n\t// Enclosed Alphanumerics\n\t{ start: 0x2460, end: 0x24ff, script: Script.Common },\n\t// Box Drawing\n\t{ start: 0x2500, end: 0x257f, script: Script.Common },\n\t// Block Elements\n\t{ start: 0x2580, end: 0x259f, script: Script.Common },\n\t// Geometric Shapes\n\t{ start: 0x25a0, end: 0x25ff, script: Script.Common },\n\t// Miscellaneous Symbols\n\t{ start: 0x2600, end: 0x26ff, script: Script.Common },\n\t// Dingbats\n\t{ start: 0x2700, end: 0x27bf, script: Script.Common },\n\t// Miscellaneous Mathematical Symbols-A\n\t{ start: 0x27c0, end: 0x27ef, script: Script.Common },\n\t// Supplemental Arrows-A\n\t{ start: 0x27f0, end: 0x27ff, script: Script.Common },\n\t// Braille Patterns\n\t{ start: 0x2800, end: 0x28ff, script: Script.Braille },\n\t// Supplemental Arrows-B\n\t{ start: 0x2900, end: 0x297f, script: Script.Common },\n\t// Miscellaneous Mathematical Symbols-B\n\t{ start: 0x2980, end: 0x29ff, script: Script.Common },\n\t// Supplemental Mathematical Operators\n\t{ start: 0x2a00, end: 0x2aff, script: Script.Common },\n\t// Miscellaneous Symbols and Arrows\n\t{ start: 0x2b00, end: 0x2bff, script: Script.Common },\n\t// Glagolitic\n\t{ start: 0x2c00, end: 0x2c5f, script: Script.Glagolitic },\n\t// Latin Extended-C\n\t{ start: 0x2c60, end: 0x2c7f, script: Script.Latin },\n\t// Coptic\n\t{ start: 0x2c80, end: 0x2cff, script: Script.Coptic },\n\t// Georgian Supplement\n\t{ start: 0x2d00, end: 0x2d2f, script: Script.Georgian },\n\t// Tifinagh\n\t{ start: 0x2d30, end: 0x2d7f, script: Script.Tifinagh },\n\t// Ethiopic Extended\n\t{ start: 0x2d80, end: 0x2ddf, script: Script.Ethiopic },\n\t// Cyrillic Extended-A\n\t{ start: 0x2de0, end: 0x2dff, script: Script.Cyrillic },\n\t// Supplemental Punctuation\n\t{ start: 0x2e00, end: 0x2e7f, script: Script.Common },\n\t// CJK Radicals Supplement\n\t{ start: 0x2e80, end: 0x2eff, script: Script.Han },\n\t// Kangxi Radicals\n\t{ start: 0x2f00, end: 0x2fdf, script: Script.Han },\n\t// Ideographic Description Characters\n\t{ start: 0x2ff0, end: 0x2fff, script: Script.Common },\n\t// CJK Symbols and Punctuation\n\t{ start: 0x3000, end: 0x303f, script: Script.Common },\n\t// Hiragana\n\t{ start: 0x3040, end: 0x309f, script: Script.Hiragana },\n\t// Katakana\n\t{ start: 0x30a0, end: 0x30ff, script: Script.Katakana },\n\t// Bopomofo\n\t{ start: 0x3100, end: 0x312f, script: Script.Bopomofo },\n\t// Hangul Compatibility Jamo\n\t{ start: 0x3130, end: 0x318f, script: Script.Hangul },\n\t// Kanbun\n\t{ start: 0x3190, end: 0x319f, script: Script.Common },\n\t// Bopomofo Extended\n\t{ start: 0x31a0, end: 0x31bf, script: Script.Bopomofo },\n\t// CJK Strokes\n\t{ start: 0x31c0, end: 0x31ef, script: Script.Common },\n\t// Katakana Phonetic Extensions\n\t{ start: 0x31f0, end: 0x31ff, script: Script.Katakana },\n\t// Enclosed CJK Letters and Months\n\t{ start: 0x3200, end: 0x32ff, script: Script.Common },\n\t// CJK Compatibility\n\t{ start: 0x3300, end: 0x33ff, script: Script.Common },\n\t// CJK Unified Ideographs Extension A\n\t{ start: 0x3400, end: 0x4dbf, script: Script.Han },\n\t// Yijing Hexagram Symbols\n\t{ start: 0x4dc0, end: 0x4dff, script: Script.Common },\n\t// CJK Unified Ideographs\n\t{ start: 0x4e00, end: 0x9fff, script: Script.Han },\n\t// Yi Syllables\n\t{ start: 0xa000, end: 0xa48f, script: Script.Yi },\n\t// Yi Radicals\n\t{ start: 0xa490, end: 0xa4cf, script: Script.Yi },\n\t// Lisu\n\t{ start: 0xa4d0, end: 0xa4ff, script: Script.Lisu },\n\t// Vai\n\t{ start: 0xa500, end: 0xa63f, script: Script.Vai },\n\t// Cyrillic Extended-B\n\t{ start: 0xa640, end: 0xa69f, script: Script.Cyrillic },\n\t// Bamum\n\t{ start: 0xa6a0, end: 0xa6ff, script: Script.Bamum },\n\t// Modifier Tone Letters\n\t{ start: 0xa700, end: 0xa71f, script: Script.Common },\n\t// Latin Extended-D\n\t{ start: 0xa720, end: 0xa7ff, script: Script.Latin },\n\t// Syloti Nagri\n\t{ start: 0xa800, end: 0xa82f, script: Script.SylotiNagri },\n\t// Common Indic Number Forms\n\t{ start: 0xa830, end: 0xa83f, script: Script.Common },\n\t// Phags-pa\n\t{ start: 0xa840, end: 0xa87f, script: Script.PhagsPa },\n\t// Saurashtra\n\t{ start: 0xa880, end: 0xa8df, script: Script.Saurashtra },\n\t// Devanagari Extended\n\t{ start: 0xa8e0, end: 0xa8ff, script: Script.Devanagari },\n\t// Kayah Li\n\t{ start: 0xa900, end: 0xa92f, script: Script.KayahLi },\n\t// Rejang\n\t{ start: 0xa930, end: 0xa95f, script: Script.Rejang },\n\t// Hangul Jamo Extended-A\n\t{ start: 0xa960, end: 0xa97f, script: Script.Hangul },\n\t// Javanese\n\t{ start: 0xa980, end: 0xa9df, script: Script.Javanese },\n\t// Myanmar Extended-B\n\t{ start: 0xa9e0, end: 0xa9ff, script: Script.Myanmar },\n\t// Cham\n\t{ start: 0xaa00, end: 0xaa5f, script: Script.Cham },\n\t// Myanmar Extended-A\n\t{ start: 0xaa60, end: 0xaa7f, script: Script.Myanmar },\n\t// Tai Viet\n\t{ start: 0xaa80, end: 0xaadf, script: Script.TaiViet },\n\t// Meetei Mayek Extensions\n\t{ start: 0xaae0, end: 0xaaff, script: Script.MeeteiMayek },\n\t// Ethiopic Extended-A\n\t{ start: 0xab00, end: 0xab2f, script: Script.Ethiopic },\n\t// Latin Extended-E\n\t{ start: 0xab30, end: 0xab6f, script: Script.Latin },\n\t// Cherokee Supplement\n\t{ start: 0xab70, end: 0xabbf, script: Script.Cherokee },\n\t// Meetei Mayek\n\t{ start: 0xabc0, end: 0xabff, script: Script.MeeteiMayek },\n\t// Hangul Syllables\n\t{ start: 0xac00, end: 0xd7af, script: Script.Hangul },\n\t// Hangul Jamo Extended-B\n\t{ start: 0xd7b0, end: 0xd7ff, script: Script.Hangul },\n\t// High Surrogates, Low Surrogates\n\t{ start: 0xd800, end: 0xdfff, script: Script.Unknown },\n\t// Private Use Area\n\t{ start: 0xe000, end: 0xf8ff, script: Script.Unknown },\n\t// CJK Compatibility Ideographs\n\t{ start: 0xf900, end: 0xfaff, script: Script.Han },\n\t// Alphabetic Presentation Forms\n\t{ start: 0xfb00, end: 0xfb4f, script: Script.Latin },\n\t// Arabic Presentation Forms-A\n\t{ start: 0xfb50, end: 0xfdff, script: Script.Arabic },\n\t// Variation Selectors\n\t{ start: 0xfe00, end: 0xfe0f, script: Script.Inherited },\n\t// Vertical Forms\n\t{ start: 0xfe10, end: 0xfe1f, script: Script.Common },\n\t// Combining Half Marks\n\t{ start: 0xfe20, end: 0xfe2f, script: Script.Inherited },\n\t// CJK Compatibility Forms\n\t{ start: 0xfe30, end: 0xfe4f, script: Script.Common },\n\t// Small Form Variants\n\t{ start: 0xfe50, end: 0xfe6f, script: Script.Common },\n\t// Arabic Presentation Forms-B\n\t{ start: 0xfe70, end: 0xfeff, script: Script.Arabic },\n\t// Halfwidth and Fullwidth Forms\n\t{ start: 0xff00, end: 0xffef, script: Script.Common },\n\t// Specials\n\t{ start: 0xfff0, end: 0xffff, script: Script.Common },\n\t// Linear B Syllabary\n\t{ start: 0x10000, end: 0x1007f, script: Script.LinearB },\n\t// Linear B Ideograms\n\t{ start: 0x10080, end: 0x100ff, script: Script.LinearB },\n\t// Aegean Numbers\n\t{ start: 0x10100, end: 0x1013f, script: Script.Common },\n\t// Ancient Greek Numbers\n\t{ start: 0x10140, end: 0x1018f, script: Script.Greek },\n\t// Ancient Symbols\n\t{ start: 0x10190, end: 0x101cf, script: Script.Common },\n\t// Phaistos Disc\n\t{ start: 0x101d0, end: 0x101ff, script: Script.Common },\n\t// Lycian\n\t{ start: 0x10280, end: 0x1029f, script: Script.Lycian },\n\t// Carian\n\t{ start: 0x102a0, end: 0x102df, script: Script.Carian },\n\t// Coptic Epact Numbers\n\t{ start: 0x102e0, end: 0x102ff, script: Script.Inherited },\n\t// Old Italic\n\t{ start: 0x10300, end: 0x1032f, script: Script.OldItalic },\n\t// Gothic\n\t{ start: 0x10330, end: 0x1034f, script: Script.Gothic },\n\t// Old Permic\n\t{ start: 0x10350, end: 0x1037f, script: Script.OldPermic },\n\t// Ugaritic\n\t{ start: 0x10380, end: 0x1039f, script: Script.Ugaritic },\n\t// Old Persian\n\t{ start: 0x103a0, end: 0x103df, script: Script.OldPersian },\n\t// Deseret\n\t{ start: 0x10400, end: 0x1044f, script: Script.Deseret },\n\t// Shavian\n\t{ start: 0x10450, end: 0x1047f, script: Script.Shavian },\n\t// Osmanya\n\t{ start: 0x10480, end: 0x104af, script: Script.Osmanya },\n\t// Osage\n\t{ start: 0x104b0, end: 0x104ff, script: Script.Osage },\n\t// Elbasan\n\t{ start: 0x10500, end: 0x1052f, script: Script.Elbasan },\n\t// Caucasian Albanian\n\t{ start: 0x10530, end: 0x1056f, script: Script.CaucasianAlbanian },\n\t// Vithkuqi\n\t{ start: 0x10570, end: 0x105bf, script: Script.Vithkuqi },\n\t// Linear A\n\t{ start: 0x10600, end: 0x1077f, script: Script.LinearA },\n\t// Latin Extended-F\n\t{ start: 0x10780, end: 0x107bf, script: Script.Latin },\n\t// Cypriot Syllabary\n\t{ start: 0x10800, end: 0x1083f, script: Script.Cypriot },\n\t// Imperial Aramaic\n\t{ start: 0x10840, end: 0x1085f, script: Script.ImperialAramaic },\n\t// Palmyrene\n\t{ start: 0x10860, end: 0x1087f, script: Script.Palmyrene },\n\t// Nabataean\n\t{ start: 0x10880, end: 0x108af, script: Script.Nabataean },\n\t// Hatran\n\t{ start: 0x108e0, end: 0x108ff, script: Script.Hatran },\n\t// Phoenician\n\t{ start: 0x10900, end: 0x1091f, script: Script.Phoenician },\n\t// Lydian\n\t{ start: 0x10920, end: 0x1093f, script: Script.Lydian },\n\t// Meroitic Hieroglyphs\n\t{ start: 0x10980, end: 0x1099f, script: Script.MeroiticHieroglyphs },\n\t// Meroitic Cursive\n\t{ start: 0x109a0, end: 0x109ff, script: Script.MeroiticCursive },\n\t// Kharoshthi\n\t{ start: 0x10a00, end: 0x10a5f, script: Script.Kharoshthi },\n\t// Old South Arabian\n\t{ start: 0x10a60, end: 0x10a7f, script: Script.OldSouthArabian },\n\t// Old North Arabian\n\t{ start: 0x10a80, end: 0x10a9f, script: Script.OldNorthArabian },\n\t// Manichaean\n\t{ start: 0x10ac0, end: 0x10aff, script: Script.Manichaean },\n\t// Avestan\n\t{ start: 0x10b00, end: 0x10b3f, script: Script.Avestan },\n\t// Inscriptional Parthian\n\t{ start: 0x10b40, end: 0x10b5f, script: Script.InscriptionalParthian },\n\t// Inscriptional Pahlavi\n\t{ start: 0x10b60, end: 0x10b7f, script: Script.InscriptionalPahlavi },\n\t// Psalter Pahlavi\n\t{ start: 0x10b80, end: 0x10baf, script: Script.PsalterPahlavi },\n\t// Old Turkic\n\t{ start: 0x10c00, end: 0x10c4f, script: Script.OldTurkic },\n\t// Old Hungarian\n\t{ start: 0x10c80, end: 0x10cff, script: Script.OldHungarian },\n\t// Hanifi Rohingya\n\t{ start: 0x10d00, end: 0x10d3f, script: Script.HanifiRohingya },\n\t// Yezidi\n\t{ start: 0x10e80, end: 0x10ebf, script: Script.Yezidi },\n\t// Old Sogdian\n\t{ start: 0x10f00, end: 0x10f2f, script: Script.OldSogdian },\n\t// Sogdian\n\t{ start: 0x10f30, end: 0x10f6f, script: Script.Sogdian },\n\t// Old Uyghur\n\t{ start: 0x10f70, end: 0x10faf, script: Script.OldUyghur },\n\t// Chorasmian\n\t{ start: 0x10fb0, end: 0x10fdf, script: Script.Chorasmian },\n\t// Elymaic\n\t{ start: 0x10fe0, end: 0x10fff, script: Script.Elymaic },\n\t// Brahmi\n\t{ start: 0x11000, end: 0x1107f, script: Script.Brahmi },\n\t// Kaithi\n\t{ start: 0x11080, end: 0x110cf, script: Script.Kaithi },\n\t// Sora Sompeng\n\t{ start: 0x110d0, end: 0x110ff, script: Script.SoraSompeng },\n\t// Chakma\n\t{ start: 0x11100, end: 0x1114f, script: Script.Chakma },\n\t// Mahajani\n\t{ start: 0x11150, end: 0x1117f, script: Script.Mahajani },\n\t// Sharada\n\t{ start: 0x11180, end: 0x111df, script: Script.Sharada },\n\t// Sinhala Archaic Numbers\n\t{ start: 0x111e0, end: 0x111ff, script: Script.Sinhala },\n\t// Khojki\n\t{ start: 0x11200, end: 0x1124f, script: Script.Khojki },\n\t// Multani\n\t{ start: 0x11280, end: 0x112af, script: Script.Multani },\n\t// Khudawadi\n\t{ start: 0x112b0, end: 0x112ff, script: Script.Khudawadi },\n\t// Grantha\n\t{ start: 0x11300, end: 0x1137f, script: Script.Grantha },\n\t// Newa\n\t{ start: 0x11400, end: 0x1147f, script: Script.Newa },\n\t// Tirhuta\n\t{ start: 0x11480, end: 0x114df, script: Script.Tirhuta },\n\t// Siddham\n\t{ start: 0x11580, end: 0x115ff, script: Script.Siddham },\n\t// Modi\n\t{ start: 0x11600, end: 0x1165f, script: Script.Modi },\n\t// Mongolian Supplement\n\t{ start: 0x11660, end: 0x1167f, script: Script.Mongolian },\n\t// Takri\n\t{ start: 0x11680, end: 0x116cf, script: Script.Takri },\n\t// Ahom\n\t{ start: 0x11700, end: 0x1174f, script: Script.Ahom },\n\t// Dogra\n\t{ start: 0x11800, end: 0x1184f, script: Script.Dogra },\n\t// Warang Citi\n\t{ start: 0x118a0, end: 0x118ff, script: Script.WarangCiti },\n\t// Dives Akuru\n\t{ start: 0x11900, end: 0x1195f, script: Script.DivesAkuru },\n\t// Nandinagari\n\t{ start: 0x119a0, end: 0x119ff, script: Script.Nandinagari },\n\t// Zanabazar Square\n\t{ start: 0x11a00, end: 0x11a4f, script: Script.ZanabazarSquare },\n\t// Soyombo\n\t{ start: 0x11a50, end: 0x11aaf, script: Script.Soyombo },\n\t// UCAS Extended-A\n\t{ start: 0x11ab0, end: 0x11abf, script: Script.CanadianAboriginal },\n\t// Pau Cin Hau\n\t{ start: 0x11ac0, end: 0x11aff, script: Script.PauCinHau },\n\t// Bhaiksuki\n\t{ start: 0x11c00, end: 0x11c6f, script: Script.Bhaiksuki },\n\t// Marchen\n\t{ start: 0x11c70, end: 0x11cbf, script: Script.Marchen },\n\t// Masaram Gondi\n\t{ start: 0x11d00, end: 0x11d5f, script: Script.MasaramGondi },\n\t// Gunjala Gondi\n\t{ start: 0x11d60, end: 0x11daf, script: Script.GunjalaGondi },\n\t// Makasar\n\t{ start: 0x11ee0, end: 0x11eff, script: Script.Makasar },\n\t// Kawi\n\t{ start: 0x11f00, end: 0x11f5f, script: Script.Kawi },\n\t// Cuneiform\n\t{ start: 0x12000, end: 0x123ff, script: Script.Cuneiform },\n\t// Cuneiform Numbers and Punctuation\n\t{ start: 0x12400, end: 0x1247f, script: Script.Cuneiform },\n\t// Early Dynastic Cuneiform\n\t{ start: 0x12480, end: 0x1254f, script: Script.Cuneiform },\n\t// Cypro-Minoan\n\t{ start: 0x12f90, end: 0x12fff, script: Script.Cypro_Minoan },\n\t// Egyptian Hieroglyphs\n\t{ start: 0x13000, end: 0x1342f, script: Script.EgyptianHieroglyphs },\n\t// Egyptian Hieroglyph Format Controls\n\t{ start: 0x13430, end: 0x1345f, script: Script.EgyptianHieroglyphs },\n\t// Anatolian Hieroglyphs\n\t{ start: 0x14400, end: 0x1467f, script: Script.AnatolianHieroglyphs },\n\t// Bamum Supplement\n\t{ start: 0x16800, end: 0x16a3f, script: Script.Bamum },\n\t// Mro\n\t{ start: 0x16a40, end: 0x16a6f, script: Script.Mro },\n\t// Tangsa\n\t{ start: 0x16a70, end: 0x16acf, script: Script.Tangsa },\n\t// Bassa Vah\n\t{ start: 0x16ad0, end: 0x16aff, script: Script.BassaVah },\n\t// Pahawh Hmong\n\t{ start: 0x16b00, end: 0x16b8f, script: Script.PahawhHmong },\n\t// Medefaidrin\n\t{ start: 0x16e40, end: 0x16e9f, script: Script.Medefaidrin },\n\t// Miao\n\t{ start: 0x16f00, end: 0x16f9f, script: Script.Miao },\n\t// Ideographic Symbols and Punctuation\n\t{ start: 0x16fe0, end: 0x16fff, script: Script.Common },\n\t// Tangut\n\t{ start: 0x17000, end: 0x187ff, script: Script.Tangut },\n\t// Tangut Components\n\t{ start: 0x18800, end: 0x18aff, script: Script.Tangut },\n\t// Khitan Small Script\n\t{ start: 0x18b00, end: 0x18cff, script: Script.KhitanSmallScript },\n\t// Tangut Supplement\n\t{ start: 0x18d00, end: 0x18d7f, script: Script.Tangut },\n\t// Kana Extended-B\n\t{ start: 0x1aff0, end: 0x1afff, script: Script.Katakana },\n\t// Kana Supplement\n\t{ start: 0x1b000, end: 0x1b0ff, script: Script.Hiragana },\n\t// Kana Extended-A\n\t{ start: 0x1b100, end: 0x1b12f, script: Script.Hiragana },\n\t// Small Kana Extension\n\t{ start: 0x1b130, end: 0x1b16f, script: Script.Katakana },\n\t// Nushu\n\t{ start: 0x1b170, end: 0x1b2ff, script: Script.Nushu },\n\t// Duployan\n\t{ start: 0x1bc00, end: 0x1bc9f, script: Script.Duployan },\n\t// Shorthand Format Controls\n\t{ start: 0x1bca0, end: 0x1bcaf, script: Script.Common },\n\t// Znamenny Musical Notation\n\t{ start: 0x1cf00, end: 0x1cfcf, script: Script.Common },\n\t// Byzantine Musical Symbols\n\t{ start: 0x1d000, end: 0x1d0ff, script: Script.Common },\n\t// Musical Symbols\n\t{ start: 0x1d100, end: 0x1d1ff, script: Script.Common },\n\t// Ancient Greek Musical Notation\n\t{ start: 0x1d200, end: 0x1d24f, script: Script.Greek },\n\t// Kaktovik Numerals\n\t{ start: 0x1d2c0, end: 0x1d2df, script: Script.Common },\n\t// Mayan Numerals\n\t{ start: 0x1d2e0, end: 0x1d2ff, script: Script.Common },\n\t// Tai Xuan Jing Symbols\n\t{ start: 0x1d300, end: 0x1d35f, script: Script.Common },\n\t// Counting Rod Numerals\n\t{ start: 0x1d360, end: 0x1d37f, script: Script.Common },\n\t// Mathematical Alphanumeric Symbols\n\t{ start: 0x1d400, end: 0x1d7ff, script: Script.Common },\n\t// Sutton SignWriting\n\t{ start: 0x1d800, end: 0x1daaf, script: Script.SignWriting },\n\t// Latin Extended-G\n\t{ start: 0x1df00, end: 0x1dfff, script: Script.Latin },\n\t// Glagolitic Supplement\n\t{ start: 0x1e000, end: 0x1e02f, script: Script.Glagolitic },\n\t// Cyrillic Extended-D\n\t{ start: 0x1e030, end: 0x1e08f, script: Script.Cyrillic },\n\t// Nyiakeng Puachue Hmong\n\t{ start: 0x1e100, end: 0x1e14f, script: Script.NyiakengPuachueHmong },\n\t// Toto\n\t{ start: 0x1e290, end: 0x1e2bf, script: Script.Toto },\n\t// Wancho\n\t{ start: 0x1e2c0, end: 0x1e2ff, script: Script.Wancho },\n\t// Nag Mundari\n\t{ start: 0x1e4d0, end: 0x1e4ff, script: Script.NagMundari },\n\t// Ethiopic Extended-B\n\t{ start: 0x1e7e0, end: 0x1e7ff, script: Script.Ethiopic },\n\t// Mende Kikakui\n\t{ start: 0x1e800, end: 0x1e8df, script: Script.MendeKikakui },\n\t// Adlam\n\t{ start: 0x1e900, end: 0x1e95f, script: Script.Adlam },\n\t// Indic Siyaq Numbers\n\t{ start: 0x1ec70, end: 0x1ecbf, script: Script.Common },\n\t// Ottoman Siyaq Numbers\n\t{ start: 0x1ed00, end: 0x1ed4f, script: Script.Common },\n\t// Arabic Mathematical Alphabetic Symbols\n\t{ start: 0x1ee00, end: 0x1eeff, script: Script.Arabic },\n\t// Mahjong Tiles\n\t{ start: 0x1f000, end: 0x1f02f, script: Script.Common },\n\t// Domino Tiles\n\t{ start: 0x1f030, end: 0x1f09f, script: Script.Common },\n\t// Playing Cards\n\t{ start: 0x1f0a0, end: 0x1f0ff, script: Script.Common },\n\t// Enclosed Alphanumeric Supplement\n\t{ start: 0x1f100, end: 0x1f1ff, script: Script.Common },\n\t// Enclosed Ideographic Supplement\n\t{ start: 0x1f200, end: 0x1f2ff, script: Script.Common },\n\t// Miscellaneous Symbols and Pictographs\n\t{ start: 0x1f300, end: 0x1f5ff, script: Script.Common },\n\t// Emoticons\n\t{ start: 0x1f600, end: 0x1f64f, script: Script.Common },\n\t// Ornamental Dingbats\n\t{ start: 0x1f650, end: 0x1f67f, script: Script.Common },\n\t// Transport and Map Symbols\n\t{ start: 0x1f680, end: 0x1f6ff, script: Script.Common },\n\t// Alchemical Symbols\n\t{ start: 0x1f700, end: 0x1f77f, script: Script.Common },\n\t// Geometric Shapes Extended\n\t{ start: 0x1f780, end: 0x1f7ff, script: Script.Common },\n\t// Supplemental Arrows-C\n\t{ start: 0x1f800, end: 0x1f8ff, script: Script.Common },\n\t// Supplemental Symbols and Pictographs\n\t{ start: 0x1f900, end: 0x1f9ff, script: Script.Common },\n\t// Chess Symbols\n\t{ start: 0x1fa00, end: 0x1fa6f, script: Script.Common },\n\t// Symbols and Pictographs Extended-A\n\t{ start: 0x1fa70, end: 0x1faff, script: Script.Common },\n\t// Symbols for Legacy Computing\n\t{ start: 0x1fb00, end: 0x1fbff, script: Script.Common },\n\t// CJK Unified Ideographs Extension B\n\t{ start: 0x20000, end: 0x2a6df, script: Script.Han },\n\t// CJK Unified Ideographs Extension C\n\t{ start: 0x2a700, end: 0x2b73f, script: Script.Han },\n\t// CJK Unified Ideographs Extension D\n\t{ start: 0x2b740, end: 0x2b81f, script: Script.Han },\n\t// CJK Unified Ideographs Extension E\n\t{ start: 0x2b820, end: 0x2ceaf, script: Script.Han },\n\t// CJK Unified Ideographs Extension F\n\t{ start: 0x2ceb0, end: 0x2ebef, script: Script.Han },\n\t// CJK Compatibility Ideographs Supplement\n\t{ start: 0x2f800, end: 0x2fa1f, script: Script.Han },\n\t// CJK Unified Ideographs Extension G\n\t{ start: 0x30000, end: 0x3134f, script: Script.Han },\n\t// CJK Unified Ideographs Extension H\n\t{ start: 0x31350, end: 0x323af, script: Script.Han },\n\t// Tags\n\t{ start: 0xe0000, end: 0xe007f, script: Script.Common },\n\t// Variation Selectors Supplement\n\t{ start: 0xe0100, end: 0xe01ef, script: Script.Inherited },\n\t// Supplementary Private Use Area-A\n\t{ start: 0xf0000, end: 0xfffff, script: Script.Unknown },\n\t// Supplementary Private Use Area-B\n\t{ start: 0x100000, end: 0x10ffff, script: Script.Unknown },\n];\n\n/**\n * Get script for a codepoint using binary search\n */\nexport function getScript(cp: number): Script {\n\tlet left = 0;\n\tlet right = SCRIPT_RANGES.length - 1;\n\n\twhile (left <= right) {\n\t\tconst mid = (left + right) >>> 1;\n\t\tconst range = SCRIPT_RANGES[mid]!;\n\n\t\tif (cp < range.start) {\n\t\t\tright = mid - 1;\n\t\t} else if (cp > range.end) {\n\t\t\tleft = mid + 1;\n\t\t} else {\n\t\t\treturn range.script;\n\t\t}\n\t}\n\n\treturn Script.Unknown;\n}\n\n/**\n * Get script for a string (returns the dominant non-Common/Inherited script)\n */\nexport function detectScript(text: string): Script {\n\tconst counts = new Map<Script, number>();\n\n\tfor (const char of text) {\n\t\tconst cp = char.codePointAt(0) ?? 0;\n\t\tconst script = getScript(cp);\n\n\t\t// Skip Common and Inherited scripts\n\t\tif (script === Script.Common || script === Script.Inherited) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tcounts.set(script, (counts.get(script) ?? 0) + 1);\n\t}\n\n\tif (counts.size === 0) {\n\t\treturn Script.Common;\n\t}\n\n\t// Return the most frequent script\n\tlet maxScript = Script.Common;\n\tlet maxCount = 0;\n\n\tfor (const [script, count] of counts) {\n\t\tif (count > maxCount) {\n\t\t\tmaxCount = count;\n\t\t\tmaxScript = script;\n\t\t}\n\t}\n\n\treturn maxScript;\n}\n\n/**\n * Get all scripts present in text\n */\nexport function getScripts(text: string): Script[] {\n\tconst scripts = new Set<Script>();\n\n\tfor (const char of text) {\n\t\tconst cp = char.codePointAt(0) ?? 0;\n\t\tconst script = getScript(cp);\n\t\tscripts.add(script);\n\t}\n\n\treturn Array.from(scripts);\n}\n\n/**\n * Check if text contains only characters from a specific script\n * (Common and Inherited are allowed)\n */\nexport function isScript(text: string, script: Script): boolean {\n\tfor (const char of text) {\n\t\tconst cp = char.codePointAt(0) ?? 0;\n\t\tconst charScript = getScript(cp);\n\n\t\tif (\n\t\t\tcharScript !== script &&\n\t\t\tcharScript !== Script.Common &&\n\t\t\tcharScript !== Script.Inherited\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Script run - a contiguous sequence of characters with the same script\n */\nexport interface ScriptRun {\n\tscript: Script;\n\tstart: number;\n\tend: number;\n\ttext: string;\n}\n\n/**\n * Split text into script runs\n */\nexport function getScriptRuns(text: string): ScriptRun[] {\n\tconst runs: ScriptRun[] = [];\n\tif (text.length === 0) return runs;\n\n\tlet currentScript: Script | null = null;\n\tlet runStart = 0;\n\tlet charIndex = 0;\n\n\tconst chars: string[] = [];\n\tfor (const char of text) {\n\t\tchars.push(char);\n\t}\n\n\tfor (let i = 0; i < chars.length; i++) {\n\t\tconst char = chars[i]!;\n\t\tconst cp = char.codePointAt(0) ?? 0;\n\t\tlet script = getScript(cp);\n\n\t\t// Treat Common and Inherited as part of the current run\n\t\tif (script === Script.Common || script === Script.Inherited) {\n\t\t\tif (currentScript !== null) {\n\t\t\t\tscript = currentScript;\n\t\t\t}\n\t\t}\n\n\t\tif (currentScript === null) {\n\t\t\tcurrentScript = script;\n\t\t\trunStart = i;\n\t\t} else if (script !== currentScript && script !== Script.Common && script !== Script.Inherited) {\n\t\t\t// End current run\n\t\t\truns.push({\n\t\t\t\tscript: currentScript,\n\t\t\t\tstart: runStart,\n\t\t\t\tend: i,\n\t\t\t\ttext: chars.slice(runStart, i).join(\"\"),\n\t\t\t});\n\t\t\tcurrentScript = script;\n\t\t\trunStart = i;\n\t\t}\n\t}\n\n\t// Add final run\n\tif (currentScript !== null) {\n\t\truns.push({\n\t\t\tscript: currentScript,\n\t\t\tstart: runStart,\n\t\t\tend: chars.length,\n\t\t\ttext: chars.slice(runStart).join(\"\"),\n\t\t});\n\t}\n\n\treturn runs;\n}\n\n/**\n * Get OpenType script tag for a Unicode script\n */\nexport function getScriptTag(script: Script): string {\n\t// Map Script enum to OpenType script tags\n\tconst tagMap: Record<Script, string> = {\n\t\t[Script.Common]: \"DFLT\",\n\t\t[Script.Inherited]: \"DFLT\",\n\t\t[Script.Unknown]: \"DFLT\",\n\t\t[Script.Latin]: \"latn\",\n\t\t[Script.Greek]: \"grek\",\n\t\t[Script.Cyrillic]: \"cyrl\",\n\t\t[Script.Armenian]: \"armn\",\n\t\t[Script.Hebrew]: \"hebr\",\n\t\t[Script.Arabic]: \"arab\",\n\t\t[Script.Syriac]: \"syrc\",\n\t\t[Script.Thaana]: \"thaa\",\n\t\t[Script.Devanagari]: \"deva\",\n\t\t[Script.Bengali]: \"beng\",\n\t\t[Script.Gurmukhi]: \"guru\",\n\t\t[Script.Gujarati]: \"gujr\",\n\t\t[Script.Oriya]: \"orya\",\n\t\t[Script.Tamil]: \"taml\",\n\t\t[Script.Telugu]: \"telu\",\n\t\t[Script.Kannada]: \"knda\",\n\t\t[Script.Malayalam]: \"mlym\",\n\t\t[Script.Sinhala]: \"sinh\",\n\t\t[Script.Thai]: \"thai\",\n\t\t[Script.Lao]: \"lao \",\n\t\t[Script.Tibetan]: \"tibt\",\n\t\t[Script.Myanmar]: \"mymr\",\n\t\t[Script.Georgian]: \"geor\",\n\t\t[Script.Hangul]: \"hang\",\n\t\t[Script.Ethiopic]: \"ethi\",\n\t\t[Script.Cherokee]: \"cher\",\n\t\t[Script.CanadianAboriginal]: \"cans\",\n\t\t[Script.Ogham]: \"ogam\",\n\t\t[Script.Runic]: \"runr\",\n\t\t[Script.Khmer]: \"khmr\",\n\t\t[Script.Mongolian]: \"mong\",\n\t\t[Script.Hiragana]: \"kana\",\n\t\t[Script.Katakana]: \"kana\",\n\t\t[Script.Bopomofo]: \"bopo\",\n\t\t[Script.Han]: \"hani\",\n\t\t[Script.Yi]: \"yi \",\n\t\t[Script.OldItalic]: \"ital\",\n\t\t[Script.Gothic]: \"goth\",\n\t\t[Script.Deseret]: \"dsrt\",\n\t\t[Script.Tagalog]: \"tglg\",\n\t\t[Script.Hanunoo]: \"hano\",\n\t\t[Script.Buhid]: \"buhd\",\n\t\t[Script.Tagbanwa]: \"tagb\",\n\t\t[Script.Limbu]: \"limb\",\n\t\t[Script.TaiLe]: \"tale\",\n\t\t[Script.LinearB]: \"linb\",\n\t\t[Script.Ugaritic]: \"ugar\",\n\t\t[Script.Shavian]: \"shaw\",\n\t\t[Script.Osmanya]: \"osma\",\n\t\t[Script.Cypriot]: \"cprt\",\n\t\t[Script.Braille]: \"brai\",\n\t\t[Script.Buginese]: \"bugi\",\n\t\t[Script.Coptic]: \"copt\",\n\t\t[Script.NewTaiLue]: \"talu\",\n\t\t[Script.Glagolitic]: \"glag\",\n\t\t[Script.Tifinagh]: \"tfng\",\n\t\t[Script.SylotiNagri]: \"sylo\",\n\t\t[Script.OldPersian]: \"xpeo\",\n\t\t[Script.Kharoshthi]: \"khar\",\n\t\t[Script.Balinese]: \"bali\",\n\t\t[Script.Cuneiform]: \"xsux\",\n\t\t[Script.Phoenician]: \"phnx\",\n\t\t[Script.PhagsPa]: \"phag\",\n\t\t[Script.Nko]: \"nko \",\n\t\t[Script.Sundanese]: \"sund\",\n\t\t[Script.Lepcha]: \"lepc\",\n\t\t[Script.OlChiki]: \"olck\",\n\t\t[Script.Vai]: \"vai \",\n\t\t[Script.Saurashtra]: \"saur\",\n\t\t[Script.KayahLi]: \"kali\",\n\t\t[Script.Rejang]: \"rjng\",\n\t\t[Script.Lycian]: \"lyci\",\n\t\t[Script.Carian]: \"cari\",\n\t\t[Script.Lydian]: \"lydi\",\n\t\t[Script.Cham]: \"cham\",\n\t\t[Script.TaiTham]: \"lana\",\n\t\t[Script.TaiViet]: \"tavt\",\n\t\t[Script.Avestan]: \"avst\",\n\t\t[Script.EgyptianHieroglyphs]: \"egyp\",\n\t\t[Script.Samaritan]: \"samr\",\n\t\t[Script.Lisu]: \"lisu\",\n\t\t[Script.Bamum]: \"bamu\",\n\t\t[Script.Javanese]: \"java\",\n\t\t[Script.MeeteiMayek]: \"mtei\",\n\t\t[Script.ImperialAramaic]: \"armi\",\n\t\t[Script.OldSouthArabian]: \"sarb\",\n\t\t[Script.InscriptionalParthian]: \"prti\",\n\t\t[Script.InscriptionalPahlavi]: \"phli\",\n\t\t[Script.OldTurkic]: \"orkh\",\n\t\t[Script.Kaithi]: \"kthi\",\n\t\t[Script.Batak]: \"batk\",\n\t\t[Script.Brahmi]: \"brah\",\n\t\t[Script.Mandaic]: \"mand\",\n\t\t[Script.Chakma]: \"cakm\",\n\t\t[Script.MeroiticCursive]: \"merc\",\n\t\t[Script.MeroiticHieroglyphs]: \"mero\",\n\t\t[Script.Miao]: \"plrd\",\n\t\t[Script.Sharada]: \"shrd\",\n\t\t[Script.SoraSompeng]: \"sora\",\n\t\t[Script.Takri]: \"takr\",\n\t\t[Script.CaucasianAlbanian]: \"aghb\",\n\t\t[Script.BassaVah]: \"bass\",\n\t\t[Script.Duployan]: \"dupl\",\n\t\t[Script.Elbasan]: \"elba\",\n\t\t[Script.Grantha]: \"gran\",\n\t\t[Script.PahawhHmong]: \"hmng\",\n\t\t[Script.Khojki]: \"khoj\",\n\t\t[Script.LinearA]: \"lina\",\n\t\t[Script.Mahajani]: \"mahj\",\n\t\t[Script.Manichaean]: \"mani\",\n\t\t[Script.MendeKikakui]: \"mend\",\n\t\t[Script.Modi]: \"modi\",\n\t\t[Script.Mro]: \"mroo\",\n\t\t[Script.OldNorthArabian]: \"narb\",\n\t\t[Script.Nabataean]: \"nbat\",\n\t\t[Script.Palmyrene]: \"palm\",\n\t\t[Script.PauCinHau]: \"pauc\",\n\t\t[Script.OldPermic]: \"perm\",\n\t\t[Script.PsalterPahlavi]: \"phlp\",\n\t\t[Script.Siddham]: \"sidd\",\n\t\t[Script.Khudawadi]: \"sind\",\n\t\t[Script.Tirhuta]: \"tirh\",\n\t\t[Script.WarangCiti]: \"wara\",\n\t\t[Script.Ahom]: \"ahom\",\n\t\t[Script.AnatolianHieroglyphs]: \"hluw\",\n\t\t[Script.Hatran]: \"hatr\",\n\t\t[Script.Multani]: \"mult\",\n\t\t[Script.OldHungarian]: \"hung\",\n\t\t[Script.SignWriting]: \"sgnw\",\n\t\t[Script.Adlam]: \"adlm\",\n\t\t[Script.Bhaiksuki]: \"bhks\",\n\t\t[Script.Marchen]: \"marc\",\n\t\t[Script.Newa]: \"newa\",\n\t\t[Script.Osage]: \"osge\",\n\t\t[Script.Tangut]: \"tang\",\n\t\t[Script.MasaramGondi]: \"gonm\",\n\t\t[Script.Nushu]: \"nshu\",\n\t\t[Script.Soyombo]: \"soyo\",\n\t\t[Script.ZanabazarSquare]: \"zanb\",\n\t\t[Script.Dogra]: \"dogr\",\n\t\t[Script.GunjalaGondi]: \"gong\",\n\t\t[Script.Makasar]: \"maka\",\n\t\t[Script.Medefaidrin]: \"medf\",\n\t\t[Script.HanifiRohingya]: \"rohg\",\n\t\t[Script.Sogdian]: \"sogd\",\n\t\t[Script.OldSogdian]: \"sogo\",\n\t\t[Script.Elymaic]: \"elym\",\n\t\t[Script.Nandinagari]: \"nand\",\n\t\t[Script.NyiakengPuachueHmong]: \"hmnp\",\n\t\t[Script.Wancho]: \"wcho\",\n\t\t[Script.Yezidi]: \"yezi\",\n\t\t[Script.Chorasmian]: \"chrs\",\n\t\t[Script.DivesAkuru]: \"diak\",\n\t\t[Script.KhitanSmallScript]: \"kits\",\n\t\t[Script.Vithkuqi]: \"vith\",\n\t\t[Script.OldUyghur]: \"ougr\",\n\t\t[Script.Cypro_Minoan]: \"cpmn\",\n\t\t[Script.Tangsa]: \"tnsa\",\n\t\t[Script.Toto]: \"toto\",\n\t\t[Script.Kawi]: \"kawi\",\n\t\t[Script.NagMundari]: \"nagm\",\n\t};\n\n\treturn tagMap[script] ?? \"DFLT\";\n}\n\n/**\n * Check if a script requires complex shaping\n */\nexport function isComplexScript(script: Script): boolean {\n\tconst complexScripts = new Set([\n\t\tScript.Arabic,\n\t\tScript.Syriac,\n\t\tScript.Hebrew,\n\t\tScript.Thaana,\n\t\tScript.Nko,\n\t\tScript.Devanagari,\n\t\tScript.Bengali,\n\t\tScript.Gurmukhi,\n\t\tScript.Gujarati,\n\t\tScript.Oriya,\n\t\tScript.Tamil,\n\t\tScript.Telugu,\n\t\tScript.Kannada,\n\t\tScript.Malayalam,\n\t\tScript.Sinhala,\n\t\tScript.Thai,\n\t\tScript.Lao,\n\t\tScript.Tibetan,\n\t\tScript.Myanmar,\n\t\tScript.Khmer,\n\t\tScript.Mongolian,\n\t\tScript.Hangul,\n\t]);\n\n\treturn complexScripts.has(script);\n}\n\n/**\n * Get script direction (LTR or RTL)\n */\nexport function getScriptDirection(script: Script): \"ltr\" | \"rtl\" {\n\tconst rtlScripts = new Set([\n\t\tScript.Arabic,\n\t\tScript.Hebrew,\n\t\tScript.Syriac,\n\t\tScript.Thaana,\n\t\tScript.Nko,\n\t\tScript.Samaritan,\n\t\tScript.Mandaic,\n\t\tScript.ImperialAramaic,\n\t\tScript.Phoenician,\n\t\tScript.OldSouthArabian,\n\t\tScript.OldNorthArabian,\n\t\tScript.Avestan,\n\t\tScript.InscriptionalParthian,\n\t\tScript.InscriptionalPahlavi,\n\t\tScript.PsalterPahlavi,\n\t\tScript.Hatran,\n\t\tScript.Lydian,\n\t\tScript.Nabataean,\n\t\tScript.Palmyrene,\n\t\tScript.Manichaean,\n\t\tScript.MendeKikakui,\n\t\tScript.HanifiRohingya,\n\t\tScript.Yezidi,\n\t\tScript.OldSogdian,\n\t\tScript.Sogdian,\n\t\tScript.Elymaic,\n\t\tScript.Chorasmian,\n\t\tScript.OldUyghur,\n\t\tScript.Adlam,\n\t]);\n\n\treturn rtlScripts.has(script) ? \"rtl\" : \"ltr\";\n}\n"
88
+ ],
89
+ "mappings": "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SAAW,EAAK,MAAc,IAAO,GACrC,SAAW,EAAK,MAAc,IAAO,GACrC,QAAS,EAAK,IACf,EAGA,OAAU,CACT,OAAQ,EAAK,KACb,MAAO,EAAK,KACZ,SAAW,EAAK,MAAc,IAAO,GACrC,SAAW,EAAK,MAAc,IAAO,GACrC,QAAS,EAAK,IACf,EACA,GAAU,EAEX,KACD,KACK,IAAI,CAER,EAAU,CAAE,OAAQ,EAAG,MAAO,EAAG,SAAU,EAAG,SAAU,EAAG,QAAS,CAAE,EACtE,KACD,SAEC,OAAO,KAGT,MAAO,CACN,UACA,cACA,KAAM,EAAK,MAAM,CAAM,CACxB,EAMM,SAAS,EAAc,CAC7B,EACA,EACA,EACU,CACV,QAAW,KAAQ,EAAK,YAAa,CACpC,GAAI,IAAS,QAAa,EAAK,QAAU,EAAM,SAC/C,GAAI,EAAU,EAAK,iBAAmB,EAAU,EAAK,cACpD,SAED,QAAW,KAAY,EAAK,eAC3B,GAAI,EAAS,aAAa,IAAI,CAAO,EACpC,MAAO,GAIV,MAAO,GAMD,SAAS,EAAmB,CAAC,EAA2B,CAC9D,IAAM,EAAQ,IAAI,IAClB,QAAW,KAAQ,EAAK,YACvB,EAAM,IAAI,EAAK,KAAK,EAErB,OAAO,MAAM,KAAK,CAAK,EAAE,KAAK,CAAC,EAAG,IAAM,EAAI,CAAC,EC1X9C,IAAM,GAAmB,CACxB,UACA,QACA,SACA,WACA,aACA,SACA,UACA,YACA,aACA,YACA,aACA,WACA,OACA,QACA,SACA,SACA,QACA,OACA,MACA,MACA,QACA,OACA,OACA,MACA,QACA,QACA,OACA,QACA,YACA,OACA,QACA,UACA,WACA,KACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,cACA,YACA,eACA,cACA,aACA,YACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,YACA,MACA,aACA,aACA,aACA,OACA,WACA,WACA,MACA,SACA,UACA,WACA,cACA,eACA,gBACA,gBACA,iBACA,KACA,KACA,SACA,SACA,YACA,iBACA,YACA,SACA,iBACA,eACA,gBACA,iBACA,WACA,cACA,eACA,QACA,QACA,aACA,QACA,SACA,QACA,YACA,WACA,OACA,UACA,eACA,SACA,QACA,SACA,KACA,cACA,SACA,SACA,KACA,eACA,KACA,WACA,SACA,SACA,KACA,aACA,cACA,aACA,KACA,YACA,MACA,UACA,YACA,QACA,aACA,SACA,YACA,SACA,QACA,gBACA,cACA,aACA,QACA,MACA,WACA,gBACA,YACA,SACA,cACA,YACA,SACA,QACA,SACA,WACA,SACA,cACA,YACA,SACA,SACA,cACA,YACA,SACA,SACA,SACA,cACA,YACA,SACA,SACA,SACA,SACA,cACA,YACA,SACA,SACA,YACA,SACA,SACA,cACA,YACA,SACA,QACA,SACA,WACA,SACA,cACA,YACA,SACA,SACA,cACA,YACA,SACA,SACA,SACA,cACA,YACA,SACA,SACA,SACA,SACA,cACA,YACA,SACA,SACA,YACA,SACA,cACA,oBACA,iBACA,iBACA,iBACA,aACA,oBACA,qBACA,iBACA,iBACA,eACA,cACA,cACA,gBACA,eACA,eACA,cACA,gBACA,gBACA,eACA,gBACA,sBACA,iBACA,gBACA,YACA,YACA,eACA,YACA,YACA,YACA,YACA,YACA,YACA,YACA,YACA,YACA,YACA,KACA,MACA,MACA,oBACA,qBACA,kBACA,iBACA,aACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,gBACA,YACA,SACA,aACA,kBACA,eACA,cACA,cACA,cACA,gBACA,aACA,aACA,iBACA,cACA,aACA,iBACA,cACA,YACA,eACA,oBACA,YACA,eACA,cACA,eACA,WACA,YA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CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EAEzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EAEzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,IAAQ,CAAC,IAAQ,GAAM,CAAC,EAEzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,IAAQ,GAAM,CAAC,EACzB,CAAC,KAAQ,CAAC,GAAQ,GAAM,CAAC,EACz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,GAAM,MAAU,GAAM,KAAQ,MAAO,IACzC,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAI1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,IACzC,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,IACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,IACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,IACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,IACzC,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,IACzC,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,IACzC,GAAI,IAAO,KAAQ,MAAO,IAI1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,IAAO,KAAQ,MAAO,IAC1B,GAAI,I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GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,G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AI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,IAAO,MAAS,MAAO,GAC3B,GAAI,IAAO,MAAS,MAAO,GAC3B,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,IAAO,MAAS,MAAO,GAC3B,GAAI,IAAO,MAAS,MAAO,GAC3B,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,IAAO,MAAS,MAAO,GAC3B,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,IAAO,MAAS,MAAO,GAC3B,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,IAAO,MAAS,MAAO,GAC3B,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,GAAM,OAAW,GAAM,MAAS,MAAO,GAC3C,GAAI,IAAO,MA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AAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,MAAU,IAAO,KAAQ,MAAO,GAC3C,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GAGzC,GAAI,GAAM,KAAU,GAAM,IAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,IAAO,KAAQ,MAAO,GAC1B,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,MAAU,GAAM,KAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAAI,GAAM,OAAU,GAAM,MAAQ,MAAO,GACzC,GAAI,IAAO,MAAQ,MAAO,GAC1B,GAA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,QACjB,QAAsB,QACtB,QAAqB,QACrB,QAAe,QACf,QAAmB,QACnB,QAAiB,QACjB,QAAc,QACd,QAAe,QACf,QAAgB,QAChB,QAAsB,QACtB,QAAe,QACf,QAAiB,QACjB,QAAyB,QACzB,QAAe,QACf,QAAsB,QACtB,QAAiB,QACjB,QAAqB,QACrB,QAAwB,QACxB,QAAiB,QACjB,QAAoB,QACpB,QAAiB,QACjB,QAAqB,QACrB,QAA8B,QAC9B,QAAgB,QAChB,QAAgB,QAChB,QAAoB,QACpB,QAAoB,QACpB,QAA2B,QAC3B,QAAkB,QAClB,QAAmB,QACnB,QAAsB,QACtB,QAAgB,QAChB,QAAc,QACd,QAAc,QACd,QAAoB,MACtB,EAEc,IAAW,OAMnB,SAAS,EAAe,CAAC,EAAyB,CA0BxD,OAzBuB,IAAI,IAAI,CAC9B,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,MACD,CAAC,EAEqB,IAAI,CAAM,EAM1B,SAAS,EAAkB,CAAC,EAA+B,CAiCjE,OAhCmB,IAAI,IAAI,CAC1B,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,OACA,MACD,CAAC,EAEiB,IAAI,CAAM,EAAI,MAAQ",
90
+ "debugId": "F272CAB70E2CC43364756E2164756E21",
91
+ "names": []
92
+ }