pagyra-js 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 (540) hide show
  1. package/.eslintrc.json +30 -0
  2. package/CHANGELOG.md +13 -0
  3. package/README.md +275 -0
  4. package/UA_Styles_Chromium.md +93 -0
  5. package/_ext/woff2_conversion/brotli-decode.d.ts +139 -0
  6. package/_ext/woff2_conversion/brotli-encode.d.ts +129 -0
  7. package/_ext/woff2_conversion/brotli-port.d.ts +12 -0
  8. package/_ext/woff2_conversion/brotli-shared-dictionary.d.ts +25 -0
  9. package/_ext/woff2_conversion/brotli-types.d.ts +15 -0
  10. package/_ext/woff2_conversion/woff2-common.d.ts +37 -0
  11. package/_ext/woff2_conversion/woff2-decode.d.ts +32 -0
  12. package/_ext/woff2_conversion/woff2-encode.d.ts +31 -0
  13. package/_ext/woff2_conversion/woff2-output.d.ts +39 -0
  14. package/_ext/woff2_original_cpp/brotli/brotli.c +1559 -0
  15. package/_ext/woff2_original_cpp/brotli/brotli.md +116 -0
  16. package/_ext/woff2_original_cpp/brotli/decode.h +409 -0
  17. package/_ext/woff2_original_cpp/brotli/encode.h +505 -0
  18. package/_ext/woff2_original_cpp/brotli/port.h +302 -0
  19. package/_ext/woff2_original_cpp/brotli/shared_dictionary.h +100 -0
  20. package/_ext/woff2_original_cpp/brotli/types.h +83 -0
  21. package/_ext/woff2_original_cpp/cmake/FindBrotliDec.cmake +35 -0
  22. package/_ext/woff2_original_cpp/cmake/FindBrotliEnc.cmake +35 -0
  23. package/_ext/woff2_original_cpp/include/woff2/decode.h +36 -0
  24. package/_ext/woff2_original_cpp/include/woff2/encode.h +43 -0
  25. package/_ext/woff2_original_cpp/include/woff2/output.h +86 -0
  26. package/_ext/woff2_original_cpp/src/buffer.h +164 -0
  27. package/_ext/woff2_original_cpp/src/convert_woff2ttf_fuzzer.cc +13 -0
  28. package/_ext/woff2_original_cpp/src/convert_woff2ttf_fuzzer_new_entry.cc +12 -0
  29. package/_ext/woff2_original_cpp/src/file.h +30 -0
  30. package/_ext/woff2_original_cpp/src/font.cc +400 -0
  31. package/_ext/woff2_original_cpp/src/font.h +105 -0
  32. package/_ext/woff2_original_cpp/src/glyph.cc +383 -0
  33. package/_ext/woff2_original_cpp/src/glyph.h +71 -0
  34. package/_ext/woff2_original_cpp/src/normalize.cc +314 -0
  35. package/_ext/woff2_original_cpp/src/normalize.h +39 -0
  36. package/_ext/woff2_original_cpp/src/port.h +66 -0
  37. package/_ext/woff2_original_cpp/src/round.h +27 -0
  38. package/_ext/woff2_original_cpp/src/store_bytes.h +55 -0
  39. package/_ext/woff2_original_cpp/src/table_tags.cc +82 -0
  40. package/_ext/woff2_original_cpp/src/table_tags.h +30 -0
  41. package/_ext/woff2_original_cpp/src/transform.cc +430 -0
  42. package/_ext/woff2_original_cpp/src/transform.h +26 -0
  43. package/_ext/woff2_original_cpp/src/variable_length.cc +129 -0
  44. package/_ext/woff2_original_cpp/src/variable_length.h +30 -0
  45. package/_ext/woff2_original_cpp/src/woff2_common.cc +50 -0
  46. package/_ext/woff2_original_cpp/src/woff2_common.h +64 -0
  47. package/_ext/woff2_original_cpp/src/woff2_compress.cc +43 -0
  48. package/_ext/woff2_original_cpp/src/woff2_dec.cc +1398 -0
  49. package/_ext/woff2_original_cpp/src/woff2_decompress.cc +41 -0
  50. package/_ext/woff2_original_cpp/src/woff2_enc.cc +458 -0
  51. package/_ext/woff2_original_cpp/src/woff2_info.cc +142 -0
  52. package/_ext/woff2_original_cpp/src/woff2_out.cc +63 -0
  53. package/assets/fonts/ttf/arimo/Arimo-Bold.ttf +0 -0
  54. package/assets/fonts/ttf/arimo/Arimo-BoldItalic.ttf +0 -0
  55. package/assets/fonts/ttf/arimo/Arimo-Italic.ttf +0 -0
  56. package/assets/fonts/ttf/arimo/Arimo-Regular.ttf +0 -0
  57. package/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Black.ttf +0 -0
  58. package/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Bold.ttf +0 -0
  59. package/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Regular.ttf +0 -0
  60. package/assets/fonts/ttf/dejavu/DejaVuSans.ttf +0 -0
  61. package/assets/fonts/ttf/firecode/FiraCode-Bold.ttf +0 -0
  62. package/assets/fonts/ttf/firecode/FiraCode-Light.ttf +0 -0
  63. package/assets/fonts/ttf/firecode/FiraCode-Medium.ttf +0 -0
  64. package/assets/fonts/ttf/firecode/FiraCode-Regular.ttf +0 -0
  65. package/assets/fonts/ttf/firecode/FiraCode-SemiBold.ttf +0 -0
  66. package/assets/fonts/ttf/notoemoji/NotoEmoji-Bold.ttf +0 -0
  67. package/assets/fonts/ttf/notoemoji/NotoEmoji-Light.ttf +0 -0
  68. package/assets/fonts/ttf/notoemoji/NotoEmoji-Medium.ttf +0 -0
  69. package/assets/fonts/ttf/notoemoji/NotoEmoji-Regular.ttf +0 -0
  70. package/assets/fonts/ttf/notoemoji/NotoEmoji-SemiBold.ttf +0 -0
  71. package/assets/fonts/ttf/notosans/NotoSans-Regular.ttf +0 -0
  72. package/assets/fonts/ttf/roboto/Roboto-Bold.ttf +0 -0
  73. package/assets/fonts/ttf/roboto/Roboto-BoldItalic.ttf +0 -0
  74. package/assets/fonts/ttf/roboto/Roboto-Italic.ttf +0 -0
  75. package/assets/fonts/ttf/roboto/Roboto-Regular.ttf +0 -0
  76. package/assets/fonts/ttf/stixtwomath/STIXTwoMath-Regular.ttf +0 -0
  77. package/assets/fonts/ttf/tinos/Tinos-Bold.ttf +0 -0
  78. package/assets/fonts/ttf/tinos/Tinos-BoldItalic.ttf +0 -0
  79. package/assets/fonts/ttf/tinos/Tinos-Italic.ttf +0 -0
  80. package/assets/fonts/ttf/tinos/Tinos-Regular.ttf +0 -0
  81. package/assets/fonts/woff/lato/lato-latin-400-italic.woff +0 -0
  82. package/assets/fonts/woff/lato/lato-latin-400-normal.woff +0 -0
  83. package/assets/fonts/woff/lato/lato-latin-700-italic.woff +0 -0
  84. package/assets/fonts/woff/lato/lato-latin-700-normal.woff +0 -0
  85. package/assets/fonts/woff2/caveat/Caveat-Bold.woff2 +0 -0
  86. package/assets/fonts/woff2/caveat/Caveat-Regular.woff2 +0 -0
  87. package/assets/fonts/woff2/lato/lato-latin-400-italic.woff2 +0 -0
  88. package/assets/fonts/woff2/lato/lato-latin-400-normal.woff2 +0 -0
  89. package/assets/fonts/woff2/lato/lato-latin-700-italic.woff2 +0 -0
  90. package/assets/fonts/woff2/lato/lato-latin-700-normal.woff2 +0 -0
  91. package/docs/AGENTS.md +288 -0
  92. package/docs/BACKGROUND-REPEAT-IMPLEMENTATION.md +127 -0
  93. package/docs/BACKGROUND-REPEAT-REFERENCE.md +127 -0
  94. package/docs/BACKGROUND-REPEAT-SPACE-ROUND.md +164 -0
  95. package/docs/css-properties-support.md +256 -0
  96. package/docs/src_modules_table.md +172 -0
  97. package/docs/text-overlap-fix.md +85 -0
  98. package/docs/text-overlap-investigation.md +27 -0
  99. package/eslint.config.js +36 -0
  100. package/glyph_measure.htm +1458 -0
  101. package/package.json +50 -0
  102. package/playground/browser-entry.ts +2 -0
  103. package/playground/exports/background-text-debug.pdf +0 -0
  104. package/playground/public/app.js +875 -0
  105. package/playground/public/assets/1.webp +0 -0
  106. package/playground/public/examples/accents-test.html +24 -0
  107. package/playground/public/examples/advanced-selectors-demo.html +118 -0
  108. package/playground/public/examples/background-advanced-showcase.html +82 -0
  109. package/playground/public/examples/background-clip-text.html +36 -0
  110. package/playground/public/examples/background-origin-showcase.html +137 -0
  111. package/playground/public/examples/background-position-showcase.html +83 -0
  112. package/playground/public/examples/background-repeat-showcase.html +83 -0
  113. package/playground/public/examples/background-repeat-space-round.html +348 -0
  114. package/playground/public/examples/background-size-showcase.html +82 -0
  115. package/playground/public/examples/background-text-debug.html +18 -0
  116. package/playground/public/examples/baseline-test.html +24 -0
  117. package/playground/public/examples/bold-showcase.html +150 -0
  118. package/playground/public/examples/bold-strike-example.html +12 -0
  119. package/playground/public/examples/border-collapse-test.html +23 -0
  120. package/playground/public/examples/centered-shadow-div.html +72 -0
  121. package/playground/public/examples/css-variables.html +50 -0
  122. package/playground/public/examples/debug-accents.html +11 -0
  123. package/playground/public/examples/debug-text-overlap.html +46 -0
  124. package/playground/public/examples/flex-gap-column.html +130 -0
  125. package/playground/public/examples/flex-gap-row.html +137 -0
  126. package/playground/public/examples/flex-padding-test.html +29 -0
  127. package/playground/public/examples/flexbox-text-test.html +193 -0
  128. package/playground/public/examples/fonts-demo.html +126 -0
  129. package/playground/public/examples/footer-example.html +4 -0
  130. package/playground/public/examples/gradient-text.html +54 -0
  131. package/playground/public/examples/grid-gap-demo.html +156 -0
  132. package/playground/public/examples/header-example.html +4 -0
  133. package/playground/public/examples/header-footer-example.html +27 -0
  134. package/playground/public/examples/image-showcase.html +33 -0
  135. package/playground/public/examples/justify-text.html +22 -0
  136. package/playground/public/examples/linear-gradient-example.html +38 -0
  137. package/playground/public/examples/lorem-span.html +14 -0
  138. package/playground/public/examples/margin-block-showcase.html +21 -0
  139. package/playground/public/examples/margin-inline-showcase.html +21 -0
  140. package/playground/public/examples/monthly-summary.html +95 -0
  141. package/playground/public/examples/multi-page-lorem.html +190 -0
  142. package/playground/public/examples/opacity-debug.html +39 -0
  143. package/playground/public/examples/opacity-example.html +70 -0
  144. package/playground/public/examples/png-image-example.html +13 -0
  145. package/playground/public/examples/red-rectangle.html +18 -0
  146. package/playground/public/examples/repro.html +24 -0
  147. package/playground/public/examples/rounded-borders-test.html +24 -0
  148. package/playground/public/examples/simple-list.html +89 -0
  149. package/playground/public/examples/simple-svg.html +37 -0
  150. package/playground/public/examples/simple-table.html +52 -0
  151. package/playground/public/examples/skew-div.html +138 -0
  152. package/playground/public/examples/skew-text.html +21 -0
  153. package/playground/public/examples/starter-report.css +51 -0
  154. package/playground/public/examples/starter-report.html +23 -0
  155. package/playground/public/examples/svg-aspect-ratio-showcase.html +116 -0
  156. package/playground/public/examples/svg-gradients-linear.html +28 -0
  157. package/playground/public/examples/svg-gradients-radial.html +29 -0
  158. package/playground/public/examples/svg-gradients-showcase.html +66 -0
  159. package/playground/public/examples/svg-image-path-test.html +43 -0
  160. package/playground/public/examples/svg-images-clipping.html +27 -0
  161. package/playground/public/examples/svg-path-gallery.html +118 -0
  162. package/playground/public/examples/svg-radial-transform-demo.html +78 -0
  163. package/playground/public/examples/svg-transform-stack.html +103 -0
  164. package/playground/public/examples/svg-transforms-demo.html +127 -0
  165. package/playground/public/examples/table-merge-test.html +34 -0
  166. package/playground/public/examples/text-decoration-showcase.html +138 -0
  167. package/playground/public/examples/text-indent-showcase.html +137 -0
  168. package/playground/public/examples/text-shadow-example.html +29 -0
  169. package/playground/public/examples/very-complex-css.html +293 -0
  170. package/playground/public/examples/webp-example.html +13 -0
  171. package/playground/public/examples/z-index-demo.html +93 -0
  172. package/playground/public/examples.json +240 -0
  173. package/playground/public/images/dice.png +0 -0
  174. package/playground/public/images/duck.jpg +0 -0
  175. package/playground/public/index.html +149 -0
  176. package/playground/public/mode.js +1 -0
  177. package/playground/public/styles.css +382 -0
  178. package/playground/public/tmp-h2-debug.html +33 -0
  179. package/playground/public/tmp-italic-debug.html +32 -0
  180. package/playground/public/vendor/codemirror/codemirror.min.css +1 -0
  181. package/playground/public/vendor/codemirror/codemirror.min.js +1 -0
  182. package/playground/public/vendor/codemirror/css.min.js +1 -0
  183. package/playground/public/vendor/codemirror/darcula.min.css +1 -0
  184. package/playground/public/vendor/codemirror/htmlmixed.min.js +1 -0
  185. package/playground/public/vendor/codemirror/javascript.min.js +1 -0
  186. package/playground/public/vendor/codemirror/xml.min.js +1 -0
  187. package/playground/public/vendor/pagyra-playground-browser.js +165966 -0
  188. package/playground/public/vendor/pagyra-playground-browser.js.map +7 -0
  189. package/playground/server.d.ts +1 -0
  190. package/playground/server.js +68 -0
  191. package/playground/server.ts +128 -0
  192. package/scripts/browser-build.ts +101 -0
  193. package/scripts/build-browser-bundle.ts +52 -0
  194. package/scripts/glyph-comparison/simulate.ts +744 -0
  195. package/scripts/playground-browser-server.ts +57 -0
  196. package/scripts/probe-roboto.ts +6 -0
  197. package/scripts/render-playground-example.ts +121 -0
  198. package/scripts/run-glyph-atlas-tuner-runner.mjs +113 -0
  199. package/scripts/run-glyph-atlas-tuner.ts +141 -0
  200. package/scripts/top-ts-files.ps1 +39 -0
  201. package/scripts/top-ts-files.sh +37 -0
  202. package/scripts/woff2_info.ps1 +132 -0
  203. package/src/browser-entry.ts +14 -0
  204. package/src/compression/adler32.ts +45 -0
  205. package/src/compression/brotli/brotli.ts +463 -0
  206. package/src/compression/brotli/index.ts +15 -0
  207. package/src/compression/brotli/transform.ts +184 -0
  208. package/src/compression/brotli/types.ts +58 -0
  209. package/src/compression/brotli/utils.ts +157 -0
  210. package/src/compression/brotli/vendor/bit_reader.js +124 -0
  211. package/src/compression/brotli/vendor/context.js +250 -0
  212. package/src/compression/brotli/vendor/decode.d.ts +2 -0
  213. package/src/compression/brotli/vendor/decode.js +938 -0
  214. package/src/compression/brotli/vendor/dictionary-data.js +9469 -0
  215. package/src/compression/brotli/vendor/dictionary.js +36 -0
  216. package/src/compression/brotli/vendor/huffman.js +123 -0
  217. package/src/compression/brotli/vendor/package.json +3 -0
  218. package/src/compression/brotli/vendor/prefix.js +60 -0
  219. package/src/compression/brotli/vendor/streams.js +31 -0
  220. package/src/compression/brotli/vendor/transform.js +247 -0
  221. package/src/compression/brotli/vendor-decode.d.ts +4 -0
  222. package/src/compression/brotli/woff2-glyf-transform.ts +623 -0
  223. package/src/compression/decompress.ts +16 -0
  224. package/src/compression/deflate.ts +295 -0
  225. package/src/compression/index.ts +4 -0
  226. package/src/compression/types.ts +26 -0
  227. package/src/compression/utils.ts +107 -0
  228. package/src/core.ts +18 -0
  229. package/src/css/apply-declarations.ts +86 -0
  230. package/src/css/background-types.ts +65 -0
  231. package/src/css/browser-defaults.ts +16 -0
  232. package/src/css/clip-path-types.ts +13 -0
  233. package/src/css/compute-style.ts +494 -0
  234. package/src/css/css-unit-resolver.ts +65 -0
  235. package/src/css/custom-properties.ts +215 -0
  236. package/src/css/enums.ts +127 -0
  237. package/src/css/font-face-parser.ts +233 -0
  238. package/src/css/font-weight.ts +65 -0
  239. package/src/css/inline-style-parser.ts +27 -0
  240. package/src/css/layout-property-resolver.ts +75 -0
  241. package/src/css/length.ts +141 -0
  242. package/src/css/line-height.ts +96 -0
  243. package/src/css/named-colors.ts +150 -0
  244. package/src/css/parsers/background-parser-extended.ts +111 -0
  245. package/src/css/parsers/background-parser.ts +456 -0
  246. package/src/css/parsers/border-block-parser.ts +26 -0
  247. package/src/css/parsers/border-inline-parser.ts +26 -0
  248. package/src/css/parsers/border-parser-extended.ts +256 -0
  249. package/src/css/parsers/border-parser.ts +175 -0
  250. package/src/css/parsers/box-shadow-parser.ts +106 -0
  251. package/src/css/parsers/clip-path-parser.ts +92 -0
  252. package/src/css/parsers/color-parser.ts +14 -0
  253. package/src/css/parsers/dimension-parser.ts +117 -0
  254. package/src/css/parsers/display-flex-parser.ts +59 -0
  255. package/src/css/parsers/flex-parser.ts +144 -0
  256. package/src/css/parsers/font-parser.ts +40 -0
  257. package/src/css/parsers/gradient-parser.ts +366 -0
  258. package/src/css/parsers/grid-parser-extended.ts +55 -0
  259. package/src/css/parsers/grid-parser.ts +218 -0
  260. package/src/css/parsers/length-parser.ts +95 -0
  261. package/src/css/parsers/list-style-parser.ts +39 -0
  262. package/src/css/parsers/margin-block-parser.ts +12 -0
  263. package/src/css/parsers/margin-inline-parser.ts +12 -0
  264. package/src/css/parsers/margin-parser.ts +30 -0
  265. package/src/css/parsers/opacity-parser.ts +32 -0
  266. package/src/css/parsers/overflow-wrap-parser.ts +38 -0
  267. package/src/css/parsers/padding-block-parser.ts +12 -0
  268. package/src/css/parsers/padding-inline-parser.ts +12 -0
  269. package/src/css/parsers/padding-parser.ts +30 -0
  270. package/src/css/parsers/position-parser.ts +75 -0
  271. package/src/css/parsers/register-parsers.ts +302 -0
  272. package/src/css/parsers/registry.ts +18 -0
  273. package/src/css/parsers/text-parser-extended.ts +144 -0
  274. package/src/css/parsers/text-parser.ts +25 -0
  275. package/src/css/parsers/text-shadow-parser.ts +94 -0
  276. package/src/css/properties/box-model.ts +82 -0
  277. package/src/css/properties/flexbox.ts +44 -0
  278. package/src/css/properties/gap.ts +14 -0
  279. package/src/css/properties/grid.ts +94 -0
  280. package/src/css/properties/layout.ts +59 -0
  281. package/src/css/properties/misc.ts +44 -0
  282. package/src/css/properties/typography.ts +71 -0
  283. package/src/css/properties/visual.ts +68 -0
  284. package/src/css/selectors/matcher.ts +219 -0
  285. package/src/css/selectors/parser.ts +163 -0
  286. package/src/css/selectors/simple-key.ts +31 -0
  287. package/src/css/selectors/specificity.ts +41 -0
  288. package/src/css/selectors/types.ts +31 -0
  289. package/src/css/shorthands/border-shorthand.ts +68 -0
  290. package/src/css/shorthands/box-shorthand.ts +33 -0
  291. package/src/css/style-inheritance.ts +50 -0
  292. package/src/css/style.ts +402 -0
  293. package/src/css/ua-defaults/base-defaults.ts +266 -0
  294. package/src/css/ua-defaults/browser-defaults.ts +134 -0
  295. package/src/css/ua-defaults/element-defaults.ts +374 -0
  296. package/src/css/ua-defaults/types.ts +43 -0
  297. package/src/css/unit-conversion.ts +24 -0
  298. package/src/css/utils.ts +108 -0
  299. package/src/css/viewport.ts +17 -0
  300. package/src/debug/audit.ts +20 -0
  301. package/src/debug/ids.ts +13 -0
  302. package/src/debug/log.js +28 -0
  303. package/src/debug/log.ts +52 -0
  304. package/src/debug/tree.ts +57 -0
  305. package/src/dom/node.ts +133 -0
  306. package/src/environment/browser-environment.ts +78 -0
  307. package/src/environment/environment.ts +35 -0
  308. package/src/environment/global.ts +13 -0
  309. package/src/environment/node-environment.browser.ts +28 -0
  310. package/src/environment/node-environment.ts +64 -0
  311. package/src/fonts/detector.ts +28 -0
  312. package/src/fonts/engines/ttf-engine.ts +28 -0
  313. package/src/fonts/engines/woff-engine.ts +38 -0
  314. package/src/fonts/engines/woff2-engine.ts +41 -0
  315. package/src/fonts/extractors/metrics-extractor.ts +362 -0
  316. package/src/fonts/font-registry-resolver.ts +132 -0
  317. package/src/fonts/index.ts +3 -0
  318. package/src/fonts/orchestrator.ts +92 -0
  319. package/src/fonts/parsers/base-parser.ts +23 -0
  320. package/src/fonts/types.ts +85 -0
  321. package/src/fonts/utils/ttf-reconstructor.ts +120 -0
  322. package/src/fonts/woff/decoder.ts +105 -0
  323. package/src/fonts/woff2/buffer.ts +106 -0
  324. package/src/fonts/woff2/decoder.ts +981 -0
  325. package/src/geometry/box.ts +48 -0
  326. package/src/geometry/matrix.ts +59 -0
  327. package/src/html/css/parse-css.ts +85 -0
  328. package/src/html/dom-converter.ts +433 -0
  329. package/src/html/image-converter.ts +200 -0
  330. package/src/html-to-pdf.ts +410 -0
  331. package/src/image/base-decoder.ts +149 -0
  332. package/src/image/image-service.ts +188 -0
  333. package/src/image/jpeg-decoder.ts +73 -0
  334. package/src/image/png-decoder.ts +550 -0
  335. package/src/image/types.ts +20 -0
  336. package/src/image/webp-decoder.ts +242 -0
  337. package/src/image/webp-huffman.ts +218 -0
  338. package/src/image/webp-riff-parser.ts +54 -0
  339. package/src/image/webp-vp8l-decoder.ts +199 -0
  340. package/src/index.ts +35 -0
  341. package/src/layout/context/float-context.ts +62 -0
  342. package/src/layout/context/layout-environment.ts +29 -0
  343. package/src/layout/debug.ts +18 -0
  344. package/src/layout/inline/bounding-box-calculator.ts +132 -0
  345. package/src/layout/inline/font-baseline-calculator.ts +76 -0
  346. package/src/layout/inline/inline-utils.ts +94 -0
  347. package/src/layout/inline/layout.ts +285 -0
  348. package/src/layout/inline/line_breaker.ts +109 -0
  349. package/src/layout/inline/measurement.ts +144 -0
  350. package/src/layout/inline/run-placer.ts +139 -0
  351. package/src/layout/inline/text-alignment.ts +70 -0
  352. package/src/layout/inline/tokenizer.ts +195 -0
  353. package/src/layout/inline/types.ts +76 -0
  354. package/src/layout/pipeline/context-factory.ts +16 -0
  355. package/src/layout/pipeline/default-engine.ts +24 -0
  356. package/src/layout/pipeline/engine.ts +59 -0
  357. package/src/layout/pipeline/layout-tree.ts +13 -0
  358. package/src/layout/pipeline/out-of-flow-manager.ts +73 -0
  359. package/src/layout/pipeline/strategy.ts +12 -0
  360. package/src/layout/pipeline/text-metrics-initializer.ts +13 -0
  361. package/src/layout/strategies/block.ts +236 -0
  362. package/src/layout/strategies/display-none.ts +14 -0
  363. package/src/layout/strategies/fallback.ts +15 -0
  364. package/src/layout/strategies/flex.ts +477 -0
  365. package/src/layout/strategies/fragmentation.ts +17 -0
  366. package/src/layout/strategies/grid.ts +247 -0
  367. package/src/layout/strategies/image.ts +342 -0
  368. package/src/layout/strategies/inline.ts +128 -0
  369. package/src/layout/strategies/table.ts +595 -0
  370. package/src/layout/table/cell_layout.ts +31 -0
  371. package/src/layout/table/diagnostics.ts +19 -0
  372. package/src/layout/text-run.ts +42 -0
  373. package/src/layout/utils/content-measurer.ts +117 -0
  374. package/src/layout/utils/display-utils.ts +24 -0
  375. package/src/layout/utils/floats.ts +98 -0
  376. package/src/layout/utils/gap-calculator.ts +167 -0
  377. package/src/layout/utils/inline-formatter.ts +31 -0
  378. package/src/layout/utils/inline-formatting.ts +9 -0
  379. package/src/layout/utils/margin.ts +140 -0
  380. package/src/layout/utils/node-math.ts +237 -0
  381. package/src/layout/utils/overflow.ts +14 -0
  382. package/src/layout/utils/sizing.ts +12 -0
  383. package/src/layout/utils/text-metrics.ts +361 -0
  384. package/src/logging/debug.ts +58 -0
  385. package/src/pdf/font/base14/widths-courier-bold.ts +159 -0
  386. package/src/pdf/font/base14/widths-courier.ts +159 -0
  387. package/src/pdf/font/base14/widths-helvetica-bold.ts +158 -0
  388. package/src/pdf/font/base14/widths-helvetica.ts +158 -0
  389. package/src/pdf/font/base14/widths-times-bold.ts +158 -0
  390. package/src/pdf/font/base14/widths-times-roman.ts +158 -0
  391. package/src/pdf/font/base14/widths-types.ts +25 -0
  392. package/src/pdf/font/base14-widths.ts +32 -0
  393. package/src/pdf/font/blur.ts +81 -0
  394. package/src/pdf/font/builtin-fonts.browser.ts +262 -0
  395. package/src/pdf/font/builtin-fonts.ts +126 -0
  396. package/src/pdf/font/composite-glyph-parser.ts +242 -0
  397. package/src/pdf/font/embedder.ts +395 -0
  398. package/src/pdf/font/font-config.ts +190 -0
  399. package/src/pdf/font/font-registry.ts +263 -0
  400. package/src/pdf/font/font-subset.ts +258 -0
  401. package/src/pdf/font/glyph-atlas-maxrects.ts +305 -0
  402. package/src/pdf/font/glyph-atlas-tuner.ts +98 -0
  403. package/src/pdf/font/glyph-atlas.ts +226 -0
  404. package/src/pdf/font/glyph-cache.ts +127 -0
  405. package/src/pdf/font/loca-reader.ts +109 -0
  406. package/src/pdf/font/managers/font-resource-manager.ts +73 -0
  407. package/src/pdf/font/managers/subset-resource-manager.ts +164 -0
  408. package/src/pdf/font/rasterizer.ts +270 -0
  409. package/src/pdf/font/resolvers/base-font-mapper.ts +77 -0
  410. package/src/pdf/font/resolvers/family-resolver.ts +33 -0
  411. package/src/pdf/font/resolvers/weight-style-applicator.ts +63 -0
  412. package/src/pdf/font/simple-glyph-parser.ts +289 -0
  413. package/src/pdf/font/to-unicode.ts +109 -0
  414. package/src/pdf/font/transformation-matrix.ts +136 -0
  415. package/src/pdf/font/ttf-cmap.ts +180 -0
  416. package/src/pdf/font/ttf-global-metrics.ts +58 -0
  417. package/src/pdf/font/ttf-glyf.ts +125 -0
  418. package/src/pdf/font/ttf-glyph-metrics.ts +43 -0
  419. package/src/pdf/font/ttf-lite.ts +269 -0
  420. package/src/pdf/font/ttf-table-parser.ts +132 -0
  421. package/src/pdf/font/ttf-table-provider.ts +61 -0
  422. package/src/pdf/font/widths.ts +79 -0
  423. package/src/pdf/font-subset/font-registry.ts +127 -0
  424. package/src/pdf/header-footer-layout.ts +153 -0
  425. package/src/pdf/header-footer-painter.ts +209 -0
  426. package/src/pdf/header-footer-renderer.ts +357 -0
  427. package/src/pdf/header-footer-tokens.ts +55 -0
  428. package/src/pdf/header-footer.ts +25 -0
  429. package/src/pdf/layout-tree-builder.ts +261 -0
  430. package/src/pdf/page-painter.ts +241 -0
  431. package/src/pdf/pagination.ts +155 -0
  432. package/src/pdf/primitives/pdf-builder.ts +378 -0
  433. package/src/pdf/primitives/pdf-bytes.ts +40 -0
  434. package/src/pdf/primitives/pdf-document.ts +108 -0
  435. package/src/pdf/primitives/pdf-reference-manager.ts +47 -0
  436. package/src/pdf/primitives/pdf-resource-registries.ts +255 -0
  437. package/src/pdf/primitives/pdf-serializers.ts +194 -0
  438. package/src/pdf/primitives/pdf-types.ts +73 -0
  439. package/src/pdf/render.ts +210 -0
  440. package/src/pdf/renderer/box-painter.ts +236 -0
  441. package/src/pdf/renderer/page-paint.ts +102 -0
  442. package/src/pdf/renderer/paint-box-shadows.ts +218 -0
  443. package/src/pdf/renderer/radius.ts +58 -0
  444. package/src/pdf/renderers/graphics-state-manager.ts +40 -0
  445. package/src/pdf/renderers/image-renderer.ts +127 -0
  446. package/src/pdf/renderers/radius-utils.ts +80 -0
  447. package/src/pdf/renderers/rectangle-renderer.ts +129 -0
  448. package/src/pdf/renderers/rounded-rect-path.ts +120 -0
  449. package/src/pdf/renderers/shape-renderer.ts +563 -0
  450. package/src/pdf/renderers/shape-utils.ts +194 -0
  451. package/src/pdf/renderers/text-decoration-renderer.ts +313 -0
  452. package/src/pdf/renderers/text-encoder.ts +41 -0
  453. package/src/pdf/renderers/text-font-resolver.ts +75 -0
  454. package/src/pdf/renderers/text-renderer-utils.ts +28 -0
  455. package/src/pdf/renderers/text-renderer.ts +391 -0
  456. package/src/pdf/renderers/text-shadow-renderer.ts +300 -0
  457. package/src/pdf/shading/gradient-service.ts +525 -0
  458. package/src/pdf/shading/index.ts +1 -0
  459. package/src/pdf/stacking/build-stacking-contexts.ts +93 -0
  460. package/src/pdf/stacking/resolve-paint-order.ts +157 -0
  461. package/src/pdf/stacking/types.ts +40 -0
  462. package/src/pdf/svg/aspect-ratio.ts +81 -0
  463. package/src/pdf/svg/coordinate-mapper.ts +81 -0
  464. package/src/pdf/svg/geometry-builder.ts +45 -0
  465. package/src/pdf/svg/render-svg.ts +296 -0
  466. package/src/pdf/svg/shape-renderer.ts +463 -0
  467. package/src/pdf/svg/style-computer.ts +246 -0
  468. package/src/pdf/transform-adapter.ts +26 -0
  469. package/src/pdf/types.ts +377 -0
  470. package/src/pdf/utils/background-layer-resolver.ts +439 -0
  471. package/src/pdf/utils/background-tiles.ts +192 -0
  472. package/src/pdf/utils/border-dashes.ts +109 -0
  473. package/src/pdf/utils/border-radius-utils.ts +86 -0
  474. package/src/pdf/utils/box-dimensions-utils.ts +47 -0
  475. package/src/pdf/utils/clip-path-resolver.ts +50 -0
  476. package/src/pdf/utils/clipping-path-builder.ts +190 -0
  477. package/src/pdf/utils/color-utils.ts +102 -0
  478. package/src/pdf/utils/coordinate-transformer.ts +30 -0
  479. package/src/pdf/utils/drop-shadow-raster.ts +233 -0
  480. package/src/pdf/utils/encoding.ts +98 -0
  481. package/src/pdf/utils/glyph-atlas-registrar.ts +13 -0
  482. package/src/pdf/utils/glyph-run-renderer.ts +129 -0
  483. package/src/pdf/utils/image-command-partitioner.ts +28 -0
  484. package/src/pdf/utils/image-matrix-builder.ts +31 -0
  485. package/src/pdf/utils/image-utils.ts +26 -0
  486. package/src/pdf/utils/list-utils.ts +194 -0
  487. package/src/pdf/utils/node-text-run-factory.ts +202 -0
  488. package/src/pdf/utils/page-resource-registrar.ts +46 -0
  489. package/src/pdf/utils/result-combiner.ts +102 -0
  490. package/src/pdf/utils/shadow-utils.ts +127 -0
  491. package/src/pdf/utils/text-alignment-resolver.ts +76 -0
  492. package/src/pdf/utils/text-decoration-utils.ts +64 -0
  493. package/src/pdf/utils/text-layout-adjuster.ts +185 -0
  494. package/src/pdf/utils/text-utils.ts +193 -0
  495. package/src/pdf/utils/transform-scope-manager.ts +69 -0
  496. package/src/render/offset.ts +170 -0
  497. package/src/shim/empty.ts +2 -0
  498. package/src/shim/fs-empty.ts +5 -0
  499. package/src/shim/url-empty.ts +7 -0
  500. package/src/shim/zlib-empty.ts +9 -0
  501. package/src/style/shorthands/index.ts +19 -0
  502. package/src/style/ua/defaults.ts +69 -0
  503. package/src/svg/index.ts +4 -0
  504. package/src/svg/parser-registry.ts +71 -0
  505. package/src/svg/parser.ts +486 -0
  506. package/src/svg/path-data.ts +515 -0
  507. package/src/svg/types.ts +194 -0
  508. package/src/text/line-breaker.ts +321 -0
  509. package/src/text/text-transform.ts +43 -0
  510. package/src/text/text.ts +33 -0
  511. package/src/transform/css-parser.ts +95 -0
  512. package/src/types/fonts.ts +62 -0
  513. package/src/types/public.ts +19 -0
  514. package/src/units/page-utils.ts +58 -0
  515. package/src/units/units.ts +50 -0
  516. package/src/utils/base64.ts +24 -0
  517. package/test-output.txt +79 -0
  518. package/tests/css/background-parser.spec.ts +14 -0
  519. package/tests/css/clip-path-parser.spec.ts +66 -0
  520. package/tests/environment/path-resolution.spec.ts +104 -0
  521. package/tests/helpers/ai-layout-diagnostics.ts +141 -0
  522. package/tests/helpers/render-utils.ts +52 -0
  523. package/tests/helpers/text-geometry.ts +56 -0
  524. package/tests/layout/custom-properties.test.ts +38 -0
  525. package/tests/layout/gap-calculator.spec.ts +196 -0
  526. package/tests/layout/inline-background-alignment.spec.ts +93 -0
  527. package/tests/layout/inline-fragments.spec.ts +26 -0
  528. package/tests/layout/run-placer-baseline.spec.ts +108 -0
  529. package/tests/pdf/alignments.spec.ts +26 -0
  530. package/tests/pdf/background-clip.spec.ts +57 -0
  531. package/tests/pdf/background-repeat-space-round.spec.ts +35 -0
  532. package/tests/pdf/background-repeat.spec.ts +137 -0
  533. package/tests/pdf/border-radius.spec.ts +151 -0
  534. package/tests/pdf/clip-path.spec.ts +92 -0
  535. package/tests/pdf/radial-gradient.spec.ts +50 -0
  536. package/tests/pdf/svg-stroke-dash.spec.ts +81 -0
  537. package/tests/pdf/text-transform-matrix.spec.ts +43 -0
  538. package/tsconfig.json +17 -0
  539. package/types/fonts.js +10 -0
  540. package/vitest.config.ts +9 -0
@@ -0,0 +1,289 @@
1
+ import type { GlyphOutlineCmd } from "../../types/fonts.js";
2
+ import type { DataViewReader } from "./ttf-table-provider.js";
3
+
4
+ /**
5
+ * Represents a point in a glyph contour.
6
+ */
7
+ interface Point {
8
+ x: number;
9
+ y: number;
10
+ onCurve: boolean;
11
+ }
12
+
13
+ /**
14
+ * Parses simple (non-composite) TrueType glyphs.
15
+ *
16
+ * Simple glyphs consist of one or more contours made up of on-curve and off-curve points.
17
+ * Off-curve points are quadratic Bezier control points.
18
+ */
19
+ export class SimpleGlyphParser {
20
+ constructor(private readonly reader: DataViewReader) { }
21
+
22
+ /**
23
+ * Parses a simple glyph from a DataView.
24
+ * @param view - DataView containing the glyph data starting at the glyph header
25
+ * @returns Array of glyph outline commands, or null if parsing fails
26
+ */
27
+ parse(view: DataView): GlyphOutlineCmd[] | null {
28
+ const contours = this.parseContours(view);
29
+ if (!contours) return null;
30
+
31
+ return this.buildOutlineCommands(contours);
32
+ }
33
+
34
+ /**
35
+ * Parses glyph contours from the DataView.
36
+ * @param view - DataView containing the glyph data
37
+ * @returns Array of contours (each contour is an array of points), or null if parsing fails
38
+ */
39
+ private parseContours(view: DataView): Point[][] | null {
40
+ if (view.byteLength < 10) return null;
41
+
42
+ // Read glyph header
43
+ const numberOfContours = view.getInt16(0, false);
44
+ if (numberOfContours < 0) return null; // Composite glyph, shouldn't happen here
45
+
46
+ // Read endPtsOfContours array
47
+ const endPtsOffset = 10;
48
+ const endPts: number[] = [];
49
+ for (let i = 0; i < numberOfContours; i++) {
50
+ if (endPtsOffset + i * 2 + 2 > view.byteLength) return null;
51
+ endPts.push(this.reader.getUint16(view, endPtsOffset + i * 2));
52
+ }
53
+
54
+ // Read instruction length and skip instructions
55
+ const instrLenOffset = endPtsOffset + numberOfContours * 2;
56
+ if (instrLenOffset + 2 > view.byteLength) return null;
57
+ const instructionLength = this.reader.getUint16(view, instrLenOffset);
58
+ const flagsOffset = instrLenOffset + 2 + instructionLength;
59
+ if (flagsOffset > view.byteLength) return null;
60
+
61
+ // Calculate number of points
62
+ const nPoints = endPts.length === 0 ? 0 : endPts[endPts.length - 1] + 1;
63
+ if (nPoints <= 0) return [];
64
+
65
+ // Parse flags
66
+ const flagsResult = this.parseFlags(view, nPoints, flagsOffset);
67
+ if (!flagsResult) return null;
68
+ const { flags, nextOffset: xCoordOffset } = flagsResult;
69
+
70
+ // Parse coordinates
71
+ const coordsResult = this.parseCoordinates(view, flags, xCoordOffset);
72
+ if (!coordsResult) return null;
73
+ const { points } = coordsResult;
74
+
75
+ // Split points into contours
76
+ const contours: Point[][] = [];
77
+ let startIndex = 0;
78
+ for (let c = 0; c < numberOfContours; c++) {
79
+ const endIndex = endPts[c];
80
+ if (endIndex < startIndex || endIndex >= points.length) return null;
81
+ contours.push(points.slice(startIndex, endIndex + 1));
82
+ startIndex = endIndex + 1;
83
+ }
84
+
85
+ return contours;
86
+ }
87
+
88
+ /**
89
+ * Parses glyph flags with run-length encoding.
90
+ * @param view - DataView containing the glyph data
91
+ * @param nPoints - Number of points to read
92
+ * @param offset - Starting offset for flags
93
+ * @returns Flags array and next offset, or null if parsing fails
94
+ */
95
+ private parseFlags(
96
+ view: DataView,
97
+ nPoints: number,
98
+ offset: number
99
+ ): { flags: number[]; nextOffset: number } | null {
100
+ const flags: number[] = [];
101
+ let p = offset;
102
+
103
+ try {
104
+ while (flags.length < nPoints) {
105
+ if (p >= view.byteLength) return null;
106
+ const flag = this.reader.getUint8(view, p++);
107
+ flags.push(flag);
108
+
109
+ // Repeat flag (bit 3 set)
110
+ if (flag & 0x08) {
111
+ if (p >= view.byteLength) return null;
112
+ const repeatCount = this.reader.getUint8(view, p++);
113
+ for (let r = 0; r < repeatCount; r++) {
114
+ flags.push(flag);
115
+ }
116
+ }
117
+ }
118
+ } catch {
119
+ return null;
120
+ }
121
+
122
+ return { flags, nextOffset: p };
123
+ }
124
+
125
+ /**
126
+ * Parses glyph X and Y coordinates from delta values.
127
+ * @param view - DataView containing the glyph data
128
+ * @param flags - Flag array for each point
129
+ * @param offset - Starting offset for coordinates
130
+ * @returns Points array and next offset, or null if parsing fails
131
+ */
132
+ private parseCoordinates(
133
+ view: DataView,
134
+ flags: number[],
135
+ offset: number
136
+ ): { points: Point[]; nextOffset: number } | null {
137
+ const nPoints = flags.length;
138
+ const xs: number[] = new Array(nPoints);
139
+ const ys: number[] = new Array(nPoints);
140
+
141
+ let p = offset;
142
+
143
+ // Parse X coordinates (deltas)
144
+ try {
145
+ for (let i = 0; i < nPoints; i++) {
146
+ const f = flags[i];
147
+ if (f & 0x02) {
148
+ // X-Short Vector: 1-byte delta
149
+ if (p >= view.byteLength) return null;
150
+ const val = this.reader.getUint8(view, p++);
151
+ xs[i] = (f & 0x10) ? val : -val; // Bit 4: positive if set
152
+ } else {
153
+ if (f & 0x10) {
154
+ // X is same as previous (zero delta)
155
+ xs[i] = 0;
156
+ } else {
157
+ // 2-byte signed delta
158
+ if (p + 2 > view.byteLength) return null;
159
+ xs[i] = this.reader.getInt16(view, p);
160
+ p += 2;
161
+ }
162
+ }
163
+ }
164
+ } catch {
165
+ return null;
166
+ }
167
+
168
+ // Parse Y coordinates (deltas)
169
+ try {
170
+ for (let i = 0; i < nPoints; i++) {
171
+ const f = flags[i];
172
+ if (f & 0x04) {
173
+ // Y-Short Vector: 1-byte delta
174
+ if (p >= view.byteLength) return null;
175
+ const val = this.reader.getUint8(view, p++);
176
+ ys[i] = (f & 0x20) ? val : -val; // Bit 5: positive if set
177
+ } else {
178
+ if (f & 0x20) {
179
+ // Y is same as previous (zero delta)
180
+ ys[i] = 0;
181
+ } else {
182
+ // 2-byte signed delta
183
+ if (p + 2 > view.byteLength) return null;
184
+ ys[i] = this.reader.getInt16(view, p);
185
+ p += 2;
186
+ }
187
+ }
188
+ }
189
+ } catch {
190
+ return null;
191
+ }
192
+
193
+ // Convert deltas to absolute coordinates
194
+ const points: Point[] = new Array(nPoints);
195
+ let curX = 0;
196
+ let curY = 0;
197
+ for (let i = 0; i < nPoints; i++) {
198
+ curX += xs[i];
199
+ curY += ys[i];
200
+ points[i] = {
201
+ x: curX,
202
+ y: curY,
203
+ onCurve: !!(flags[i] & 0x01) // Bit 0: on-curve flag
204
+ };
205
+ }
206
+
207
+ return { points, nextOffset: p };
208
+ }
209
+
210
+ /**
211
+ * Converts contour points into glyph outline commands.
212
+ * Handles quadratic Bezier curves with consecutive off-curve points.
213
+ * @param contours - Array of contours
214
+ * @returns Array of glyph outline commands
215
+ */
216
+ private buildOutlineCommands(contours: Point[][]): GlyphOutlineCmd[] {
217
+ const cmds: GlyphOutlineCmd[] = [];
218
+
219
+ for (const contour of contours) {
220
+ if (contour.length === 0) continue;
221
+
222
+ const n = contour.length;
223
+ const getIdx = (i: number) => ((i % n) + n) % n; // Wrap-around index
224
+
225
+ // Find a starting on-curve point, if any
226
+ let startPtIndex = -1;
227
+ for (let i = 0; i < n; i++) {
228
+ if (contour[i].onCurve) {
229
+ startPtIndex = i;
230
+ break;
231
+ }
232
+ }
233
+
234
+ let firstPoint: Point;
235
+ let curIndex: number;
236
+
237
+ if (startPtIndex === -1) {
238
+ // No on-curve points: create implied on-curve between last and first off-curve
239
+ const p0 = contour[0];
240
+ const plast = contour[n - 1];
241
+ firstPoint = {
242
+ x: (plast.x + p0.x) / 2,
243
+ y: (plast.y + p0.y) / 2,
244
+ onCurve: true
245
+ };
246
+ curIndex = 0;
247
+ } else {
248
+ firstPoint = contour[startPtIndex];
249
+ curIndex = startPtIndex;
250
+ }
251
+
252
+ cmds.push({ type: "moveTo", x: firstPoint.x, y: firstPoint.y });
253
+
254
+ // Walk through contour points
255
+ let i = curIndex + 1;
256
+ let steps = 0;
257
+ while (steps < n) {
258
+ const idx = getIdx(i);
259
+ const pt = contour[idx];
260
+ const next = contour[getIdx(i + 1)];
261
+
262
+ if (pt.onCurve) {
263
+ // Straight line to on-curve point
264
+ cmds.push({ type: "lineTo", x: pt.x, y: pt.y });
265
+ } else {
266
+ // Off-curve point (quadratic control point)
267
+ if (next.onCurve) {
268
+ // Single control point -> quadratic curve
269
+ cmds.push({ type: "quadTo", cx: pt.x, cy: pt.y, x: next.x, y: next.y });
270
+ i++; // Consume next point
271
+ steps++;
272
+ } else {
273
+ // Consecutive off-curve points: create implied on-curve midpoint
274
+ const midx = (pt.x + next.x) / 2;
275
+ const midy = (pt.y + next.y) / 2;
276
+ cmds.push({ type: "quadTo", cx: pt.x, cy: pt.y, x: midx, y: midy });
277
+ }
278
+ }
279
+
280
+ i++;
281
+ steps++;
282
+ }
283
+
284
+ cmds.push({ type: "close" });
285
+ }
286
+
287
+ return cmds;
288
+ }
289
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Build ToUnicode CMap text from explicit gid->unicode mappings.
3
+ * Entries should be pre-sorted by gid for best compression but ordering is not required.
4
+ */
5
+ export function createToUnicodeCMapText(entries: { gid: number; unicode: number }[]): string {
6
+ if (!entries || entries.length === 0) {
7
+ return `/CIDInit /ProcSet findresource begin
8
+ 12 dict begin
9
+ begincmap
10
+ /CIDSystemInfo <<
11
+ /Registry (Adobe)
12
+ /Ordering (UCS)
13
+ /Supplement 0
14
+ >> def
15
+ /CMapName /Adobe-Identity-UCS def
16
+ /CMapType 2 def
17
+ 1 begincodespacerange
18
+ <0000> <FFFF>
19
+ endcodespacerange
20
+ endcmap
21
+ CMapName currentdict /CMap defineresource pop
22
+ end
23
+ end`;
24
+ }
25
+
26
+ const es = entries.slice().sort((a, b) => a.gid - b.gid);
27
+
28
+ const uniToUtf16Hex = (cp: number): string => {
29
+ if (cp <= 0xffff) {
30
+ return cp.toString(16).padStart(4, "0").toUpperCase();
31
+ }
32
+ const v = cp - 0x10000;
33
+ const hi = 0xd800 + (v >> 10);
34
+ const lo = 0xdc00 + (v & 0x3ff);
35
+ return hi.toString(16).padStart(4, "0").toUpperCase() + lo.toString(16).padStart(4, "0").toUpperCase();
36
+ };
37
+
38
+ // Build mapping directives (group consecutive linear runs into ranges)
39
+ type Mapping = { type: "range"; startG: number; endG: number; startU: number } | { type: "char"; gid: number; unicode: number };
40
+ const mappings: Mapping[] = [];
41
+ let i = 0;
42
+ while (i < es.length) {
43
+ const start = es[i];
44
+ let j = i + 1;
45
+ while (
46
+ j < es.length &&
47
+ es[j].gid === es[j - 1].gid + 1 &&
48
+ es[j].unicode === es[j - 1].unicode + 1
49
+ ) {
50
+ j++;
51
+ }
52
+ const runLen = j - i;
53
+ if (runLen >= 2) {
54
+ mappings.push({ type: "range", startG: start.gid, endG: es[j - 1].gid, startU: start.unicode });
55
+ i = j;
56
+ } else {
57
+ mappings.push({ type: "char", gid: start.gid, unicode: start.unicode });
58
+ i++;
59
+ }
60
+ }
61
+
62
+ const lines: string[] = [];
63
+ lines.push("/CIDInit /ProcSet findresource begin");
64
+ lines.push("12 dict begin");
65
+ lines.push("begincmap");
66
+ lines.push("/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def");
67
+ lines.push("/CMapName /Adobe-Identity-UCS def");
68
+ lines.push("/CMapType 2 def");
69
+ lines.push("1 begincodespacerange");
70
+ lines.push("<0000> <FFFF>");
71
+ lines.push("endcodespacerange");
72
+
73
+ const CHUNK = 100;
74
+ let p = 0;
75
+ while (p < mappings.length) {
76
+ const currentType = mappings[p].type;
77
+ const group: Mapping[] = [];
78
+ while (p < mappings.length && mappings[p].type === currentType && group.length < CHUNK) {
79
+ group.push(mappings[p]);
80
+ p++;
81
+ }
82
+
83
+ if (currentType === "char") {
84
+ lines.push(`${group.length} beginbfchar`);
85
+ for (const m of group as { type: "char"; gid: number; unicode: number }[]) {
86
+ const cid = m.gid.toString(16).padStart(4, "0").toUpperCase();
87
+ const uniHex = uniToUtf16Hex(m.unicode);
88
+ lines.push(`<${cid}> <${uniHex}>`);
89
+ }
90
+ lines.push("endbfchar");
91
+ } else {
92
+ lines.push(`${group.length} beginbfrange`);
93
+ for (const m of group as { type: "range"; startG: number; endG: number; startU: number }[]) {
94
+ const startCid = m.startG.toString(16).padStart(4, "0").toUpperCase();
95
+ const endCid = m.endG.toString(16).padStart(4, "0").toUpperCase();
96
+ const startUniHex = uniToUtf16Hex(m.startU);
97
+ lines.push(`<${startCid}> <${endCid}> <${startUniHex}>`);
98
+ }
99
+ lines.push("endbfrange");
100
+ }
101
+ }
102
+
103
+ lines.push("endcmap");
104
+ lines.push("CMapName currentdict /CMap defineresource pop");
105
+ lines.push("end");
106
+ lines.push("end");
107
+
108
+ return lines.join("\n");
109
+ }
@@ -0,0 +1,136 @@
1
+ import type { GlyphOutlineCmd } from "../../types/fonts.js";
2
+
3
+ /**
4
+ * Represents a 2D affine transformation matrix with translation.
5
+ * Used for transforming composite glyph components in TrueType fonts.
6
+ *
7
+ * Matrix form:
8
+ * | mxx myx tx |
9
+ * | mxy myy ty |
10
+ * | 0 0 1 |
11
+ */
12
+ export class TransformationMatrix {
13
+ constructor(
14
+ public readonly mxx: number = 1,
15
+ public readonly mxy: number = 0,
16
+ public readonly myx: number = 0,
17
+ public readonly myy: number = 1,
18
+ public readonly tx: number = 0,
19
+ public readonly ty: number = 0
20
+ ) { }
21
+
22
+ /**
23
+ * Creates an identity transformation matrix (no transformation).
24
+ */
25
+ static identity(): TransformationMatrix {
26
+ return new TransformationMatrix();
27
+ }
28
+
29
+ /**
30
+ * Creates a uniform scale transformation matrix.
31
+ * @param s - Scale factor for both X and Y axes
32
+ */
33
+ static scale(s: number): TransformationMatrix {
34
+ return new TransformationMatrix(s, 0, 0, s, 0, 0);
35
+ }
36
+
37
+ /**
38
+ * Creates a non-uniform scale transformation matrix.
39
+ * @param sx - Scale factor for X axis
40
+ * @param sy - Scale factor for Y axis
41
+ */
42
+ static scaleXY(sx: number, sy: number): TransformationMatrix {
43
+ return new TransformationMatrix(sx, 0, 0, sy, 0, 0);
44
+ }
45
+
46
+ /**
47
+ * Creates a translation transformation matrix.
48
+ * @param tx - Translation along X axis
49
+ * @param ty - Translation along Y axis
50
+ */
51
+ static translate(tx: number, ty: number): TransformationMatrix {
52
+ return new TransformationMatrix(1, 0, 0, 1, tx, ty);
53
+ }
54
+
55
+ /**
56
+ * Creates a transformation matrix from TrueType component transform data.
57
+ * @param tx - Translation X
58
+ * @param ty - Translation Y
59
+ * @param mxx - Matrix element (1,1)
60
+ * @param mxy - Matrix element (1,2)
61
+ * @param myx - Matrix element (2,1)
62
+ * @param myy - Matrix element (2,2)
63
+ */
64
+ static fromComponents(
65
+ tx: number,
66
+ ty: number,
67
+ mxx: number = 1,
68
+ mxy: number = 0,
69
+ myx: number = 0,
70
+ myy: number = 1
71
+ ): TransformationMatrix {
72
+ return new TransformationMatrix(mxx, mxy, myx, myy, tx, ty);
73
+ }
74
+
75
+ /**
76
+ * Transforms a single point using this matrix.
77
+ * @param x - X coordinate
78
+ * @param y - Y coordinate
79
+ * @returns Transformed coordinates
80
+ */
81
+ transformPoint(x: number, y: number): { x: number; y: number } {
82
+ return {
83
+ x: x * this.mxx + y * this.myx + this.tx,
84
+ y: x * this.mxy + y * this.myy + this.ty
85
+ };
86
+ }
87
+
88
+ /**
89
+ * Applies this transformation to a list of glyph outline commands.
90
+ * Creates new command objects with transformed coordinates.
91
+ * @param cmds - Original glyph outline commands
92
+ * @returns New array of transformed commands
93
+ */
94
+ applyToCommands(cmds: GlyphOutlineCmd[]): GlyphOutlineCmd[] {
95
+ const out: GlyphOutlineCmd[] = [];
96
+
97
+ for (const c of cmds) {
98
+ switch (c.type) {
99
+ case "moveTo": {
100
+ const { x, y } = this.transformPoint(c.x, c.y);
101
+ out.push({ type: "moveTo", x, y });
102
+ break;
103
+ }
104
+ case "lineTo": {
105
+ const { x, y } = this.transformPoint(c.x, c.y);
106
+ out.push({ type: "lineTo", x, y });
107
+ break;
108
+ }
109
+ case "quadTo": {
110
+ const cp = this.transformPoint(c.cx, c.cy);
111
+ const ep = this.transformPoint(c.x, c.y);
112
+ out.push({ type: "quadTo", cx: cp.x, cy: cp.y, x: ep.x, y: ep.y });
113
+ break;
114
+ }
115
+ case "cubicTo": {
116
+ const cp1 = this.transformPoint(c.cx1, c.cy1);
117
+ const cp2 = this.transformPoint(c.cx2, c.cy2);
118
+ const ep = this.transformPoint(c.x, c.y);
119
+ out.push({
120
+ type: "cubicTo",
121
+ cx1: cp1.x, cy1: cp1.y,
122
+ cx2: cp2.x, cy2: cp2.y,
123
+ x: ep.x, y: ep.y
124
+ });
125
+ break;
126
+ }
127
+ case "close": {
128
+ out.push({ type: "close" });
129
+ break;
130
+ }
131
+ }
132
+ }
133
+
134
+ return out;
135
+ }
136
+ }