xbintsc 0.5.23 → 0.5.32

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 (481) hide show
  1. package/AGENTS.md +11 -2
  2. package/README.md +47 -16
  3. package/README.zh-CN.md +21 -2
  4. package/dist/scripts/support-matrix.d.ts +18 -0
  5. package/dist/scripts/support-matrix.js +141 -0
  6. package/dist/scripts/support-matrix.js.map +1 -0
  7. package/dist/src/ast/common.d.ts +2 -2
  8. package/dist/src/ast/declarations.d.ts +7 -1
  9. package/dist/src/ast/expressions.d.ts +5 -0
  10. package/dist/src/ast/kinds.d.ts +2 -0
  11. package/dist/src/ast/kinds.js +2 -0
  12. package/dist/src/ast/kinds.js.map +1 -1
  13. package/dist/src/binder/binder.d.ts +2 -1
  14. package/dist/src/binder/binder.js +2 -0
  15. package/dist/src/binder/binder.js.map +1 -1
  16. package/dist/src/binder/declarations.d.ts +9 -0
  17. package/dist/src/binder/declarations.js +64 -0
  18. package/dist/src/binder/declarations.js.map +1 -1
  19. package/dist/src/binder/references.js +99 -4
  20. package/dist/src/binder/references.js.map +1 -1
  21. package/dist/src/binder/types.d.ts +32 -0
  22. package/dist/src/binder/types.js.map +1 -1
  23. package/dist/src/canonical.d.ts +29 -0
  24. package/dist/src/canonical.js +35 -0
  25. package/dist/src/canonical.js.map +1 -0
  26. package/dist/src/checker/assignability.d.ts +13 -0
  27. package/dist/src/checker/assignability.js +146 -0
  28. package/dist/src/checker/assignability.js.map +1 -0
  29. package/dist/src/checker/calls.d.ts +13 -0
  30. package/dist/src/checker/calls.js +127 -0
  31. package/dist/src/checker/calls.js.map +1 -0
  32. package/dist/src/checker/checker.d.ts +26 -0
  33. package/dist/src/checker/checker.js +31 -0
  34. package/dist/src/checker/checker.js.map +1 -0
  35. package/dist/src/checker/declarations.d.ts +9 -0
  36. package/dist/src/checker/declarations.js +15 -0
  37. package/dist/src/checker/declarations.js.map +1 -0
  38. package/dist/src/checker/flow.d.ts +21 -0
  39. package/dist/src/checker/flow.js +241 -0
  40. package/dist/src/checker/flow.js.map +1 -0
  41. package/dist/src/checker/globals.d.ts +9 -0
  42. package/dist/src/checker/globals.js +29 -0
  43. package/dist/src/checker/globals.js.map +1 -0
  44. package/dist/src/checker/source.d.ts +38 -0
  45. package/dist/src/checker/source.js +48 -0
  46. package/dist/src/checker/source.js.map +1 -0
  47. package/dist/src/checker/type-infer.d.ts +18 -0
  48. package/dist/src/checker/type-infer.js +173 -0
  49. package/dist/src/checker/type-infer.js.map +1 -0
  50. package/dist/src/checker/type-model.d.ts +73 -0
  51. package/dist/src/checker/type-model.js +151 -0
  52. package/dist/src/checker/type-model.js.map +1 -0
  53. package/dist/src/checker/type-system.d.ts +58 -0
  54. package/dist/src/checker/type-system.js +569 -0
  55. package/dist/src/checker/type-system.js.map +1 -0
  56. package/dist/src/checker/typecheck-types.d.ts +22 -0
  57. package/dist/src/checker/typecheck-types.js +109 -0
  58. package/dist/src/checker/typecheck-types.js.map +1 -0
  59. package/dist/src/checker/typecheck.d.ts +62 -0
  60. package/dist/src/checker/typecheck.js +574 -0
  61. package/dist/src/checker/typecheck.js.map +1 -0
  62. package/dist/src/checker/undefined.d.ts +14 -0
  63. package/dist/src/checker/undefined.js +32 -0
  64. package/dist/src/checker/undefined.js.map +1 -0
  65. package/dist/src/checker/walk.d.ts +10 -0
  66. package/dist/src/checker/walk.js +15 -0
  67. package/dist/src/checker/walk.js.map +1 -0
  68. package/dist/src/cli/help.d.ts +7 -0
  69. package/dist/src/cli/help.js +64 -0
  70. package/dist/src/cli/help.js.map +1 -0
  71. package/dist/src/cli/hints.js +2 -1
  72. package/dist/src/cli/hints.js.map +1 -1
  73. package/dist/src/cli/main.js +12 -48
  74. package/dist/src/cli/main.js.map +1 -1
  75. package/dist/src/codegen/generator/calls/access.js +8 -8
  76. package/dist/src/codegen/generator/calls/access.js.map +1 -1
  77. package/dist/src/codegen/generator/calls/invocation.js +9 -4
  78. package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
  79. package/dist/src/codegen/generator/calls/super.d.ts +9 -1
  80. package/dist/src/codegen/generator/calls/super.js +56 -5
  81. package/dist/src/codegen/generator/calls/super.js.map +1 -1
  82. package/dist/src/codegen/generator/context.d.ts +13 -2
  83. package/dist/src/codegen/generator/context.js +25 -19
  84. package/dist/src/codegen/generator/context.js.map +1 -1
  85. package/dist/src/codegen/generator/debug.js +2 -1
  86. package/dist/src/codegen/generator/debug.js.map +1 -1
  87. package/dist/src/codegen/generator/expressions/primary.d.ts +4 -1
  88. package/dist/src/codegen/generator/expressions/primary.js +68 -8
  89. package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
  90. package/dist/src/codegen/generator/generator.js +11 -1
  91. package/dist/src/codegen/generator/generator.js.map +1 -1
  92. package/dist/src/codegen/generator/module.d.ts +3 -0
  93. package/dist/src/codegen/generator/module.js +116 -26
  94. package/dist/src/codegen/generator/module.js.map +1 -1
  95. package/dist/src/codegen/generator/state.d.ts +11 -1
  96. package/dist/src/codegen/generator/state.js.map +1 -1
  97. package/dist/src/codegen/generator/statements/variables.js +26 -7
  98. package/dist/src/codegen/generator/statements/variables.js.map +1 -1
  99. package/dist/src/codegen/generator/tables.d.ts +2 -0
  100. package/dist/src/codegen/generator/tables.js +4 -0
  101. package/dist/src/codegen/generator/tables.js.map +1 -1
  102. package/dist/src/driver/build-key.d.ts +2 -0
  103. package/dist/src/driver/build-key.js +1 -0
  104. package/dist/src/driver/build-key.js.map +1 -1
  105. package/dist/src/driver/bundler/graph.js +5 -1
  106. package/dist/src/driver/bundler/graph.js.map +1 -1
  107. package/dist/src/driver/bundler/merge.js +16 -1
  108. package/dist/src/driver/bundler/merge.js.map +1 -1
  109. package/dist/src/driver/bundler/types.d.ts +12 -0
  110. package/dist/src/driver/compiler.d.ts +1 -1
  111. package/dist/src/driver/compiler.js +3 -0
  112. package/dist/src/driver/compiler.js.map +1 -1
  113. package/dist/src/driver/fingerprint.js +2 -1
  114. package/dist/src/driver/fingerprint.js.map +1 -1
  115. package/dist/src/driver/frontend.d.ts +8 -6
  116. package/dist/src/driver/frontend.js +4 -0
  117. package/dist/src/driver/frontend.js.map +1 -1
  118. package/dist/src/driver/options.d.ts +6 -0
  119. package/dist/src/driver/version.d.ts +1 -1
  120. package/dist/src/driver/version.js +1 -1
  121. package/dist/src/extensions/gui/css.d.ts +26 -0
  122. package/dist/src/extensions/gui/css.js +100 -0
  123. package/dist/src/extensions/gui/css.js.map +1 -0
  124. package/dist/src/extensions/gui/html.js +28 -7
  125. package/dist/src/extensions/gui/html.js.map +1 -1
  126. package/dist/src/extensions/gui/index.js +79 -2
  127. package/dist/src/extensions/gui/index.js.map +1 -1
  128. package/dist/src/extensions/gui/three.d.ts +16 -0
  129. package/dist/src/extensions/gui/three.js +22 -0
  130. package/dist/src/extensions/gui/three.js.map +1 -0
  131. package/dist/src/extensions/media/index.d.ts +6 -5
  132. package/dist/src/extensions/media/index.js +12 -14
  133. package/dist/src/extensions/media/index.js.map +1 -1
  134. package/dist/src/extensions/registry.d.ts +38 -0
  135. package/dist/src/extensions/registry.js +10 -0
  136. package/dist/src/extensions/registry.js.map +1 -1
  137. package/dist/src/index.d.ts +1 -0
  138. package/dist/src/index.js +1 -0
  139. package/dist/src/index.js.map +1 -1
  140. package/dist/src/parser/declarations/classes.js +7 -0
  141. package/dist/src/parser/declarations/classes.js.map +1 -1
  142. package/dist/src/parser/expressions.js +14 -1
  143. package/dist/src/parser/expressions.js.map +1 -1
  144. package/dist/src/parser/literals.js +6 -2
  145. package/dist/src/parser/literals.js.map +1 -1
  146. package/dist/tests/binder/binder.test.js +29 -0
  147. package/dist/tests/binder/binder.test.js.map +1 -1
  148. package/dist/tests/canonical.test.d.ts +1 -0
  149. package/dist/tests/canonical.test.js +19 -0
  150. package/dist/tests/canonical.test.js.map +1 -0
  151. package/dist/tests/checker/checker.test.d.ts +1 -0
  152. package/dist/tests/checker/checker.test.js +245 -0
  153. package/dist/tests/checker/checker.test.js.map +1 -0
  154. package/dist/tests/cli/check.test.js +20 -0
  155. package/dist/tests/cli/check.test.js.map +1 -1
  156. package/dist/tests/conformance/matrix.test.d.ts +6 -0
  157. package/dist/tests/conformance/matrix.test.js +23 -0
  158. package/dist/tests/conformance/matrix.test.js.map +1 -0
  159. package/dist/tests/conformance/test262/manifest.d.ts +115 -0
  160. package/dist/tests/conformance/test262/manifest.js +257 -0
  161. package/dist/tests/conformance/test262/manifest.js.map +1 -0
  162. package/dist/tests/conformance/test262.test.d.ts +11 -0
  163. package/dist/tests/conformance/test262.test.js +74 -0
  164. package/dist/tests/conformance/test262.test.js.map +1 -0
  165. package/dist/tests/docs/structure.test.js +9 -11
  166. package/dist/tests/docs/structure.test.js.map +1 -1
  167. package/dist/tests/e2e/child-process.test.js +3 -2
  168. package/dist/tests/e2e/child-process.test.js.map +1 -1
  169. package/dist/tests/e2e/compile-builtins.test.js +45 -0
  170. package/dist/tests/e2e/compile-builtins.test.js.map +1 -1
  171. package/dist/tests/e2e/compile-objects-classes.test.js +77 -0
  172. package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
  173. package/dist/tests/e2e/differential-syntax.test.d.ts +5 -0
  174. package/dist/tests/e2e/differential-syntax.test.js +95 -0
  175. package/dist/tests/e2e/differential-syntax.test.js.map +1 -0
  176. package/dist/tests/e2e/differential-values.test.js +15 -0
  177. package/dist/tests/e2e/differential-values.test.js.map +1 -1
  178. package/dist/tests/e2e/gui-browser.test.d.ts +13 -0
  179. package/dist/tests/e2e/gui-browser.test.js +163 -0
  180. package/dist/tests/e2e/gui-browser.test.js.map +1 -0
  181. package/dist/tests/e2e/gui-effects.test.d.ts +6 -0
  182. package/dist/tests/e2e/gui-effects.test.js +262 -0
  183. package/dist/tests/e2e/gui-effects.test.js.map +1 -0
  184. package/dist/tests/e2e/gui-example-browser.test.js +2 -2
  185. package/dist/tests/e2e/gui-example-browser.test.js.map +1 -1
  186. package/dist/tests/e2e/gui-example-canvas.test.js +5 -4
  187. package/dist/tests/e2e/gui-example-canvas.test.js.map +1 -1
  188. package/dist/tests/e2e/gui-example-svg.test.js +4 -3
  189. package/dist/tests/e2e/gui-example-svg.test.js.map +1 -1
  190. package/dist/tests/e2e/gui-example-webgl.test.d.ts +10 -0
  191. package/dist/tests/e2e/gui-example-webgl.test.js +75 -0
  192. package/dist/tests/e2e/gui-example-webgl.test.js.map +1 -0
  193. package/dist/tests/e2e/gui-example-webgl2.test.d.ts +8 -0
  194. package/dist/tests/e2e/gui-example-webgl2.test.js +72 -0
  195. package/dist/tests/e2e/gui-example-webgl2.test.js.map +1 -0
  196. package/dist/tests/e2e/gui-example.test.js +4 -3
  197. package/dist/tests/e2e/gui-example.test.js.map +1 -1
  198. package/dist/tests/e2e/gui-helpers.js +4 -3
  199. package/dist/tests/e2e/gui-helpers.js.map +1 -1
  200. package/dist/tests/e2e/gui-layout.test.js +48 -0
  201. package/dist/tests/e2e/gui-layout.test.js.map +1 -1
  202. package/dist/tests/e2e/gui-media.test.js +10 -8
  203. package/dist/tests/e2e/gui-media.test.js.map +1 -1
  204. package/dist/tests/e2e/gui-webgl.test.d.ts +11 -0
  205. package/dist/tests/e2e/gui-webgl.test.js +179 -0
  206. package/dist/tests/e2e/gui-webgl.test.js.map +1 -0
  207. package/dist/tests/e2e/gui-webgl2.test.d.ts +10 -0
  208. package/dist/tests/e2e/gui-webgl2.test.js +238 -0
  209. package/dist/tests/e2e/gui-webgl2.test.js.map +1 -0
  210. package/dist/tests/e2e/harness.d.ts +9 -0
  211. package/dist/tests/e2e/harness.js +14 -2
  212. package/dist/tests/e2e/harness.js.map +1 -1
  213. package/dist/tests/e2e/native-extensions.test.js +2 -1
  214. package/dist/tests/e2e/native-extensions.test.js.map +1 -1
  215. package/dist/tests/e2e/property-descriptors.test.js +20 -0
  216. package/dist/tests/e2e/property-descriptors.test.js.map +1 -1
  217. package/dist/tests/e2e/unicode-output.test.js +5 -3
  218. package/dist/tests/e2e/unicode-output.test.js.map +1 -1
  219. package/dist/tests/e2e/weak-collections.test.js +16 -2
  220. package/dist/tests/e2e/weak-collections.test.js.map +1 -1
  221. package/dist/tests/extensions/gui.test.js +41 -0
  222. package/dist/tests/extensions/gui.test.js.map +1 -1
  223. package/dist/tests/extensions/media.test.js +7 -3
  224. package/dist/tests/extensions/media.test.js.map +1 -1
  225. package/dist/tests/helpers.d.ts +1 -0
  226. package/dist/tests/helpers.js +1 -0
  227. package/dist/tests/helpers.js.map +1 -1
  228. package/dist/tests/parser/declarations.test.js +20 -0
  229. package/dist/tests/parser/declarations.test.js.map +1 -1
  230. package/dist/tests/parser/expressions.test.js +36 -0
  231. package/dist/tests/parser/expressions.test.js.map +1 -1
  232. package/dist/tests/platform.d.ts +32 -0
  233. package/dist/tests/platform.js +40 -0
  234. package/dist/tests/platform.js.map +1 -0
  235. package/dist/tests/platform.test.d.ts +12 -0
  236. package/dist/tests/platform.test.js +51 -0
  237. package/dist/tests/platform.test.js.map +1 -0
  238. package/dist/tests/version.test.js +4 -4
  239. package/dist/tests/version.test.js.map +1 -1
  240. package/doc/ai/README.md +10 -4
  241. package/doc/ai/build-recipe.md +1 -0
  242. package/doc/ai/cli.md +17 -5
  243. package/doc/ai/contributing.md +59 -2
  244. package/doc/ai/extensions.md +38 -7
  245. package/doc/ai/language-support.md +25 -16
  246. package/doc/ai/troubleshooting.md +12 -8
  247. package/doc/ai/zh-CN/README.md +9 -4
  248. package/doc/ai/zh-CN/build-recipe.md +1 -0
  249. package/doc/ai/zh-CN/cli.md +13 -3
  250. package/doc/ai/zh-CN/contributing.md +49 -3
  251. package/doc/ai/zh-CN/extensions.md +33 -6
  252. package/doc/ai/zh-CN/language-support.md +23 -14
  253. package/doc/ai/zh-CN/troubleshooting.md +10 -6
  254. package/doc/gui/api.md +47 -1
  255. package/doc/gui/build.md +72 -16
  256. package/doc/gui/canvas.md +11 -3
  257. package/doc/gui/dom.md +33 -18
  258. package/doc/gui/known-issues.md +58 -15
  259. package/doc/gui/layout.md +18 -0
  260. package/doc/gui/media.md +17 -13
  261. package/doc/gui/rendering.md +50 -3
  262. package/doc/gui/runtime.md +18 -0
  263. package/doc/gui/webgl.md +256 -0
  264. package/doc/gui-scripts.md +7 -0
  265. package/doc/gui.md +108 -17
  266. package/doc/implemented/binder.md +2 -0
  267. package/doc/implemented/checker.md +117 -0
  268. package/doc/implemented/cli.md +13 -1
  269. package/doc/implemented/codegen.md +3 -2
  270. package/doc/implemented/driver.md +2 -2
  271. package/doc/implemented/operators.md +2 -1
  272. package/doc/implemented/parser.md +3 -2
  273. package/doc/implemented/pipeline.md +8 -1
  274. package/doc/implemented/stdlib.md +2 -1
  275. package/doc/implemented/tests.md +3 -1
  276. package/doc/implemented.md +2 -0
  277. package/doc/npm-package.md +419 -0
  278. package/doc/requirements.md +22 -10
  279. package/doc/support-matrix.md +83 -0
  280. package/doc/unimplemented/classes.md +3 -0
  281. package/doc/unimplemented/deviations.md +3 -2
  282. package/doc/unimplemented/toolchain.md +1 -1
  283. package/doc/unimplemented/types.md +24 -8
  284. package/doc/unimplemented.md +1 -1
  285. package/doc/zh-CN/gui/api.md +43 -1
  286. package/doc/zh-CN/gui/build.md +64 -15
  287. package/doc/zh-CN/gui/canvas.md +9 -2
  288. package/doc/zh-CN/gui/dom.md +20 -7
  289. package/doc/zh-CN/gui/known-issues.md +46 -13
  290. package/doc/zh-CN/gui/layout.md +14 -0
  291. package/doc/zh-CN/gui/media.md +15 -11
  292. package/doc/zh-CN/gui/rendering.md +41 -4
  293. package/doc/zh-CN/gui/runtime.md +16 -0
  294. package/doc/zh-CN/gui/webgl.md +115 -0
  295. package/doc/zh-CN/gui-scripts.md +5 -0
  296. package/doc/zh-CN/gui.md +89 -14
  297. package/doc/zh-CN/implemented/binder.md +2 -0
  298. package/doc/zh-CN/implemented/checker.md +99 -0
  299. package/doc/zh-CN/implemented/cli.md +12 -1
  300. package/doc/zh-CN/implemented/codegen.md +3 -2
  301. package/doc/zh-CN/implemented/driver.md +2 -2
  302. package/doc/zh-CN/implemented/operators.md +1 -1
  303. package/doc/zh-CN/implemented/parser.md +3 -2
  304. package/doc/zh-CN/implemented/pipeline.md +3 -1
  305. package/doc/zh-CN/implemented/stdlib.md +2 -1
  306. package/doc/zh-CN/implemented/tests.md +3 -1
  307. package/doc/zh-CN/implemented.md +2 -0
  308. package/doc/zh-CN/npm-package.md +394 -0
  309. package/doc/zh-CN/post/announce.md +47 -47
  310. package/doc/zh-CN/requirements.md +16 -7
  311. package/doc/zh-CN/support-matrix.md +82 -0
  312. package/doc/zh-CN/unimplemented/classes.md +3 -0
  313. package/doc/zh-CN/unimplemented/deviations.md +3 -2
  314. package/doc/zh-CN/unimplemented/toolchain.md +1 -1
  315. package/doc/zh-CN/unimplemented/types.md +16 -6
  316. package/doc/zh-CN/unimplemented.md +1 -1
  317. package/llms.txt +6 -1
  318. package/package.json +2 -1
  319. package/runtime/ext_gui/audio.cpp +316 -0
  320. package/runtime/ext_gui/browser.cpp +573 -0
  321. package/runtime/ext_gui/browser_escape.cpp +85 -0
  322. package/runtime/ext_gui/browser_loop.cpp +83 -0
  323. package/runtime/ext_gui/canvas.cpp +12 -21
  324. package/runtime/ext_gui/canvas_internal.h +10 -0
  325. package/runtime/ext_gui/canvas_raster.cpp +79 -1
  326. package/runtime/ext_gui/clip_values.cpp +246 -0
  327. package/runtime/ext_gui/css.cpp +94 -0
  328. package/runtime/ext_gui/css.h +22 -1
  329. package/runtime/ext_gui/css_match.cpp +3 -0
  330. package/runtime/ext_gui/css_selector.cpp +9 -0
  331. package/runtime/ext_gui/css_sheet.cpp +89 -45
  332. package/runtime/ext_gui/document.cpp +4 -1
  333. package/runtime/ext_gui/document.h +2 -0
  334. package/runtime/ext_gui/dom.h +16 -0
  335. package/runtime/ext_gui/dom_api.cpp +37 -0
  336. package/runtime/ext_gui/dom_api_canvas.cpp +17 -80
  337. package/runtime/ext_gui/dom_api_canvas_extra.cpp +130 -1
  338. package/runtime/ext_gui/dom_api_canvas_pending.cpp +41 -0
  339. package/runtime/ext_gui/dom_api_document.cpp +96 -5
  340. package/runtime/ext_gui/dom_api_events.cpp +20 -0
  341. package/runtime/ext_gui/dom_api_internal.h +278 -0
  342. package/runtime/ext_gui/dom_api_proto.cpp +6 -0
  343. package/runtime/ext_gui/dom_api_webgl.cpp +376 -0
  344. package/runtime/ext_gui/dom_api_webgl2.cpp +434 -0
  345. package/runtime/ext_gui/dom_api_webgl2_draw.cpp +269 -0
  346. package/runtime/ext_gui/dom_api_webgl_buffer.cpp +212 -0
  347. package/runtime/ext_gui/dom_api_webgl_rt.h +30 -0
  348. package/runtime/ext_gui/dom_api_webgl_shader.cpp +443 -0
  349. package/runtime/ext_gui/dom_api_webgl_state.cpp +444 -0
  350. package/runtime/ext_gui/dom_api_webgl_texture.cpp +445 -0
  351. package/runtime/ext_gui/effect_values.cpp +312 -0
  352. package/runtime/ext_gui/gradient_values.cpp +476 -0
  353. package/runtime/ext_gui/grid_values.cpp +230 -0
  354. package/runtime/ext_gui/gui.cpp +90 -23
  355. package/runtime/ext_gui/gui_canvas.cpp +50 -2
  356. package/runtime/ext_gui/gui_engine.h +71 -0
  357. package/runtime/ext_gui/gui_events.cpp +4 -1
  358. package/runtime/ext_gui/gui_media.cpp +1 -1
  359. package/runtime/ext_gui/gui_webgl.cpp +83 -0
  360. package/runtime/ext_gui/layout.cpp +21 -0
  361. package/runtime/ext_gui/layout_flow.cpp +81 -4
  362. package/runtime/ext_gui/layout_flow_internal.h +31 -0
  363. package/runtime/ext_gui/layout_grid.cpp +374 -0
  364. package/runtime/ext_gui/media.h +1 -1
  365. package/runtime/ext_gui/media_api.h +2 -2
  366. package/runtime/ext_gui/media_query.cpp +211 -0
  367. package/runtime/ext_gui/paint.cpp +111 -77
  368. package/runtime/ext_gui/paint.h +33 -3
  369. package/runtime/ext_gui/paint_background.cpp +229 -0
  370. package/runtime/ext_gui/paint_clip.cpp +268 -0
  371. package/runtime/ext_gui/paint_effects.cpp +324 -0
  372. package/runtime/ext_gui/paint_internal.h +85 -0
  373. package/runtime/ext_gui/renderer.cpp +8 -31
  374. package/runtime/ext_gui/renderer_clip.cpp +196 -0
  375. package/runtime/ext_gui/renderer_image.cpp +13 -8
  376. package/runtime/ext_gui/renderer_internal.h +15 -8
  377. package/runtime/ext_gui/renderer_text.cpp +6 -31
  378. package/runtime/ext_gui/style.cpp +343 -20
  379. package/runtime/ext_gui/style.h +144 -3
  380. package/runtime/ext_gui/style_print.cpp +134 -1
  381. package/runtime/ext_gui/style_values.cpp +152 -126
  382. package/runtime/ext_gui/style_values_internal.h +35 -0
  383. package/runtime/ext_gui/webgl.h +466 -0
  384. package/runtime/ext_gui/webgl2_constants.h +274 -0
  385. package/runtime/ext_gui/webgl_buffer.cpp +565 -0
  386. package/runtime/ext_gui/webgl_constants.h +317 -0
  387. package/runtime/ext_gui/webgl_context.cpp +466 -0
  388. package/runtime/ext_gui/webgl_draw.cpp +495 -0
  389. package/runtime/ext_gui/webgl_glsl.h +125 -0
  390. package/runtime/ext_gui/webgl_glsl_compile.cpp +431 -0
  391. package/runtime/ext_gui/webgl_glsl_rewrite.cpp +349 -0
  392. package/runtime/ext_gui/webgl_glsl_scan.cpp +581 -0
  393. package/runtime/ext_gui/webgl_msl.cpp +62 -0
  394. package/runtime/ext_gui/webgl_msl.h +33 -0
  395. package/runtime/ext_gui/webgl_pipeline.cpp +274 -0
  396. package/runtime/ext_gui/webgl_program_internal.h +18 -0
  397. package/runtime/ext_gui/webgl_shader.cpp +582 -0
  398. package/runtime/ext_gui/webgl_texture.cpp +293 -0
  399. package/runtime/ext_gui/webgl_uniform.cpp +167 -0
  400. package/runtime/ext_gui/webgl_webgl2.cpp +224 -0
  401. package/runtime/ext_gui/window.cpp +9 -0
  402. package/runtime/ext_media/media.cpp +1 -1
  403. package/runtime/ext_media/media_bridge.c +9 -3
  404. package/runtime/ext_node/path/path.c +7 -7
  405. package/runtime/ext_node/url/url.c +4 -2
  406. package/runtime/rt.h +15 -0
  407. package/runtime/rt_internal.h +1 -0
  408. package/runtime/xt_constructors.c +2 -1
  409. package/runtime/xt_containers/access.inc +8 -0
  410. package/runtime/xt_containers/objects.inc +22 -2
  411. package/runtime/xt_io/exception.inc +4 -2
  412. package/runtime/xt_regex/api.inc +2 -0
  413. package/runtime/xt_regex/matcher.inc +16 -3
  414. package/runtime/xt_regex/parser.inc +8 -2
  415. package/runtime/xt_regex/types.inc +3 -0
  416. package/runtime/xt_stdlib/math.inc +62 -0
  417. package/runtime/xt_stdlib2/date.inc +7 -1
  418. package/runtime/xt_stdlib2/objects.inc +14 -0
  419. package/runtime/xt_stdlib2/regexp-match.inc +60 -21
  420. package/runtime/xt_stdlib2/regexp.inc +1 -0
  421. package/runtime/xt_typed_array.c +1 -1
  422. package/scripts/build-gui.ts +90 -3
  423. package/scripts/build-media.ts +323 -58
  424. package/scripts/setup-vs-toolchain.ps1 +152 -0
  425. package/scripts/support-matrix.ts +167 -0
  426. package/src/ast/common.ts +2 -0
  427. package/src/ast/declarations.ts +12 -1
  428. package/src/ast/expressions.ts +6 -0
  429. package/src/ast/kinds.ts +2 -0
  430. package/src/binder/binder.ts +3 -0
  431. package/src/binder/declarations.ts +70 -0
  432. package/src/binder/references.ts +97 -4
  433. package/src/binder/types.ts +30 -0
  434. package/src/canonical.ts +37 -0
  435. package/src/checker/assignability.ts +134 -0
  436. package/src/checker/calls.ts +135 -0
  437. package/src/checker/checker.ts +47 -0
  438. package/src/checker/declarations.ts +26 -0
  439. package/src/checker/flow.ts +236 -0
  440. package/src/checker/globals.ts +40 -0
  441. package/src/checker/source.ts +53 -0
  442. package/src/checker/type-infer.ts +185 -0
  443. package/src/checker/type-model.ts +212 -0
  444. package/src/checker/type-system.ts +578 -0
  445. package/src/checker/typecheck-types.ts +112 -0
  446. package/src/checker/typecheck.ts +586 -0
  447. package/src/checker/undefined.ts +43 -0
  448. package/src/checker/walk.ts +16 -0
  449. package/src/cli/help.ts +65 -0
  450. package/src/cli/hints.ts +2 -1
  451. package/src/cli/main.ts +12 -49
  452. package/src/codegen/generator/calls/access.ts +8 -8
  453. package/src/codegen/generator/calls/invocation.ts +8 -5
  454. package/src/codegen/generator/calls/super.ts +67 -5
  455. package/src/codegen/generator/context.ts +31 -19
  456. package/src/codegen/generator/debug.ts +2 -1
  457. package/src/codegen/generator/expressions/primary.ts +84 -13
  458. package/src/codegen/generator/generator.ts +11 -1
  459. package/src/codegen/generator/module.ts +115 -24
  460. package/src/codegen/generator/state.ts +11 -1
  461. package/src/codegen/generator/statements/variables.ts +26 -6
  462. package/src/codegen/generator/tables.ts +5 -0
  463. package/src/driver/build-key.ts +3 -0
  464. package/src/driver/bundler/graph.ts +6 -2
  465. package/src/driver/bundler/merge.ts +14 -1
  466. package/src/driver/bundler/types.ts +13 -0
  467. package/src/driver/compiler.ts +4 -1
  468. package/src/driver/fingerprint.ts +2 -1
  469. package/src/driver/frontend.ts +13 -2
  470. package/src/driver/options.ts +6 -0
  471. package/src/driver/version.ts +1 -1
  472. package/src/extensions/gui/css.ts +113 -0
  473. package/src/extensions/gui/html.ts +31 -11
  474. package/src/extensions/gui/index.ts +81 -2
  475. package/src/extensions/gui/three.ts +25 -0
  476. package/src/extensions/media/index.ts +13 -16
  477. package/src/extensions/registry.ts +48 -0
  478. package/src/index.ts +1 -0
  479. package/src/parser/declarations/classes.ts +7 -0
  480. package/src/parser/expressions.ts +13 -1
  481. package/src/parser/literals.ts +6 -2
@@ -1,5 +1,9 @@
1
1
  /*
2
2
  * xbintsc GUI engine — display list construction.
3
+ *
4
+ * The tree walk lives here. Background layers are in `paint_background.cpp`,
5
+ * filter/shadow approximations in `paint_effects.cpp` and `clip-path`
6
+ * triangulation in `paint_clip.cpp`.
3
7
  */
4
8
 
5
9
  #include "paint.h"
@@ -8,6 +12,7 @@
8
12
  #include <cstdio>
9
13
  #include <utility>
10
14
 
15
+ #include "paint_internal.h"
11
16
  #include "style.h"
12
17
 
13
18
  namespace xtgui {
@@ -43,50 +48,14 @@ FontSpec specOf(const XtStyle &style) {
43
48
  return spec;
44
49
  }
45
50
 
46
- void addRect(DisplayList &out, float x, float y, float width, float height, float radius,
47
- const Color &color, const PaintClip &clip, const Matrix2D &transform) {
48
- if (width <= 0.0f || height <= 0.0f || color.a <= 0.0f) return;
49
- PaintRect rect;
50
- rect.x = x;
51
- rect.y = y;
52
- rect.width = width;
53
- rect.height = height;
54
- rect.radius = radius;
55
- rect.color = color;
56
- rect.transform = transform;
57
- out.rects.push_back(rect);
58
- out.ops.push_back(PaintOp{PaintKind::Rect, (uint32_t)(out.rects.size() - 1), clip});
59
- }
60
-
61
- void addTextRuns(const LayoutBox *box, const XtStyle &style, DisplayList &out,
62
- const PaintClip &clip) {
63
- if (box->fragments.empty() || style.color.a <= 0.0f) return;
64
- FontSpec spec = specOf(style);
65
- float ascent = 0;
66
- xt_text_metrics(spec, &ascent, nullptr, nullptr);
67
- if (ascent <= 0.0f) ascent = style.font_size * 0.8f;
68
- for (const TextFragment &fragment : box->fragments) {
69
- if (fragment.text.empty()) continue;
70
- PaintText run;
71
- run.x = fragment.x;
72
- run.baseline = fragment.y + ascent;
73
- run.width = fragment.width;
74
- run.height = fragment.height;
75
- run.color = style.color;
76
- run.text = fragment.text;
77
- run.font = spec;
78
- run.transform = box->world;
79
- out.texts.push_back(std::move(run));
80
- out.ops.push_back(PaintOp{PaintKind::Text, (uint32_t)(out.texts.size() - 1), clip});
81
- }
82
- }
83
-
84
- void addImage(const PaintImage &image, DisplayList &out, const PaintClip &clip) {
85
- out.images.push_back(image);
86
- out.ops.push_back(PaintOp{PaintKind::Image, (uint32_t)(out.images.size() - 1), clip});
51
+ int zIndexOf(const LayoutBox *box) {
52
+ if (box->style == nullptr || !box->style->has_z_index) return 0;
53
+ return box->style->z_index;
87
54
  }
88
55
 
89
- void paintBox(const LayoutBox *box, DisplayList &out, const PaintClip &clip);
56
+ void paintBox(const LayoutBox *box, DisplayList &out, const PaintClip &clip,
57
+ const paint_detail::FilterChain &parentChain, float viewportWidth,
58
+ float viewportHeight);
90
59
 
91
60
  /** The clip a box imposes on its content: its padding box, intersected with the
92
61
  * clip already in effect. Only `overflow: hidden/scroll/auto` clips. A
@@ -106,23 +75,32 @@ PaintClip clipForChildren(const LayoutBox *box, const PaintClip &parent) {
106
75
  width = bounds.width;
107
76
  height = bounds.height;
108
77
  }
109
- if (!parent.active) return PaintClip{true, x, y, width, height};
78
+ PaintClip result = parent;
79
+ result.active = true;
80
+ if (!parent.active) {
81
+ result.x = x;
82
+ result.y = y;
83
+ result.width = width;
84
+ result.height = height;
85
+ return result;
86
+ }
110
87
  float x0 = std::max(x, parent.x);
111
88
  float y0 = std::max(y, parent.y);
112
89
  float x1 = std::min(x + width, parent.x + parent.width);
113
90
  float y1 = std::min(y + height, parent.y + parent.height);
114
- return PaintClip{true, x0, y0, std::max(0.0f, x1 - x0), std::max(0.0f, y1 - y0)};
115
- }
116
-
117
- int zIndexOf(const LayoutBox *box) {
118
- if (box->style == nullptr || !box->style->has_z_index) return 0;
119
- return box->style->z_index;
91
+ result.x = x0;
92
+ result.y = y0;
93
+ result.width = std::max(0.0f, x1 - x0);
94
+ result.height = std::max(0.0f, y1 - y0);
95
+ return result;
120
96
  }
121
97
 
122
98
  /** Paint `box`'s children following z-index: negative z first (ascending), then
123
99
  * auto/zero in document order, then positive z (ascending), so higher stacks
124
100
  * paint last. */
125
- void paintChildren(const LayoutBox *box, DisplayList &out, const PaintClip &clip) {
101
+ void paintChildren(const LayoutBox *box, DisplayList &out, const PaintClip &clip,
102
+ const paint_detail::FilterChain &chain, float viewportWidth,
103
+ float viewportHeight) {
126
104
  std::vector<const LayoutBox *> children;
127
105
  for (const std::unique_ptr<LayoutBox> &child : box->children) {
128
106
  if (child->display == Display::None || child->style == nullptr) continue;
@@ -131,41 +109,78 @@ void paintChildren(const LayoutBox *box, DisplayList &out, const PaintClip &clip
131
109
  std::stable_sort(children.begin(), children.end(), [](const LayoutBox *a, const LayoutBox *b) {
132
110
  return zIndexOf(a) < zIndexOf(b);
133
111
  });
134
- for (const LayoutBox *child : children) paintBox(child, out, clip);
112
+ for (const LayoutBox *child : children)
113
+ paintBox(child, out, clip, chain, viewportWidth, viewportHeight);
135
114
  }
136
115
 
137
- void paintBox(const LayoutBox *box, DisplayList &out, const PaintClip &clip) {
116
+ void addTextRuns(const LayoutBox *box, const XtStyle &style, DisplayList &out,
117
+ const PaintClip &clip, const paint_detail::FilterChain &chain,
118
+ float viewportWidth, float viewportHeight) {
119
+ if (box->fragments.empty() || style.color.a <= 0.0f) return;
120
+ FontSpec spec = specOf(style);
121
+ float ascent = 0;
122
+ xt_text_metrics(spec, &ascent, nullptr, nullptr);
123
+ if (ascent <= 0.0f) ascent = style.font_size * 0.8f;
124
+ Color base = paint_detail::filterColor(chain, style.color);
125
+ for (const TextFragment &fragment : box->fragments) {
126
+ if (fragment.text.empty()) continue;
127
+ paint_detail::addTextRun(out, fragment.x, fragment.y + ascent, fragment.width,
128
+ fragment.height, fragment.text, spec, base, box->world, clip, style,
129
+ chain, viewportWidth, viewportHeight);
130
+ }
131
+ }
132
+
133
+ void paintBox(const LayoutBox *box, DisplayList &out, const PaintClip &clip,
134
+ const paint_detail::FilterChain &parentChain, float viewportWidth,
135
+ float viewportHeight) {
138
136
  if (box == nullptr) return;
139
137
  const XtStyle *style = box->style;
140
138
 
141
- /* A fully transparent box paints nothing — not itself, and not its subtree. */
142
- if (style != nullptr && style->opacity <= 0.0f) return;
139
+ /* A fully transparent or hidden box paints nothing — not itself, and not its
140
+ * subtree. */
141
+ if (style != nullptr && (style->opacity <= 0.0f || !style->visible)) return;
142
+
143
+ /* A text box points at its parent element's style; its filters were already
144
+ * folded into `parentChain`, so applying them again would double them. */
145
+ paint_detail::FilterChain chain = parentChain;
146
+ if (style != nullptr && !box->is_text && !style->filters.empty()) {
147
+ chain = paint_detail::extendFilter(parentChain, style->filters, *style, viewportWidth,
148
+ viewportHeight);
149
+ }
150
+
151
+ PaintClip own = clip;
152
+ if (style != nullptr && box->display != Display::None && !box->is_text) {
153
+ if (style->clip_path.type != ClipPathSpec::Type::None) {
154
+ int index = paint_detail::addClipPathForBox(out, *box, *style, viewportWidth, viewportHeight);
155
+ own = paint_detail::addClipPath(own, index);
156
+ }
157
+ }
143
158
 
144
159
  if (style != nullptr && box->display != Display::None) {
145
160
  if (box->is_text) {
146
- addTextRuns(box, *style, out, clip);
161
+ addTextRuns(box, *style, out, own, chain, viewportWidth, viewportHeight);
147
162
  } else {
148
- /* Background first, then the border ring, then replaced content. Children
149
- * are clipped by this box's padding box when it establishes one. Every
150
- * shape carries the box's `transform` matrix for the renderer. */
163
+ /* Drop shadows sit behind the box's own background but above earlier
164
+ * siblings. */
165
+ paint_detail::addBoxDropShadows(out, *box, *style, chain, own);
166
+ paint_detail::paintBackgrounds(out, *box, *style, chain, own, viewportWidth,
167
+ viewportHeight);
151
168
  const Matrix2D &matrix = box->world;
152
- if (style->has_background) {
153
- addRect(out, box->x, box->y, box->width, box->height, style->border_radius,
154
- style->background, clip, matrix);
155
- }
156
169
  if (style->border_style != BorderStyle::None && style->has_border_color) {
157
- const Color bc = style->border_color;
170
+ const Color bc = paint_detail::filterColor(chain, style->border_color);
158
171
  float top = box->border_top;
159
172
  float right = box->border_right;
160
173
  float bottom = box->border_bottom;
161
174
  float left = box->border_left;
162
175
  float inner_height = box->height - top - bottom;
163
- addRect(out, box->x, box->y, box->width, top, 0.0f, bc, clip, matrix);
164
- addRect(out, box->x, box->y + box->height - bottom, box->width, bottom, 0.0f, bc, clip,
165
- matrix);
166
- addRect(out, box->x, box->y + top, left, inner_height, 0.0f, bc, clip, matrix);
167
- addRect(out, box->x + box->width - right, box->y + top, right, inner_height, 0.0f, bc,
168
- clip, matrix);
176
+ paint_detail::addRectFiltered(out, box->x, box->y, box->width, top, 0.0f, bc, own,
177
+ matrix, chain);
178
+ paint_detail::addRectFiltered(out, box->x, box->y + box->height - bottom, box->width,
179
+ bottom, 0.0f, bc, own, matrix, chain);
180
+ paint_detail::addRectFiltered(out, box->x, box->y + top, left, inner_height, 0.0f, bc,
181
+ own, matrix, chain);
182
+ paint_detail::addRectFiltered(out, box->x + box->width - right, box->y + top, right,
183
+ inner_height, 0.0f, bc, own, matrix, chain);
169
184
  }
170
185
  if (box->is_canvas && box->canvas_id != 0 && box->content_width > 0.0f &&
171
186
  box->content_height > 0.0f) {
@@ -176,7 +191,7 @@ void paintBox(const LayoutBox *box, DisplayList &out, const PaintClip &clip) {
176
191
  image.height = box->content_height;
177
192
  image.canvas_id = box->canvas_id;
178
193
  image.transform = matrix;
179
- addImage(image, out, clip);
194
+ paint_detail::addImage(out, image, own, chain);
180
195
  } else if (box->is_media && box->media_id != 0 && box->content_width > 0.0f &&
181
196
  box->content_height > 0.0f) {
182
197
  PaintImage image;
@@ -186,7 +201,7 @@ void paintBox(const LayoutBox *box, DisplayList &out, const PaintClip &clip) {
186
201
  image.height = box->content_height;
187
202
  image.media_id = box->media_id;
188
203
  image.transform = matrix;
189
- addImage(image, out, clip);
204
+ paint_detail::addImage(out, image, own, chain);
190
205
  } else if (box->is_inline_svg && !box->svg_markup.empty() && box->content_width > 0.0f &&
191
206
  box->content_height > 0.0f) {
192
207
  PaintImage image;
@@ -196,7 +211,7 @@ void paintBox(const LayoutBox *box, DisplayList &out, const PaintClip &clip) {
196
211
  image.height = box->content_height;
197
212
  image.svg = box->svg_markup;
198
213
  image.transform = matrix;
199
- addImage(image, out, clip);
214
+ paint_detail::addImage(out, image, own, chain);
200
215
  } else if (box->is_image && !box->image_src.empty() && box->content_width > 0.0f &&
201
216
  box->content_height > 0.0f) {
202
217
  PaintImage image;
@@ -206,24 +221,34 @@ void paintBox(const LayoutBox *box, DisplayList &out, const PaintClip &clip) {
206
221
  image.height = box->content_height;
207
222
  image.src = box->image_src;
208
223
  image.transform = matrix;
209
- addImage(image, out, clip);
224
+ paint_detail::addImage(out, image, own, chain);
210
225
  }
211
226
  }
212
227
  }
213
228
 
214
- paintChildren(box, out, clipForChildren(box, clip));
229
+ /* Drop shadows belong to the box that declared them: its silhouette has
230
+ * already been emitted, so descendants must not repeat it. */
231
+ paint_detail::FilterChain childChain = chain;
232
+ childChain.shadows.clear();
233
+ paintChildren(box, out, clipForChildren(box, own), childChain, viewportWidth, viewportHeight);
215
234
  }
216
235
 
217
236
  } // namespace
218
237
 
219
- void xt_paint_build(const LayoutBox *root, DisplayList &out) {
238
+ void xt_paint_build(const LayoutBox *root, DisplayList &out, float viewportWidth,
239
+ float viewportHeight) {
220
240
  PaintClip none;
221
- paintBox(root, out, none);
241
+ paint_detail::FilterChain chain;
242
+ if (root != nullptr && viewportWidth <= 0.0f) {
243
+ viewportWidth = root->cb_width;
244
+ viewportHeight = root->cb_height;
245
+ }
246
+ paintBox(root, out, none, chain, viewportWidth, viewportHeight);
222
247
  }
223
248
 
224
249
  std::string DisplayList::dump() const {
225
250
  std::string text;
226
- char buffer[288];
251
+ char buffer[320];
227
252
  for (const PaintOp &op : ops) {
228
253
  std::string prefix;
229
254
  if (op.clip.active) {
@@ -231,6 +256,14 @@ std::string DisplayList::dump() const {
231
256
  op.clip.width, op.clip.height);
232
257
  prefix = buffer;
233
258
  }
259
+ if (op.clip.path_count > 0) {
260
+ prefix += "clip-path=";
261
+ for (int i = 0; i < op.clip.path_count; i++) {
262
+ if (i > 0) prefix += ",";
263
+ prefix += std::to_string(op.clip.paths[i]);
264
+ }
265
+ prefix += " ";
266
+ }
234
267
  std::string suffix;
235
268
  if (op.kind == PaintKind::Rect) {
236
269
  suffix = transformSuffix(rects[op.index].transform);
@@ -246,6 +279,7 @@ std::string DisplayList::dump() const {
246
279
  "text x=%.1f baseline=%.1f size=%.1f color=%s \"%s\"", run.x, run.baseline,
247
280
  run.font.pixel_size, formatColor(run.color).c_str(), run.text.c_str());
248
281
  text += prefix + buffer;
282
+ if (run.shadow) text += " shadow=1";
249
283
  } else {
250
284
  const PaintImage &image = images[op.index];
251
285
  suffix = transformSuffix(image.transform);
@@ -46,6 +46,9 @@ struct PaintText {
46
46
  std::string text;
47
47
  FontSpec font;
48
48
  Matrix2D transform;
49
+ /** Set on a `text-shadow` copy (diagnostics only; the renderer draws it like
50
+ * any other glyph run). */
51
+ bool shadow = false;
49
52
  };
50
53
 
51
54
  /** An image to draw, scaled into the given rectangle (viewport-relative).
@@ -65,17 +68,38 @@ struct PaintImage {
65
68
  uint64_t media_id = 0;
66
69
  uint64_t canvas_id = 0;
67
70
  Matrix2D transform;
71
+ /** Modulating colour for the image shader (white normally; a filter's
72
+ * multiplicative effect may tint it). */
73
+ Color tint{1.0f, 1.0f, 1.0f, 1.0f};
74
+ };
75
+
76
+ /** One triangle of a clip path in device-space logical pixels. The paint pass
77
+ * triangulates (possibly concave) polygons once so the renderer can clip
78
+ * convex shape/glyph quads by a simple half-plane test per triangle. */
79
+ struct ClipTriangle {
80
+ float x[3] = {0, 0, 0};
81
+ float y[3] = {0, 0, 0};
82
+ };
83
+
84
+ /** A resolved `clip-path` polygon plus its triangulation. */
85
+ struct ClipPathGeometry {
86
+ std::vector<float> points; // x, y pairs (diagnostics)
87
+ std::vector<ClipTriangle> triangles;
68
88
  };
69
89
 
70
90
  /** The clip rectangle in effect for a painted shape (device-space logical
71
91
  * pixels — a transformed subtree contributes the bounding box of its clip).
72
- * `width <= 0` means "no clip". */
92
+ * `width <= 0` means "no clip". `paths` index `DisplayList::clip_paths`; at most
93
+ * two nested `clip-path` shapes are kept (CSS would intersect every ancestor;
94
+ * deeper nesting is rare and the outermost two are the ones a UI uses). */
73
95
  struct PaintClip {
74
96
  bool active = false;
75
97
  float x = 0;
76
98
  float y = 0;
77
99
  float width = 0;
78
100
  float height = 0;
101
+ int path_count = 0;
102
+ int paths[2] = {-1, -1};
79
103
  };
80
104
 
81
105
  enum class PaintKind { Rect, Text, Image };
@@ -95,20 +119,26 @@ struct DisplayList {
95
119
  /** Shapes in painter order (backgrounds/borders first, then children, then
96
120
  * stacked siblings), each with the clip rectangle that bounds it. */
97
121
  std::vector<PaintOp> ops;
122
+ /** Device-space clip-path polygons shared by an element's ops. */
123
+ std::vector<ClipPathGeometry> clip_paths;
98
124
 
99
125
  void clear() {
100
126
  rects.clear();
101
127
  texts.clear();
102
128
  images.clear();
103
129
  ops.clear();
130
+ clip_paths.clear();
104
131
  }
105
132
  bool empty() const { return rects.empty() && texts.empty() && images.empty(); }
106
133
  /** Human-readable dump, one shape per line, in painter order (diagnostics/tests). */
107
134
  std::string dump() const;
108
135
  };
109
136
 
110
- /** Build the display list for a laid-out tree and append it to `out`. */
111
- void xt_paint_build(const LayoutBox *root, DisplayList &out);
137
+ /** Build the display list for a laid-out tree and append it to `out`. The
138
+ * viewport size resolves `vw`/`vh` units inside `clip-path` and shadows; pass 0
139
+ * to take it from the root box's containing block. */
140
+ void xt_paint_build(const LayoutBox *root, DisplayList &out, float viewportWidth = 0.0f,
141
+ float viewportHeight = 0.0f);
112
142
 
113
143
  } // namespace xtgui
114
144
 
@@ -0,0 +1,229 @@
1
+ /*
2
+ * xbintsc GUI engine — background layer painting.
3
+ *
4
+ * The renderer has one rounded-rectangle pipeline and no gradient shader, so a
5
+ * gradient is emitted as a run of solid bands: 18 strips for a linear gradient
6
+ * and 32 concentric ellipses for a radial one. Radial ellipses use the shape
7
+ * pipeline's transform slot (a unit circle scaled to the ellipse radii), which
8
+ * keeps the distance-field antialiasing intact.
9
+ */
10
+
11
+ #include "paint_internal.h"
12
+
13
+ #include <algorithm>
14
+ #include <cmath>
15
+ #include <vector>
16
+
17
+ namespace xtgui {
18
+ namespace paint_detail {
19
+
20
+ namespace {
21
+
22
+ Color gradientColorAt(const BackgroundLayer &layer, float t) {
23
+ const std::vector<BackgroundGradientStop> &stops = layer.stops;
24
+ if (stops.empty()) return Color();
25
+ if (t <= stops.front().offset) return stops.front().color;
26
+ if (t >= stops.back().offset) return stops.back().color;
27
+ for (size_t i = 1; i < stops.size(); i++) {
28
+ if (t > stops[i].offset) continue;
29
+ float span = stops[i].offset - stops[i - 1].offset;
30
+ float u = span > 0.00001f ? (t - stops[i - 1].offset) / span : 0.0f;
31
+ Color a = stops[i - 1].color;
32
+ Color b = stops[i].color;
33
+ Color out;
34
+ out.r = a.r + (b.r - a.r) * u;
35
+ out.g = a.g + (b.g - a.g) * u;
36
+ out.b = a.b + (b.b - a.b) * u;
37
+ out.a = a.a + (b.a - a.a) * u;
38
+ out.valid = true;
39
+ return out;
40
+ }
41
+ return stops.back().color;
42
+ }
43
+
44
+ /** Intersect `clip` with the box's border box (backgrounds never paint outside
45
+ * it, even when the box is not an overflow container). */
46
+ PaintClip boxClip(const PaintClip &clip, const LayoutBox &box) {
47
+ float bx = box.x;
48
+ float by = box.y;
49
+ float bw = box.width;
50
+ float bh = box.height;
51
+ if (box.has_transform) {
52
+ LayoutRect bounds = xt_layout_transform_rect(box.world, bx, by, bw, bh);
53
+ bx = bounds.x;
54
+ by = bounds.y;
55
+ bw = bounds.width;
56
+ bh = bounds.height;
57
+ }
58
+ PaintClip out = clip;
59
+ if (!out.active) {
60
+ out.active = true;
61
+ out.x = bx;
62
+ out.y = by;
63
+ out.width = bw;
64
+ out.height = bh;
65
+ return out;
66
+ }
67
+ float x0 = std::max(out.x, bx);
68
+ float y0 = std::max(out.y, by);
69
+ float x1 = std::min(out.x + out.width, bx + bw);
70
+ float y1 = std::min(out.y + out.height, by + bh);
71
+ out.x = x0;
72
+ out.y = y0;
73
+ out.width = std::max(0.0f, x1 - x0);
74
+ out.height = std::max(0.0f, y1 - y0);
75
+ return out;
76
+ }
77
+
78
+ void paintLinear(const LayoutBox &box, const BackgroundLayer &layer, const FilterChain &chain,
79
+ const PaintClip &clip, DisplayList &out) {
80
+ if (layer.stops.size() < 2 || box.width <= 0.0f || box.height <= 0.0f) return;
81
+ const int strips = 18;
82
+ bool horizontal = (layer.angle > 80.0f && layer.angle < 100.0f) ||
83
+ (layer.angle > 260.0f && layer.angle < 280.0f);
84
+ bool reverse = (layer.angle > 260.0f && layer.angle < 280.0f) || layer.angle < 10.0f ||
85
+ layer.angle > 350.0f;
86
+ for (int i = 0; i < strips; i++) {
87
+ float t = ((float)i + 0.5f) / (float)strips;
88
+ Color color = gradientColorAt(layer, reverse ? 1.0f - t : t);
89
+ color = filterColor(chain, color);
90
+ if (color.a <= 0.0f) continue;
91
+ if (horizontal) {
92
+ addRect(out, box.x + box.width * (float)i / (float)strips, box.y,
93
+ box.width / (float)strips + 0.4f, box.height, 0.0f, color, clip, box.world);
94
+ } else {
95
+ addRect(out, box.x, box.y + box.height * (float)i / (float)strips, box.width,
96
+ box.height / (float)strips + 0.4f, 0.0f, color, clip, box.world);
97
+ }
98
+ }
99
+ }
100
+
101
+ /** Default radii for `closest-side` / `farthest-side` / corner keywords. */
102
+ void radialRadii(const LayoutBox &box, const BackgroundLayer &layer, const XtStyle &style,
103
+ float viewportWidth, float viewportHeight, float *cx, float *cy, float *rx,
104
+ float *ry) {
105
+ float centerX = box.x + resolveLength(layer.center_x, box.width, style.font_size, viewportWidth,
106
+ viewportHeight);
107
+ float centerY = box.y + resolveLength(layer.center_y, box.height, style.font_size, viewportWidth,
108
+ viewportHeight);
109
+ float left = centerX - box.x;
110
+ float right = box.x + box.width - centerX;
111
+ float top = centerY - box.y;
112
+ float bottom = box.y + box.height - centerY;
113
+ left = std::max(0.0f, left);
114
+ right = std::max(0.0f, right);
115
+ top = std::max(0.0f, top);
116
+ bottom = std::max(0.0f, bottom);
117
+
118
+ if (layer.size == RadialSize::Explicit) {
119
+ float radiusX =
120
+ resolveLength(layer.radius_x, box.width, style.font_size, viewportWidth, viewportHeight);
121
+ float radiusY = layer.circle
122
+ ? radiusX
123
+ : resolveLength(layer.radius_y, box.height, style.font_size, viewportWidth,
124
+ viewportHeight);
125
+ *cx = centerX;
126
+ *cy = centerY;
127
+ *rx = std::max(0.0f, radiusX);
128
+ *ry = std::max(0.0f, radiusY);
129
+ return;
130
+ }
131
+
132
+ if (layer.circle) {
133
+ float radius = 0.0f;
134
+ switch (layer.size) {
135
+ case RadialSize::ClosestSide:
136
+ radius = std::min(std::min(left, right), std::min(top, bottom));
137
+ break;
138
+ case RadialSize::FarthestSide:
139
+ radius = std::max(std::max(left, right), std::max(top, bottom));
140
+ break;
141
+ case RadialSize::ClosestCorner:
142
+ radius = std::sqrt(std::min(left, right) * std::min(left, right) +
143
+ std::min(top, bottom) * std::min(top, bottom));
144
+ break;
145
+ case RadialSize::FarthestCorner:
146
+ default:
147
+ radius = std::sqrt(std::max(left, right) * std::max(left, right) +
148
+ std::max(top, bottom) * std::max(top, bottom));
149
+ break;
150
+ }
151
+ *rx = *ry = radius;
152
+ } else {
153
+ switch (layer.size) {
154
+ case RadialSize::ClosestCorner:
155
+ case RadialSize::ClosestSide:
156
+ *rx = std::min(left, right);
157
+ *ry = std::min(top, bottom);
158
+ break;
159
+ case RadialSize::FarthestSide:
160
+ case RadialSize::FarthestCorner:
161
+ default:
162
+ *rx = std::max(left, right);
163
+ *ry = std::max(top, bottom);
164
+ break;
165
+ }
166
+ }
167
+ *cx = centerX;
168
+ *cy = centerY;
169
+ }
170
+
171
+ /** One filled ellipse: a unit-radius rounded rect mapped by a local scale. */
172
+ void addEllipse(DisplayList &out, float cx, float cy, float rx, float ry, const Color &color,
173
+ const PaintClip &clip, const Matrix2D &world) {
174
+ if (rx <= 0.0f || ry <= 0.0f || color.a <= 0.0f) return;
175
+ Matrix2D local = Matrix2D::translate(cx, cy)
176
+ .multiply(Matrix2D::scale(rx, ry))
177
+ .multiply(Matrix2D::translate(-cx, -cy));
178
+ addRect(out, cx - 1.0f, cy - 1.0f, 2.0f, 2.0f, 1.0f, color, clip, world.multiply(local));
179
+ }
180
+
181
+ void paintRadial(const LayoutBox &box, const XtStyle &style, const BackgroundLayer &layer,
182
+ const FilterChain &chain, const PaintClip &clip, float viewportWidth,
183
+ float viewportHeight, DisplayList &out) {
184
+ if (layer.stops.size() < 2 || box.width <= 0.0f || box.height <= 0.0f) return;
185
+ float cx = 0.0f;
186
+ float cy = 0.0f;
187
+ float rx = 0.0f;
188
+ float ry = 0.0f;
189
+ radialRadii(box, layer, style, viewportWidth, viewportHeight, &cx, &cy, &rx, &ry);
190
+ if (rx <= 0.0f || ry <= 0.0f) return;
191
+ const int bands = 32;
192
+ for (int i = bands; i >= 1; i--) {
193
+ float t = (float)i / (float)bands;
194
+ Color color = filterColor(chain, gradientColorAt(layer, t));
195
+ if (color.a <= 0.0f) continue;
196
+ addEllipse(out, cx, cy, rx * t, ry * t, color, clip, box.world);
197
+ }
198
+ /* Exact centre colour (the innermost band samples just off zero). */
199
+ Color center = filterColor(chain, gradientColorAt(layer, 0.0f));
200
+ addEllipse(out, cx, cy, 0.6f, 0.6f, center, clip, box.world);
201
+ }
202
+
203
+ } // namespace
204
+
205
+ void paintBackgrounds(DisplayList &out, const LayoutBox &box, const XtStyle &style,
206
+ const FilterChain &chain, const PaintClip &clip, float viewportWidth,
207
+ float viewportHeight) {
208
+ PaintClip layerClip = boxClip(clip, box);
209
+ if (layerClip.width <= 0.0f || layerClip.height <= 0.0f) return;
210
+ if (style.has_background) {
211
+ /* The rectangle is already the border box, so the incoming clip is enough;
212
+ * narrowing it to the box again would only change the reported clip (and
213
+ * would clip a filtered/rounded fill differently from before M19). */
214
+ addRectFiltered(out, box.x, box.y, box.width, box.height, style.border_radius,
215
+ style.background, clip, box.world, chain);
216
+ }
217
+ /* CSS paints the first layer on top, so walk the list backwards. */
218
+ for (size_t i = style.background_layers.size(); i-- > 0;) {
219
+ const BackgroundLayer &layer = style.background_layers[i];
220
+ if (layer.kind == BackgroundKind::Linear) {
221
+ paintLinear(box, layer, chain, layerClip, out);
222
+ } else {
223
+ paintRadial(box, style, layer, chain, layerClip, viewportWidth, viewportHeight, out);
224
+ }
225
+ }
226
+ }
227
+
228
+ } // namespace paint_detail
229
+ } // namespace xtgui