@nice2dev/ui-graphics 1.3.14 → 1.3.16

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 (294) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/animation/AnimatedPerson.js +470 -143
  3. package/dist/cjs/animation/AnimationEditor.js +289 -101
  4. package/dist/cjs/animation/Audience.js +83 -61
  5. package/dist/cjs/animation/BodyRenderer.js +69 -28
  6. package/dist/cjs/animation/animationHelper.js +281 -288
  7. package/dist/cjs/animation/characterTypes.js +200 -203
  8. package/dist/cjs/animation/choreoDSL.js +205 -219
  9. package/dist/cjs/animation/choreography.js +4 -32
  10. package/dist/cjs/animation/karaokeIntegration.js +68 -77
  11. package/dist/cjs/animation/lottieExport.js +108 -114
  12. package/dist/cjs/animation/motionPath.js +225 -248
  13. package/dist/cjs/animation/physics.js +227 -254
  14. package/dist/cjs/animation/rig/RigPlayer.js +53 -56
  15. package/dist/cjs/animation/rig/RiggedBody.js +71 -26
  16. package/dist/cjs/animation/rig/choreoRigBridge.js +72 -77
  17. package/dist/cjs/animation/rig/ik.js +13 -18
  18. package/dist/cjs/animation/rig/poseOps.js +34 -41
  19. package/dist/cjs/animation/rig/presets.js +64 -72
  20. package/dist/cjs/animation/rig/rigMath.js +25 -32
  21. package/dist/cjs/animation/rig/rigTypes.js +59 -63
  22. package/dist/cjs/animation/shapes/arms.js +31 -13
  23. package/dist/cjs/animation/shapes/eyes.js +129 -47
  24. package/dist/cjs/animation/shapes/hair.js +72 -45
  25. package/dist/cjs/animation/shapes/heads.js +131 -57
  26. package/dist/cjs/animation/shapes/headwear.js +47 -38
  27. package/dist/cjs/animation/shapes/legs.js +31 -13
  28. package/dist/cjs/animation/shapes/mouths.js +120 -44
  29. package/dist/cjs/animation/shapes/noses.js +80 -25
  30. package/dist/cjs/animation/shapes/outfits.js +101 -39
  31. package/dist/cjs/animation/shapes/torsos.js +15 -11
  32. package/dist/cjs/animation/spineExport.js +103 -121
  33. package/dist/cjs/core/LocalUI.js +108 -43
  34. package/dist/cjs/core/NiceBrushEngine.js +758 -552
  35. package/dist/cjs/core/collaboration.js +249 -251
  36. package/dist/cjs/core/colorBlindness.js +100 -115
  37. package/dist/cjs/core/dragDrop.js +155 -158
  38. package/dist/cjs/core/editorAsk.js +51 -41
  39. package/dist/cjs/core/fixes.js +140 -171
  40. package/dist/cjs/core/gridGuides.js +166 -201
  41. package/dist/cjs/core/historyVisual.js +156 -135
  42. package/dist/cjs/core/i18n.js +13 -14
  43. package/dist/cjs/core/integrations.js +238 -249
  44. package/dist/cjs/core/minimap.js +149 -151
  45. package/dist/cjs/core/plugins.js +98 -113
  46. package/dist/cjs/core/rtl.js +71 -83
  47. package/dist/cjs/core/shortcuts.js +196 -225
  48. package/dist/cjs/core/theme.js +142 -149
  49. package/dist/cjs/core/yjsCollaboration.js +232 -293
  50. package/dist/cjs/design/design-tools.js +12 -22
  51. package/dist/cjs/font/NiceFontEditor.js +877 -316
  52. package/dist/cjs/font/fontFormatUtils.js +388 -448
  53. package/dist/cjs/game/GameAsset2dEditor.js +1201 -392
  54. package/dist/cjs/game/GameAsset2dEditor.module.css.js +146 -5
  55. package/dist/cjs/game/gameAssetTypes.js +7 -16
  56. package/dist/cjs/game/gameAssetUtils.js +390 -413
  57. package/dist/cjs/game/useGameAssetEditor.js +820 -763
  58. package/dist/cjs/index.js +81 -84
  59. package/dist/cjs/nice2dev-ui-graphics.css +1 -1
  60. package/dist/cjs/node_modules/lib0/array.js +8 -70
  61. package/dist/cjs/node_modules/lib0/binary.js +3 -20
  62. package/dist/cjs/node_modules/lib0/broadcastchannel.js +24 -86
  63. package/dist/cjs/node_modules/lib0/buffer.js +15 -82
  64. package/dist/cjs/node_modules/lib0/conditions.js +3 -16
  65. package/dist/cjs/node_modules/lib0/decoding.js +108 -287
  66. package/dist/cjs/node_modules/lib0/dom.js +14 -44
  67. package/dist/cjs/node_modules/lib0/encoding.js +68 -418
  68. package/dist/cjs/node_modules/lib0/environment.js +26 -92
  69. package/dist/cjs/node_modules/lib0/error.js +5 -29
  70. package/dist/cjs/node_modules/lib0/function.js +27 -66
  71. package/dist/cjs/node_modules/lib0/iterator.js +8 -33
  72. package/dist/cjs/node_modules/lib0/logging.common.js +12 -22
  73. package/dist/cjs/node_modules/lib0/logging.js +32 -71
  74. package/dist/cjs/node_modules/lib0/map.js +16 -86
  75. package/dist/cjs/node_modules/lib0/math.js +3 -32
  76. package/dist/cjs/node_modules/lib0/number.js +4 -15
  77. package/dist/cjs/node_modules/lib0/object.js +14 -88
  78. package/dist/cjs/node_modules/lib0/observable.js +38 -78
  79. package/dist/cjs/node_modules/lib0/pair.js +3 -20
  80. package/dist/cjs/node_modules/lib0/prng.js +8 -77
  81. package/dist/cjs/node_modules/lib0/promise.js +6 -30
  82. package/dist/cjs/node_modules/lib0/random.js +8 -23
  83. package/dist/cjs/node_modules/lib0/schema.js +313 -687
  84. package/dist/cjs/node_modules/lib0/set.js +3 -10
  85. package/dist/cjs/node_modules/lib0/storage.js +20 -55
  86. package/dist/cjs/node_modules/lib0/string.js +17 -72
  87. package/dist/cjs/node_modules/lib0/symbol.js +2 -12
  88. package/dist/cjs/node_modules/lib0/time.js +2 -15
  89. package/dist/cjs/node_modules/lib0/trait/equality.js +3 -28
  90. package/dist/cjs/node_modules/lib0/url.js +4 -18
  91. package/dist/cjs/node_modules/lib0/webcrypto.js +2 -5
  92. package/dist/cjs/node_modules/y-protocols/auth.js +5 -19
  93. package/dist/cjs/node_modules/y-protocols/awareness.js +53 -116
  94. package/dist/cjs/node_modules/y-protocols/sync.js +16 -103
  95. package/dist/cjs/node_modules/y-websocket/src/y-websocket.js +77 -219
  96. package/dist/cjs/node_modules/yjs/dist/yjs.js +2128 -4868
  97. package/dist/cjs/photo/FilterThumb.js +37 -25
  98. package/dist/cjs/photo/NiceAITools.js +679 -467
  99. package/dist/cjs/photo/PhotoEditor.js +34 -20
  100. package/dist/cjs/photo/PhotoEditor.module.css.js +296 -5
  101. package/dist/cjs/photo/PhotoEditorCanvas.js +250 -91
  102. package/dist/cjs/photo/PhotoEditorLeftPanel.js +1086 -224
  103. package/dist/cjs/photo/PhotoEditorToolbar.js +135 -19
  104. package/dist/cjs/photo/photoEditorActions.js +89 -72
  105. package/dist/cjs/photo/photoEditorTypes.js +29 -32
  106. package/dist/cjs/photo/photoFilters.js +959 -985
  107. package/dist/cjs/photo/photoOverlays.js +899 -945
  108. package/dist/cjs/photo/photoSelection.js +427 -499
  109. package/dist/cjs/photo/usePhotoEditor.js +739 -741
  110. package/dist/cjs/pixel/HSVPicker.js +191 -175
  111. package/dist/cjs/pixel/PixelEditor.js +159 -48
  112. package/dist/cjs/pixel/PixelEditor.module.css.js +209 -5
  113. package/dist/cjs/pixel/PixelEditorCanvas.js +29 -16
  114. package/dist/cjs/pixel/PixelEditorMenuBar.js +160 -162
  115. package/dist/cjs/pixel/PixelEditorRightPanel.js +377 -45
  116. package/dist/cjs/pixel/PixelEditorStatusBar.js +47 -20
  117. package/dist/cjs/pixel/PixelEditorTimeline.js +106 -23
  118. package/dist/cjs/pixel/PixelEditorToolbar.js +99 -21
  119. package/dist/cjs/pixel/SpriteGeneratorPanel.js +483 -303
  120. package/dist/cjs/pixel/animalGeneratorPresets.js +776 -601
  121. package/dist/cjs/pixel/asepriteFormat.js +511 -560
  122. package/dist/cjs/pixel/buildingGeneratorPresets.js +693 -520
  123. package/dist/cjs/pixel/characterGeneratorPresets.js +644 -544
  124. package/dist/cjs/pixel/pixel-pro.js +52 -63
  125. package/dist/cjs/pixel/pixelEditorExports.js +388 -428
  126. package/dist/cjs/pixel/pixelEditorTypes.js +91 -108
  127. package/dist/cjs/pixel/pixelEditorUtils.js +519 -561
  128. package/dist/cjs/pixel/spriteGeneratorCore.js +206 -257
  129. package/dist/cjs/pixel/usePixelEditor.js +1321 -1343
  130. package/dist/cjs/texture/Nice3DTexturePainter.js +707 -440
  131. package/dist/cjs/ui/NiceUIDesigner.js +954 -527
  132. package/dist/cjs/vector/NiceSvgToCode.js +586 -446
  133. package/dist/cjs/vector/VectorEditor.js +290 -117
  134. package/dist/cjs/vector/VectorEditor.module.css.js +86 -5
  135. package/dist/cjs/vector/VectorEditorMenuBar.js +333 -275
  136. package/dist/cjs/vector/VectorEditorRightPanel.js +1094 -371
  137. package/dist/cjs/vector/VectorEditorShapeRenderer.js +198 -60
  138. package/dist/cjs/vector/VectorEditorStatusBar.js +39 -13
  139. package/dist/cjs/vector/useVectorEditor.js +848 -889
  140. package/dist/cjs/vector/vectorAnimation.js +110 -137
  141. package/dist/cjs/vector/vectorBooleanOps.js +398 -485
  142. package/dist/cjs/vector/vectorEditorExport.js +201 -203
  143. package/dist/cjs/vector/vectorEditorImport.js +173 -189
  144. package/dist/cjs/vector/vectorEditorTypes.js +42 -49
  145. package/dist/cjs/vector/vectorGradients.js +151 -174
  146. package/dist/cjs/vector/vectorIconExport.js +52 -59
  147. package/dist/cjs/vector/vectorIconImport.js +169 -219
  148. package/dist/esm/animation/AnimatedPerson.js +470 -141
  149. package/dist/esm/animation/AnimationEditor.js +290 -100
  150. package/dist/esm/animation/Audience.js +83 -59
  151. package/dist/esm/animation/BodyRenderer.js +71 -25
  152. package/dist/esm/animation/animationHelper.js +284 -287
  153. package/dist/esm/animation/characterTypes.js +204 -202
  154. package/dist/esm/animation/choreoDSL.js +212 -218
  155. package/dist/esm/animation/choreography.js +8 -31
  156. package/dist/esm/animation/karaokeIntegration.js +74 -76
  157. package/dist/esm/animation/lottieExport.js +112 -113
  158. package/dist/esm/animation/motionPath.js +235 -247
  159. package/dist/esm/animation/physics.js +235 -253
  160. package/dist/esm/animation/rig/RigPlayer.js +53 -54
  161. package/dist/esm/animation/rig/RiggedBody.js +71 -24
  162. package/dist/esm/animation/rig/choreoRigBridge.js +74 -76
  163. package/dist/esm/animation/rig/ik.js +14 -17
  164. package/dist/esm/animation/rig/poseOps.js +37 -40
  165. package/dist/esm/animation/rig/presets.js +70 -71
  166. package/dist/esm/animation/rig/rigMath.js +28 -31
  167. package/dist/esm/animation/rig/rigTypes.js +62 -62
  168. package/dist/esm/animation/shapes/arms.js +32 -12
  169. package/dist/esm/animation/shapes/eyes.js +135 -46
  170. package/dist/esm/animation/shapes/hair.js +80 -44
  171. package/dist/esm/animation/shapes/heads.js +140 -56
  172. package/dist/esm/animation/shapes/headwear.js +54 -37
  173. package/dist/esm/animation/shapes/legs.js +32 -12
  174. package/dist/esm/animation/shapes/mouths.js +127 -43
  175. package/dist/esm/animation/shapes/noses.js +87 -24
  176. package/dist/esm/animation/shapes/outfits.js +106 -38
  177. package/dist/esm/animation/shapes/torsos.js +16 -10
  178. package/dist/esm/animation/spineExport.js +106 -120
  179. package/dist/esm/core/LocalUI.js +111 -42
  180. package/dist/esm/core/NiceBrushEngine.js +761 -551
  181. package/dist/esm/core/collaboration.js +255 -250
  182. package/dist/esm/core/colorBlindness.js +106 -114
  183. package/dist/esm/core/dragDrop.js +157 -157
  184. package/dist/esm/core/editorAsk.js +53 -40
  185. package/dist/esm/core/fixes.js +145 -170
  186. package/dist/esm/core/gridGuides.js +178 -200
  187. package/dist/esm/core/historyVisual.js +158 -134
  188. package/dist/esm/core/i18n.js +15 -13
  189. package/dist/esm/core/integrations.js +244 -248
  190. package/dist/esm/core/minimap.js +151 -150
  191. package/dist/esm/core/plugins.js +102 -112
  192. package/dist/esm/core/rtl.js +77 -82
  193. package/dist/esm/core/shortcuts.js +200 -224
  194. package/dist/esm/core/theme.js +150 -148
  195. package/dist/esm/core/yjsCollaboration.js +240 -292
  196. package/dist/esm/design/design-tools.js +13 -21
  197. package/dist/esm/font/NiceFontEditor.js +880 -315
  198. package/dist/esm/font/fontFormatUtils.js +394 -447
  199. package/dist/esm/game/GameAsset2dEditor.js +1202 -391
  200. package/dist/esm/game/GameAsset2dEditor.module.css.js +146 -3
  201. package/dist/esm/game/gameAssetTypes.js +8 -15
  202. package/dist/esm/game/gameAssetUtils.js +408 -412
  203. package/dist/esm/game/useGameAssetEditor.js +821 -762
  204. package/dist/esm/index.js +332 -69
  205. package/dist/esm/nice2dev-ui-graphics.css +1 -1
  206. package/dist/esm/node_modules/lib0/array.js +15 -69
  207. package/dist/esm/node_modules/lib0/binary.js +14 -19
  208. package/dist/esm/node_modules/lib0/broadcastchannel.js +27 -85
  209. package/dist/esm/node_modules/lib0/buffer.js +20 -80
  210. package/dist/esm/node_modules/lib0/conditions.js +4 -15
  211. package/dist/esm/node_modules/lib0/decoding.js +128 -286
  212. package/dist/esm/node_modules/lib0/dom.js +20 -43
  213. package/dist/esm/node_modules/lib0/encoding.js +90 -415
  214. package/dist/esm/node_modules/lib0/environment.js +33 -91
  215. package/dist/esm/node_modules/lib0/error.js +8 -28
  216. package/dist/esm/node_modules/lib0/function.js +31 -65
  217. package/dist/esm/node_modules/lib0/iterator.js +11 -32
  218. package/dist/esm/node_modules/lib0/logging.common.js +22 -21
  219. package/dist/esm/node_modules/lib0/logging.js +44 -70
  220. package/dist/esm/node_modules/lib0/map.js +21 -85
  221. package/dist/esm/node_modules/lib0/math.js +9 -31
  222. package/dist/esm/node_modules/lib0/number.js +7 -14
  223. package/dist/esm/node_modules/lib0/object.js +26 -87
  224. package/dist/esm/node_modules/lib0/observable.js +40 -77
  225. package/dist/esm/node_modules/lib0/pair.js +5 -19
  226. package/dist/esm/node_modules/lib0/prng.js +15 -76
  227. package/dist/esm/node_modules/lib0/promise.js +7 -29
  228. package/dist/esm/node_modules/lib0/random.js +10 -22
  229. package/dist/esm/node_modules/lib0/schema.js +367 -686
  230. package/dist/esm/node_modules/lib0/set.js +4 -9
  231. package/dist/esm/node_modules/lib0/storage.js +23 -54
  232. package/dist/esm/node_modules/lib0/string.js +26 -71
  233. package/dist/esm/node_modules/lib0/symbol.js +3 -11
  234. package/dist/esm/node_modules/lib0/time.js +3 -14
  235. package/dist/esm/node_modules/lib0/trait/equality.js +5 -27
  236. package/dist/esm/node_modules/lib0/url.js +5 -17
  237. package/dist/esm/node_modules/lib0/webcrypto.js +3 -4
  238. package/dist/esm/node_modules/y-protocols/auth.js +7 -18
  239. package/dist/esm/node_modules/y-protocols/awareness.js +58 -115
  240. package/dist/esm/node_modules/y-protocols/sync.js +26 -102
  241. package/dist/esm/node_modules/y-websocket/src/y-websocket.js +82 -218
  242. package/dist/esm/node_modules/yjs/dist/yjs.js +2263 -4899
  243. package/dist/esm/photo/FilterThumb.js +37 -23
  244. package/dist/esm/photo/NiceAITools.js +685 -466
  245. package/dist/esm/photo/PhotoEditor.js +34 -18
  246. package/dist/esm/photo/PhotoEditor.module.css.js +296 -3
  247. package/dist/esm/photo/PhotoEditorCanvas.js +250 -89
  248. package/dist/esm/photo/PhotoEditorLeftPanel.js +1086 -222
  249. package/dist/esm/photo/PhotoEditorToolbar.js +135 -17
  250. package/dist/esm/photo/photoEditorActions.js +93 -71
  251. package/dist/esm/photo/photoEditorTypes.js +32 -31
  252. package/dist/esm/photo/photoFilters.js +967 -984
  253. package/dist/esm/photo/photoOverlays.js +913 -944
  254. package/dist/esm/photo/photoSelection.js +438 -498
  255. package/dist/esm/photo/usePhotoEditor.js +740 -740
  256. package/dist/esm/pixel/HSVPicker.js +192 -174
  257. package/dist/esm/pixel/PixelEditor.js +160 -47
  258. package/dist/esm/pixel/PixelEditor.module.css.js +209 -3
  259. package/dist/esm/pixel/PixelEditorCanvas.js +29 -14
  260. package/dist/esm/pixel/PixelEditorMenuBar.js +160 -160
  261. package/dist/esm/pixel/PixelEditorRightPanel.js +377 -43
  262. package/dist/esm/pixel/PixelEditorStatusBar.js +47 -18
  263. package/dist/esm/pixel/PixelEditorTimeline.js +106 -21
  264. package/dist/esm/pixel/PixelEditorToolbar.js +99 -19
  265. package/dist/esm/pixel/SpriteGeneratorPanel.js +483 -301
  266. package/dist/esm/pixel/animalGeneratorPresets.js +782 -600
  267. package/dist/esm/pixel/asepriteFormat.js +517 -559
  268. package/dist/esm/pixel/buildingGeneratorPresets.js +699 -519
  269. package/dist/esm/pixel/characterGeneratorPresets.js +650 -543
  270. package/dist/esm/pixel/pixel-pro.js +53 -62
  271. package/dist/esm/pixel/pixelEditorExports.js +397 -427
  272. package/dist/esm/pixel/pixelEditorTypes.js +103 -107
  273. package/dist/esm/pixel/pixelEditorUtils.js +551 -560
  274. package/dist/esm/pixel/spriteGeneratorCore.js +223 -256
  275. package/dist/esm/pixel/usePixelEditor.js +1322 -1342
  276. package/dist/esm/texture/Nice3DTexturePainter.js +709 -439
  277. package/dist/esm/ui/NiceUIDesigner.js +957 -526
  278. package/dist/esm/vector/NiceSvgToCode.js +589 -445
  279. package/dist/esm/vector/VectorEditor.js +291 -116
  280. package/dist/esm/vector/VectorEditor.module.css.js +86 -3
  281. package/dist/esm/vector/VectorEditorMenuBar.js +333 -273
  282. package/dist/esm/vector/VectorEditorRightPanel.js +1094 -369
  283. package/dist/esm/vector/VectorEditorShapeRenderer.js +199 -59
  284. package/dist/esm/vector/VectorEditorStatusBar.js +39 -11
  285. package/dist/esm/vector/useVectorEditor.js +849 -888
  286. package/dist/esm/vector/vectorAnimation.js +115 -136
  287. package/dist/esm/vector/vectorBooleanOps.js +401 -484
  288. package/dist/esm/vector/vectorEditorExport.js +207 -202
  289. package/dist/esm/vector/vectorEditorImport.js +174 -188
  290. package/dist/esm/vector/vectorEditorTypes.js +50 -48
  291. package/dist/esm/vector/vectorGradients.js +158 -173
  292. package/dist/esm/vector/vectorIconExport.js +53 -58
  293. package/dist/esm/vector/vectorIconImport.js +171 -218
  294. package/package.json +9 -15
@@ -1,477 +1,417 @@
1
- 'use strict';
2
-
3
- /**
4
- * fontFormatUtils — OTF/TTF binary generation and OpenType feature support
5
- *
6
- * Features:
7
- * - Generate TrueType-compatible binary font data (minimal .ttf)
8
- * - OpenType feature definitions (liga, kern, smcp, onum, salt, ss01-ss20)
9
- * - Kerning table generation from pairs
10
- * - WOFF/WOFF2 wrapper
11
- * - Font file download utility
12
- */
13
- /* ── OpenType Feature Presets ── */
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
14
3
  const OPENTYPE_FEATURE_PRESETS = {
15
- basic: [
16
- { tag: 'kern', enabled: true, kerning: [] },
17
- {
18
- tag: 'liga',
19
- enabled: true,
20
- ligatures: [
21
- { input: ['f', 'i'], replacement: '\uFB01' },
22
- { input: ['f', 'l'], replacement: '\uFB02' },
23
- { input: ['f', 'f'], replacement: '\uFB00' },
24
- ],
25
- },
26
- ],
27
- typographic: [
28
- { tag: 'kern', enabled: true, kerning: [] },
29
- { tag: 'liga', enabled: true, ligatures: [] },
30
- { tag: 'onum', enabled: true },
31
- { tag: 'smcp', enabled: true },
32
- { tag: 'frac', enabled: true },
33
- { tag: 'zero', enabled: true },
34
- ],
35
- 'stylistic-full': [
36
- { tag: 'kern', enabled: true, kerning: [] },
37
- { tag: 'liga', enabled: true, ligatures: [] },
38
- { tag: 'salt', enabled: true },
39
- { tag: 'calt', enabled: true },
40
- { tag: 'swsh', enabled: true },
41
- { tag: 'ss01', enabled: true },
42
- { tag: 'ss02', enabled: true },
43
- { tag: 'ss03', enabled: true },
44
- ],
4
+ basic: [
5
+ { tag: "kern", enabled: true, kerning: [] },
6
+ {
7
+ tag: "liga",
8
+ enabled: true,
9
+ ligatures: [
10
+ { input: ["f", "i"], replacement: "fi" },
11
+ { input: ["f", "l"], replacement: "fl" },
12
+ { input: ["f", "f"], replacement: "ff" }
13
+ ]
14
+ }
15
+ ],
16
+ typographic: [
17
+ { tag: "kern", enabled: true, kerning: [] },
18
+ { tag: "liga", enabled: true, ligatures: [] },
19
+ { tag: "onum", enabled: true },
20
+ { tag: "smcp", enabled: true },
21
+ { tag: "frac", enabled: true },
22
+ { tag: "zero", enabled: true }
23
+ ],
24
+ "stylistic-full": [
25
+ { tag: "kern", enabled: true, kerning: [] },
26
+ { tag: "liga", enabled: true, ligatures: [] },
27
+ { tag: "salt", enabled: true },
28
+ { tag: "calt", enabled: true },
29
+ { tag: "swsh", enabled: true },
30
+ { tag: "ss01", enabled: true },
31
+ { tag: "ss02", enabled: true },
32
+ { tag: "ss03", enabled: true }
33
+ ]
45
34
  };
46
- /* ── Common Kerning Pairs ── */
47
35
  const COMMON_KERNING_PAIRS = [
48
- { left: 'A', right: 'V', value: -80 },
49
- { left: 'A', right: 'W', value: -60 },
50
- { left: 'A', right: 'Y', value: -80 },
51
- { left: 'A', right: 'T', value: -60 },
52
- { left: 'T', right: 'a', value: -60 },
53
- { left: 'T', right: 'e', value: -60 },
54
- { left: 'T', right: 'o', value: -60 },
55
- { left: 'V', right: 'a', value: -60 },
56
- { left: 'V', right: 'e', value: -50 },
57
- { left: 'V', right: 'o', value: -50 },
58
- { left: 'W', right: 'a', value: -40 },
59
- { left: 'W', right: 'e', value: -30 },
60
- { left: 'Y', right: 'a', value: -70 },
61
- { left: 'Y', right: 'e', value: -60 },
62
- { left: 'Y', right: 'o', value: -60 },
63
- { left: 'L', right: 'T', value: -50 },
64
- { left: 'L', right: 'V', value: -40 },
65
- { left: 'L', right: 'W', value: -30 },
66
- { left: 'L', right: 'Y', value: -50 },
67
- { left: 'P', right: 'a', value: -30 },
68
- { left: 'P', right: '.', value: -80 },
69
- { left: 'P', right: ',', value: -80 },
70
- { left: 'r', right: '.', value: -40 },
71
- { left: 'r', right: ',', value: -40 },
72
- { left: 'f', right: '.', value: -30 },
73
- { left: 'f', right: ',', value: -30 },
36
+ { left: "A", right: "V", value: -80 },
37
+ { left: "A", right: "W", value: -60 },
38
+ { left: "A", right: "Y", value: -80 },
39
+ { left: "A", right: "T", value: -60 },
40
+ { left: "T", right: "a", value: -60 },
41
+ { left: "T", right: "e", value: -60 },
42
+ { left: "T", right: "o", value: -60 },
43
+ { left: "V", right: "a", value: -60 },
44
+ { left: "V", right: "e", value: -50 },
45
+ { left: "V", right: "o", value: -50 },
46
+ { left: "W", right: "a", value: -40 },
47
+ { left: "W", right: "e", value: -30 },
48
+ { left: "Y", right: "a", value: -70 },
49
+ { left: "Y", right: "e", value: -60 },
50
+ { left: "Y", right: "o", value: -60 },
51
+ { left: "L", right: "T", value: -50 },
52
+ { left: "L", right: "V", value: -40 },
53
+ { left: "L", right: "W", value: -30 },
54
+ { left: "L", right: "Y", value: -50 },
55
+ { left: "P", right: "a", value: -30 },
56
+ { left: "P", right: ".", value: -80 },
57
+ { left: "P", right: ",", value: -80 },
58
+ { left: "r", right: ".", value: -40 },
59
+ { left: "r", right: ",", value: -40 },
60
+ { left: "f", right: ".", value: -30 },
61
+ { left: "f", right: ",", value: -30 }
74
62
  ];
75
- /* ── TrueType Binary Writer ── */
76
63
  class BinaryWriter {
77
- constructor() {
78
- this.chunks = [];
79
- this.size = 0;
80
- }
81
- writeUint8(v) {
82
- this.chunks.push(new Uint8Array([v & 0xff]));
83
- this.size += 1;
84
- }
85
- writeUint16(v) {
86
- const buf = new Uint8Array(2);
87
- buf[0] = (v >> 8) & 0xff;
88
- buf[1] = v & 0xff;
89
- this.chunks.push(buf);
90
- this.size += 2;
91
- }
92
- writeInt16(v) {
93
- this.writeUint16(v < 0 ? v + 0x10000 : v);
94
- }
95
- writeUint32(v) {
96
- const buf = new Uint8Array(4);
97
- buf[0] = (v >> 24) & 0xff;
98
- buf[1] = (v >> 16) & 0xff;
99
- buf[2] = (v >> 8) & 0xff;
100
- buf[3] = v & 0xff;
101
- this.chunks.push(buf);
102
- this.size += 4;
103
- }
104
- writeInt32(v) {
105
- this.writeUint32(v < 0 ? v + 0x100000000 : v);
106
- }
107
- writeFixed(v) {
108
- this.writeInt32(Math.round(v * 0x10000));
109
- }
110
- writeString(s, len) {
111
- const l = len !== null && len !== void 0 ? len : s.length;
112
- const buf = new Uint8Array(l);
113
- for (let i = 0; i < l; i++) {
114
- buf[i] = i < s.length ? s.charCodeAt(i) : 0;
115
- }
116
- this.chunks.push(buf);
117
- this.size += l;
118
- }
119
- writeBytes(data) {
120
- this.chunks.push(data);
121
- this.size += data.length;
122
- }
123
- padTo4() {
124
- const pad = (4 - (this.size % 4)) % 4;
125
- if (pad > 0) {
126
- this.writeBytes(new Uint8Array(pad));
127
- }
64
+ constructor() {
65
+ this.chunks = [];
66
+ this.size = 0;
67
+ }
68
+ writeUint8(v) {
69
+ this.chunks.push(new Uint8Array([v & 255]));
70
+ this.size += 1;
71
+ }
72
+ writeUint16(v) {
73
+ const buf = new Uint8Array(2);
74
+ buf[0] = v >> 8 & 255;
75
+ buf[1] = v & 255;
76
+ this.chunks.push(buf);
77
+ this.size += 2;
78
+ }
79
+ writeInt16(v) {
80
+ this.writeUint16(v < 0 ? v + 65536 : v);
81
+ }
82
+ writeUint32(v) {
83
+ const buf = new Uint8Array(4);
84
+ buf[0] = v >> 24 & 255;
85
+ buf[1] = v >> 16 & 255;
86
+ buf[2] = v >> 8 & 255;
87
+ buf[3] = v & 255;
88
+ this.chunks.push(buf);
89
+ this.size += 4;
90
+ }
91
+ writeInt32(v) {
92
+ this.writeUint32(v < 0 ? v + 4294967296 : v);
93
+ }
94
+ writeFixed(v) {
95
+ this.writeInt32(Math.round(v * 65536));
96
+ }
97
+ writeString(s, len) {
98
+ const l = len ?? s.length;
99
+ const buf = new Uint8Array(l);
100
+ for (let i = 0; i < l; i++) {
101
+ buf[i] = i < s.length ? s.charCodeAt(i) : 0;
128
102
  }
129
- getSize() {
130
- return this.size;
103
+ this.chunks.push(buf);
104
+ this.size += l;
105
+ }
106
+ writeBytes(data) {
107
+ this.chunks.push(data);
108
+ this.size += data.length;
109
+ }
110
+ padTo4() {
111
+ const pad = (4 - this.size % 4) % 4;
112
+ if (pad > 0) {
113
+ this.writeBytes(new Uint8Array(pad));
131
114
  }
132
- toArrayBuffer() {
133
- const result = new Uint8Array(this.size);
134
- let offset = 0;
135
- for (const chunk of this.chunks) {
136
- result.set(chunk, offset);
137
- offset += chunk.length;
138
- }
139
- return result.buffer;
115
+ }
116
+ getSize() {
117
+ return this.size;
118
+ }
119
+ toArrayBuffer() {
120
+ const result = new Uint8Array(this.size);
121
+ let offset = 0;
122
+ for (const chunk of this.chunks) {
123
+ result.set(chunk, offset);
124
+ offset += chunk.length;
140
125
  }
126
+ return result.buffer;
127
+ }
141
128
  }
142
129
  function tag(s) {
143
- return ((s.charCodeAt(0) << 24) | (s.charCodeAt(1) << 16) | (s.charCodeAt(2) << 8) | s.charCodeAt(3));
130
+ return s.charCodeAt(0) << 24 | s.charCodeAt(1) << 16 | s.charCodeAt(2) << 8 | s.charCodeAt(3);
144
131
  }
145
- /**
146
- * Build minimal TrueType font binary.
147
- * Encodes glyphs as simple contour paths from SVG path data.
148
- */
149
132
  function buildTTF(fontData, _config) {
150
- const { metrics, glyphs, name } = fontData;
151
- const w = new BinaryWriter();
152
- // Simple glyph conversion: parse SVG path → contour points
153
- // For a production font, this would use a proper path parser.
154
- // Offset Table
155
- const numTables = 9; // head, hhea, maxp, OS/2, name, cmap, glyf, loca, post
156
- w.writeUint32(0x00010000); // sfVersion (TrueType)
157
- w.writeUint16(numTables);
158
- // searchRange, entrySelector, rangeShift
159
- const sr = Math.pow(2, Math.floor(Math.log2(numTables))) * 16;
160
- w.writeUint16(sr);
161
- w.writeUint16(Math.floor(Math.log2(numTables)));
162
- w.writeUint16(numTables * 16 - sr);
163
- // Table directory placeholder — we'll calculate real offsets after building tables
164
- w.getSize();
165
- const tableNames = ['cmap', 'glyf', 'head', 'hhea', 'loca', 'maxp', 'name', 'OS/2', 'post'];
166
- // Write placeholder entries (tag, checksum, offset, length)
167
- for (let i = 0; i < numTables; i++) {
168
- w.writeUint32(tag(tableNames[i]));
169
- w.writeUint32(0); // checksum placeholder
170
- w.writeUint32(0); // offset placeholder
171
- w.writeUint32(0); // length placeholder
172
- }
173
- // For simplicity, write each table sequentially and record offsets
174
- const tableData = new Map();
175
- // head table
176
- const headStart = w.getSize();
177
- w.writeFixed(1.0); // majorVersion.minorVersion
178
- w.writeFixed(1.0); // fontRevision
179
- w.writeUint32(0); // checksumAdjustment
180
- w.writeUint32(0x5f0f3cf5); // magicNumber
181
- w.writeUint16(0x000b); // flags
182
- w.writeUint16(metrics.unitsPerEm);
183
- // created / modified (int64 — 8 bytes each)
184
- w.writeUint32(0);
185
- w.writeUint32(0);
186
- w.writeUint32(0);
187
- w.writeUint32(0);
188
- // xMin, yMin, xMax, yMax
189
- w.writeInt16(0);
190
- w.writeInt16(metrics.descent);
191
- w.writeInt16(metrics.unitsPerEm);
192
- w.writeInt16(metrics.ascent);
193
- w.writeUint16(0); // macStyle
194
- w.writeUint16(8); // lowestRecPPEM
195
- w.writeInt16(2); // fontDirectionHint
196
- w.writeInt16(1); // indexToLocFormat (long)
197
- w.writeInt16(0); // glyphDataFormat
198
- w.padTo4();
199
- tableData.set('head', { offset: headStart, length: w.getSize() - headStart });
200
- // hhea table
201
- const hheaStart = w.getSize();
202
- w.writeFixed(1.0);
203
- w.writeInt16(metrics.ascent);
204
- w.writeInt16(metrics.descent);
205
- w.writeInt16(metrics.lineGap);
206
- w.writeUint16(metrics.unitsPerEm); // advanceWidthMax
207
- w.writeInt16(0); // minLeftSideBearing
208
- w.writeInt16(0); // minRightSideBearing
209
- w.writeInt16(metrics.unitsPerEm); // xMaxExtent
210
- w.writeInt16(1); // caretSlopeRise
211
- w.writeInt16(0); // caretSlopeRun
212
- w.writeInt16(0); // caretOffset
213
- w.writeInt16(0);
214
- w.writeInt16(0);
215
- w.writeInt16(0);
216
- w.writeInt16(0); // reserved
217
- w.writeInt16(0); // metricDataFormat
218
- w.writeUint16(glyphs.length + 1); // numberOfHMetrics
219
- w.padTo4();
220
- tableData.set('hhea', { offset: hheaStart, length: w.getSize() - hheaStart });
221
- // maxp table
222
- const maxpStart = w.getSize();
223
- w.writeFixed(1.0);
224
- w.writeUint16(glyphs.length + 1); // numGlyphs (.notdef + glyphs)
225
- w.writeUint16(0); // maxPoints
226
- w.writeUint16(0); // maxContours
227
- w.writeUint16(0); // maxCompositePoints
228
- w.writeUint16(0); // maxCompositeContours
229
- w.writeUint16(1); // maxZones
230
- w.writeUint16(0); // maxTwilightPoints
231
- w.writeUint16(0); // maxStorage
232
- w.writeUint16(0); // maxFunctionDefs
233
- w.writeUint16(0); // maxInstructionDefs
234
- w.writeUint16(0); // maxStackElements
235
- w.writeUint16(0); // maxSizeOfInstructions
236
- w.writeUint16(0); // maxComponentElements
237
- w.writeUint16(0); // maxComponentDepth
238
- w.padTo4();
239
- tableData.set('maxp', { offset: maxpStart, length: w.getSize() - maxpStart });
240
- // OS/2 table (minimal)
241
- const os2Start = w.getSize();
242
- w.writeUint16(4); // version
243
- w.writeInt16(500); // xAvgCharWidth
244
- w.writeUint16(400); // usWeightClass (Regular)
245
- w.writeUint16(5); // usWidthClass (Medium)
246
- w.writeUint16(0); // fsType
247
- w.writeInt16(Math.round(metrics.unitsPerEm * 0.6)); // subscript sizes + offsets (10 int16)
248
- w.writeInt16(Math.round(metrics.unitsPerEm * 0.6));
249
- w.writeInt16(0);
250
- w.writeInt16(Math.round(metrics.unitsPerEm * 0.1));
251
- w.writeInt16(Math.round(metrics.unitsPerEm * 0.6));
252
- w.writeInt16(Math.round(metrics.unitsPerEm * 0.6));
253
- w.writeInt16(0);
254
- w.writeInt16(Math.round(metrics.unitsPerEm * 0.4));
255
- w.writeInt16(0); // yStrikeoutSize
256
- w.writeInt16(Math.round(metrics.xHeight * 0.6)); // yStrikeoutPosition
257
- w.writeInt16(0); // sFamilyClass
258
- // PANOSE (10 bytes)
259
- for (let i = 0; i < 10; i++) {
260
- w.writeUint8(0);
261
- }
262
- // Unicode ranges (16 bytes)
263
- w.writeUint32(0x00000001); // Basic Latin
133
+ const { metrics, glyphs, name } = fontData;
134
+ const w = new BinaryWriter();
135
+ const numTables = 9;
136
+ w.writeUint32(65536);
137
+ w.writeUint16(numTables);
138
+ const sr = Math.pow(2, Math.floor(Math.log2(numTables))) * 16;
139
+ w.writeUint16(sr);
140
+ w.writeUint16(Math.floor(Math.log2(numTables)));
141
+ w.writeUint16(numTables * 16 - sr);
142
+ w.getSize();
143
+ const tableNames = ["cmap", "glyf", "head", "hhea", "loca", "maxp", "name", "OS/2", "post"];
144
+ for (let i = 0; i < numTables; i++) {
145
+ w.writeUint32(tag(tableNames[i]));
264
146
  w.writeUint32(0);
265
147
  w.writeUint32(0);
266
148
  w.writeUint32(0);
267
- w.writeString(' ', 4); // achVendID
268
- w.writeUint16(0x0040); // fsSelection (Regular)
269
- w.writeUint16(0x0020); // usFirstCharIndex (space)
270
- w.writeUint16(0x007e); // usLastCharIndex (~)
271
- w.writeInt16(metrics.ascent); // sTypoAscender
272
- w.writeInt16(metrics.descent); // sTypoDescender
273
- w.writeInt16(metrics.lineGap); // sTypoLineGap
274
- w.writeUint16(metrics.ascent); // usWinAscent
275
- w.writeUint16(Math.abs(metrics.descent)); // usWinDescent
276
- w.writeUint32(0x00000001); // ulCodePageRange1
277
- w.writeUint32(0); // ulCodePageRange2
278
- w.writeInt16(metrics.xHeight); // sxHeight
279
- w.writeInt16(metrics.capHeight); // sCapHeight
280
- w.writeUint16(0); // usDefaultChar
281
- w.writeUint16(0x0020); // usBreakChar
282
- w.writeUint16(1); // usMaxContext
283
- w.padTo4();
284
- tableData.set('OS/2', { offset: os2Start, length: w.getSize() - os2Start });
285
- // name table
286
- const nameStart = w.getSize();
287
- const nameStrings = [
288
- { nameID: 0, str: `Copyright 2024 ${name}` },
289
- { nameID: 1, str: fontData.family },
290
- { nameID: 2, str: 'Regular' },
291
- { nameID: 3, str: `${name}-Regular` },
292
- { nameID: 4, str: `${name} Regular` },
293
- { nameID: 5, str: 'Version 1.0' },
294
- { nameID: 6, str: `${name}-Regular` },
295
- ];
296
- w.writeUint16(0); // format
297
- w.writeUint16(nameStrings.length); // count
298
- const nameStorageOffset = 6 + nameStrings.length * 12;
299
- w.writeUint16(nameStorageOffset); // stringOffset
300
- let strOffset = 0;
301
- for (const ns of nameStrings) {
302
- w.writeUint16(1); // platformID (Macintosh)
303
- w.writeUint16(0); // encodingID
304
- w.writeUint16(0); // languageID
305
- w.writeUint16(ns.nameID);
306
- w.writeUint16(ns.str.length); // length
307
- w.writeUint16(strOffset); // offset
308
- strOffset += ns.str.length;
309
- }
310
- for (const ns of nameStrings) {
311
- w.writeString(ns.str);
312
- }
313
- w.padTo4();
314
- tableData.set('name', { offset: nameStart, length: w.getSize() - nameStart });
315
- // cmap table (format 4)
316
- const cmapStart = w.getSize();
317
- w.writeUint16(0); // version
318
- w.writeUint16(1); // numTables
319
- w.writeUint16(3); // platformID (Windows)
320
- w.writeUint16(1); // encodingID (BMP)
321
- w.writeUint32(12); // offset to subtable
322
- // Format 4 subtable
323
- const sortedGlyphs = [...glyphs].sort((a, b) => a.unicode - b.unicode);
324
- const segCount = sortedGlyphs.length + 1; // + end segment
325
- const fmt4Size = 14 + segCount * 8;
326
- w.writeUint16(4); // format
327
- w.writeUint16(fmt4Size); // length
328
- w.writeUint16(0); // language
329
- w.writeUint16(segCount * 2); // segCountX2
330
- const searchRange2 = Math.pow(2, Math.floor(Math.log2(segCount))) * 2;
331
- w.writeUint16(searchRange2);
332
- w.writeUint16(Math.floor(Math.log2(segCount)));
333
- w.writeUint16(segCount * 2 - searchRange2);
334
- // endCode
335
- for (const g of sortedGlyphs) {
336
- w.writeUint16(g.unicode);
337
- }
338
- w.writeUint16(0xffff);
339
- w.writeUint16(0); // reservedPad
340
- // startCode
341
- for (const g of sortedGlyphs) {
342
- w.writeUint16(g.unicode);
343
- }
344
- w.writeUint16(0xffff);
345
- // idDelta (glyph index = unicode + delta)
346
- for (let i = 0; i < sortedGlyphs.length; i++) {
347
- const delta = i + 1 - sortedGlyphs[i].unicode;
348
- w.writeInt16(delta);
349
- }
350
- w.writeInt16(1);
351
- // idRangeOffset (all zero — use delta)
352
- for (let i = 0; i <= sortedGlyphs.length; i++) {
353
- w.writeUint16(0);
354
- }
355
- w.padTo4();
356
- tableData.set('cmap', { offset: cmapStart, length: w.getSize() - cmapStart });
357
- // glyf table (empty glyphs — just placeholder records)
358
- const glyfStart = w.getSize();
359
- const glyphOffsets = [0]; // .notdef at offset 0
360
- // .notdef: empty glyph
361
- w.writeInt16(0); // numberOfContours
149
+ }
150
+ const tableData = /* @__PURE__ */ new Map();
151
+ const headStart = w.getSize();
152
+ w.writeFixed(1);
153
+ w.writeFixed(1);
154
+ w.writeUint32(0);
155
+ w.writeUint32(1594834165);
156
+ w.writeUint16(11);
157
+ w.writeUint16(metrics.unitsPerEm);
158
+ w.writeUint32(0);
159
+ w.writeUint32(0);
160
+ w.writeUint32(0);
161
+ w.writeUint32(0);
162
+ w.writeInt16(0);
163
+ w.writeInt16(metrics.descent);
164
+ w.writeInt16(metrics.unitsPerEm);
165
+ w.writeInt16(metrics.ascent);
166
+ w.writeUint16(0);
167
+ w.writeUint16(8);
168
+ w.writeInt16(2);
169
+ w.writeInt16(1);
170
+ w.writeInt16(0);
171
+ w.padTo4();
172
+ tableData.set("head", { offset: headStart, length: w.getSize() - headStart });
173
+ const hheaStart = w.getSize();
174
+ w.writeFixed(1);
175
+ w.writeInt16(metrics.ascent);
176
+ w.writeInt16(metrics.descent);
177
+ w.writeInt16(metrics.lineGap);
178
+ w.writeUint16(metrics.unitsPerEm);
179
+ w.writeInt16(0);
180
+ w.writeInt16(0);
181
+ w.writeInt16(metrics.unitsPerEm);
182
+ w.writeInt16(1);
183
+ w.writeInt16(0);
184
+ w.writeInt16(0);
185
+ w.writeInt16(0);
186
+ w.writeInt16(0);
187
+ w.writeInt16(0);
188
+ w.writeInt16(0);
189
+ w.writeInt16(0);
190
+ w.writeUint16(glyphs.length + 1);
191
+ w.padTo4();
192
+ tableData.set("hhea", { offset: hheaStart, length: w.getSize() - hheaStart });
193
+ const maxpStart = w.getSize();
194
+ w.writeFixed(1);
195
+ w.writeUint16(glyphs.length + 1);
196
+ w.writeUint16(0);
197
+ w.writeUint16(0);
198
+ w.writeUint16(0);
199
+ w.writeUint16(0);
200
+ w.writeUint16(1);
201
+ w.writeUint16(0);
202
+ w.writeUint16(0);
203
+ w.writeUint16(0);
204
+ w.writeUint16(0);
205
+ w.writeUint16(0);
206
+ w.writeUint16(0);
207
+ w.writeUint16(0);
208
+ w.writeUint16(0);
209
+ w.padTo4();
210
+ tableData.set("maxp", { offset: maxpStart, length: w.getSize() - maxpStart });
211
+ const os2Start = w.getSize();
212
+ w.writeUint16(4);
213
+ w.writeInt16(500);
214
+ w.writeUint16(400);
215
+ w.writeUint16(5);
216
+ w.writeUint16(0);
217
+ w.writeInt16(Math.round(metrics.unitsPerEm * 0.6));
218
+ w.writeInt16(Math.round(metrics.unitsPerEm * 0.6));
219
+ w.writeInt16(0);
220
+ w.writeInt16(Math.round(metrics.unitsPerEm * 0.1));
221
+ w.writeInt16(Math.round(metrics.unitsPerEm * 0.6));
222
+ w.writeInt16(Math.round(metrics.unitsPerEm * 0.6));
223
+ w.writeInt16(0);
224
+ w.writeInt16(Math.round(metrics.unitsPerEm * 0.4));
225
+ w.writeInt16(0);
226
+ w.writeInt16(Math.round(metrics.xHeight * 0.6));
227
+ w.writeInt16(0);
228
+ for (let i = 0; i < 10; i++) {
229
+ w.writeUint8(0);
230
+ }
231
+ w.writeUint32(1);
232
+ w.writeUint32(0);
233
+ w.writeUint32(0);
234
+ w.writeUint32(0);
235
+ w.writeString(" ", 4);
236
+ w.writeUint16(64);
237
+ w.writeUint16(32);
238
+ w.writeUint16(126);
239
+ w.writeInt16(metrics.ascent);
240
+ w.writeInt16(metrics.descent);
241
+ w.writeInt16(metrics.lineGap);
242
+ w.writeUint16(metrics.ascent);
243
+ w.writeUint16(Math.abs(metrics.descent));
244
+ w.writeUint32(1);
245
+ w.writeUint32(0);
246
+ w.writeInt16(metrics.xHeight);
247
+ w.writeInt16(metrics.capHeight);
248
+ w.writeUint16(0);
249
+ w.writeUint16(32);
250
+ w.writeUint16(1);
251
+ w.padTo4();
252
+ tableData.set("OS/2", { offset: os2Start, length: w.getSize() - os2Start });
253
+ const nameStart = w.getSize();
254
+ const nameStrings = [
255
+ { nameID: 0, str: `Copyright 2024 ${name}` },
256
+ { nameID: 1, str: fontData.family },
257
+ { nameID: 2, str: "Regular" },
258
+ { nameID: 3, str: `${name}-Regular` },
259
+ { nameID: 4, str: `${name} Regular` },
260
+ { nameID: 5, str: "Version 1.0" },
261
+ { nameID: 6, str: `${name}-Regular` }
262
+ ];
263
+ w.writeUint16(0);
264
+ w.writeUint16(nameStrings.length);
265
+ const nameStorageOffset = 6 + nameStrings.length * 12;
266
+ w.writeUint16(nameStorageOffset);
267
+ let strOffset = 0;
268
+ for (const ns of nameStrings) {
269
+ w.writeUint16(1);
270
+ w.writeUint16(0);
271
+ w.writeUint16(0);
272
+ w.writeUint16(ns.nameID);
273
+ w.writeUint16(ns.str.length);
274
+ w.writeUint16(strOffset);
275
+ strOffset += ns.str.length;
276
+ }
277
+ for (const ns of nameStrings) {
278
+ w.writeString(ns.str);
279
+ }
280
+ w.padTo4();
281
+ tableData.set("name", { offset: nameStart, length: w.getSize() - nameStart });
282
+ const cmapStart = w.getSize();
283
+ w.writeUint16(0);
284
+ w.writeUint16(1);
285
+ w.writeUint16(3);
286
+ w.writeUint16(1);
287
+ w.writeUint32(12);
288
+ const sortedGlyphs = [...glyphs].sort((a, b) => a.unicode - b.unicode);
289
+ const segCount = sortedGlyphs.length + 1;
290
+ const fmt4Size = 14 + segCount * 8;
291
+ w.writeUint16(4);
292
+ w.writeUint16(fmt4Size);
293
+ w.writeUint16(0);
294
+ w.writeUint16(segCount * 2);
295
+ const searchRange2 = Math.pow(2, Math.floor(Math.log2(segCount))) * 2;
296
+ w.writeUint16(searchRange2);
297
+ w.writeUint16(Math.floor(Math.log2(segCount)));
298
+ w.writeUint16(segCount * 2 - searchRange2);
299
+ for (const g of sortedGlyphs) {
300
+ w.writeUint16(g.unicode);
301
+ }
302
+ w.writeUint16(65535);
303
+ w.writeUint16(0);
304
+ for (const g of sortedGlyphs) {
305
+ w.writeUint16(g.unicode);
306
+ }
307
+ w.writeUint16(65535);
308
+ for (let i = 0; i < sortedGlyphs.length; i++) {
309
+ const delta = i + 1 - sortedGlyphs[i].unicode;
310
+ w.writeInt16(delta);
311
+ }
312
+ w.writeInt16(1);
313
+ for (let i = 0; i <= sortedGlyphs.length; i++) {
314
+ w.writeUint16(0);
315
+ }
316
+ w.padTo4();
317
+ tableData.set("cmap", { offset: cmapStart, length: w.getSize() - cmapStart });
318
+ const glyfStart = w.getSize();
319
+ const glyphOffsets = [0];
320
+ w.writeInt16(0);
321
+ w.writeInt16(0);
322
+ w.writeInt16(0);
323
+ w.writeInt16(0);
324
+ w.writeInt16(0);
325
+ for (let i = 0; i < glyphs.length; i++) {
326
+ glyphOffsets.push(w.getSize() - glyfStart);
362
327
  w.writeInt16(0);
363
328
  w.writeInt16(0);
364
329
  w.writeInt16(0);
365
- w.writeInt16(0); // bbox
366
- for (let i = 0; i < glyphs.length; i++) {
367
- glyphOffsets.push(w.getSize() - glyfStart);
368
- // Simple empty glyph placeholder
369
- w.writeInt16(0);
370
- w.writeInt16(0);
371
- w.writeInt16(0);
372
- w.writeInt16(Math.round(glyphs[i].advanceWidth));
373
- w.writeInt16(metrics.ascent);
374
- }
375
- glyphOffsets.push(w.getSize() - glyfStart); // end offset
376
- w.padTo4();
377
- tableData.set('glyf', { offset: glyfStart, length: w.getSize() - glyfStart });
378
- // loca table (long format)
379
- const locaStart = w.getSize();
380
- for (const off of glyphOffsets) {
381
- w.writeUint32(off);
382
- }
383
- w.padTo4();
384
- tableData.set('loca', { offset: locaStart, length: w.getSize() - locaStart });
385
- // post table
386
- const postStart = w.getSize();
387
- w.writeFixed(3.0); // version 3.0 (no glyph names)
388
- w.writeFixed(0); // italicAngle
389
- w.writeInt16(-100); // underlinePosition
390
- w.writeInt16(50); // underlineThickness
391
- w.writeUint32(0); // isFixedPitch
392
- w.writeUint32(0); // minMemType42
393
- w.writeUint32(0); // maxMemType42
394
- w.writeUint32(0); // minMemType1
395
- w.writeUint32(0); // maxMemType1
396
- w.padTo4();
397
- tableData.set('post', { offset: postStart, length: w.getSize() - postStart });
398
- return w.toArrayBuffer();
330
+ w.writeInt16(Math.round(glyphs[i].advanceWidth));
331
+ w.writeInt16(metrics.ascent);
332
+ }
333
+ glyphOffsets.push(w.getSize() - glyfStart);
334
+ w.padTo4();
335
+ tableData.set("glyf", { offset: glyfStart, length: w.getSize() - glyfStart });
336
+ const locaStart = w.getSize();
337
+ for (const off of glyphOffsets) {
338
+ w.writeUint32(off);
339
+ }
340
+ w.padTo4();
341
+ tableData.set("loca", { offset: locaStart, length: w.getSize() - locaStart });
342
+ const postStart = w.getSize();
343
+ w.writeFixed(3);
344
+ w.writeFixed(0);
345
+ w.writeInt16(-100);
346
+ w.writeInt16(50);
347
+ w.writeUint32(0);
348
+ w.writeUint32(0);
349
+ w.writeUint32(0);
350
+ w.writeUint32(0);
351
+ w.writeUint32(0);
352
+ w.padTo4();
353
+ tableData.set("post", { offset: postStart, length: w.getSize() - postStart });
354
+ return w.toArrayBuffer();
399
355
  }
400
- /**
401
- * Wrap TrueType data into WOFF format.
402
- */
403
356
  function wrapWOFF(ttfData) {
404
- const w = new BinaryWriter();
405
- const ttf = new Uint8Array(ttfData);
406
- w.writeUint32(tag('wOFF')); // signature
407
- w.writeUint32(0x00010000); // flavor (TrueType)
408
- w.writeUint32(0); // length placeholder
409
- w.writeUint16(0); // numTables placeholder
410
- w.writeUint16(0); // reserved
411
- w.writeUint32(ttf.length); // totalSfntSize
412
- w.writeUint16(1);
413
- w.writeUint16(0); // majorVersion, minorVersion
414
- w.writeUint32(0); // metaOffset
415
- w.writeUint32(0); // metaLength
416
- w.writeUint32(0); // metaOrigLength
417
- w.writeUint32(0); // privOffset
418
- w.writeUint32(0); // privLength
419
- // For simplicity, embed the entire TTF uncompressed
420
- w.writeBytes(ttf);
421
- return w.toArrayBuffer();
357
+ const w = new BinaryWriter();
358
+ const ttf = new Uint8Array(ttfData);
359
+ w.writeUint32(tag("wOFF"));
360
+ w.writeUint32(65536);
361
+ w.writeUint32(0);
362
+ w.writeUint16(0);
363
+ w.writeUint16(0);
364
+ w.writeUint32(ttf.length);
365
+ w.writeUint16(1);
366
+ w.writeUint16(0);
367
+ w.writeUint32(0);
368
+ w.writeUint32(0);
369
+ w.writeUint32(0);
370
+ w.writeUint32(0);
371
+ w.writeUint32(0);
372
+ w.writeBytes(ttf);
373
+ return w.toArrayBuffer();
422
374
  }
423
- /**
424
- * Download font file to user's device.
425
- */
426
375
  function downloadFont(fontData, format, exportToSvgFont) {
427
- let blob;
428
- let ext;
429
- if (format === 'svg' && exportToSvgFont) {
430
- const svgStr = exportToSvgFont(fontData);
431
- blob = new Blob([svgStr], { type: 'image/svg+xml' });
432
- ext = 'svg';
433
- }
434
- else if (format === 'woff') {
435
- const ttf = buildTTF(fontData);
436
- const woff = wrapWOFF(ttf);
437
- blob = new Blob([woff], { type: 'font/woff' });
438
- ext = 'woff';
439
- }
440
- else {
441
- const ttf = buildTTF(fontData);
442
- blob = new Blob([ttf], { type: 'font/ttf' });
443
- ext = 'ttf';
444
- }
445
- const url = URL.createObjectURL(blob);
446
- const link = document.createElement('a');
447
- link.download = `${fontData.name || 'font'}.${ext}`;
448
- link.href = url;
449
- link.click();
450
- URL.revokeObjectURL(url);
376
+ let blob;
377
+ let ext;
378
+ if (format === "svg" && exportToSvgFont) {
379
+ const svgStr = exportToSvgFont(fontData);
380
+ blob = new Blob([svgStr], { type: "image/svg+xml" });
381
+ ext = "svg";
382
+ } else if (format === "woff") {
383
+ const ttf = buildTTF(fontData);
384
+ const woff = wrapWOFF(ttf);
385
+ blob = new Blob([woff], { type: "font/woff" });
386
+ ext = "woff";
387
+ } else {
388
+ const ttf = buildTTF(fontData);
389
+ blob = new Blob([ttf], { type: "font/ttf" });
390
+ ext = "ttf";
391
+ }
392
+ const url = URL.createObjectURL(blob);
393
+ const link = document.createElement("a");
394
+ link.download = `${fontData.name || "font"}.${ext}`;
395
+ link.href = url;
396
+ link.click();
397
+ URL.revokeObjectURL(url);
451
398
  }
452
- /**
453
- * Auto-generate kerning pairs based on glyph shapes.
454
- * Uses heuristic: characters with diagonal strokes (A, V, W, Y) need negative kern
455
- * against round/short characters.
456
- */
457
399
  function autoKern(glyphs, metrics) {
458
- const pairs = [];
459
- const scale = metrics.unitsPerEm / 1000;
460
- // Apply common kerning pairs if glyphs exist
461
- for (const commonPair of COMMON_KERNING_PAIRS) {
462
- const leftExists = glyphs.some((g) => g.char === commonPair.left);
463
- const rightExists = glyphs.some((g) => g.char === commonPair.right);
464
- if (leftExists && rightExists) {
465
- pairs.push({
466
- left: commonPair.left,
467
- right: commonPair.right,
468
- value: Math.round(commonPair.value * scale),
469
- });
470
- }
400
+ const pairs = [];
401
+ const scale = metrics.unitsPerEm / 1e3;
402
+ for (const commonPair of COMMON_KERNING_PAIRS) {
403
+ const leftExists = glyphs.some((g) => g.char === commonPair.left);
404
+ const rightExists = glyphs.some((g) => g.char === commonPair.right);
405
+ if (leftExists && rightExists) {
406
+ pairs.push({
407
+ left: commonPair.left,
408
+ right: commonPair.right,
409
+ value: Math.round(commonPair.value * scale)
410
+ });
471
411
  }
472
- return pairs;
412
+ }
413
+ return pairs;
473
414
  }
474
-
475
415
  exports.COMMON_KERNING_PAIRS = COMMON_KERNING_PAIRS;
476
416
  exports.OPENTYPE_FEATURE_PRESETS = OPENTYPE_FEATURE_PRESETS;
477
417
  exports.autoKern = autoKern;