@react-x11/components 0.9.0 → 0.11.0

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 (579) hide show
  1. package/README.md +10 -4
  2. package/dist/charts/node.d.ts +11 -1
  3. package/dist/charts/node.d.ts.map +1 -1
  4. package/dist/charts/node.js +44 -14
  5. package/dist/charts/node.js.map +1 -1
  6. package/dist/charts/render.d.ts +12 -3
  7. package/dist/charts/render.d.ts.map +1 -1
  8. package/dist/charts/render.js +94 -25
  9. package/dist/charts/render.js.map +1 -1
  10. package/dist/code/index.d.ts.map +1 -1
  11. package/dist/code/index.js +27 -24
  12. package/dist/code/index.js.map +1 -1
  13. package/dist/code-editor/completion.d.ts.map +1 -1
  14. package/dist/code-editor/completion.js +3 -2
  15. package/dist/code-editor/completion.js.map +1 -1
  16. package/dist/code-editor/index.d.ts.map +1 -1
  17. package/dist/code-editor/index.js +19 -0
  18. package/dist/code-editor/index.js.map +1 -1
  19. package/dist/code-editor/node.d.ts +177 -7
  20. package/dist/code-editor/node.d.ts.map +1 -1
  21. package/dist/code-editor/node.js +1329 -164
  22. package/dist/code-editor/node.js.map +1 -1
  23. package/dist/code-language/index.d.ts +1 -1
  24. package/dist/code-language/index.d.ts.map +1 -1
  25. package/dist/code-language/index.js +1 -1
  26. package/dist/code-language/index.js.map +1 -1
  27. package/dist/code-language/languages/glsl.d.ts.map +1 -1
  28. package/dist/code-language/languages/glsl.js +10 -2
  29. package/dist/code-language/languages/glsl.js.map +1 -1
  30. package/dist/code-language/languages/javascript.d.ts.map +1 -1
  31. package/dist/code-language/languages/javascript.js +18 -3
  32. package/dist/code-language/languages/javascript.js.map +1 -1
  33. package/dist/code-language/languages/json.d.ts.map +1 -1
  34. package/dist/code-language/languages/json.js +10 -2
  35. package/dist/code-language/languages/json.js.map +1 -1
  36. package/dist/code-language/languages/shell.d.ts.map +1 -1
  37. package/dist/code-language/languages/shell.js +10 -2
  38. package/dist/code-language/languages/shell.js.map +1 -1
  39. package/dist/code-language/languages/sql.d.ts.map +1 -1
  40. package/dist/code-language/languages/sql.js +20 -2
  41. package/dist/code-language/languages/sql.js.map +1 -1
  42. package/dist/code-language/runs.d.ts +31 -0
  43. package/dist/code-language/runs.d.ts.map +1 -1
  44. package/dist/code-language/runs.js +105 -0
  45. package/dist/code-language/runs.js.map +1 -1
  46. package/dist/code-language/stream.d.ts +22 -0
  47. package/dist/code-language/stream.d.ts.map +1 -1
  48. package/dist/code-language/stream.js +259 -9
  49. package/dist/code-language/stream.js.map +1 -1
  50. package/dist/code-language/types.d.ts +5 -4
  51. package/dist/code-language/types.d.ts.map +1 -1
  52. package/dist/codeblock/index.d.ts +26 -2
  53. package/dist/codeblock/index.d.ts.map +1 -1
  54. package/dist/codeblock/index.js +57 -4
  55. package/dist/codeblock/index.js.map +1 -1
  56. package/dist/flow/draw.d.ts +50 -0
  57. package/dist/flow/draw.d.ts.map +1 -1
  58. package/dist/flow/draw.js +132 -33
  59. package/dist/flow/draw.js.map +1 -1
  60. package/dist/flow/gl/color.d.ts +13 -0
  61. package/dist/flow/gl/color.d.ts.map +1 -0
  62. package/dist/flow/gl/color.js +82 -0
  63. package/dist/flow/gl/color.js.map +1 -0
  64. package/dist/flow/gl/index.d.ts +60 -0
  65. package/dist/flow/gl/index.d.ts.map +1 -0
  66. package/dist/flow/gl/index.js +283 -0
  67. package/dist/flow/gl/index.js.map +1 -0
  68. package/dist/flow/gl/pack.d.ts +133 -0
  69. package/dist/flow/gl/pack.d.ts.map +1 -0
  70. package/dist/flow/gl/pack.js +408 -0
  71. package/dist/flow/gl/pack.js.map +1 -0
  72. package/dist/flow/gl/renderer.d.ts +95 -0
  73. package/dist/flow/gl/renderer.d.ts.map +1 -0
  74. package/dist/flow/gl/renderer.js +459 -0
  75. package/dist/flow/gl/renderer.js.map +1 -0
  76. package/dist/flow/gl/shaders.d.ts +79 -0
  77. package/dist/flow/gl/shaders.d.ts.map +1 -0
  78. package/dist/flow/gl/shaders.js +346 -0
  79. package/dist/flow/gl/shaders.js.map +1 -0
  80. package/dist/flow/gl/text.d.ts +318 -0
  81. package/dist/flow/gl/text.d.ts.map +1 -0
  82. package/dist/flow/gl/text.js +1103 -0
  83. package/dist/flow/gl/text.js.map +1 -0
  84. package/dist/flow/index.d.ts +1 -1
  85. package/dist/flow/index.d.ts.map +1 -1
  86. package/dist/flow/index.js +619 -64
  87. package/dist/flow/index.js.map +1 -1
  88. package/dist/flow/node.d.ts +621 -72
  89. package/dist/flow/node.d.ts.map +1 -1
  90. package/dist/flow/node.js +2253 -1018
  91. package/dist/flow/node.js.map +1 -1
  92. package/dist/flow/paint.d.ts +35 -0
  93. package/dist/flow/paint.d.ts.map +1 -0
  94. package/dist/flow/paint.js +393 -0
  95. package/dist/flow/paint.js.map +1 -0
  96. package/dist/flow/paths.d.ts +14 -0
  97. package/dist/flow/paths.d.ts.map +1 -1
  98. package/dist/flow/paths.js +45 -19
  99. package/dist/flow/paths.js.map +1 -1
  100. package/dist/flow/scene.d.ts +584 -0
  101. package/dist/flow/scene.d.ts.map +1 -0
  102. package/dist/flow/scene.js +1453 -0
  103. package/dist/flow/scene.js.map +1 -0
  104. package/dist/flow/types.d.ts +111 -1
  105. package/dist/flow/types.d.ts.map +1 -1
  106. package/dist/html/controls.d.ts +28 -0
  107. package/dist/html/controls.d.ts.map +1 -1
  108. package/dist/html/controls.js +52 -2
  109. package/dist/html/controls.js.map +1 -1
  110. package/dist/html/css/calc.d.ts +14 -0
  111. package/dist/html/css/calc.d.ts.map +1 -0
  112. package/dist/html/css/calc.js +344 -0
  113. package/dist/html/css/calc.js.map +1 -0
  114. package/dist/html/css/cascade.d.ts +262 -6
  115. package/dist/html/css/cascade.d.ts.map +1 -1
  116. package/dist/html/css/cascade.js +1373 -67
  117. package/dist/html/css/cascade.js.map +1 -1
  118. package/dist/html/css/color.d.ts +23 -0
  119. package/dist/html/css/color.d.ts.map +1 -0
  120. package/dist/html/css/color.js +740 -0
  121. package/dist/html/css/color.js.map +1 -0
  122. package/dist/html/css/content.d.ts +92 -0
  123. package/dist/html/css/content.d.ts.map +1 -0
  124. package/dist/html/css/content.js +388 -0
  125. package/dist/html/css/content.js.map +1 -0
  126. package/dist/html/css/counter-styles.d.ts +76 -0
  127. package/dist/html/css/counter-styles.d.ts.map +1 -0
  128. package/dist/html/css/counter-styles.js +893 -0
  129. package/dist/html/css/counter-styles.js.map +1 -0
  130. package/dist/html/css/decode.d.ts +12 -0
  131. package/dist/html/css/decode.d.ts.map +1 -0
  132. package/dist/html/css/decode.js +116 -0
  133. package/dist/html/css/decode.js.map +1 -0
  134. package/dist/html/css/parse.d.ts +110 -10
  135. package/dist/html/css/parse.d.ts.map +1 -1
  136. package/dist/html/css/parse.js +1473 -180
  137. package/dist/html/css/parse.js.map +1 -1
  138. package/dist/html/css/style.d.ts +501 -15
  139. package/dist/html/css/style.d.ts.map +1 -1
  140. package/dist/html/css/style.js +3729 -206
  141. package/dist/html/css/style.js.map +1 -1
  142. package/dist/html/css/ua.d.ts.map +1 -1
  143. package/dist/html/css/ua.js +65 -16
  144. package/dist/html/css/ua.js.map +1 -1
  145. package/dist/html/css/values.d.ts +37 -3
  146. package/dist/html/css/values.d.ts.map +1 -1
  147. package/dist/html/css/values.js +122 -48
  148. package/dist/html/css/values.js.map +1 -1
  149. package/dist/html/css/vars.d.ts +52 -0
  150. package/dist/html/css/vars.d.ts.map +1 -0
  151. package/dist/html/css/vars.js +358 -0
  152. package/dist/html/css/vars.js.map +1 -0
  153. package/dist/html/dom.d.ts +30 -4
  154. package/dist/html/dom.d.ts.map +1 -1
  155. package/dist/html/dom.js +278 -17
  156. package/dist/html/dom.js.map +1 -1
  157. package/dist/html/fonts.d.ts +106 -0
  158. package/dist/html/fonts.d.ts.map +1 -0
  159. package/dist/html/fonts.js +565 -0
  160. package/dist/html/fonts.js.map +1 -0
  161. package/dist/html/gif.d.ts +15 -0
  162. package/dist/html/gif.d.ts.map +1 -0
  163. package/dist/html/gif.js +229 -0
  164. package/dist/html/gif.js.map +1 -0
  165. package/dist/html/index.d.ts +50 -11
  166. package/dist/html/index.d.ts.map +1 -1
  167. package/dist/html/index.js +115 -9
  168. package/dist/html/index.js.map +1 -1
  169. package/dist/html/layout/block.d.ts +226 -3
  170. package/dist/html/layout/block.d.ts.map +1 -1
  171. package/dist/html/layout/block.js +3077 -219
  172. package/dist/html/layout/block.js.map +1 -1
  173. package/dist/html/layout/boxes.d.ts +367 -17
  174. package/dist/html/layout/boxes.d.ts.map +1 -1
  175. package/dist/html/layout/boxes.js +1742 -182
  176. package/dist/html/layout/boxes.js.map +1 -1
  177. package/dist/html/layout/cache.d.ts +58 -0
  178. package/dist/html/layout/cache.d.ts.map +1 -0
  179. package/dist/html/layout/cache.js +224 -0
  180. package/dist/html/layout/cache.js.map +1 -0
  181. package/dist/html/layout/collapse.d.ts +45 -0
  182. package/dist/html/layout/collapse.d.ts.map +1 -0
  183. package/dist/html/layout/collapse.js +246 -0
  184. package/dist/html/layout/collapse.js.map +1 -0
  185. package/dist/html/layout/css-grid.d.ts +7 -0
  186. package/dist/html/layout/css-grid.d.ts.map +1 -0
  187. package/dist/html/layout/css-grid.js +900 -0
  188. package/dist/html/layout/css-grid.js.map +1 -0
  189. package/dist/html/layout/flex.d.ts.map +1 -1
  190. package/dist/html/layout/flex.js +1025 -89
  191. package/dist/html/layout/flex.js.map +1 -1
  192. package/dist/html/layout/floats.d.ts +45 -6
  193. package/dist/html/layout/floats.d.ts.map +1 -1
  194. package/dist/html/layout/floats.js +113 -14
  195. package/dist/html/layout/floats.js.map +1 -1
  196. package/dist/html/layout/grid-lines.d.ts +39 -0
  197. package/dist/html/layout/grid-lines.d.ts.map +1 -0
  198. package/dist/html/layout/grid-lines.js +119 -0
  199. package/dist/html/layout/grid-lines.js.map +1 -0
  200. package/dist/html/layout/grid.d.ts +53 -0
  201. package/dist/html/layout/grid.d.ts.map +1 -0
  202. package/dist/html/layout/grid.js +153 -0
  203. package/dist/html/layout/grid.js.map +1 -0
  204. package/dist/html/layout/inline.d.ts +154 -1
  205. package/dist/html/layout/inline.d.ts.map +1 -1
  206. package/dist/html/layout/inline.js +3598 -175
  207. package/dist/html/layout/inline.js.map +1 -1
  208. package/dist/html/layout/shaping.d.ts +6 -0
  209. package/dist/html/layout/shaping.d.ts.map +1 -0
  210. package/dist/html/layout/shaping.js +100 -0
  211. package/dist/html/layout/shaping.js.map +1 -0
  212. package/dist/html/layout/table.d.ts +3 -0
  213. package/dist/html/layout/table.d.ts.map +1 -1
  214. package/dist/html/layout/table.js +681 -175
  215. package/dist/html/layout/table.js.map +1 -1
  216. package/dist/html/layout/tracks.d.ts +44 -0
  217. package/dist/html/layout/tracks.d.ts.map +1 -0
  218. package/dist/html/layout/tracks.js +349 -0
  219. package/dist/html/layout/tracks.js.map +1 -0
  220. package/dist/html/node.d.ts +169 -4
  221. package/dist/html/node.d.ts.map +1 -1
  222. package/dist/html/node.js +1429 -137
  223. package/dist/html/node.js.map +1 -1
  224. package/dist/html/paint.d.ts +92 -3
  225. package/dist/html/paint.d.ts.map +1 -1
  226. package/dist/html/paint.js +3635 -107
  227. package/dist/html/paint.js.map +1 -1
  228. package/dist/html/resources.d.ts +60 -14
  229. package/dist/html/resources.d.ts.map +1 -1
  230. package/dist/html/resources.js +122 -36
  231. package/dist/html/resources.js.map +1 -1
  232. package/dist/html/surfaces.d.ts +23 -0
  233. package/dist/html/surfaces.d.ts.map +1 -0
  234. package/dist/html/surfaces.js +68 -0
  235. package/dist/html/surfaces.js.map +1 -0
  236. package/dist/html/svg.d.ts +80 -0
  237. package/dist/html/svg.d.ts.map +1 -0
  238. package/dist/html/svg.js +442 -0
  239. package/dist/html/svg.js.map +1 -0
  240. package/dist/html/url.d.ts +23 -0
  241. package/dist/html/url.d.ts.map +1 -0
  242. package/dist/html/url.js +80 -0
  243. package/dist/html/url.js.map +1 -0
  244. package/dist/index.d.ts +1 -1
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js.map +1 -1
  247. package/dist/internal/codelines.d.ts +42 -0
  248. package/dist/internal/codelines.d.ts.map +1 -0
  249. package/dist/internal/codelines.js +170 -0
  250. package/dist/internal/codelines.js.map +1 -0
  251. package/dist/internal/collate.d.ts +3 -0
  252. package/dist/internal/collate.d.ts.map +1 -0
  253. package/dist/internal/collate.js +11 -0
  254. package/dist/internal/collate.js.map +1 -0
  255. package/dist/internal/markdown/ast.d.ts +11 -0
  256. package/dist/internal/markdown/ast.d.ts.map +1 -1
  257. package/dist/internal/markdown/parse.d.ts.map +1 -1
  258. package/dist/internal/markdown/parse.js +109 -8
  259. package/dist/internal/markdown/parse.js.map +1 -1
  260. package/dist/internal/prewarm.d.ts +18 -0
  261. package/dist/internal/prewarm.d.ts.map +1 -0
  262. package/dist/internal/prewarm.js +42 -0
  263. package/dist/internal/prewarm.js.map +1 -0
  264. package/dist/internal/sdf.d.ts +20 -0
  265. package/dist/internal/sdf.d.ts.map +1 -0
  266. package/dist/internal/sdf.js +216 -0
  267. package/dist/internal/sdf.js.map +1 -0
  268. package/dist/internal/splice.d.ts +12 -0
  269. package/dist/internal/splice.d.ts.map +1 -0
  270. package/dist/internal/splice.js +23 -0
  271. package/dist/internal/splice.js.map +1 -0
  272. package/dist/internal/window.d.ts +12 -0
  273. package/dist/internal/window.d.ts.map +1 -1
  274. package/dist/internal/window.js +23 -6
  275. package/dist/internal/window.js.map +1 -1
  276. package/dist/maps/anchors.d.ts +6 -1
  277. package/dist/maps/anchors.d.ts.map +1 -1
  278. package/dist/maps/anchors.js +260 -1
  279. package/dist/maps/anchors.js.map +1 -1
  280. package/dist/maps/controller.d.ts +57 -0
  281. package/dist/maps/controller.d.ts.map +1 -1
  282. package/dist/maps/controller.js +97 -18
  283. package/dist/maps/controller.js.map +1 -1
  284. package/dist/maps/gl/buckets.d.ts +5 -1
  285. package/dist/maps/gl/buckets.d.ts.map +1 -1
  286. package/dist/maps/gl/buckets.js +5 -2
  287. package/dist/maps/gl/buckets.js.map +1 -1
  288. package/dist/maps/gl/build-worker.d.ts +2 -0
  289. package/dist/maps/gl/build-worker.d.ts.map +1 -1
  290. package/dist/maps/gl/build-worker.js +1 -1
  291. package/dist/maps/gl/build-worker.js.map +1 -1
  292. package/dist/maps/gl/cover.d.ts +23 -4
  293. package/dist/maps/gl/cover.d.ts.map +1 -1
  294. package/dist/maps/gl/cover.js +61 -48
  295. package/dist/maps/gl/cover.js.map +1 -1
  296. package/dist/maps/gl/placement.d.ts +21 -8
  297. package/dist/maps/gl/placement.d.ts.map +1 -1
  298. package/dist/maps/gl/placement.js +133 -58
  299. package/dist/maps/gl/placement.js.map +1 -1
  300. package/dist/maps/gl/renderer.d.ts +36 -4
  301. package/dist/maps/gl/renderer.d.ts.map +1 -1
  302. package/dist/maps/gl/renderer.js +81 -24
  303. package/dist/maps/gl/renderer.js.map +1 -1
  304. package/dist/maps/gl/shaders.d.ts +18 -17
  305. package/dist/maps/gl/shaders.d.ts.map +1 -1
  306. package/dist/maps/gl/shaders.js +34 -32
  307. package/dist/maps/gl/shaders.js.map +1 -1
  308. package/dist/maps/gl/store.d.ts +10 -0
  309. package/dist/maps/gl/store.d.ts.map +1 -1
  310. package/dist/maps/gl/store.js +47 -4
  311. package/dist/maps/gl/store.js.map +1 -1
  312. package/dist/maps/gl/text.d.ts +153 -24
  313. package/dist/maps/gl/text.d.ts.map +1 -1
  314. package/dist/maps/gl/text.js +379 -63
  315. package/dist/maps/gl/text.js.map +1 -1
  316. package/dist/maps/gl/view.d.ts +293 -2
  317. package/dist/maps/gl/view.d.ts.map +1 -1
  318. package/dist/maps/gl/view.js +317 -82
  319. package/dist/maps/gl/view.js.map +1 -1
  320. package/dist/maps/icons.d.ts +32 -0
  321. package/dist/maps/icons.d.ts.map +1 -0
  322. package/dist/maps/icons.js +151 -0
  323. package/dist/maps/icons.js.map +1 -0
  324. package/dist/maps/index.d.ts +2 -0
  325. package/dist/maps/index.d.ts.map +1 -1
  326. package/dist/maps/index.js +2 -0
  327. package/dist/maps/index.js.map +1 -1
  328. package/dist/maps/labels.d.ts +56 -4
  329. package/dist/maps/labels.d.ts.map +1 -1
  330. package/dist/maps/labels.js +213 -46
  331. package/dist/maps/labels.js.map +1 -1
  332. package/dist/maps/node.d.ts +17 -0
  333. package/dist/maps/node.d.ts.map +1 -1
  334. package/dist/maps/node.js +64 -30
  335. package/dist/maps/node.js.map +1 -1
  336. package/dist/maps/proj.d.ts +48 -0
  337. package/dist/maps/proj.d.ts.map +1 -1
  338. package/dist/maps/proj.js +73 -0
  339. package/dist/maps/proj.js.map +1 -1
  340. package/dist/maps/sources.d.ts +5 -3
  341. package/dist/maps/sources.d.ts.map +1 -1
  342. package/dist/maps/sources.js +5 -3
  343. package/dist/maps/sources.js.map +1 -1
  344. package/dist/maps/style.d.ts +35 -0
  345. package/dist/maps/style.d.ts.map +1 -1
  346. package/dist/maps/style.js.map +1 -1
  347. package/dist/maps/styles.d.ts +12 -0
  348. package/dist/maps/styles.d.ts.map +1 -1
  349. package/dist/maps/styles.js +120 -6
  350. package/dist/maps/styles.js.map +1 -1
  351. package/dist/maps/tiles.d.ts +31 -11
  352. package/dist/maps/tiles.d.ts.map +1 -1
  353. package/dist/maps/tiles.js +61 -27
  354. package/dist/maps/tiles.js.map +1 -1
  355. package/dist/maps/types.d.ts +28 -4
  356. package/dist/maps/types.d.ts.map +1 -1
  357. package/dist/markdown/index.d.ts.map +1 -1
  358. package/dist/markdown/index.js +209 -68
  359. package/dist/markdown/index.js.map +1 -1
  360. package/dist/markdown/spans.d.ts.map +1 -1
  361. package/dist/markdown/spans.js +6 -0
  362. package/dist/markdown/spans.js.map +1 -1
  363. package/dist/qml/containers.d.ts.map +1 -1
  364. package/dist/qml/containers.js +6 -1
  365. package/dist/qml/containers.js.map +1 -1
  366. package/dist/qml/interaction.d.ts.map +1 -1
  367. package/dist/qml/interaction.js +38 -5
  368. package/dist/qml/interaction.js.map +1 -1
  369. package/dist/qml/layouts.d.ts.map +1 -1
  370. package/dist/qml/layouts.js +21 -6
  371. package/dist/qml/layouts.js.map +1 -1
  372. package/dist/qml/qtquick.d.ts.map +1 -1
  373. package/dist/qml/qtquick.js +9 -2
  374. package/dist/qml/qtquick.js.map +1 -1
  375. package/dist/qml/react.d.ts.map +1 -1
  376. package/dist/qml/react.js +9 -7
  377. package/dist/qml/react.js.map +1 -1
  378. package/dist/reorder/clock.d.ts +7 -0
  379. package/dist/reorder/clock.d.ts.map +1 -0
  380. package/dist/reorder/clock.js +26 -0
  381. package/dist/reorder/clock.js.map +1 -0
  382. package/dist/reorder/index.d.ts +25 -3
  383. package/dist/reorder/index.d.ts.map +1 -1
  384. package/dist/reorder/index.js +64 -19
  385. package/dist/reorder/index.js.map +1 -1
  386. package/dist/rich-text-editor/index.d.ts +0 -11
  387. package/dist/rich-text-editor/index.d.ts.map +1 -1
  388. package/dist/rich-text-editor/index.js +38 -9
  389. package/dist/rich-text-editor/index.js.map +1 -1
  390. package/dist/rich-text-editor/keymap.d.ts.map +1 -1
  391. package/dist/rich-text-editor/keymap.js +2 -1
  392. package/dist/rich-text-editor/keymap.js.map +1 -1
  393. package/dist/rich-text-editor/keys.d.ts +17 -6
  394. package/dist/rich-text-editor/keys.d.ts.map +1 -1
  395. package/dist/rich-text-editor/keys.js +135 -26
  396. package/dist/rich-text-editor/keys.js.map +1 -1
  397. package/dist/rich-text-editor/markdown.d.ts.map +1 -1
  398. package/dist/rich-text-editor/markdown.js +30 -1
  399. package/dist/rich-text-editor/markdown.js.map +1 -1
  400. package/dist/rich-text-editor/marks.d.ts +9 -0
  401. package/dist/rich-text-editor/marks.d.ts.map +1 -0
  402. package/dist/rich-text-editor/marks.js +83 -0
  403. package/dist/rich-text-editor/marks.js.map +1 -0
  404. package/dist/rich-text-editor/render.d.ts.map +1 -1
  405. package/dist/rich-text-editor/render.js +28 -10
  406. package/dist/rich-text-editor/render.js.map +1 -1
  407. package/dist/rich-text-editor/replace.d.ts +13 -0
  408. package/dist/rich-text-editor/replace.d.ts.map +1 -0
  409. package/dist/rich-text-editor/replace.js +64 -0
  410. package/dist/rich-text-editor/replace.js.map +1 -0
  411. package/dist/rich-text-editor/toolbar.d.ts.map +1 -1
  412. package/dist/rich-text-editor/toolbar.js +1 -1
  413. package/dist/rich-text-editor/toolbar.js.map +1 -1
  414. package/dist/rich-text-editor/virtual.d.ts.map +1 -1
  415. package/dist/rich-text-editor/virtual.js +17 -0
  416. package/dist/rich-text-editor/virtual.js.map +1 -1
  417. package/dist/richtext/node.d.ts +46 -2
  418. package/dist/richtext/node.d.ts.map +1 -1
  419. package/dist/richtext/node.js +187 -4
  420. package/dist/richtext/node.js.map +1 -1
  421. package/dist/richtext/runs.d.ts +13 -8
  422. package/dist/richtext/runs.d.ts.map +1 -1
  423. package/dist/richtext/runs.js +18 -8
  424. package/dist/richtext/runs.js.map +1 -1
  425. package/dist/table/index.d.ts.map +1 -1
  426. package/dist/table/index.js +23 -0
  427. package/dist/table/index.js.map +1 -1
  428. package/dist/table/rows.d.ts +3 -2
  429. package/dist/table/rows.d.ts.map +1 -1
  430. package/dist/table/rows.js +20 -6
  431. package/dist/table/rows.js.map +1 -1
  432. package/dist/terminal/index.d.ts.map +1 -1
  433. package/dist/terminal/index.js +4 -0
  434. package/dist/terminal/index.js.map +1 -1
  435. package/dist/terminal/vt/pty.d.ts +13 -2
  436. package/dist/terminal/vt/pty.d.ts.map +1 -1
  437. package/dist/terminal/vt/pty.js +18 -3
  438. package/dist/terminal/vt/pty.js.map +1 -1
  439. package/dist/terminal-output/index.d.ts.map +1 -1
  440. package/dist/terminal-output/index.js +103 -23
  441. package/dist/terminal-output/index.js.map +1 -1
  442. package/dist/terminal-output/runs.d.ts +4 -1
  443. package/dist/terminal-output/runs.d.ts.map +1 -1
  444. package/dist/terminal-output/runs.js +5 -1
  445. package/dist/terminal-output/runs.js.map +1 -1
  446. package/dist/three/canvas.d.ts.map +1 -1
  447. package/dist/three/canvas.js +85 -7
  448. package/dist/three/canvas.js.map +1 -1
  449. package/dist/three/events.d.ts +22 -4
  450. package/dist/three/events.d.ts.map +1 -1
  451. package/dist/three/events.js +34 -4
  452. package/dist/three/events.js.map +1 -1
  453. package/dist/tree/index.d.ts.map +1 -1
  454. package/dist/tree/index.js +17 -0
  455. package/dist/tree/index.js.map +1 -1
  456. package/package.json +42 -33
  457. package/src/charts/node.ts +62 -26
  458. package/src/charts/render.ts +120 -30
  459. package/src/code/index.ts +36 -32
  460. package/src/code-editor/completion.ts +3 -2
  461. package/src/code-editor/index.ts +19 -0
  462. package/src/code-editor/node.ts +1574 -184
  463. package/src/code-language/index.ts +1 -1
  464. package/src/code-language/languages/glsl.ts +12 -2
  465. package/src/code-language/languages/javascript.ts +21 -4
  466. package/src/code-language/languages/json.ts +12 -2
  467. package/src/code-language/languages/shell.ts +12 -2
  468. package/src/code-language/languages/sql.ts +22 -2
  469. package/src/code-language/runs.ts +111 -1
  470. package/src/code-language/stream.ts +257 -17
  471. package/src/code-language/types.ts +5 -4
  472. package/src/codeblock/index.ts +68 -4
  473. package/src/flow/draw.ts +167 -41
  474. package/src/flow/gl/color.ts +85 -0
  475. package/src/flow/gl/index.ts +342 -0
  476. package/src/flow/gl/pack.ts +585 -0
  477. package/src/flow/gl/renderer.ts +679 -0
  478. package/src/flow/gl/shaders.ts +371 -0
  479. package/src/flow/gl/text.ts +1295 -0
  480. package/src/flow/index.ts +794 -67
  481. package/src/flow/node.ts +2496 -1256
  482. package/src/flow/paint.ts +511 -0
  483. package/src/flow/paths.ts +80 -15
  484. package/src/flow/scene.ts +2199 -0
  485. package/src/flow/types.ts +113 -1
  486. package/src/html/controls.ts +73 -2
  487. package/src/html/css/calc.ts +385 -0
  488. package/src/html/css/cascade.ts +1481 -62
  489. package/src/html/css/color.ts +755 -0
  490. package/src/html/css/content.ts +417 -0
  491. package/src/html/css/counter-styles.ts +973 -0
  492. package/src/html/css/decode.ts +130 -0
  493. package/src/html/css/parse.ts +1514 -160
  494. package/src/html/css/style.ts +4131 -223
  495. package/src/html/css/ua.ts +66 -17
  496. package/src/html/css/values.ts +150 -50
  497. package/src/html/css/vars.ts +348 -0
  498. package/src/html/dom.ts +284 -17
  499. package/src/html/fonts.ts +641 -0
  500. package/src/html/gif.ts +233 -0
  501. package/src/html/index.ts +180 -20
  502. package/src/html/layout/block.ts +3560 -208
  503. package/src/html/layout/boxes.ts +2141 -190
  504. package/src/html/layout/cache.ts +289 -0
  505. package/src/html/layout/collapse.ts +317 -0
  506. package/src/html/layout/css-grid.ts +1063 -0
  507. package/src/html/layout/flex.ts +1115 -106
  508. package/src/html/layout/floats.ts +128 -14
  509. package/src/html/layout/grid-lines.ts +141 -0
  510. package/src/html/layout/grid.ts +181 -0
  511. package/src/html/layout/inline.ts +4187 -192
  512. package/src/html/layout/shaping.ts +140 -0
  513. package/src/html/layout/table.ts +696 -186
  514. package/src/html/layout/tracks.ts +437 -0
  515. package/src/html/node.ts +1585 -156
  516. package/src/html/paint.ts +4582 -267
  517. package/src/html/resources.ts +161 -50
  518. package/src/html/surfaces.ts +81 -0
  519. package/src/html/svg.ts +504 -0
  520. package/src/html/url.ts +86 -0
  521. package/src/index.ts +2 -0
  522. package/src/internal/codelines.ts +200 -0
  523. package/src/internal/collate.ts +12 -0
  524. package/src/internal/markdown/ast.ts +11 -0
  525. package/src/internal/markdown/parse.ts +154 -11
  526. package/src/internal/prewarm.ts +45 -0
  527. package/src/internal/sdf.ts +227 -0
  528. package/src/internal/splice.ts +25 -0
  529. package/src/internal/window.ts +36 -5
  530. package/src/maps/anchors.ts +307 -1
  531. package/src/maps/controller.ts +116 -31
  532. package/src/maps/gl/buckets.ts +5 -1
  533. package/src/maps/gl/build-worker.ts +13 -2
  534. package/src/maps/gl/cover.ts +79 -44
  535. package/src/maps/gl/placement.ts +221 -69
  536. package/src/maps/gl/renderer.ts +104 -20
  537. package/src/maps/gl/shaders.ts +35 -32
  538. package/src/maps/gl/store.ts +66 -17
  539. package/src/maps/gl/text.ts +444 -71
  540. package/src/maps/gl/view.ts +361 -96
  541. package/src/maps/icons.ts +183 -0
  542. package/src/maps/index.ts +4 -0
  543. package/src/maps/labels.ts +269 -49
  544. package/src/maps/node.ts +82 -49
  545. package/src/maps/proj.ts +87 -0
  546. package/src/maps/sources.ts +5 -3
  547. package/src/maps/style.ts +32 -0
  548. package/src/maps/styles.ts +215 -4
  549. package/src/maps/tiles.ts +64 -31
  550. package/src/maps/types.ts +28 -4
  551. package/src/markdown/index.ts +293 -92
  552. package/src/markdown/spans.ts +5 -0
  553. package/src/qml/containers.tsx +6 -1
  554. package/src/qml/interaction.tsx +42 -5
  555. package/src/qml/layouts.tsx +21 -6
  556. package/src/qml/qtquick.tsx +9 -2
  557. package/src/qml/react.tsx +7 -5
  558. package/src/reorder/clock.ts +27 -0
  559. package/src/reorder/index.ts +100 -27
  560. package/src/rich-text-editor/index.ts +37 -12
  561. package/src/rich-text-editor/keymap.ts +1 -1
  562. package/src/rich-text-editor/keys.ts +135 -26
  563. package/src/rich-text-editor/markdown.ts +36 -1
  564. package/src/rich-text-editor/marks.ts +101 -0
  565. package/src/rich-text-editor/render.ts +49 -12
  566. package/src/rich-text-editor/replace.ts +85 -0
  567. package/src/rich-text-editor/toolbar.ts +1 -1
  568. package/src/rich-text-editor/virtual.ts +25 -0
  569. package/src/richtext/node.ts +235 -14
  570. package/src/richtext/runs.ts +23 -12
  571. package/src/table/index.ts +29 -0
  572. package/src/table/rows.ts +18 -8
  573. package/src/terminal/index.ts +4 -0
  574. package/src/terminal/vt/pty.ts +16 -2
  575. package/src/terminal-output/index.ts +129 -31
  576. package/src/terminal-output/runs.ts +16 -2
  577. package/src/three/canvas.ts +102 -8
  578. package/src/three/events.ts +49 -9
  579. package/src/tree/index.ts +19 -0
@@ -0,0 +1,1103 @@
1
+ // Labels on the GPU: strings set by the platform's text engine, read back as
2
+ // coverage, kept as signed distance fields in one texture, and drawn as boxes
3
+ // that sample it.
4
+ //
5
+ // A `<glarea>` is stacked over everything 2D in its window, so a label on a
6
+ // GL graph has to be *in* the GL frame. The glyphs come from where every other
7
+ // string in the app does: `app.fonts.layout()` shapes it (CoreText on Cocoa,
8
+ // ntk's shaper on X11, fallback and all), the layout draws into an offscreen
9
+ // `Surface`, and the pixels come back — one readback per *batch*, not per
10
+ // label. What is kept is not that coverage but its distance field
11
+ // (`src/internal/sdf.ts`, the one `<Map>`'s labels are drawn from): a byte a
12
+ // texel, each texel's distance to the glyphs' edge, which the shader turns
13
+ // back into ink at whatever size the label is drawn (`./shaders.ts`). Shaped
14
+ // in white, because the colour is the shader's too, so one field serves
15
+ // every palette.
16
+ //
17
+ // **One field per string, at every size.** A graph zooms continuously and
18
+ // every label changes size with it. Coverage is exact for one size, so this
19
+ // atlas used to set every label again at each size a zoom came to rest at:
20
+ // ~580 strings after an eight-notch wheel zoom over a lattice, 80-120 ms of
21
+ // shaping, drawing and readback and 3.6 MB of texture, the labels drawn soft
22
+ // from the nearest size until the last batch landed ~170 ms after the wheel
23
+ // stopped. A field is set once, at `base`, and sharp at any size — every
24
+ // frame of a zoom gesture included — so a zoom asks the atlas for nothing.
25
+ // What that costs is the engine's hinting at the drawn size: the type is its
26
+ // outline, scaled, antialiased across one device pixel.
27
+ //
28
+ // So a label is also *measured* once, at the base size, and scaled: its box,
29
+ // and where it is cut to fit its card — `fitText`, the 2D painter's own, at
30
+ // the width the label's size allows. One string at every zoom is one field;
31
+ // a cut that moved by a character between two zooms would be a second.
32
+ // Advances are linear in size, so the cut is where the 2D painter makes it.
33
+ //
34
+ // Three things a graph needs that a map does not:
35
+ //
36
+ // - **Strings arrive a slice at a time, nearest the middle first.** A pan
37
+ // to an unseen part of the graph asks for hundreds at once. The world
38
+ // packs a box for every label, the ones still being set drawn as
39
+ // nothing (`GlyphQuad.ready`), and each frame writes in the fields that
40
+ // landed since the last (`FlowGlRenderer.landLabels`) — where the labels
41
+ // used to wait for the last of them and a world packed again.
42
+ // - **Nothing new while a zoom gesture moves** (`admit`). A zoom asks for
43
+ // nothing it has drawn before, but zooming out uncovers strings; they
44
+ // are set when it stops, as maps admit labels at rest. A single step —
45
+ // `setCenter`, a button — is not a gesture, and its labels are set at
46
+ // once.
47
+ // - **The atlas fills.** A world is built for three panes each way round
48
+ // the view, so a big graph zoomed out asks for many more strings than
49
+ // are on screen — 2,000 titles in the 2,000-node lattice at 0.6, where
50
+ // one page holds 660 at 2x. The texture's four channels are four pages,
51
+ // alpha first, so an atlas under the old limit is what it was. Past
52
+ // them, a field is dropped in place for a label nearer the view: first
53
+ // what no pack draws, then what is drawn farthest off screen, never
54
+ // what is on it (`room`). A box drawn from a dropped field is drawn as
55
+ // nothing until its field is back (`slotOf`), with no world packed
56
+ // again; a label that finds no room waits until the view moves.
57
+ import { Surface } from 'react-x11/ntk';
58
+ import { distanceField } from '../../internal/sdf.js';
59
+ import { fitText, shape } from '../draw.js';
60
+ /** The atlas texture's side, texels: 16 MB of RGBA, four pages of fields —
61
+ * some 8,000 titles at 1x and 2,600 at 2x. */
62
+ export const ATLAS_SIZE = 2048;
63
+ /** Pages in the texture: its four channels, each a field a texel. */
64
+ const PAGES = 4;
65
+ /** The channel each page is in: alpha first, which is where one page's
66
+ * fields went before there were pages. */
67
+ const CHANNELS = [3, 0, 1, 2];
68
+ /** Shelf heights round up to this many texels. */
69
+ const SHELF_STEP = 4;
70
+ /** The surface a batch is set on. A readback has to stay inside it. */
71
+ const STAGING_WIDTH = 1024;
72
+ const STAGING_HEIGHT = 512;
73
+ /** Strings per batch at most, and milliseconds of drawing one may take: a
74
+ * batch runs between frames. */
75
+ const BATCH = 48;
76
+ const DRAW_BUDGET_MS = 2;
77
+ /** Milliseconds of fields one slice may make — about a dozen strings at
78
+ * 1x — before the frames have the thread back. */
79
+ const FIELD_BUDGET_MS = 3;
80
+ /** Milliseconds of measuring new strings a world pack may spend, past the
81
+ * first: what is left is measured between frames. */
82
+ const SHAPE_BUDGET_MS = 4;
83
+ /**
84
+ * A label's request: its weight, its string, and the width it is cut to in
85
+ * device pixels at the base size — the same at every zoom, since a card's
86
+ * width and its label's size scale together, so one request resolves once.
87
+ */
88
+ function requestOf(t, texel) {
89
+ const fit = t.maxWidth
90
+ ? Math.round((t.maxWidth / texel) * 64) / 64
91
+ : undefined;
92
+ return { key: `${t.weight ?? 400}|${fit ?? ''}|${t.text}`, fit };
93
+ }
94
+ /**
95
+ * Texels the drawn quad leaves off each side of a field: a bilinear sample
96
+ * at its edge then stays inside the field's own margin, never reaching a
97
+ * neighbour's.
98
+ */
99
+ export const QUAD_INSET = 1;
100
+ /** The device size a display scale sets fields at: 16 at 1x, 32 at 2x. A
101
+ * card's title is 13 at zoom 1, so a field is mostly drawn at or under the
102
+ * size it was set at, where it is sharpest, and at twice it at the
103
+ * default `maxZoom` of 2.5. */
104
+ export const fieldBase = (scale) => Math.round(16 * Math.min(2, Math.max(1, scale)));
105
+ /**
106
+ * A field's margin and spread at a base size, texels. A graph's labels have
107
+ * no halo, so the field only has to reach as far as the antialiasing ramp
108
+ * of the smallest label drawn: a handle's 10 at `LABEL_ZOOM`, under a
109
+ * third of the base, is a ramp of 2.3 texels, and a sixth of the base
110
+ * reaches three. A quarter, which the first cut used, drew the same pixels
111
+ * to within 5/255 from fields 12% larger, whose every texel was made.
112
+ */
113
+ export const fieldPad = (base) => Math.ceil(base / 6);
114
+ /** The clock, through `globalThis`: `src/` compiles with `types: []`. */
115
+ const globals = globalThis;
116
+ const now = () => globals.performance?.now() ?? Date.now();
117
+ /**
118
+ * The next task: what lets a frame in between two slices. `setImmediate`,
119
+ * after the loop has polled for what came in — a frame's callback among it
120
+ * — where a timeout of 0 is a millisecond at least, idle, between every
121
+ * slice of a first appearance.
122
+ */
123
+ const nextTask = () => new Promise((resolve) => {
124
+ if (globals.setImmediate)
125
+ globals.setImmediate(resolve);
126
+ else if (globals.setTimeout)
127
+ globals.setTimeout(resolve, 0);
128
+ else
129
+ resolve();
130
+ });
131
+ export class LabelAtlas {
132
+ source;
133
+ /** Measured and shaped in white, at device size — the scale is 1 here,
134
+ * and a size is the base in device pixels — and cached apart from the
135
+ * pane's own text: nothing measured here is a size the pane draws. */
136
+ white;
137
+ /** The device size every field is set at: a label drawn at `size`
138
+ * scales its field by `size / base`. */
139
+ base;
140
+ /** The margin set round every field, texels, which is also the distance
141
+ * its values span — the shader's `u_spread`. */
142
+ pad;
143
+ entries = new Map();
144
+ /** Wanted and not yet set: key → what to set it from, and where the
145
+ * label nearest the view that asks for it is. */
146
+ missing = new Map();
147
+ /**
148
+ * Wanted, and waiting for room: the atlas is full of fields at least as
149
+ * near the view as these, so nothing is set for them until the view
150
+ * moves (`setView`) or a pack starts. Every key here is in `missing` too;
151
+ * what `wanting` counts is the rest.
152
+ */
153
+ stalled = new Set();
154
+ /**
155
+ * Requests measured: request → the string as cut. Measuring is what a
156
+ * label's first appearance costs the frame that packs it — 60-80 µs a
157
+ * string, on DirectWrite and on ntk alike, so a view of three hundred new
158
+ * labels was one frame 20 ms long before any of them could arrive. A pack
159
+ * measures for `shapeBudgetMs` and leaves the rest to the slices between
160
+ * frames; the ones it measured no pack measures again.
161
+ */
162
+ resolved = new Map();
163
+ /**
164
+ * What the pack under way has spent measuring, and how many strings it
165
+ * has measured — at least one a pack. Measuring alone is charged: a pack
166
+ * writes every edge before its first label, and a deadline from its start
167
+ * put off, after a zoom, labels whose cut had moved a fraction of a pixel
168
+ * and whose every measurement was cached.
169
+ */
170
+ spent = 0;
171
+ measured = 0;
172
+ /** Read back and waiting for their fields, oldest first — as wanted as
173
+ * anything in `missing`, so a pack does not ask for them again. */
174
+ fieldQueue = [];
175
+ queued = new Set();
176
+ /** The pages' shelves, and how far down each page they reach. */
177
+ shelves = [];
178
+ tops;
179
+ /** Pages in the texture: one per channel, alpha first. */
180
+ pages;
181
+ /**
182
+ * The whole texture, four bytes a texel, made when the first field goes
183
+ * on a page past the first. An upload writes every channel of the rect
184
+ * it covers, so from then on a field is uploaded from here, with the
185
+ * fields of the other pages under it. An atlas that never fills its first
186
+ * page never makes it: 16 MB, paid only past the old limit.
187
+ */
188
+ mirror = null;
189
+ /** The last placement found no room, and nothing has been freed since:
190
+ * a want that cannot evict is stalled before it is shaped. */
191
+ full = false;
192
+ /** Fields that may be dropped for a nearer one, farthest from the view
193
+ * first — made when first needed in a slice, and consumed in order. */
194
+ victims = null;
195
+ victimAt = 0;
196
+ /** Placements, counted: a field's `slot` changes whenever it lands, so a
197
+ * box drawn from an old one is found by comparing the two. */
198
+ nextSlot = 1;
199
+ staging = null;
200
+ stagingCtx = null;
201
+ busy = false;
202
+ /** Whether the layouts answer their own coverage (react-x11#673): unknown
203
+ * until the first string asks, and false for good once one does not. */
204
+ coverage = null;
205
+ /** Bumped whenever a field lands or is dropped — the renderer writes in
206
+ * what landed, and uploads, when it moves. */
207
+ generation = 0;
208
+ /** Bumped whenever a field is dropped: the renderer finds the boxes that
209
+ * drew from it (`slotOf`) and draws them as nothing until it is back. */
210
+ moves = 0;
211
+ /** Fields set are uploaded when the renderer next binds the atlas. */
212
+ pending = new Set();
213
+ /** Whether new strings may be set: false while the zoom is moving. */
214
+ admit = true;
215
+ /** Milliseconds of fields one slice may make, past the first field. */
216
+ fieldBudgetMs = FIELD_BUDGET_MS;
217
+ /** Milliseconds of measuring new strings a world pack may spend. */
218
+ shapeBudgetMs = SHAPE_BUDGET_MS;
219
+ texture = null;
220
+ textureGeneration = -1;
221
+ /** A field's rect as uploaded: widened to RGBA — the shader reads one
222
+ * channel, and a one-channel texture is a format GLES 2 and a core
223
+ * profile do not share. Grown to the largest field. */
224
+ scratch = new Uint8Array(0);
225
+ /** Counts world packs; an entry stamped with the current one is drawn. */
226
+ epoch = 0;
227
+ /** The texture's side, texels. */
228
+ side;
229
+ /** `side` and `pages` are for tests, which fill an atlas without setting
230
+ * thousands of labels. */
231
+ constructor(source, side = ATLAS_SIZE, pages = PAGES) {
232
+ this.source = source;
233
+ this.side = side;
234
+ this.pages = Math.max(1, Math.min(PAGES, pages));
235
+ this.tops = new Array(this.pages).fill(0);
236
+ this.base = fieldBase(source.options.scale);
237
+ this.pad = fieldPad(this.base);
238
+ this.white = {
239
+ ...source.options,
240
+ color: '#ffffff',
241
+ scale: 1,
242
+ cache: new Map(),
243
+ approximateText: false,
244
+ };
245
+ }
246
+ /**
247
+ * A world pack is starting: the labels it asks for are the ones drawn
248
+ * until the next — and **all** that is wanted. What earlier packs asked
249
+ * for and nothing has set is forgotten here: the strings a pan went past
250
+ * are not worth a batch once it has.
251
+ */
252
+ beginPack() {
253
+ this.epoch++;
254
+ this.missing.clear();
255
+ this.stalled.clear();
256
+ this.victims = null;
257
+ this.spent = 0;
258
+ this.measured = 0;
259
+ }
260
+ /**
261
+ * The view's centre, in the world's coordinates. What is wanted is set
262
+ * nearest it first: on a first appearance the labels arrive over a
263
+ * hundred milliseconds or more, and the ones in the middle of the view
264
+ * are the ones being read.
265
+ */
266
+ focus = null;
267
+ /** The view, in the world's coordinates — the surface says where each
268
+ * frame. Null draws everything as if it were on screen. */
269
+ view = null;
270
+ /**
271
+ * Where the view is now. A field on screen is never dropped for another;
272
+ * one off it is dropped for a label nearer the view, and a move of the
273
+ * view is what can make a stalled label nearer than one that is set.
274
+ */
275
+ setView(view) {
276
+ const v = this.view;
277
+ if (v === view ||
278
+ (v &&
279
+ view &&
280
+ v.x === view.x &&
281
+ v.y === view.y &&
282
+ v.width === view.width &&
283
+ v.height === view.height)) {
284
+ return;
285
+ }
286
+ this.view = view;
287
+ if (view) {
288
+ this.focus = { x: view.x + view.width / 2, y: view.y + view.height / 2 };
289
+ }
290
+ this.stalled.clear();
291
+ this.victims = null;
292
+ }
293
+ /** How far a rect is from the view, in the world's units: 0 on it. */
294
+ far(x, y, w, h) {
295
+ const v = this.view;
296
+ if (!v)
297
+ return 0;
298
+ const dx = Math.max(v.x - (x + w), x - (v.x + v.width), 0);
299
+ const dy = Math.max(v.y - (y + h), y - (v.y + v.height), 0);
300
+ return dx > dy ? dx + dy / 2 : dy + dx / 2;
301
+ }
302
+ /** How near a label is, for ordering what is wanted: from the view,
303
+ * then from its middle. */
304
+ nearness(x, y) {
305
+ const f = this.focus;
306
+ const d = f ? (x - f.x) * (x - f.x) + (y - f.y) * (y - f.y) : 0;
307
+ return [this.far(x, y, 0, 0), d];
308
+ }
309
+ /** A want moved to the label asking for it nearest the view. */
310
+ nearer(want, t) {
311
+ const [a, b] = this.nearness(want.x, want.y);
312
+ const [c, d] = this.nearness(t.x, t.y);
313
+ if (c < a || (c === a && d < b)) {
314
+ want.x = t.x;
315
+ want.y = t.y;
316
+ }
317
+ }
318
+ /**
319
+ * A label's quad, or null when there is nothing to draw it from yet —
320
+ * which asks for its field.
321
+ */
322
+ quad(t, lifted = false) {
323
+ // Logical pixels, at the scene's zoom, per device pixel at the base
324
+ // size: one texel of the field.
325
+ const texel = t.size / this.base;
326
+ if (!(texel > 0))
327
+ return null;
328
+ const request = requestOf(t, texel);
329
+ let shown = this.resolved.get(request.key);
330
+ if (shown === undefined) {
331
+ if (this.measured > 0 && this.spent > this.shapeBudgetMs) {
332
+ // Past the pack's budget: measured between frames, and the whole
333
+ // quad written in once its field lands (`landing`).
334
+ const key = `?${request.key}`;
335
+ const had = this.missing.get(key);
336
+ if (had)
337
+ this.nearer(had, t);
338
+ else {
339
+ this.missing.set(key, {
340
+ text: t.text,
341
+ weight: t.weight,
342
+ x: t.x,
343
+ y: t.y,
344
+ request: request.key,
345
+ fit: request.fit,
346
+ });
347
+ }
348
+ return {
349
+ key,
350
+ ready: false,
351
+ x: t.x,
352
+ y: t.y,
353
+ w: 0,
354
+ h: 0,
355
+ margin: 0,
356
+ texel,
357
+ page: 0,
358
+ slot: 0,
359
+ u0: 0,
360
+ v0: 0,
361
+ u1: 0,
362
+ v1: 0,
363
+ };
364
+ }
365
+ this.measured++;
366
+ const started = now();
367
+ shown = this.cut(t.text, t.weight, request.fit);
368
+ this.remember(request.key, shown);
369
+ if (shown) {
370
+ shape(this.white, shown, {
371
+ size: this.base,
372
+ weight: t.weight,
373
+ color: '#ffffff',
374
+ });
375
+ }
376
+ this.spent += now() - started;
377
+ }
378
+ if (!shown)
379
+ return null;
380
+ const style = {
381
+ size: this.base,
382
+ weight: t.weight,
383
+ color: '#ffffff',
384
+ };
385
+ const shaped = shape(this.white, shown, style);
386
+ if (!shaped)
387
+ return null;
388
+ const width = shaped.width * texel;
389
+ const height = shaped.height * texel;
390
+ // Placed as `Painter.text` places it: anchored by `align` and
391
+ // `baseline`, its top-left put on the device grid — by the shader here,
392
+ // after the pan's offset, which is where the grid is.
393
+ const dx = t.align === 'center' ? -width / 2 : t.align === 'right' ? -width : 0;
394
+ const dy = t.baseline === 'middle' ? -height / 2 : 0;
395
+ const key = `${t.weight ?? 400}|${shown}`;
396
+ const entry = this.entries.get(key);
397
+ const inset = QUAD_INSET;
398
+ if (!entry) {
399
+ if (!this.queued.has(key)) {
400
+ const had = this.missing.get(key);
401
+ if (had)
402
+ this.nearer(had, t);
403
+ else {
404
+ this.missing.set(key, {
405
+ text: shown,
406
+ weight: t.weight,
407
+ x: t.x,
408
+ y: t.y,
409
+ });
410
+ }
411
+ }
412
+ // Its field will be the layout box in whole pixels and the margin,
413
+ // which is known now: packed where it will be drawn, and drawn once
414
+ // its field lands.
415
+ return {
416
+ key,
417
+ ready: false,
418
+ x: t.x + dx,
419
+ y: t.y + dy,
420
+ w: (Math.ceil(shaped.width) + (this.pad - inset) * 2) * texel,
421
+ h: (Math.ceil(shaped.height) + (this.pad - inset) * 2) * texel,
422
+ margin: (this.pad - inset) * texel,
423
+ texel,
424
+ page: 0,
425
+ slot: 0,
426
+ u0: 0,
427
+ v0: 0,
428
+ u1: 0,
429
+ v1: 0,
430
+ };
431
+ }
432
+ const q = {
433
+ key,
434
+ ready: true,
435
+ x: t.x + dx,
436
+ y: t.y + dy,
437
+ w: (entry.width - inset * 2) * texel,
438
+ h: (entry.height - inset * 2) * texel,
439
+ margin: (this.pad - inset) * texel,
440
+ texel,
441
+ page: entry.page,
442
+ slot: entry.slot,
443
+ u0: (entry.x + inset) / this.side,
444
+ v0: (entry.y + inset) / this.side,
445
+ u1: (entry.x + entry.width - inset) / this.side,
446
+ v1: (entry.y + entry.height - inset) / this.side,
447
+ };
448
+ // Where it is drawn this pack, for how far from the view it is.
449
+ if (entry.used !== this.epoch) {
450
+ entry.used = this.epoch;
451
+ entry.at.length = 0;
452
+ }
453
+ if (lifted) {
454
+ entry.live = [q.x - q.margin, q.y - q.margin, q.w, q.h];
455
+ entry.liveAt = this.epoch;
456
+ }
457
+ else {
458
+ entry.at.push(q.x - q.margin, q.y - q.margin, q.w, q.h);
459
+ }
460
+ return q;
461
+ }
462
+ /**
463
+ * The quad a label packed before its field existed draws from, now that
464
+ * it can be drawn — null until then. One the pack did not measure (a `?`
465
+ * key) is placed now, from the string its request resolved to: the pack
466
+ * gave it a box of no size, and this is its whole quad.
467
+ */
468
+ landing(key, t, lifted = false) {
469
+ if (key.startsWith('?')) {
470
+ const shown = this.resolved.get(key.slice(1));
471
+ if (shown === undefined)
472
+ return null;
473
+ if (!this.entries.has(`${t.weight ?? 400}|${shown}`))
474
+ return null;
475
+ }
476
+ else if (!this.entries.has(key)) {
477
+ return null;
478
+ }
479
+ // measured and set: `quad` does no work but place it, and marks it
480
+ const q = this.quad(t, lifted);
481
+ return q?.ready ? q : null;
482
+ }
483
+ /** The placement a field is at now — -1 when it is not set — for a box
484
+ * to tell whether the field it was drawn from is still there. */
485
+ slotOf(key) {
486
+ return this.entries.get(key)?.slot ?? -1;
487
+ }
488
+ /** A field a drawn label lost, wanted again from where that label is. */
489
+ want(key, t) {
490
+ if (this.entries.has(key) || this.queued.has(key))
491
+ return;
492
+ const had = this.missing.get(key);
493
+ if (had) {
494
+ this.nearer(had, t);
495
+ return;
496
+ }
497
+ const bar = key.indexOf('|');
498
+ this.missing.set(key, {
499
+ text: key.slice(bar + 1),
500
+ weight: t.weight,
501
+ x: t.x,
502
+ y: t.y,
503
+ });
504
+ }
505
+ /** A string cut to the width it fits, measured at the base size. */
506
+ cut(text, weight, fit) {
507
+ if (fit === undefined)
508
+ return text;
509
+ const style = { size: this.base, weight, color: '#ffffff' };
510
+ return fitText(this.white, text, style, fit);
511
+ }
512
+ remember(request, shown) {
513
+ if (this.resolved.size > 20000)
514
+ this.resolved.clear();
515
+ this.resolved.set(request, shown);
516
+ }
517
+ /** No longer wanted: set, or given up on. */
518
+ unwant(key) {
519
+ this.missing.delete(key);
520
+ this.stalled.delete(key);
521
+ }
522
+ /**
523
+ * A request the pack left unmeasured, measured: its string cut and
524
+ * shaped, and wanted under its field's key from then on. Null when that
525
+ * field is set, being set or waiting for room already — the request is
526
+ * answered, and a frame writes its labels in.
527
+ */
528
+ resolve(key, want) {
529
+ if (want.request === undefined)
530
+ return { key, text: want.text, want };
531
+ this.unwant(key);
532
+ const shown = this.cut(want.text, want.weight, want.fit);
533
+ this.remember(want.request, shown);
534
+ if (!shown)
535
+ return null;
536
+ const field = `${want.weight ?? 400}|${shown}`;
537
+ if (this.entries.has(field) ||
538
+ this.queued.has(field) ||
539
+ this.stalled.has(field)) {
540
+ return null;
541
+ }
542
+ let wanted = this.missing.get(field);
543
+ if (wanted)
544
+ this.nearer(wanted, want);
545
+ else {
546
+ wanted = { ...want, text: shown, request: undefined };
547
+ this.missing.set(field, wanted);
548
+ }
549
+ return { key: field, text: shown, want: wanted };
550
+ }
551
+ /** What is wanted and not waiting for room, nearest the view first. */
552
+ wanted() {
553
+ const list = [];
554
+ for (const [key, want] of this.missing) {
555
+ if (this.stalled.has(key))
556
+ continue;
557
+ const [a, b] = this.nearness(want.x, want.y);
558
+ list.push([key, want, a, b]);
559
+ }
560
+ if (list.length > 1)
561
+ list.sort((p, q) => p[2] - q[2] || p[3] - q[3]);
562
+ return list.map(([key, want]) => [key, want]);
563
+ }
564
+ /** Whether any label drawn so far is still waiting for a field that can
565
+ * be set — not counting those waiting for room. */
566
+ get wanting() {
567
+ return this.fieldQueue.length > 0 || this.missing.size > this.stalled.size;
568
+ }
569
+ /**
570
+ * Whether a want this far from the view is worth shaping: not when the
571
+ * atlas is full and holds nothing farther to drop for it.
572
+ */
573
+ hopeful(distance) {
574
+ return !this.full || this.victim(distance) !== null;
575
+ }
576
+ /**
577
+ * One slice of setting what was asked for: fields for what was read back
578
+ * already, in a task of their own, or else one batch drawn and read back
579
+ * and the first of its fields. Resolves true when any field landed — the
580
+ * caller asks for a frame then, which draws what landed — and does
581
+ * nothing while one is already in flight,
582
+ * while the zoom is moving, or with nothing to set.
583
+ */
584
+ async pump() {
585
+ if (this.busy || !this.admit)
586
+ return false;
587
+ const fonts = this.source.options.fonts;
588
+ if (this.fieldQueue.length === 0 && (!this.wanting || !fonts)) {
589
+ return false;
590
+ }
591
+ this.busy = true;
592
+ try {
593
+ // A frame first, if one is waiting: every slice is a task of its own.
594
+ // A readback can answer at once (the Windows surface does), so a
595
+ // batch that set its fields in the same slice left nothing to wait
596
+ // on, and a whole appearance ran as one task — every label at the
597
+ // end of it, and no frame in between.
598
+ await nextTask();
599
+ // what may be dropped is worked out again: the view may have moved
600
+ this.victims = null;
601
+ if (this.fieldQueue.length > 0)
602
+ return this.makeFields();
603
+ if (!this.wanting)
604
+ return false;
605
+ if (this.coverage !== false) {
606
+ const landed = this.coverageSlice();
607
+ if (landed !== null)
608
+ return landed;
609
+ }
610
+ return await this.readBack();
611
+ }
612
+ finally {
613
+ this.busy = false;
614
+ }
615
+ }
616
+ /**
617
+ * One batch drawn onto the staging surface and read back, and the first
618
+ * of its fields: the way a string is set on an engine whose layouts do not
619
+ * answer their own coverage.
620
+ */
621
+ async readBack() {
622
+ if (!this.staging) {
623
+ this.staging = new Surface(this.source.app, {
624
+ width: STAGING_WIDTH,
625
+ height: STAGING_HEIGHT,
626
+ });
627
+ this.stagingCtx = this.staging.getContext('2d');
628
+ }
629
+ const staging = this.staging;
630
+ const ctx = this.stagingCtx;
631
+ staging.clear();
632
+ // Drawing and measuring are budgeted apart: a batch read back costs
633
+ // what it costs however few strings are in it, so measuring the ones
634
+ // the pack left out of the drawing's budget made the batches small and
635
+ // the readbacks many.
636
+ let drawing = 0;
637
+ let measuring = 0;
638
+ const pad = this.pad;
639
+ const placed = [];
640
+ let x = 0;
641
+ let y = 0;
642
+ let row = 0;
643
+ let answered = false;
644
+ for (const [asked, wanted] of this.wanted()) {
645
+ if (placed.length >= BATCH ||
646
+ drawing > DRAW_BUDGET_MS ||
647
+ measuring > this.shapeBudgetMs) {
648
+ break;
649
+ }
650
+ if (!this.hopeful(this.far(wanted.x, wanted.y, 0, 0))) {
651
+ this.stalled.add(asked);
652
+ continue;
653
+ }
654
+ const measured = now();
655
+ const want = this.resolve(asked, wanted);
656
+ if (!want) {
657
+ measuring += now() - measured;
658
+ answered = true;
659
+ continue;
660
+ }
661
+ const key = want.key;
662
+ const shaped = shape(this.white, want.text, {
663
+ size: this.base,
664
+ weight: wanted.weight,
665
+ color: '#ffffff',
666
+ });
667
+ measuring += now() - measured;
668
+ if (!shaped)
669
+ break;
670
+ const layout = shaped.layout;
671
+ const w = Math.ceil(layout.width) + pad * 2;
672
+ const h = Math.ceil(layout.height || this.base * 1.3) + pad * 2;
673
+ if (w > STAGING_WIDTH || h > STAGING_HEIGHT) {
674
+ // wider than anything can set: never drawn, and never asked again
675
+ this.unwant(key);
676
+ continue;
677
+ }
678
+ if (x + w > STAGING_WIDTH) {
679
+ x = 0;
680
+ y += row;
681
+ row = 0;
682
+ }
683
+ if (y + h > STAGING_HEIGHT)
684
+ break;
685
+ const drawn = now();
686
+ layout.draw(ctx, x + pad, y + pad);
687
+ drawing += now() - drawn;
688
+ placed.push({ key, want: want.want, x, y, w, h });
689
+ x += w;
690
+ row = Math.max(row, h);
691
+ }
692
+ if (placed.length === 0) {
693
+ if (!answered)
694
+ return false;
695
+ this.generation++;
696
+ return true;
697
+ }
698
+ const used = Math.max(...placed.map((p) => p.y + p.h));
699
+ const image = await ctx.getImageData(0, 0, STAGING_WIDTH, used);
700
+ for (const p of placed) {
701
+ this.unwant(p.key);
702
+ // Row by row, as the readback has them; the field reads alpha.
703
+ const rowBytes = p.w * 4;
704
+ const pixels = new Uint8Array(rowBytes * p.h);
705
+ for (let r = 0; r < p.h; r++) {
706
+ const src = ((p.y + r) * image.width + p.x) * 4;
707
+ pixels.set(image.data.subarray(src, src + rowBytes), r * rowBytes);
708
+ }
709
+ this.fieldQueue.push({
710
+ key: p.key,
711
+ width: p.w,
712
+ height: p.h,
713
+ pixels,
714
+ want: p.want,
715
+ });
716
+ this.queued.add(p.key);
717
+ }
718
+ if (this.makeFields())
719
+ return true;
720
+ if (!answered)
721
+ return false;
722
+ this.generation++;
723
+ return true;
724
+ }
725
+ /**
726
+ * One slice of strings set from their layouts' own coverage, where the
727
+ * engine answers it: no staging surface and no readback, so a string
728
+ * shaped this slice is a field this slice, until the budget is spent — at
729
+ * least one. Null when the layouts cannot answer, and the batches read
730
+ * back instead from then on.
731
+ */
732
+ coverageSlice() {
733
+ const started = now();
734
+ let landed = false;
735
+ let answered = false;
736
+ for (const [asked, wanted] of this.wanted()) {
737
+ if ((landed || answered) && now() - started >= this.fieldBudgetMs)
738
+ break;
739
+ const distance = this.far(wanted.x, wanted.y, 0, 0);
740
+ if (!this.hopeful(distance)) {
741
+ // Full of fields at least as near: not shaped, and not asked for
742
+ // again until the view moves.
743
+ this.stalled.add(asked);
744
+ continue;
745
+ }
746
+ const want = this.resolve(asked, wanted);
747
+ if (!want) {
748
+ answered = true;
749
+ continue;
750
+ }
751
+ const key = want.key;
752
+ const shaped = shape(this.white, want.text, {
753
+ size: this.base,
754
+ weight: wanted.weight,
755
+ color: '#ffffff',
756
+ });
757
+ const coverage = shaped?.layout.coverage?.({ pad: this.pad }) ?? null;
758
+ if (!coverage) {
759
+ if (landed || answered || this.coverage)
760
+ break;
761
+ this.coverage = false;
762
+ return null;
763
+ }
764
+ this.coverage = true;
765
+ if (coverage.width > STAGING_WIDTH || coverage.height > STAGING_HEIGHT) {
766
+ // wider than a batch could set: never drawn, as there
767
+ this.unwant(key);
768
+ continue;
769
+ }
770
+ const place = this.room(coverage.width, coverage.height, distance);
771
+ if (!place) {
772
+ this.stalled.add(key);
773
+ continue;
774
+ }
775
+ this.unwant(key);
776
+ const field = distanceField(coverage.data, coverage.width, coverage.height, this.pad, 1, 0);
777
+ landed = true;
778
+ this.put(key, place, coverage.width, coverage.height, field, want.want);
779
+ }
780
+ if (landed || answered)
781
+ this.generation++;
782
+ return landed || answered;
783
+ }
784
+ /**
785
+ * Fields for what was read back, oldest first, until the slice's budget
786
+ * is spent — at least one. A field is 0.1-0.4 ms (more texels at 2x);
787
+ * a batch's worth made as it landed was a frame held back.
788
+ */
789
+ makeFields() {
790
+ const started = now();
791
+ let landed = false;
792
+ while (this.fieldQueue.length > 0 &&
793
+ (!landed || now() - started < this.fieldBudgetMs)) {
794
+ const { key, width, height, pixels, want } = this.fieldQueue.shift();
795
+ this.queued.delete(key);
796
+ const place = this.room(width, height, this.far(want.x, want.y, 0, 0));
797
+ if (!place) {
798
+ // no room nearer than it: wanted again once the view moves
799
+ this.missing.set(key, want);
800
+ this.stalled.add(key);
801
+ continue;
802
+ }
803
+ const field = distanceField(pixels, width, height, this.pad);
804
+ landed = true;
805
+ this.put(key, place, width, height, field, want);
806
+ }
807
+ if (landed)
808
+ this.generation++;
809
+ return landed;
810
+ }
811
+ /**
812
+ * Room for a field of a label this far from the view: free room, or room
813
+ * made by dropping fields — first the ones no pack draws, then the ones
814
+ * drawn farthest from the view, so long as they are farther than it.
815
+ * Nothing on screen is dropped for anything. Null when there is none, and
816
+ * the atlas is `full` until something is freed.
817
+ */
818
+ room(w, h, distance) {
819
+ let place = this.allot(w, h) ?? this.squeeze(w, h);
820
+ while (!place) {
821
+ const v = this.victim(distance);
822
+ if (!v) {
823
+ this.full = true;
824
+ return null;
825
+ }
826
+ this.evict(v.key);
827
+ this.victimAt++;
828
+ place = this.allot(w, h) ?? this.squeeze(w, h);
829
+ }
830
+ return place;
831
+ }
832
+ /**
833
+ * Room made by sliding a shelf's fields together over its gaps: fields
834
+ * of one height are not one width — `node 7` and `node 1234` — and a
835
+ * narrow one dropped leaves a gap a wide one does not fit, so gaps apart
836
+ * are room nothing uses. The fields moved are new placements: a box
837
+ * drawn from one is written again from where it is now, in the same
838
+ * frame (`slotOf`).
839
+ */
840
+ squeeze(w, h) {
841
+ const height = Math.ceil(h / SHELF_STEP) * SHELF_STEP;
842
+ const shelf = this.shelves.find((s) => s.height === height &&
843
+ s.gaps.length > 0 &&
844
+ s.gaps.reduce((n, g) => n + g.w, this.side - s.end) >= w);
845
+ if (!shelf)
846
+ return null;
847
+ const on = [...this.entries]
848
+ .filter(([, e]) => e.shelf === shelf)
849
+ .sort((a, b) => a[1].x - b[1].x);
850
+ let x = 0;
851
+ for (const [key, e] of on) {
852
+ if (e.x !== x) {
853
+ e.x = x;
854
+ e.slot = this.nextSlot++;
855
+ this.pending.add(key);
856
+ if (this.mirror)
857
+ this.paint(e);
858
+ }
859
+ x += e.width;
860
+ }
861
+ shelf.gaps = [];
862
+ shelf.end = x;
863
+ this.moves++;
864
+ this.generation++;
865
+ return this.allot(w, h);
866
+ }
867
+ /** The next field that may go for a label this far from the view, or
868
+ * null — skipping the ones already gone, or set again since. */
869
+ victim(distance) {
870
+ if (!this.victims) {
871
+ const list = [];
872
+ for (const [key, e] of this.entries) {
873
+ const d = e.used < this.epoch ? Infinity : this.reach(e);
874
+ if (d > 0)
875
+ list.push({ key, d, used: e.used, entry: e });
876
+ }
877
+ list.sort((a, b) => b.d - a.d || a.used - b.used);
878
+ this.victims = list;
879
+ this.victimAt = 0;
880
+ }
881
+ const list = this.victims;
882
+ while (this.victimAt < list.length) {
883
+ const v = list[this.victimAt];
884
+ if (this.entries.get(v.key) !== v.entry) {
885
+ this.victimAt++;
886
+ continue;
887
+ }
888
+ return v.d > distance ? v : null;
889
+ }
890
+ return null;
891
+ }
892
+ /** How far from the view the nearest label drawn from a field is. */
893
+ reach(e) {
894
+ let d = e.live && e.liveAt === this.epoch
895
+ ? this.far(e.live[0], e.live[1], e.live[2], e.live[3])
896
+ : Infinity;
897
+ for (let i = 0; i < e.at.length && d > 0; i += 4) {
898
+ d = Math.min(d, this.far(e.at[i], e.at[i + 1], e.at[i + 2], e.at[i + 3]));
899
+ }
900
+ return d === Infinity ? 0 : d;
901
+ }
902
+ /** A field into the place made for it — drawn, until a pack says where,
903
+ * where the label that asked for it is. */
904
+ put(key, place, width, height, field, want) {
905
+ const entry = {
906
+ x: place.x,
907
+ y: place.shelf.y,
908
+ width,
909
+ height,
910
+ field,
911
+ // drawn as soon as its labels are written in
912
+ used: this.epoch,
913
+ at: [want.x, want.y, 0, 0],
914
+ live: null,
915
+ liveAt: -1,
916
+ page: place.shelf.page,
917
+ shelf: place.shelf,
918
+ slot: this.nextSlot++,
919
+ };
920
+ this.entries.set(key, entry);
921
+ if (entry.page > 0 && !this.mirror) {
922
+ this.mirror = new Uint8Array(this.side * this.side * 4);
923
+ for (const e of this.entries.values())
924
+ this.paint(e);
925
+ }
926
+ else if (this.mirror) {
927
+ this.paint(entry);
928
+ }
929
+ this.pending.add(key);
930
+ }
931
+ /** A field written into its channel of the mirror. */
932
+ paint(e) {
933
+ const m = this.mirror;
934
+ const channel = CHANNELS[e.page];
935
+ const side = this.side;
936
+ const field = e.field;
937
+ for (let r = 0; r < e.height; r++) {
938
+ let at = ((e.y + r) * side + e.x) * 4 + channel;
939
+ const row = r * e.width;
940
+ for (let c = 0; c < e.width; c++, at += 4)
941
+ m[at] = field[row + c];
942
+ }
943
+ }
944
+ /** A field dropped, and its room given back to its shelf. */
945
+ evict(key) {
946
+ const e = this.entries.get(key);
947
+ if (!e)
948
+ return;
949
+ this.entries.delete(key);
950
+ this.pending.delete(key);
951
+ this.free(e);
952
+ this.full = false;
953
+ this.moves++;
954
+ this.generation++;
955
+ }
956
+ /**
957
+ * Shelves by height, in steps: a label's field is as tall as the base
958
+ * size's line and the margin, so nearly every field is one height, and a
959
+ * field dropped leaves a gap the next one fits. The first fit in a gap,
960
+ * then the end of a shelf, then a new shelf — on the first page with
961
+ * room, alpha first.
962
+ */
963
+ allot(w, h) {
964
+ if (w > this.side || h > this.side)
965
+ return null;
966
+ const height = Math.ceil(h / SHELF_STEP) * SHELF_STEP;
967
+ for (const shelf of this.shelves) {
968
+ if (shelf.height !== height)
969
+ continue;
970
+ const gaps = shelf.gaps;
971
+ for (let i = 0; i < gaps.length; i++) {
972
+ const gap = gaps[i];
973
+ if (gap.w < w)
974
+ continue;
975
+ const x = gap.x;
976
+ gap.x += w;
977
+ gap.w -= w;
978
+ if (gap.w === 0)
979
+ gaps.splice(i, 1);
980
+ return { shelf, x };
981
+ }
982
+ }
983
+ for (const shelf of this.shelves) {
984
+ if (shelf.height !== height || shelf.end + w > this.side)
985
+ continue;
986
+ const x = shelf.end;
987
+ shelf.end += w;
988
+ return { shelf, x };
989
+ }
990
+ for (let page = 0; page < this.pages; page++) {
991
+ const y = this.tops[page];
992
+ if (y + height > this.side)
993
+ continue;
994
+ const shelf = { page, y, height, end: w, gaps: [] };
995
+ this.tops[page] = y + height;
996
+ this.shelves.push(shelf);
997
+ return { shelf, x: 0 };
998
+ }
999
+ return null;
1000
+ }
1001
+ /** A field's room back to its shelf, merged with the gaps beside it; a
1002
+ * shelf left empty at the bottom of its page goes back to the page. */
1003
+ free(e) {
1004
+ const shelf = e.shelf;
1005
+ const gaps = shelf.gaps;
1006
+ gaps.push({ x: e.x, w: e.width });
1007
+ gaps.sort((a, b) => a.x - b.x);
1008
+ let n = 0;
1009
+ for (const gap of gaps) {
1010
+ const last = n > 0 ? gaps[n - 1] : null;
1011
+ if (last && last.x + last.w === gap.x)
1012
+ last.w += gap.w;
1013
+ else
1014
+ gaps[n++] = gap;
1015
+ }
1016
+ gaps.length = n;
1017
+ const last = gaps[n - 1];
1018
+ if (last && last.x + last.w === shelf.end) {
1019
+ shelf.end = last.x;
1020
+ gaps.pop();
1021
+ }
1022
+ if (shelf.end === 0 &&
1023
+ gaps.length === 0 &&
1024
+ shelf.y + shelf.height === this.tops[shelf.page]) {
1025
+ this.tops[shelf.page] = shelf.y;
1026
+ this.shelves.splice(this.shelves.indexOf(shelf), 1);
1027
+ }
1028
+ }
1029
+ /**
1030
+ * The atlas texture, bound to unit 0, with every field set since the last
1031
+ * call uploaded into it. Made on first use — and made again for a new
1032
+ * context, into which every field is uploaded again from the copies kept
1033
+ * here.
1034
+ */
1035
+ bind(gl, fresh) {
1036
+ if (!this.texture || fresh) {
1037
+ this.texture = gl.createTexture();
1038
+ gl.bindTexture(gl.TEXTURE_2D, this.texture);
1039
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
1040
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.side, this.side, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.mirror);
1041
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
1042
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
1043
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
1044
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
1045
+ // the mirror went up whole; without one, every field goes up again
1046
+ if (this.mirror)
1047
+ this.pending.clear();
1048
+ else
1049
+ for (const key of this.entries.keys())
1050
+ this.pending.add(key);
1051
+ }
1052
+ gl.activeTexture(gl.TEXTURE0);
1053
+ gl.bindTexture(gl.TEXTURE_2D, this.texture);
1054
+ if (this.textureGeneration === this.generation && this.pending.size === 0) {
1055
+ return;
1056
+ }
1057
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
1058
+ const side = this.side;
1059
+ for (const key of this.pending) {
1060
+ const entry = this.entries.get(key);
1061
+ if (!entry)
1062
+ continue;
1063
+ const texels = entry.width * entry.height;
1064
+ if (this.scratch.length < texels * 4) {
1065
+ this.scratch = new Uint8Array(texels * 4).fill(255);
1066
+ }
1067
+ const rgba = this.scratch.subarray(0, texels * 4);
1068
+ const mirror = this.mirror;
1069
+ if (mirror) {
1070
+ // the rect as the mirror has it: this field, and the other pages'
1071
+ for (let r = 0; r < entry.height; r++) {
1072
+ const src = ((entry.y + r) * side + entry.x) * 4;
1073
+ rgba.set(mirror.subarray(src, src + entry.width * 4), r * entry.width * 4);
1074
+ }
1075
+ }
1076
+ else {
1077
+ // the first page alone: white, the field in alpha
1078
+ const field = entry.field;
1079
+ for (let i = 0; i < texels; i++) {
1080
+ rgba[i * 4] = 255;
1081
+ rgba[i * 4 + 1] = 255;
1082
+ rgba[i * 4 + 2] = 255;
1083
+ rgba[i * 4 + 3] = field[i];
1084
+ }
1085
+ }
1086
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, entry.x, entry.y, entry.width, entry.height, gl.RGBA, gl.UNSIGNED_BYTE, rgba);
1087
+ }
1088
+ this.pending.clear();
1089
+ this.textureGeneration = this.generation;
1090
+ }
1091
+ dispose(gl) {
1092
+ if (gl && this.texture)
1093
+ gl.deleteTexture(this.texture);
1094
+ this.texture = null;
1095
+ this.fieldQueue = [];
1096
+ this.queued.clear();
1097
+ this.stagingCtx?.destroy?.();
1098
+ this.stagingCtx = null;
1099
+ this.staging?.destroy();
1100
+ this.staging = null;
1101
+ }
1102
+ }
1103
+ //# sourceMappingURL=text.js.map