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,270 @@
1
+ import type { GlyphOutlineCmd } from "../../types/fonts.js";
2
+
3
+ export interface BitmapMask {
4
+ width: number;
5
+ height: number;
6
+ data: Uint8ClampedArray; // alpha 0..255, length = width * height
7
+ // Offset (in px) from the glyph origin to the top-left of the bitmap
8
+ offsetX: number;
9
+ offsetY: number;
10
+ }
11
+
12
+ /**
13
+ * Flatten quadratic bezier adaptively.
14
+ * p0, p1, p2 in pixel coordinates.
15
+ */
16
+ function flattenQuadratic(p0: { x: number; y: number }, p1: { x: number; y: number }, p2: { x: number; y: number }, tol: number, out: { x: number; y: number }[]) {
17
+ // recursive subdivision
18
+ const stack: Array<{ x0: number; y0: number; cx: number; cy: number; x1: number; y1: number }> = [];
19
+ stack.push({ x0: p0.x, y0: p0.y, cx: p1.x, cy: p1.y, x1: p2.x, y1: p2.y });
20
+
21
+ while (stack.length > 0) {
22
+ const seg = stack.pop()!;
23
+
24
+ // approximate flatness: distance from control to chord
25
+ const ax = seg.x0, ay = seg.y0;
26
+ const bx = seg.x1, by = seg.y1;
27
+ const cx = seg.cx, cy = seg.cy;
28
+
29
+ // chord vector
30
+ const vx = bx - ax, vy = by - ay;
31
+ const len2 = vx * vx + vy * vy;
32
+ let dist = 0;
33
+ if (len2 === 0) {
34
+ // degenerate, distance from control to p0
35
+ const dx = cx - ax, dy = cy - ay;
36
+ dist = Math.hypot(dx, dy);
37
+ } else {
38
+ // projection factor of control onto chord
39
+ const t = ((cx - ax) * vx + (cy - ay) * vy) / len2;
40
+ const projx = ax + t * vx;
41
+ const projy = ay + t * vy;
42
+ dist = Math.hypot(cx - projx, cy - projy);
43
+ }
44
+
45
+ if (dist <= tol) {
46
+ // emit end point
47
+ out.push({ x: bx, y: by });
48
+ } else {
49
+ // subdivide into two quadratics using De Casteljau
50
+ const x01 = (ax + cx) / 2;
51
+ const y01 = (ay + cy) / 2;
52
+ const x12 = (cx + bx) / 2;
53
+ const y12 = (cy + by) / 2;
54
+ const x012 = (x01 + x12) / 2;
55
+ const y012 = (y01 + y12) / 2;
56
+
57
+ // push right then left so left is processed first
58
+ stack.push({ x0: x012, y0: y012, cx: x12, cy: y12, x1: bx, y1: by });
59
+ stack.push({ x0: ax, y0: ay, cx: x01, cy: y01, x1: x012, y1: y012 });
60
+ }
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Convert GlyphOutlineCmd sequence into flattened contours in pixel coordinates.
66
+ * - scale: pixels per font unit (fontSizePx / unitsPerEm)
67
+ * - tolPx: flatness tolerance in pixels (suggest 0.35..1.0)
68
+ */
69
+ export function flattenOutline(cmds: GlyphOutlineCmd[], scale: number, tolPx = 0.5): { contours: { x: number; y: number }[][] } {
70
+ const contours: { x: number; y: number }[][] = [];
71
+ let cursorX = 0;
72
+ let cursorY = 0;
73
+ // Use an always-array for curContour to avoid union narrowing issues in TS.
74
+ // Empty array means "no active contour".
75
+ let curContour: { x: number; y: number }[] = [];
76
+
77
+ const emitMove = (x: number, y: number) => {
78
+ if (curContour.length > 0) {
79
+ // implicit close previous
80
+ contours.push(curContour);
81
+ }
82
+ curContour = [{ x, y }];
83
+ cursorX = x;
84
+ cursorY = y;
85
+ };
86
+
87
+ const emitLine = (x: number, y: number) => {
88
+ if (!curContour) curContour = [{ x: cursorX, y: cursorY }];
89
+ curContour.push({ x, y });
90
+ cursorX = x;
91
+ cursorY = y;
92
+ };
93
+
94
+ const emitQuad = (cx: number, cy: number, x: number, y: number) => {
95
+ if (!curContour) curContour = [{ x: cursorX, y: cursorY }];
96
+ // subdivide from current cursor -> control -> x,y
97
+ const start = { x: cursorX, y: cursorY };
98
+ const ctrl = { x: cx, y: cy };
99
+ const end = { x: x, y: y };
100
+ // flattening writes successive points ending with end
101
+ flattenQuadratic(start, ctrl, end, tolPx, curContour);
102
+ cursorX = x;
103
+ cursorY = y;
104
+ };
105
+
106
+ for (const c of cmds) {
107
+ switch (c.type) {
108
+ case "moveTo": {
109
+ const x = c.x * scale;
110
+ const y = -c.y * scale; // flip Y to match layout/PDF coordinate (downward positive)
111
+ emitMove(x, y);
112
+ break;
113
+ }
114
+ case "lineTo": {
115
+ const x = c.x * scale;
116
+ const y = -c.y * scale;
117
+ emitLine(x, y);
118
+ break;
119
+ }
120
+ case "quadTo": {
121
+ const cx = c.cx * scale;
122
+ const cy = -c.cy * scale;
123
+ const x = c.x * scale;
124
+ const y = -c.y * scale;
125
+ emitQuad(cx, cy, x, y);
126
+ break;
127
+ }
128
+ case "cubicTo": {
129
+ // Not implementing cubic flattening for now - approximate by splitting into quads (simple approach)
130
+ // Convert cubic to two quadratics via degree reduction (rough) or fallback: sample with small steps
131
+ const steps = 8;
132
+ for (let i = 1; i <= steps; i++) {
133
+ const t = i / steps;
134
+ // cubic bezier evaluate using standard formula
135
+ const x = Math.pow(1 - t, 3) * (cursorX) + 3 * t * Math.pow(1 - t, 2) * (c.cx1 * scale) + 3 * t * t * (1 - t) * (c.cx2 * scale) + t * t * t * (c.x * scale);
136
+ const y = Math.pow(1 - t, 3) * (cursorY) + 3 * t * Math.pow(1 - t, 2) * (-c.cy1 * scale) + 3 * t * t * (1 - t) * (-c.cy2 * scale) + t * t * t * (-c.y * scale);
137
+ emitLine(x, y);
138
+ }
139
+ break;
140
+ }
141
+ case "close": {
142
+ if (curContour.length > 0) {
143
+ // ensure last point equals first (closed)
144
+ const first = curContour[0];
145
+ const last = curContour[curContour.length - 1];
146
+ if (Math.abs(first.x - last.x) > 1e-6 || Math.abs(first.y - last.y) > 1e-6) {
147
+ curContour.push({ x: first.x, y: first.y });
148
+ }
149
+ contours.push(curContour);
150
+ curContour = [];
151
+ }
152
+ break;
153
+ }
154
+ }
155
+ }
156
+
157
+ if (curContour.length > 0) {
158
+ // close if needed
159
+ const first = curContour[0];
160
+ const last = curContour[curContour.length - 1];
161
+ if (Math.abs(first.x - last.x) > 1e-6 || Math.abs(first.y - last.y) > 1e-6) {
162
+ curContour.push({ x: first.x, y: first.y });
163
+ }
164
+ contours.push(curContour);
165
+ }
166
+
167
+ return { contours };
168
+ }
169
+
170
+ /**
171
+ * Rasterize flattened contours using scanline even-odd fill on an integer high-res grid and downsample.
172
+ * - contours: array of closed polylines (points in pixel coordinates)
173
+ * - supersample: integer factor >=1
174
+ * Returns alpha bitmap in target pixels.
175
+ */
176
+ export function rasterizeContours(contours: { x: number; y: number }[][], supersample = 4): BitmapMask | null {
177
+ if (!contours || contours.length === 0) return null;
178
+
179
+ // compute bounding box
180
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
181
+ for (const c of contours) {
182
+ for (const p of c) {
183
+ if (p.x < minX) minX = p.x;
184
+ if (p.y < minY) minY = p.y;
185
+ if (p.x > maxX) maxX = p.x;
186
+ if (p.y > maxY) maxY = p.y;
187
+ }
188
+ }
189
+
190
+ if (!isFinite(minX) || !isFinite(minY)) return null;
191
+
192
+ // Add small padding so strokes at edge are visible
193
+ const pad = 1;
194
+ minX = Math.floor(minX) - pad;
195
+ minY = Math.floor(minY) - pad;
196
+ maxX = Math.ceil(maxX) + pad;
197
+ maxY = Math.ceil(maxY) + pad;
198
+
199
+ const width = maxX - minX;
200
+ const height = maxY - minY;
201
+ if (width <= 0 || height <= 0) return null;
202
+
203
+ const hiW = width * supersample;
204
+ const hiH = height * supersample;
205
+ // allocate high-res buffer (byte per pixel)
206
+ const hi = new Uint8ClampedArray(hiW * hiH);
207
+
208
+ // For each scanline in high-res, compute intersections with edges
209
+ for (let y = 0; y < hiH; y++) {
210
+ const fy = minY + y / supersample + 0.5 / supersample; // sample at center of hi-pixel
211
+ const intersections: number[] = [];
212
+
213
+ for (const contour of contours) {
214
+ for (let i = 0; i < contour.length - 1; i++) {
215
+ const a = contour[i];
216
+ const b = contour[i + 1];
217
+ const y0 = a.y;
218
+ const y1 = b.y;
219
+ // skip horizontal edges or scanlines outside edge bounds
220
+ if (y0 === y1) continue;
221
+ // include when fy is >= min(y0,y1) and < max(y0,y1) (half-open)
222
+ const ymin = Math.min(y0, y1);
223
+ const ymax = Math.max(y0, y1);
224
+ if (fy < ymin || fy >= ymax) continue;
225
+ const t = (fy - y0) / (y1 - y0);
226
+ const ix = a.x + t * (b.x - a.x);
227
+ intersections.push(ix);
228
+ }
229
+ }
230
+
231
+ if (intersections.length === 0) continue;
232
+ intersections.sort((a, b) => a - b);
233
+
234
+ // fill between pairs
235
+ for (let k = 0; k < intersections.length; k += 2) {
236
+ const x0 = intersections[k];
237
+ const x1 = intersections[k + 1];
238
+ if (x1 === undefined) break;
239
+ // convert to high-res x indices
240
+ const hiX0 = Math.max(0, Math.floor((x0 - minX) * supersample));
241
+ const hiX1 = Math.min(hiW, Math.ceil((x1 - minX) * supersample));
242
+ if (hiX1 <= hiX0) continue;
243
+ const base = y * hiW;
244
+ for (let hx = hiX0; hx < hiX1; hx++) hi[base + hx] = 255;
245
+ }
246
+ }
247
+
248
+ // Downsample hi -> target
249
+ const outW = width;
250
+ const outH = height;
251
+ const out = new Uint8ClampedArray(outW * outH);
252
+
253
+ for (let ty = 0; ty < outH; ty++) {
254
+ for (let tx = 0; tx < outW; tx++) {
255
+ let sum = 0;
256
+ const startY = ty * supersample;
257
+ const startX = tx * supersample;
258
+ for (let sy = 0; sy < supersample; sy++) {
259
+ const row = (startY + sy) * hiW;
260
+ for (let sx = 0; sx < supersample; sx++) {
261
+ sum += hi[row + startX + sx];
262
+ }
263
+ }
264
+ const avg = Math.round(sum / (supersample * supersample));
265
+ out[ty * outW + tx] = avg;
266
+ }
267
+ }
268
+
269
+ return { width: outW, height: outH, data: out, offsetX: minX, offsetY: minY };
270
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Logic for mapping font families to base font names.
3
+ *
4
+ * This module handles the resolution of a font family + weight + style to a specific
5
+ * base font name (e.g., "Helvetica-Bold"). It considers:
6
+ * 1. CSS @font-face definitions
7
+ * 2. Base14 fallbacks
8
+ * 3. Font aliases
9
+ * 4. Generic families
10
+ */
11
+
12
+ import type { CSSFontFace } from "../../types.js";
13
+ import {
14
+ selectFaceForWeight,
15
+ baseFontFromFace,
16
+ } from "../../../css/font-face-parser.js";
17
+ import {
18
+ BASE_FONT_ALIASES,
19
+ BASE14_FALLBACKS,
20
+ BASE14_VARIANT_LOOKUP,
21
+ GENERIC_FAMILIES,
22
+ } from "../font-config.js";
23
+ import { applyWeightToBaseFont } from "./weight-style-applicator.js";
24
+
25
+ const DEFAULT_FONT = "Times New Roman";
26
+
27
+ /**
28
+ * Resolve a font family to a base font name.
29
+ *
30
+ * @param family - The requested font family
31
+ * @param weight - The requested font weight
32
+ * @param style - The requested font style
33
+ * @param allowEmbeddedAlias - Whether to allow mapping to embedded font aliases (e.g. Tinos)
34
+ * @param facesByFamily - Map of available @font-face definitions
35
+ * @returns The resolved base font name
36
+ */
37
+ export function resolveBaseFont(
38
+ family: string,
39
+ weight: number,
40
+ style: string | undefined,
41
+ allowEmbeddedAlias: boolean,
42
+ facesByFamily: Map<string, CSSFontFace[]>
43
+ ): string {
44
+ const faces = facesByFamily.get(family);
45
+ if (faces && faces.length > 0) {
46
+ const selectedFace = selectFaceForWeight(faces, weight);
47
+ if (selectedFace) {
48
+ const base = baseFontFromFace(selectedFace, BASE_FONT_ALIASES);
49
+ if (base) {
50
+ return applyWeightToBaseFont(base, weight, style);
51
+ }
52
+ }
53
+ }
54
+
55
+ if (!allowEmbeddedAlias) {
56
+ const base14Fallback = BASE14_FALLBACKS.get(family);
57
+ if (base14Fallback) {
58
+ return applyWeightToBaseFont(base14Fallback, weight, style);
59
+ }
60
+ }
61
+
62
+ const alias = BASE_FONT_ALIASES.get(family);
63
+ if (alias) {
64
+ const isAliasBase14 = BASE14_VARIANT_LOOKUP.has(alias.toLowerCase());
65
+ // When we can't embed fonts, avoid mapping to non-Base14 aliases (e.g. Tinos)
66
+ if (allowEmbeddedAlias || isAliasBase14) {
67
+ return applyWeightToBaseFont(alias, weight, style);
68
+ }
69
+ }
70
+
71
+ const generic = GENERIC_FAMILIES.get(family);
72
+ if (generic) {
73
+ return applyWeightToBaseFont(generic, weight, style);
74
+ }
75
+
76
+ return applyWeightToBaseFont(DEFAULT_FONT, weight, style);
77
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Logic for resolving font family stacks with aliases and fallbacks.
3
+ *
4
+ * This module handles the expansion of font family names into a stack of candidates,
5
+ * including aliases (e.g., "Arial" -> "Arimo") and generic families (e.g., "serif" -> "Tinos").
6
+ */
7
+
8
+ import { parseFamilyList, normalizeToken } from "../../../css/font-face-parser.js";
9
+ import { BASE_FONT_ALIASES, GENERIC_FAMILIES } from "../font-config.js";
10
+
11
+ /**
12
+ * Build a family stack enriched with aliases and generic fallbacks.
13
+ *
14
+ * @param family - The requested font family string (comma-separated)
15
+ * @param defaultStack - Default font stack to use if family is undefined/empty
16
+ * @returns Array of font family names including aliases and generics
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * buildAliasedFamilyStack("Times New Roman")
21
+ * // => ["Times New Roman", "Tinos", "serif"]
22
+ * ```
23
+ */
24
+ export function buildAliasedFamilyStack(family: string | undefined, defaultStack: string[] = []): string[] {
25
+ const baseStack = family ? parseFamilyList(family) : defaultStack;
26
+
27
+ return baseStack.flatMap((f) => {
28
+ const normalized = normalizeToken(f);
29
+ const alias = BASE_FONT_ALIASES.get(normalized);
30
+ const generic = GENERIC_FAMILIES.get(normalized);
31
+ return [f, alias, generic].filter((x): x is string => !!x);
32
+ });
33
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Logic for applying weight and style transformations to base font names.
3
+ *
4
+ * This module handles the complex logic of mapping a base font name + weight + style
5
+ * to a specific variant name (e.g., "Helvetica" + bold -> "Helvetica-Bold").
6
+ * It handles both Base14 standard fonts and generic font naming conventions.
7
+ */
8
+
9
+ import { isBoldFontWeight } from "../../../css/font-weight.js";
10
+ import { isItalicStyle } from "../../../css/font-face-parser.js";
11
+ import {
12
+ BASE14_FAMILY_VARIANTS,
13
+ detectBase14Family,
14
+ classifyBase14Variant,
15
+ type Base14Variant,
16
+ } from "../font-config.js";
17
+
18
+ /**
19
+ * Apply weight and style transformations to a base font name.
20
+ *
21
+ * @param baseFont - The base font name (e.g., "Helvetica", "Arial")
22
+ * @param weight - The requested font weight (100-900)
23
+ * @param style - The requested font style ("normal", "italic", "oblique")
24
+ * @returns The transformed font name (e.g., "Helvetica-Bold", "Arial-BoldItalic")
25
+ */
26
+ export function applyWeightToBaseFont(baseFont: string, weight: number, style?: string): string {
27
+ const wantsItalic = isItalicStyle(style);
28
+ const wantsBold = isBoldFontWeight(weight);
29
+
30
+ const base14Family = detectBase14Family(baseFont);
31
+ if (base14Family) {
32
+ const variants = BASE14_FAMILY_VARIANTS[base14Family];
33
+ const currentVariant = classifyBase14Variant(baseFont);
34
+ const targetVariant: Base14Variant =
35
+ wantsBold && wantsItalic ? "boldItalic"
36
+ : wantsBold ? "bold"
37
+ : wantsItalic ? "italic"
38
+ : "normal";
39
+
40
+ if (currentVariant === targetVariant) {
41
+ return baseFont;
42
+ }
43
+ return variants[targetVariant];
44
+ }
45
+
46
+ let result = baseFont;
47
+
48
+ if (wantsItalic && !/-italic$/i.test(result) && !/-oblique$/i.test(result)) {
49
+ result = `${result}-Italic`;
50
+ }
51
+
52
+ if (wantsBold && !/-bold$/i.test(result)) {
53
+ if (/-italic$/i.test(result)) {
54
+ result = result.replace(/-italic$/i, "");
55
+ } else if (/-oblique$/i.test(result)) {
56
+ result = result.replace(/-oblique$/i, "");
57
+ }
58
+
59
+ return wantsItalic ? `${result}-BoldItalic` : `${result}-Bold`;
60
+ }
61
+
62
+ return result;
63
+ }