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
@@ -0,0 +1,268 @@
1
+ /*
2
+ * xbintsc GUI engine — `clip-path` geometry.
3
+ *
4
+ * CSS shapes become one device-space polygon, which is triangulated with ear
5
+ * clipping (so concave `polygon()` shapes work). The renderer intersects every
6
+ * convex shape/text/image quad with those triangles; no stencil or shader
7
+ * change is needed.
8
+ */
9
+
10
+ #include "paint_internal.h"
11
+
12
+ #include <algorithm>
13
+ #include <cmath>
14
+ #include <vector>
15
+
16
+ namespace xtgui {
17
+ namespace paint_detail {
18
+
19
+ namespace {
20
+
21
+ constexpr float kPi = 3.14159265358979323846f;
22
+
23
+ struct Point {
24
+ float x = 0.0f;
25
+ float y = 0.0f;
26
+ };
27
+
28
+ float resolveX(const Length &length, float base, float em, float vw, float vh) {
29
+ return resolveLength(length, base, em, vw, vh);
30
+ }
31
+
32
+ float resolveY(const Length &length, float base, float em, float vw, float vh) {
33
+ return resolveLength(length, base, em, vw, vh);
34
+ }
35
+
36
+ void appendPoint(std::vector<Point> *points, const Point &point) {
37
+ if (!points->empty()) {
38
+ const Point &last = points->back();
39
+ if (std::fabs(last.x - point.x) < 0.0001f && std::fabs(last.y - point.y) < 0.0001f) return;
40
+ }
41
+ points->push_back(point);
42
+ }
43
+
44
+ /** Rounded-rectangle outline (used by `inset(... round r)`). */
45
+ void insetOutline(const LayoutBox &box, const XtStyle &style, const ClipPathSpec &clip, float vw,
46
+ float vh, std::vector<Point> *points) {
47
+ float em = style.font_size;
48
+ float top = resolveY(clip.inset_top, box.height, em, vw, vh);
49
+ float right = resolveX(clip.inset_right, box.width, em, vw, vh);
50
+ float bottom = resolveY(clip.inset_bottom, box.height, em, vw, vh);
51
+ float left = resolveX(clip.inset_left, box.width, em, vw, vh);
52
+ float x0 = box.x + left;
53
+ float y0 = box.y + top;
54
+ float x1 = box.x + box.width - right;
55
+ float y1 = box.y + box.height - bottom;
56
+ if (x1 < x0) std::swap(x0, x1);
57
+ if (y1 < y0) std::swap(y0, y1);
58
+ if (x1 - x0 <= 0.0f || y1 - y0 <= 0.0f) return;
59
+ float radius = resolveLength(clip.inset_radius, std::min(x1 - x0, y1 - y0), em, vw, vh);
60
+ radius = std::max(0.0f, std::min(radius, std::min(x1 - x0, y1 - y0) * 0.5f));
61
+ if (radius <= 0.0f) {
62
+ appendPoint(points, {x0, y0});
63
+ appendPoint(points, {x1, y0});
64
+ appendPoint(points, {x1, y1});
65
+ appendPoint(points, {x0, y1});
66
+ return;
67
+ }
68
+ const int segments = 6;
69
+ /* Clockwise from the top-left corner's start, one quarter arc per corner. */
70
+ for (int i = 0; i <= segments; i++) {
71
+ float angle = kPi + (float)i / (float)segments * (kPi * 0.5f);
72
+ appendPoint(points, {x0 + radius + std::cos(angle) * radius,
73
+ y0 + radius + std::sin(angle) * radius});
74
+ }
75
+ for (int i = 0; i <= segments; i++) {
76
+ float angle = kPi * 1.5f + (float)i / (float)segments * (kPi * 0.5f);
77
+ appendPoint(points, {x1 - radius + std::cos(angle) * radius,
78
+ y0 + radius + std::sin(angle) * radius});
79
+ }
80
+ for (int i = 0; i <= segments; i++) {
81
+ float angle = (float)i / (float)segments * (kPi * 0.5f);
82
+ appendPoint(points, {x1 - radius + std::cos(angle) * radius,
83
+ y1 - radius + std::sin(angle) * radius});
84
+ }
85
+ for (int i = 0; i <= segments; i++) {
86
+ float angle = kPi * 0.5f + (float)i / (float)segments * (kPi * 0.5f);
87
+ appendPoint(points, {x0 + radius + std::cos(angle) * radius,
88
+ y1 - radius + std::sin(angle) * radius});
89
+ }
90
+ }
91
+
92
+ void ellipseOutline(const LayoutBox &box, const XtStyle &style, const ClipPathSpec &clip, float vw,
93
+ float vh, std::vector<Point> *points) {
94
+ float em = style.font_size;
95
+ float cx = box.x + resolveX(clip.center_x, box.width, em, vw, vh);
96
+ float cy = box.y + resolveY(clip.center_y, box.height, em, vw, vh);
97
+ bool circle = clip.type == ClipPathSpec::Type::Circle;
98
+ float rx = 0.0f;
99
+ float ry = 0.0f;
100
+ if (clip.radius_explicit) {
101
+ if (circle && clip.radius_x.unit == Unit::Percent) {
102
+ /* CSS resolves a circle percentage against sqrt(w² + h²) / sqrt(2). */
103
+ float diagonal = std::sqrt(box.width * box.width + box.height * box.height);
104
+ rx = ry = diagonal / std::sqrt(2.0f) * clip.radius_x.value / 100.0f;
105
+ } else {
106
+ rx = resolveX(clip.radius_x, box.width, em, vw, vh);
107
+ ry = circle ? rx : resolveY(clip.radius_y, box.height, em, vw, vh);
108
+ }
109
+ } else {
110
+ float left = std::max(0.0f, cx - box.x);
111
+ float right = std::max(0.0f, box.x + box.width - cx);
112
+ float top = std::max(0.0f, cy - box.y);
113
+ float bottom = std::max(0.0f, box.y + box.height - cy);
114
+ if (circle) {
115
+ rx = ry = std::min(std::min(left, right), std::min(top, bottom));
116
+ } else {
117
+ rx = std::min(left, right);
118
+ ry = std::min(top, bottom);
119
+ }
120
+ }
121
+ if (rx <= 0.0f || ry <= 0.0f) return;
122
+ const int segments = 48;
123
+ for (int i = 0; i < segments; i++) {
124
+ float angle = (float)i / (float)segments * kPi * 2.0f;
125
+ appendPoint(points, {cx + std::cos(angle) * rx, cy + std::sin(angle) * ry});
126
+ }
127
+ }
128
+
129
+ void polygonOutline(const LayoutBox &box, const XtStyle &style, const ClipPathSpec &clip, float vw,
130
+ float vh, std::vector<Point> *points) {
131
+ float em = style.font_size;
132
+ for (size_t i = 0; i + 1 < clip.polygon.size(); i += 2) {
133
+ float x = box.x + resolveX(clip.polygon[i], box.width, em, vw, vh);
134
+ float y = box.y + resolveY(clip.polygon[i + 1], box.height, em, vw, vh);
135
+ appendPoint(points, {x, y});
136
+ }
137
+ }
138
+
139
+ float cross(const Point &a, const Point &b, const Point &c) {
140
+ return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
141
+ }
142
+
143
+ bool pointInTriangle(const Point &p, const Point &a, const Point &b, const Point &c) {
144
+ float c1 = cross(a, b, p);
145
+ float c2 = cross(b, c, p);
146
+ float c3 = cross(c, a, p);
147
+ const float eps = 0.0001f;
148
+ bool hasNeg = c1 < -eps || c2 < -eps || c3 < -eps;
149
+ bool hasPos = c1 > eps || c2 > eps || c3 > eps;
150
+ return !(hasNeg && hasPos);
151
+ }
152
+
153
+ /** Ear clipping for a simple polygon; falls back to a fan if it stalls. */
154
+ void triangulate(std::vector<Point> points, std::vector<ClipTriangle> *triangles) {
155
+ if (points.size() < 3) return;
156
+ /* Remove a repeated closing point. */
157
+ if (std::fabs(points.front().x - points.back().x) < 0.0001f &&
158
+ std::fabs(points.front().y - points.back().y) < 0.0001f)
159
+ points.pop_back();
160
+ if (points.size() < 3) return;
161
+ float area = 0.0f;
162
+ for (size_t i = 0; i < points.size(); i++) {
163
+ const Point &a = points[i];
164
+ const Point &b = points[(i + 1) % points.size()];
165
+ area += a.x * b.y - b.x * a.y;
166
+ }
167
+ if (area < 0.0f) std::reverse(points.begin(), points.end());
168
+ std::vector<size_t> indices(points.size());
169
+ for (size_t i = 0; i < indices.size(); i++) indices[i] = i;
170
+ size_t guard = 0;
171
+ while (indices.size() > 3 && guard++ < indices.size() * indices.size() + 8) {
172
+ bool clipped = false;
173
+ for (size_t i = 0; i < indices.size(); i++) {
174
+ size_t previous = indices[(i + indices.size() - 1) % indices.size()];
175
+ size_t current = indices[i];
176
+ size_t next = indices[(i + 1) % indices.size()];
177
+ const Point &a = points[previous];
178
+ const Point &b = points[current];
179
+ const Point &c = points[next];
180
+ if (cross(a, b, c) <= 0.0001f) continue;
181
+ bool contains = false;
182
+ for (size_t other : indices) {
183
+ if (other == previous || other == current || other == next) continue;
184
+ if (pointInTriangle(points[other], a, b, c)) {
185
+ contains = true;
186
+ break;
187
+ }
188
+ }
189
+ if (contains) continue;
190
+ ClipTriangle triangle;
191
+ triangle.x[0] = a.x;
192
+ triangle.y[0] = a.y;
193
+ triangle.x[1] = b.x;
194
+ triangle.y[1] = b.y;
195
+ triangle.x[2] = c.x;
196
+ triangle.y[2] = c.y;
197
+ triangles->push_back(triangle);
198
+ indices.erase(indices.begin() + (long)i);
199
+ clipped = true;
200
+ break;
201
+ }
202
+ if (!clipped) break;
203
+ }
204
+ if (indices.size() >= 3) {
205
+ for (size_t i = 1; i + 1 < indices.size(); i++) {
206
+ ClipTriangle triangle;
207
+ triangle.x[0] = points[indices[0]].x;
208
+ triangle.y[0] = points[indices[0]].y;
209
+ triangle.x[1] = points[indices[i]].x;
210
+ triangle.y[1] = points[indices[i]].y;
211
+ triangle.x[2] = points[indices[i + 1]].x;
212
+ triangle.y[2] = points[indices[i + 1]].y;
213
+ triangles->push_back(triangle);
214
+ }
215
+ }
216
+ }
217
+
218
+ } // namespace
219
+
220
+ int addClipPathForBox(DisplayList &out, const LayoutBox &box, const XtStyle &style,
221
+ float viewportWidth, float viewportHeight) {
222
+ if (style.clip_path.type == ClipPathSpec::Type::None) return -1;
223
+ std::vector<Point> points;
224
+ switch (style.clip_path.type) {
225
+ case ClipPathSpec::Type::Inset:
226
+ insetOutline(box, style, style.clip_path, viewportWidth, viewportHeight, &points);
227
+ break;
228
+ case ClipPathSpec::Type::Circle:
229
+ case ClipPathSpec::Type::Ellipse:
230
+ ellipseOutline(box, style, style.clip_path, viewportWidth, viewportHeight, &points);
231
+ break;
232
+ case ClipPathSpec::Type::Polygon:
233
+ polygonOutline(box, style, style.clip_path, viewportWidth, viewportHeight, &points);
234
+ break;
235
+ default:
236
+ return -1;
237
+ }
238
+ /* An empty but valid shape (`inset(50%)`, `circle(0)`) clips everything away;
239
+ * it must not fall back to "no clip". The paint walk keeps the empty geometry
240
+ * and the renderer emits no geometry for ops that reference it. */
241
+ ClipPathGeometry geometry;
242
+ geometry.points.reserve(points.size() * 2);
243
+ for (Point &point : points) {
244
+ float x = point.x;
245
+ float y = point.y;
246
+ box.world.apply(point.x, point.y, &x, &y);
247
+ geometry.points.push_back(x);
248
+ geometry.points.push_back(y);
249
+ }
250
+ if (points.size() >= 3) {
251
+ std::vector<Point> device;
252
+ device.reserve(points.size());
253
+ for (size_t i = 0; i + 1 < geometry.points.size(); i += 2)
254
+ device.push_back({geometry.points[i], geometry.points[i + 1]});
255
+ triangulate(device, &geometry.triangles);
256
+ }
257
+ out.clip_paths.push_back(std::move(geometry));
258
+ return (int)(out.clip_paths.size() - 1);
259
+ }
260
+
261
+ PaintClip addClipPath(PaintClip clip, int index) {
262
+ if (index < 0) return clip;
263
+ if (clip.path_count < 2) clip.paths[clip.path_count++] = index;
264
+ return clip;
265
+ }
266
+
267
+ } // namespace paint_detail
268
+ } // namespace xtgui
@@ -0,0 +1,324 @@
1
+ /*
2
+ * xbintsc GUI engine — CSS filter and shadow approximations.
3
+ *
4
+ * Colour functions are applied per painted shape (a group would need an
5
+ * offscreen layer). `blur()` is approximated by spreading nine translucent
6
+ * copies around the shape, and `drop-shadow()` by a shadow silhouette per box.
7
+ * Both are deterministic and need no render-target pass, which keeps the
8
+ * single-pass painter intact; `backdrop-filter` still needs a backdrop snapshot
9
+ * and is documented as not composited.
10
+ */
11
+
12
+ #include "paint_internal.h"
13
+
14
+ #include <algorithm>
15
+ #include <cmath>
16
+ #include <utility>
17
+ #include <vector>
18
+
19
+ #include "style_internal.h"
20
+
21
+ namespace xtgui {
22
+ namespace paint_detail {
23
+
24
+ namespace {
25
+
26
+ float clamp01(float value) { return value < 0.0f ? 0.0f : (value > 1.0f ? 1.0f : value); }
27
+
28
+ Color lerpColor(const Color &from, const Color &to, float amount) {
29
+ Color out;
30
+ out.r = from.r + (to.r - from.r) * amount;
31
+ out.g = from.g + (to.g - from.g) * amount;
32
+ out.b = from.b + (to.b - from.b) * amount;
33
+ out.a = from.a + (to.a - from.a) * amount;
34
+ out.valid = true;
35
+ return out;
36
+ }
37
+
38
+ float luminance(const Color &color) {
39
+ return color.r * 0.2126f + color.g * 0.7152f + color.b * 0.0722f;
40
+ }
41
+
42
+ Color applySepia(const Color &color, float amount) {
43
+ Color sepia;
44
+ sepia.r = color.r * 0.393f + color.g * 0.769f + color.b * 0.189f;
45
+ sepia.g = color.r * 0.349f + color.g * 0.686f + color.b * 0.168f;
46
+ sepia.b = color.r * 0.272f + color.g * 0.534f + color.b * 0.131f;
47
+ sepia.a = color.a;
48
+ sepia.valid = true;
49
+ return lerpColor(color, sepia, amount);
50
+ }
51
+
52
+ Color applySaturate(const Color &color, float amount) {
53
+ float luma = luminance(color);
54
+ Color out;
55
+ out.r = luma + (color.r - luma) * amount;
56
+ out.g = luma + (color.g - luma) * amount;
57
+ out.b = luma + (color.b - luma) * amount;
58
+ out.a = color.a;
59
+ out.valid = true;
60
+ return out;
61
+ }
62
+
63
+ Color applyHueRotate(const Color &color, float degrees) {
64
+ float radians = degrees * 3.141592653589793f / 180.0f;
65
+ float c = std::cos(radians);
66
+ float s = std::sin(radians);
67
+ Color out;
68
+ out.r = color.r * (0.213f + c * 0.787f - s * 0.213f) +
69
+ color.g * (0.715f - c * 0.715f - s * 0.715f) +
70
+ color.b * (0.072f - c * 0.072f + s * 0.928f);
71
+ out.g = color.r * (0.213f - c * 0.213f + s * 0.143f) +
72
+ color.g * (0.715f + c * 0.285f + s * 0.140f) +
73
+ color.b * (0.072f - c * 0.072f - s * 0.283f);
74
+ out.b = color.r * (0.213f - c * 0.213f - s * 0.787f) +
75
+ color.g * (0.715f - c * 0.715f + s * 0.715f) +
76
+ color.b * (0.072f + c * 0.928f + s * 0.072f);
77
+ out.a = color.a;
78
+ out.valid = true;
79
+ return out;
80
+ }
81
+
82
+ struct Tap {
83
+ float dx;
84
+ float dy;
85
+ };
86
+ constexpr float kBlurTapWeight = 0.12f;
87
+
88
+ std::vector<Tap> blurTaps(float radius) {
89
+ if (radius <= 0.0f) return {Tap{0.0f, 0.0f}};
90
+ std::vector<Tap> taps;
91
+ for (int y = -1; y <= 1; y++) {
92
+ for (int x = -1; x <= 1; x++) taps.push_back(Tap{x * radius, y * radius});
93
+ }
94
+ return taps;
95
+ }
96
+
97
+ } // namespace
98
+
99
+ float resolveLength(const Length &length, float base, float em, float viewportWidth,
100
+ float viewportHeight) {
101
+ return xt_style_resolve_absolute(length, base, em, 16.0f, viewportWidth, viewportHeight);
102
+ }
103
+
104
+ FilterChain extendFilter(const FilterChain &parent, const std::vector<FilterOp> &filters,
105
+ const XtStyle &style, float viewportWidth, float viewportHeight) {
106
+ FilterChain chain = parent;
107
+ /* Drop shadows are silhouettes of one box, never inherited. */
108
+ chain.shadows.clear();
109
+ for (const FilterOp &filter : filters) {
110
+ if (filter.kind == FilterKind::Blur) {
111
+ float blur = resolveLength(filter.blur, 0.0f, style.font_size, viewportWidth, viewportHeight);
112
+ if (blur > 0.0f) chain.blur += blur;
113
+ } else if (filter.kind == FilterKind::DropShadow) {
114
+ FilterChain::Shadow shadow;
115
+ shadow.dx = resolveLength(filter.dx, 0.0f, style.font_size, viewportWidth, viewportHeight);
116
+ shadow.dy = resolveLength(filter.dy, 0.0f, style.font_size, viewportWidth, viewportHeight);
117
+ shadow.blur =
118
+ resolveLength(filter.blur, 0.0f, style.font_size, viewportWidth, viewportHeight);
119
+ shadow.color = filter.has_color ? filter.color : style.color;
120
+ chain.shadows.push_back(shadow);
121
+ } else {
122
+ chain.ops.push_back(filter);
123
+ }
124
+ }
125
+ return chain;
126
+ }
127
+
128
+ Color filterColor(const FilterChain &chain, Color color) {
129
+ for (const FilterOp &filter : chain.ops) {
130
+ switch (filter.kind) {
131
+ case FilterKind::Brightness:
132
+ color.r *= filter.amount;
133
+ color.g *= filter.amount;
134
+ color.b *= filter.amount;
135
+ break;
136
+ case FilterKind::Contrast:
137
+ color.r = (color.r - 0.5f) * filter.amount + 0.5f;
138
+ color.g = (color.g - 0.5f) * filter.amount + 0.5f;
139
+ color.b = (color.b - 0.5f) * filter.amount + 0.5f;
140
+ break;
141
+ case FilterKind::Grayscale: {
142
+ float luma = luminance(color);
143
+ Color gray{luma, luma, luma, color.a, true};
144
+ color = lerpColor(color, gray, filter.amount);
145
+ break;
146
+ }
147
+ case FilterKind::Sepia:
148
+ color = applySepia(color, filter.amount);
149
+ break;
150
+ case FilterKind::Invert:
151
+ color.r = color.r + (1.0f - 2.0f * color.r) * filter.amount;
152
+ color.g = color.g + (1.0f - 2.0f * color.g) * filter.amount;
153
+ color.b = color.b + (1.0f - 2.0f * color.b) * filter.amount;
154
+ break;
155
+ case FilterKind::Saturate:
156
+ color = applySaturate(color, filter.amount);
157
+ break;
158
+ case FilterKind::HueRotate:
159
+ color = applyHueRotate(color, filter.amount);
160
+ break;
161
+ case FilterKind::Opacity:
162
+ color.a *= filter.amount;
163
+ break;
164
+ default:
165
+ break;
166
+ }
167
+ color.r = clamp01(color.r);
168
+ color.g = clamp01(color.g);
169
+ color.b = clamp01(color.b);
170
+ color.a = clamp01(color.a);
171
+ }
172
+ return color;
173
+ }
174
+
175
+ Color imageTint(const FilterChain &chain) {
176
+ /* The image shader multiplies the sampled texel by this colour, which can
177
+ * express brightness and opacity exactly. Other colour functions need a
178
+ * per-pixel pass; leaving the tint neutral is less wrong than a channel
179
+ * multiply, so they are skipped for images. */
180
+ Color tint{1.0f, 1.0f, 1.0f, 1.0f};
181
+ for (const FilterOp &filter : chain.ops) {
182
+ if (filter.kind == FilterKind::Brightness) {
183
+ tint.r *= filter.amount;
184
+ tint.g *= filter.amount;
185
+ tint.b *= filter.amount;
186
+ } else if (filter.kind == FilterKind::Opacity) {
187
+ tint.a *= filter.amount;
188
+ }
189
+ }
190
+ tint.r = clamp01(tint.r);
191
+ tint.g = clamp01(tint.g);
192
+ tint.b = clamp01(tint.b);
193
+ tint.a = clamp01(tint.a);
194
+ return tint;
195
+ }
196
+
197
+ void addRect(DisplayList &out, float x, float y, float width, float height, float radius,
198
+ const Color &color, const PaintClip &clip, const Matrix2D &transform) {
199
+ if (width <= 0.0f || height <= 0.0f || color.a <= 0.0f) return;
200
+ PaintRect rect;
201
+ rect.x = x;
202
+ rect.y = y;
203
+ rect.width = width;
204
+ rect.height = height;
205
+ rect.radius = radius;
206
+ rect.color = color;
207
+ rect.transform = transform;
208
+ out.rects.push_back(rect);
209
+ out.ops.push_back(PaintOp{PaintKind::Rect, (uint32_t)(out.rects.size() - 1), clip});
210
+ }
211
+
212
+ void addRectFiltered(DisplayList &out, float x, float y, float width, float height, float radius,
213
+ const Color &color, const PaintClip &clip, const Matrix2D &transform,
214
+ const FilterChain &chain) {
215
+ Color filtered = filterColor(chain, color);
216
+ if (filtered.a <= 0.0f) return;
217
+ if (chain.blur <= 0.0f) {
218
+ addRect(out, x, y, width, height, radius, filtered, clip, transform);
219
+ return;
220
+ }
221
+ for (const Tap &tap : blurTaps(chain.blur)) {
222
+ Color copy = filtered;
223
+ copy.a *= kBlurTapWeight;
224
+ addRect(out, x + tap.dx, y + tap.dy, width, height, radius, copy, clip, transform);
225
+ }
226
+ }
227
+
228
+ void addBoxDropShadows(DisplayList &out, const LayoutBox &box, const XtStyle &style,
229
+ const FilterChain &chain, const PaintClip &clip) {
230
+ if (chain.shadows.empty()) return;
231
+ for (const FilterChain::Shadow &shadow : chain.shadows) {
232
+ Color color = filterColor(chain, shadow.color);
233
+ if (color.a <= 0.0f) continue;
234
+ std::vector<Tap> taps = blurTaps(shadow.blur);
235
+ for (const Tap &tap : taps) {
236
+ Color copy = color;
237
+ if (shadow.blur > 0.0f) copy.a *= kBlurTapWeight;
238
+ addRect(out, box.x + shadow.dx + tap.dx, box.y + shadow.dy + tap.dy, box.width, box.height,
239
+ style.border_radius, copy, clip, box.world);
240
+ }
241
+ }
242
+ }
243
+
244
+ void addTextRun(DisplayList &out, float x, float baseline, float width, float height,
245
+ const std::string &text, const FontSpec &font, const Color &color,
246
+ const Matrix2D &transform, const PaintClip &clip, const XtStyle &style,
247
+ const FilterChain &chain, float viewportWidth, float viewportHeight) {
248
+ if (text.empty() || color.a <= 0.0f) return;
249
+ auto emit = [&](float dx, float dy, Color runColor, bool shadow) {
250
+ if (runColor.a <= 0.0f) return;
251
+ PaintText run;
252
+ run.x = x + dx;
253
+ run.baseline = baseline + dy;
254
+ run.width = width;
255
+ run.height = height;
256
+ run.color = runColor;
257
+ run.text = text;
258
+ run.font = font;
259
+ run.transform = transform;
260
+ run.shadow = shadow;
261
+ out.texts.push_back(std::move(run));
262
+ out.ops.push_back(PaintOp{PaintKind::Text, (uint32_t)(out.texts.size() - 1), clip});
263
+ };
264
+
265
+ /* `filter: drop-shadow()` first (behind the glyphs). */
266
+ for (const FilterChain::Shadow &shadow : chain.shadows) {
267
+ Color shadowColor = filterColor(chain, shadow.color);
268
+ for (const Tap &tap : blurTaps(shadow.blur)) {
269
+ Color copy = shadowColor;
270
+ if (shadow.blur > 0.0f) copy.a *= kBlurTapWeight;
271
+ emit(shadow.dx + tap.dx, shadow.dy + tap.dy, copy, true);
272
+ }
273
+ }
274
+
275
+ /* `text-shadow`, bottom-most first: CSS paints later layers under earlier
276
+ * ones, so reverse the declaration list. */
277
+ for (size_t index = style.text_shadow.size(); index-- > 0;) {
278
+ const TextShadow &shadow = style.text_shadow[index];
279
+ float dx = resolveLength(shadow.dx, 0.0f, style.font_size, viewportWidth, viewportHeight);
280
+ float dy = resolveLength(shadow.dy, 0.0f, style.font_size, viewportWidth, viewportHeight);
281
+ float blur =
282
+ resolveLength(shadow.blur, 0.0f, style.font_size, viewportWidth, viewportHeight);
283
+ Color shadowColor = shadow.has_color ? filterColor(chain, shadow.color) : color;
284
+ for (const Tap &tap : blurTaps(blur)) {
285
+ Color copy = shadowColor;
286
+ if (blur > 0.0f) copy.a *= kBlurTapWeight;
287
+ emit(dx + tap.dx, dy + tap.dy, copy, true);
288
+ }
289
+ }
290
+
291
+ /* `filter: blur()` spreads the glyphs themselves. */
292
+ if (chain.blur > 0.0f) {
293
+ for (const Tap &tap : blurTaps(chain.blur)) {
294
+ Color copy = color;
295
+ copy.a *= kBlurTapWeight;
296
+ emit(tap.dx, tap.dy, copy, false);
297
+ }
298
+ return;
299
+ }
300
+ emit(0.0f, 0.0f, color, false);
301
+ }
302
+
303
+ void addImage(DisplayList &out, PaintImage image, const PaintClip &clip,
304
+ const FilterChain &chain) {
305
+ if (image.width <= 0.0f || image.height <= 0.0f) return;
306
+ image.tint = imageTint(chain);
307
+ if (image.tint.a <= 0.0f) return;
308
+ if (chain.blur <= 0.0f) {
309
+ out.images.push_back(std::move(image));
310
+ out.ops.push_back(PaintOp{PaintKind::Image, (uint32_t)(out.images.size() - 1), clip});
311
+ return;
312
+ }
313
+ for (const Tap &tap : blurTaps(chain.blur)) {
314
+ PaintImage copy = image;
315
+ copy.x += tap.dx;
316
+ copy.y += tap.dy;
317
+ copy.tint.a *= kBlurTapWeight;
318
+ out.images.push_back(std::move(copy));
319
+ out.ops.push_back(PaintOp{PaintKind::Image, (uint32_t)(out.images.size() - 1), clip});
320
+ }
321
+ }
322
+
323
+ } // namespace paint_detail
324
+ } // namespace xtgui
@@ -0,0 +1,85 @@
1
+ /*
2
+ * xbintsc GUI engine — shared paint helpers.
3
+ *
4
+ * `paint.cpp` owns the tree walk; the background, effect and clip-path
5
+ * translation units fill in the shapes. They all append through the small
6
+ * `addRect` / `addText` / `addImage` helpers here so painter order and the
7
+ * active clip stay consistent.
8
+ */
9
+ #ifndef XT_GUI_PAINT_INTERNAL_H
10
+ #define XT_GUI_PAINT_INTERNAL_H
11
+
12
+ #include <string>
13
+ #include <vector>
14
+
15
+ #include "paint.h"
16
+ #include "style.h"
17
+
18
+ namespace xtgui {
19
+ namespace paint_detail {
20
+
21
+ /** A resolved chain of `filter` functions. `filter` applies to the element and
22
+ * its subtree, so it accumulates down the tree. Only the colour functions are
23
+ * group-accurate; blur and drop-shadow are approximated per shape (see the
24
+ * docs). */
25
+ struct FilterChain {
26
+ std::vector<FilterOp> ops; // colour functions (and any unknown no-ops)
27
+ float blur = 0.0f; // resolved px
28
+ struct Shadow {
29
+ float dx = 0.0f;
30
+ float dy = 0.0f;
31
+ float blur = 0.0f;
32
+ Color color;
33
+ };
34
+ std::vector<Shadow> shadows;
35
+
36
+ bool empty() const { return ops.empty() && blur <= 0.0f && shadows.empty(); }
37
+ };
38
+
39
+ /** Append `filters` (declared on a box with `style`) to `parent`. */
40
+ FilterChain extendFilter(const FilterChain &parent, const std::vector<FilterOp> &filters,
41
+ const XtStyle &style, float viewportWidth, float viewportHeight);
42
+
43
+ /** Apply the colour half of a filter chain. */
44
+ Color filterColor(const FilterChain &chain, Color color);
45
+
46
+ /** The multiplicative tint an image shader can carry (brightness/opacity). */
47
+ Color imageTint(const FilterChain &chain);
48
+
49
+ float resolveLength(const Length &length, float base, float em, float viewportWidth,
50
+ float viewportHeight);
51
+
52
+ /** Append one shape; skips empty geometry and fully transparent colours. */
53
+ void addRect(DisplayList &out, float x, float y, float width, float height, float radius,
54
+ const Color &color, const PaintClip &clip, const Matrix2D &transform);
55
+ /** Solid rectangle with the chain's blur spread into offset copies. */
56
+ void addRectFiltered(DisplayList &out, float x, float y, float width, float height, float radius,
57
+ const Color &color, const PaintClip &clip, const Matrix2D &transform,
58
+ const FilterChain &chain);
59
+ /** Add a text run (and its shadows/blur copies) for one laid-out fragment. */
60
+ void addTextRun(DisplayList &out, float x, float baseline, float width, float height,
61
+ const std::string &text, const FontSpec &font, const Color &color,
62
+ const Matrix2D &transform, const PaintClip &clip, const XtStyle &style,
63
+ const FilterChain &chain, float viewportWidth, float viewportHeight);
64
+ void addImage(DisplayList &out, PaintImage image, const PaintClip &clip, const FilterChain &chain);
65
+
66
+ /** Paint the `background-color` and every `background-image` layer. */
67
+ void paintBackgrounds(DisplayList &out, const LayoutBox &box, const XtStyle &style,
68
+ const FilterChain &chain, const PaintClip &clip, float viewportWidth,
69
+ float viewportHeight);
70
+
71
+ /** Append the drop-shadow silhouettes of a box (once, before its content). */
72
+ void addBoxDropShadows(DisplayList &out, const LayoutBox &box, const XtStyle &style,
73
+ const FilterChain &chain, const PaintClip &clip);
74
+
75
+ /** Resolve `clip-path` into a device-space triangulated polygon. */
76
+ int addClipPathForBox(DisplayList &out, const LayoutBox &box, const XtStyle &style,
77
+ float viewportWidth, float viewportHeight);
78
+
79
+ /** Push `index` onto a clip chain (at most two survive). */
80
+ PaintClip addClipPath(PaintClip clip, int index);
81
+
82
+ } // namespace paint_detail
83
+ } // namespace xtgui
84
+
85
+ #endif /* XT_GUI_PAINT_INTERNAL_H */