xbintsc 0.5.31 → 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.
- package/README.md +16 -10
- package/dist/src/binder/references.js +14 -1
- package/dist/src/binder/references.js.map +1 -1
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/codegen/generator/module.d.ts +1 -0
- package/dist/src/codegen/generator/module.js +54 -0
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/statements/variables.js +6 -4
- package/dist/src/codegen/generator/statements/variables.js.map +1 -1
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/gui/css.d.ts +26 -0
- package/dist/src/extensions/gui/css.js +100 -0
- package/dist/src/extensions/gui/css.js.map +1 -0
- package/dist/src/extensions/gui/html.js +9 -2
- package/dist/src/extensions/gui/html.js.map +1 -1
- package/dist/src/extensions/gui/index.js +16 -2
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/gui/three.d.ts +16 -0
- package/dist/src/extensions/gui/three.js +22 -0
- package/dist/src/extensions/gui/three.js.map +1 -0
- package/dist/src/extensions/media/index.d.ts +6 -5
- package/dist/src/extensions/media/index.js +12 -14
- package/dist/src/extensions/media/index.js.map +1 -1
- package/dist/tests/e2e/compile-builtins.test.js +24 -0
- package/dist/tests/e2e/compile-builtins.test.js.map +1 -1
- package/dist/tests/e2e/compile-objects-classes.test.js +23 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
- package/dist/tests/e2e/gui-browser.test.js +1 -1
- package/dist/tests/e2e/gui-browser.test.js.map +1 -1
- package/dist/tests/e2e/gui-effects.test.d.ts +6 -0
- package/dist/tests/e2e/gui-effects.test.js +262 -0
- package/dist/tests/e2e/gui-effects.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-webgl.test.d.ts +10 -0
- package/dist/tests/e2e/gui-example-webgl.test.js +75 -0
- package/dist/tests/e2e/gui-example-webgl.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-webgl2.test.d.ts +8 -0
- package/dist/tests/e2e/gui-example-webgl2.test.js +72 -0
- package/dist/tests/e2e/gui-example-webgl2.test.js.map +1 -0
- package/dist/tests/e2e/gui-layout.test.js +48 -0
- package/dist/tests/e2e/gui-layout.test.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.js +5 -4
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl.test.d.ts +11 -0
- package/dist/tests/e2e/gui-webgl.test.js +179 -0
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2.test.js +238 -0
- package/dist/tests/e2e/gui-webgl2.test.js.map +1 -0
- package/dist/tests/extensions/gui.test.js +41 -0
- package/dist/tests/extensions/gui.test.js.map +1 -1
- package/dist/tests/extensions/media.test.js +7 -3
- package/dist/tests/extensions/media.test.js.map +1 -1
- package/doc/ai/extensions.md +29 -9
- package/doc/ai/troubleshooting.md +12 -8
- package/doc/ai/zh-CN/extensions.md +26 -8
- package/doc/ai/zh-CN/troubleshooting.md +10 -6
- package/doc/gui/api.md +3 -2
- package/doc/gui/build.md +72 -16
- package/doc/gui/canvas.md +11 -3
- package/doc/gui/dom.md +33 -18
- package/doc/gui/known-issues.md +57 -24
- package/doc/gui/layout.md +18 -0
- package/doc/gui/media.md +17 -13
- package/doc/gui/rendering.md +50 -3
- package/doc/gui/webgl.md +256 -0
- package/doc/gui.md +108 -17
- package/doc/npm-package.md +6 -4
- package/doc/requirements.md +18 -9
- package/doc/zh-CN/gui/api.md +3 -2
- package/doc/zh-CN/gui/build.md +64 -15
- package/doc/zh-CN/gui/canvas.md +9 -2
- package/doc/zh-CN/gui/dom.md +20 -7
- package/doc/zh-CN/gui/known-issues.md +45 -19
- package/doc/zh-CN/gui/layout.md +14 -0
- package/doc/zh-CN/gui/media.md +15 -11
- package/doc/zh-CN/gui/rendering.md +41 -4
- package/doc/zh-CN/gui/webgl.md +115 -0
- package/doc/zh-CN/gui.md +89 -14
- package/doc/zh-CN/npm-package.md +9 -6
- package/doc/zh-CN/requirements.md +12 -6
- package/llms.txt +2 -0
- package/package.json +1 -1
- package/runtime/ext_gui/browser.cpp +39 -13
- package/runtime/ext_gui/canvas.cpp +3 -18
- package/runtime/ext_gui/canvas_internal.h +10 -0
- package/runtime/ext_gui/canvas_raster.cpp +60 -0
- package/runtime/ext_gui/clip_values.cpp +246 -0
- package/runtime/ext_gui/css.cpp +94 -0
- package/runtime/ext_gui/css.h +22 -1
- package/runtime/ext_gui/css_match.cpp +3 -0
- package/runtime/ext_gui/css_selector.cpp +9 -0
- package/runtime/ext_gui/css_sheet.cpp +89 -45
- package/runtime/ext_gui/document.cpp +4 -1
- package/runtime/ext_gui/document.h +2 -0
- package/runtime/ext_gui/dom.h +16 -0
- package/runtime/ext_gui/dom_api.cpp +1 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +17 -80
- package/runtime/ext_gui/dom_api_canvas_extra.cpp +130 -1
- package/runtime/ext_gui/dom_api_canvas_pending.cpp +41 -0
- package/runtime/ext_gui/dom_api_internal.h +259 -0
- package/runtime/ext_gui/dom_api_webgl.cpp +376 -0
- package/runtime/ext_gui/dom_api_webgl2.cpp +434 -0
- package/runtime/ext_gui/dom_api_webgl2_draw.cpp +269 -0
- package/runtime/ext_gui/dom_api_webgl_buffer.cpp +212 -0
- package/runtime/ext_gui/dom_api_webgl_rt.h +30 -0
- package/runtime/ext_gui/dom_api_webgl_shader.cpp +443 -0
- package/runtime/ext_gui/dom_api_webgl_state.cpp +444 -0
- package/runtime/ext_gui/dom_api_webgl_texture.cpp +445 -0
- package/runtime/ext_gui/effect_values.cpp +312 -0
- package/runtime/ext_gui/gradient_values.cpp +476 -0
- package/runtime/ext_gui/grid_values.cpp +230 -0
- package/runtime/ext_gui/gui_canvas.cpp +50 -2
- package/runtime/ext_gui/gui_engine.h +27 -0
- package/runtime/ext_gui/gui_events.cpp +4 -1
- package/runtime/ext_gui/gui_media.cpp +1 -1
- package/runtime/ext_gui/gui_webgl.cpp +83 -0
- package/runtime/ext_gui/layout.cpp +21 -0
- package/runtime/ext_gui/layout_flow.cpp +81 -4
- package/runtime/ext_gui/layout_flow_internal.h +31 -0
- package/runtime/ext_gui/layout_grid.cpp +374 -0
- package/runtime/ext_gui/media.h +1 -1
- package/runtime/ext_gui/media_api.h +2 -2
- package/runtime/ext_gui/media_query.cpp +211 -0
- package/runtime/ext_gui/paint.cpp +111 -77
- package/runtime/ext_gui/paint.h +33 -3
- package/runtime/ext_gui/paint_background.cpp +229 -0
- package/runtime/ext_gui/paint_clip.cpp +268 -0
- package/runtime/ext_gui/paint_effects.cpp +324 -0
- package/runtime/ext_gui/paint_internal.h +85 -0
- package/runtime/ext_gui/renderer.cpp +8 -31
- package/runtime/ext_gui/renderer_clip.cpp +196 -0
- package/runtime/ext_gui/renderer_image.cpp +13 -8
- package/runtime/ext_gui/renderer_internal.h +15 -8
- package/runtime/ext_gui/renderer_text.cpp +6 -31
- package/runtime/ext_gui/style.cpp +343 -20
- package/runtime/ext_gui/style.h +144 -3
- package/runtime/ext_gui/style_print.cpp +134 -1
- package/runtime/ext_gui/style_values.cpp +152 -126
- package/runtime/ext_gui/style_values_internal.h +35 -0
- package/runtime/ext_gui/webgl.h +466 -0
- package/runtime/ext_gui/webgl2_constants.h +274 -0
- package/runtime/ext_gui/webgl_buffer.cpp +565 -0
- package/runtime/ext_gui/webgl_constants.h +317 -0
- package/runtime/ext_gui/webgl_context.cpp +466 -0
- package/runtime/ext_gui/webgl_draw.cpp +495 -0
- package/runtime/ext_gui/webgl_glsl.h +125 -0
- package/runtime/ext_gui/webgl_glsl_compile.cpp +431 -0
- package/runtime/ext_gui/webgl_glsl_rewrite.cpp +349 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +581 -0
- package/runtime/ext_gui/webgl_msl.cpp +62 -0
- package/runtime/ext_gui/webgl_msl.h +33 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +274 -0
- package/runtime/ext_gui/webgl_program_internal.h +18 -0
- package/runtime/ext_gui/webgl_shader.cpp +582 -0
- package/runtime/ext_gui/webgl_texture.cpp +293 -0
- package/runtime/ext_gui/webgl_uniform.cpp +167 -0
- package/runtime/ext_gui/webgl_webgl2.cpp +224 -0
- package/runtime/ext_media/media.cpp +1 -1
- package/runtime/ext_media/media_bridge.c +9 -3
- package/runtime/rt_internal.h +1 -0
- package/runtime/xt_containers/access.inc +8 -0
- package/runtime/xt_regex/api.inc +2 -0
- package/runtime/xt_regex/matcher.inc +16 -3
- package/runtime/xt_regex/parser.inc +8 -2
- package/runtime/xt_regex/types.inc +3 -0
- package/runtime/xt_stdlib2/regexp-match.inc +60 -21
- package/runtime/xt_stdlib2/regexp.inc +1 -0
- package/runtime/xt_typed_array.c +1 -1
- package/scripts/build-gui.ts +90 -3
- package/scripts/build-media.ts +323 -58
- package/scripts/setup-vs-toolchain.ps1 +152 -0
- package/src/binder/references.ts +13 -1
- package/src/codegen/generator/module.ts +50 -0
- package/src/codegen/generator/statements/variables.ts +6 -3
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/css.ts +113 -0
- package/src/extensions/gui/html.ts +9 -2
- package/src/extensions/gui/index.ts +16 -2
- package/src/extensions/gui/three.ts +25 -0
- package/src/extensions/media/index.ts +13 -16
package/doc/gui/build.md
CHANGED
|
@@ -8,8 +8,14 @@
|
|
|
8
8
|
`runtime/ext_media/` and is built separately.
|
|
9
9
|
- `npm run gui` (`scripts/build-gui.ts`) fetches a pinned SDL3 (`SDL3_TAG`,
|
|
10
10
|
default `release-3.2.10`), builds a static SDL3, fetches and builds static
|
|
11
|
-
FreeType (`FREETYPE_VERSION`) and HarfBuzz (`HARFBUZZ_VERSION`),
|
|
12
|
-
|
|
11
|
+
FreeType (`FREETYPE_VERSION`) and HarfBuzz (`HARFBUZZ_VERSION`), and fetches
|
|
12
|
+
and builds static **glslang** (`GLSLANG_VERSION`, default `16.6.0`) against
|
|
13
|
+
the pinned SPIR-V headers (`SPIRV_HEADERS_VERSION`), and **SPIRV-Cross**
|
|
14
|
+
(`SPIRV_CROSS_VERSION`, default `vulkan-sdk-1.4.313.0`). glslang is the
|
|
15
|
+
runtime GLSL ES compiler behind WebGL and SPIRV-Cross turns its SPIR-V into
|
|
16
|
+
MSL for the Metal backend (see [WebGL](./webgl.md)); both are merged into the
|
|
17
|
+
archive like the other libraries. The script then compiles the engine and
|
|
18
|
+
merges everything into `runtime/lib/<os>-<arch>/gui.a` (or
|
|
13
19
|
`gui.lib` with the MSVC ABI on Windows), same convention as `core.a`,
|
|
14
20
|
statically bundling all three. The merge uses `libtool` on macOS and
|
|
15
21
|
`ar -M` (GNU/LLVM) elsewhere; CMake archives are discovered under the build
|
|
@@ -18,12 +24,13 @@
|
|
|
18
24
|
backend. It fetches FFmpeg (`FFMPEG_VERSION`, default `7.1`), configures a
|
|
19
25
|
minimal static build with only the demuxers/parsers/decoders the media
|
|
20
26
|
elements need, compiles `runtime/ext_media/media.cpp` against it and merges
|
|
21
|
-
everything into `runtime/lib/<os>-<arch>/media.a
|
|
22
|
-
FFmpeg: a program enables playback
|
|
27
|
+
everything into `runtime/lib/<os>-<arch>/media.a` (`media.lib` with the MSVC
|
|
28
|
+
ABI on Windows). `gui.a` does **not** link FFmpeg: a program enables playback
|
|
29
|
+
explicitly with `--ext media`.
|
|
23
30
|
- `src/extensions/gui/index.ts` exposes the engine archive through
|
|
24
31
|
`nativeObjects()` (via `findRuntimeLibrary`, so `.a`/`.lib` both work) and the
|
|
25
32
|
OS frameworks through `linkerFlags()`. `src/extensions/media/index.ts` does
|
|
26
|
-
the same for `media.a` and compiles the registration bridge
|
|
33
|
+
the same for `media.a`/`media.lib` and compiles the registration bridge
|
|
27
34
|
(`runtime/ext_media/media_bridge.c`) as a normal runtime source.
|
|
28
35
|
- `scripts/build-gui.ts` compiles with the *same* clang the driver resolves
|
|
29
36
|
(`src/driver/toolchain-provider.ts`); on Windows that is the MSVC-targeting
|
|
@@ -32,14 +39,39 @@
|
|
|
32
39
|
fallbacks, and Windows always uses `llvm-ar`, so the archive cannot mix object
|
|
33
40
|
formats or C++ runtimes. The Visual Studio toolchain is found by absolute
|
|
34
41
|
path, so no developer prompt is required. On Windows SDL_GPU selects the
|
|
35
|
-
Vulkan backend; no DXIL/`dxc` toolchain is needed.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
Vulkan backend; no DXIL/`dxc` toolchain is needed.
|
|
43
|
+
- `scripts/build-media.ts` uses the same resolved toolchain. On Windows it
|
|
44
|
+
drives FFmpeg's own MSVC mode: `configure --toolchain=msvc --cc=clang-cl`
|
|
45
|
+
compiles static FFmpeg against the static MSVC CRT, `clang++` compiles the
|
|
46
|
+
player, and `llvm-ar` merges the COFF archives into `media.lib`. The compiler
|
|
47
|
+
chain is entirely Visual Studio (clang-cl, `cl.exe`, `lib.exe`, `llvm-ar`).
|
|
48
|
+
FFmpeg's configure is a POSIX shell script and its
|
|
49
|
+
Makefiles need GNU make, so those two build drivers remain: the shell is Git
|
|
50
|
+
for Windows' bundled bash (Git is already required to clone SDL3), and make is
|
|
51
|
+
a native GNU make such as Chocolatey's `make` (or `xbintsc_MAKE`). The script
|
|
52
|
+
rewrites the generated source path to a drive-letter form and skips dependency
|
|
53
|
+
extraction, which native make cannot pass through the MSVC `/showIncludes` awk
|
|
54
|
+
pipeline. The MSVC tools are only needed by configure's toolchain probe; they
|
|
55
|
+
are resolved from the Visual Studio installation, not from a developer prompt.
|
|
56
|
+
`xbintsc_SHELL` and `xbintsc_MAKE` override the discovered shell/make. Headers
|
|
57
|
+
and libraries are copied into `vendor/ffmpeg-build-msvc/dist` by the script
|
|
58
|
+
rather than through `make install`.
|
|
59
|
+
- CI builds `gui.a`/`gui.lib` and `media.a`/`media.lib` before assembling the
|
|
60
|
+
release archive so they ship inside `runtime/lib/<slug>/` (the release tarball
|
|
61
|
+
copies the whole `runtime/` tree). The archives are built and the examples are
|
|
62
|
+
run on Linux (under Xvfb, with the lavapipe software Vulkan driver) and macOS;
|
|
63
|
+
the Windows x64 job builds both archives and links a `gui,media` program, so
|
|
64
|
+
the MSVC build is validated even though *running* the examples there stays
|
|
65
|
+
provisional (the hosted runner has no GPU/Vulkan driver). Windows arm64 still
|
|
66
|
+
skips both archives: FFmpeg's MSVC arm64 build is not validated yet.
|
|
67
|
+
- The Windows CI steps call `.github/actions/vs-toolchain` →
|
|
68
|
+
`scripts/setup-vs-toolchain.ps1`, which imports the same Visual Studio
|
|
69
|
+
`vcvarsall` environment and bundled LLVM a local build uses (no separate
|
|
70
|
+
Chocolatey LLVM). For the media build the action also installs GNU make
|
|
71
|
+
through Chocolatey and points `xbintsc_MAKE` at it; the FFmpeg source and the
|
|
72
|
+
installed `vendor/ffmpeg-build-msvc/dist` prefix are cached by script hash.
|
|
73
|
+
The configure/make tree itself is not cached (absolute paths and compiler
|
|
74
|
+
options from another machine).
|
|
43
75
|
- The existing cache fingerprint already hashes `nativeObjects()` contents and
|
|
44
76
|
`runtimeSources()` content, so rebuilding either archive invalidates cached
|
|
45
77
|
binaries automatically.
|
|
@@ -65,6 +97,28 @@ npm run media # optional: build media.a (fetches and builds FFmpeg once)
|
|
|
65
97
|
xbintsc run examples/gui/hello.ts --ext gui
|
|
66
98
|
```
|
|
67
99
|
|
|
100
|
+
On Windows the same commands produce `gui.lib` and `media.lib` from a normal
|
|
101
|
+
PowerShell — no developer command prompt. The Visual Studio installation
|
|
102
|
+
supplies the MSVC-targeting `clang++`, `clang-cl`, `cl.exe` and `lib.exe`, and
|
|
103
|
+
`npm run media` additionally needs a POSIX shell and GNU make for FFmpeg's
|
|
104
|
+
`configure`: Git for Windows supplies the shell (and is already needed to clone
|
|
105
|
+
SDL3), while GNU make is a native binary — install it with `choco install make`,
|
|
106
|
+
or point `xbintsc_MAKE` at one. The script reports whichever tool is missing and
|
|
107
|
+
accepts `xbintsc_SHELL` / `xbintsc_MAKE` overrides.
|
|
108
|
+
|
|
109
|
+
To select that toolchain explicitly (useful in a fresh shell or to pin the same
|
|
110
|
+
compiler CI uses), run:
|
|
111
|
+
|
|
112
|
+
```powershell
|
|
113
|
+
pwsh -File scripts/setup-vs-toolchain.ps1
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
It imports `vcvarsall` (MSVC, Windows SDK, MSBuild) and points `xbintsc_CLANG`
|
|
117
|
+
at the LLVM bundled with that Visual Studio installation. GitHub Actions uses
|
|
118
|
+
the same script through `.github/actions/vs-toolchain`, so no separate
|
|
119
|
+
Chocolatey/standalone LLVM is installed there and CI, local builds and the
|
|
120
|
+
prebuilt archives share one compiler chain.
|
|
121
|
+
|
|
68
122
|
Two examples live here: `hello.ts` (HTML/CSS + a reactive counter) and
|
|
69
123
|
[`pelican-bike/`](../../examples/gui/pelican-bike), a playable 2D game that uses
|
|
70
124
|
positioned layers, CSS sprites, `requestAnimationFrame` and keyboard input — see
|
|
@@ -82,11 +136,13 @@ which the e2e test (`tests/e2e/gui-*.test.ts`) uses to run headlessly.
|
|
|
82
136
|
|
|
83
137
|
Those suites are skipped on Windows by default (the archive is built and runs
|
|
84
138
|
locally through Vulkan, but CI runners have no GPU driver to run it). With a
|
|
85
|
-
`gui.lib` and a working GPU, opt in with `xbintsc_GUI_TESTS=1
|
|
139
|
+
`gui.lib` and a working GPU, opt in with `xbintsc_GUI_TESTS=1`; if you also ran
|
|
140
|
+
`npm run media`, the media suite then exercises the real decoder on Windows too:
|
|
86
141
|
|
|
87
142
|
```bat
|
|
88
143
|
set xbintsc_GUI_TESTS=1
|
|
89
144
|
npx vitest run tests/e2e/gui-layout.test.ts tests/e2e/gui-example.test.ts
|
|
145
|
+
npx vitest run tests/e2e/gui-media.test.ts
|
|
90
146
|
```
|
|
91
147
|
|
|
92
148
|
On a headless Linux box, install the SDL3 build headers and run under Xvfb with a
|
|
@@ -101,8 +157,8 @@ xvfb-run -a --server-args="-screen 0 1280x720x24" \
|
|
|
101
157
|
```
|
|
102
158
|
|
|
103
159
|
The media e2e suite (`tests/e2e/gui-media.test.ts`) skips itself unless both
|
|
104
|
-
`gui.a` and `media.a` exist; `tests/e2e/gui-media-disabled.test.ts`
|
|
105
|
-
GUI-only build and runs with
|
|
160
|
+
`gui.a`/`gui.lib` and `media.a`/`media.lib` exist; `tests/e2e/gui-media-disabled.test.ts`
|
|
161
|
+
covers the GUI-only build and runs with the GUI archive alone.
|
|
106
162
|
|
|
107
163
|
`scripts/install-gui-deps.sh` holds the package list (`apt-get install -y clang
|
|
108
164
|
cmake libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev
|
package/doc/gui/canvas.md
CHANGED
|
@@ -23,9 +23,14 @@ state parsing in `canvas_style.cpp`; the DOM bindings live in
|
|
|
23
23
|
|
|
24
24
|
```ts
|
|
25
25
|
const canvas: any = document.getElementById("c");
|
|
26
|
-
const ctx = canvas.getContext("2d"); // or
|
|
26
|
+
const ctx = canvas.getContext("2d"); // or "webgl" for a GPU context
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
A canvas has one context kind. `getContext("webgl")` or `getContext("webgl2")`
|
|
30
|
+
returns a WebGL context (see [WebGL](./webgl.md)); once a canvas has a 2D context,
|
|
31
|
+
asking for either WebGL kind answers `null`, and vice versa. A canvas that never
|
|
32
|
+
asked for a context stays transparent.
|
|
33
|
+
|
|
29
34
|
`getContext("2d")` returns a context handle whose methods and accessors live on
|
|
30
35
|
a shared prototype. The handle is cached on the element, so every call returns
|
|
31
36
|
the **same** object and the drawing state (transform, styles, path) is per
|
|
@@ -101,8 +106,11 @@ rotate the glyph bitmaps. `strokeText` currently fills with the stroke style
|
|
|
101
106
|
rather than producing an outline.
|
|
102
107
|
|
|
103
108
|
Images: `drawImage(source, …)` in the 3-argument (`dx, dy`), 5-argument
|
|
104
|
-
(`dx, dy, dw, dh`) and 9-argument (`dx, dy, dw, dh, sx, sy, sw, sh
|
|
105
|
-
|
|
109
|
+
(`dx, dy, dw, dh`) and 9-argument (`dx, dy, dw, dh, sx, sy, sw, sh`; this
|
|
110
|
+
engine's 9-argument form is destination-first) forms. A full affine transform
|
|
111
|
+
(rotation/skew/scale) is honoured: the destination rectangle becomes a
|
|
112
|
+
parallelogram and every device pixel is inverse-mapped to the source rectangle
|
|
113
|
+
(nearest-neighbour). `source` may be an `<img>` element (decoded through the image module) or another
|
|
106
114
|
`<canvas>` element (its current bitmap). Sampling is nearest-neighbour, so a
|
|
107
115
|
large upscale of a small source is blocky — fine for icons and pixel art, not a
|
|
108
116
|
photo pipeline.
|
package/doc/gui/dom.md
CHANGED
|
@@ -11,28 +11,43 @@ comments and doctype skipped, entity decoding (named + numeric/hex), void
|
|
|
11
11
|
elements, raw-text elements (`<style>`/`<script>`), and the common implicit
|
|
12
12
|
close rules (`li`, `dt`/`dd`, `option`, `p`, headings, table cells/rows).
|
|
13
13
|
|
|
14
|
-
**CSS parser** (`runtime/ext_gui/css.{h,cpp}`): comments
|
|
15
|
-
(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
(`
|
|
24
|
-
`
|
|
25
|
-
|
|
26
|
-
`transform
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
**CSS parser** (`runtime/ext_gui/css.{h,cpp}`): comments are stripped; `@media`
|
|
15
|
+
blocks are parsed recursively (nested queries combine with `and`, and a comma
|
|
16
|
+
list distributes over the inner query) while other at-rules are skipped. Rules
|
|
17
|
+
support multiple selectors and declarations. Selectors: type, `.class`, `#id`,
|
|
18
|
+
attribute (`=`, `~=`, `|=`, `^=`, `$=`, `*=`), the four combinators
|
|
19
|
+
(descendant, child, adjacent and general sibling), the pseudo-classes
|
|
20
|
+
`:first-child`, `:last-child`, `:only-child`, `:empty`, `:root`, `:not(...)`,
|
|
21
|
+
`:nth-child(an+b)`, `:disabled`, `:checked`, plus the stateful `:hover` and
|
|
22
|
+
`:focus` (see [Input](./input.md)), and the pseudo-elements `::before`/`::after`
|
|
23
|
+
(legacy `:before`/`:after` too). Values: lengths (`px`, `%`, `em`, `rem`, `vw`,
|
|
24
|
+
`vh`, `pt`, `pc`, `in`, `cm`, `mm`, `q`), colors (hex, `rgb()`/`rgba()`, a named
|
|
25
|
+
subset), numbers, keywords and shorthands (`margin`/`padding`/`border`/`flex`).
|
|
26
|
+
`transform` (`translate`/`translate3d`/`translateX`/`translateY`, `scale`/
|
|
27
|
+
`scale3d`/`scaleX`/`scaleY`, `rotate`/`rotateZ`, `matrix`; the `3d` spellings'
|
|
28
|
+
`z` argument is dropped) and `transform-origin` are parsed into the computed
|
|
29
|
+
style as a list of operations plus two (unresolved) origin lengths; an
|
|
30
|
+
unsupported function invalidates the whole declaration
|
|
31
|
+
([Layout](./layout.md#transforms-m15)). M19 adds `background-image` layer lists
|
|
32
|
+
(linear/radial), `clip-path` (`inset`/`circle`/`ellipse`/`polygon`), the
|
|
33
|
+
`filter`/`backdrop-filter` function lists, `text-shadow` and `content`.
|
|
29
34
|
|
|
30
35
|
**Cascade & computed style** (`runtime/ext_gui/style.{h,cpp}`): a small built-in
|
|
31
36
|
UA stylesheet, author rules sorted by `(!important, specificity, source order)`,
|
|
32
37
|
then inline `style=""` (highest specificity, but non-`!important` inline loses to
|
|
33
|
-
`!important`), plus CSS inheritance of the text properties.
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
`!important`), plus CSS inheritance of the text properties. `@media` rules are
|
|
39
|
+
filtered against the current viewport on every restyle, so a resize switches
|
|
40
|
+
them. Relative lengths are kept unresolved until layout, except `font-size`
|
|
41
|
+
(resolved against the *parent* font size) and `line-height`.
|
|
42
|
+
|
|
43
|
+
`::before`/`::after` styles are computed after their originating element: the
|
|
44
|
+
selector's last compound must name the pseudo-element, and the rest of the
|
|
45
|
+
selector is matched against the origin (so `.card.info::before` works). The
|
|
46
|
+
pseudo style inherits the origin's computed style, `content` is resolved
|
|
47
|
+
(strings, escapes, `attr()`, quotes), and a synthetic node is placed in a
|
|
48
|
+
per-restyle arena. Layout inserts its box before/after the real children;
|
|
49
|
+
traversal, queries, `innerHTML` and `elementIndex()` never see it, and hit
|
|
50
|
+
testing targets the origin element.
|
|
36
51
|
|
|
37
52
|
## Interactive DOM (M8)
|
|
38
53
|
|
package/doc/gui/known-issues.md
CHANGED
|
@@ -5,15 +5,24 @@
|
|
|
5
5
|
|
|
6
6
|
## Known issues
|
|
7
7
|
|
|
8
|
-
- **
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
- **WebGL 1.0 and 2.0 run on the GPU, with a subset of each.**
|
|
9
|
+
`canvas.getContext("webgl")` / `"webgl2"` return real GPU contexts (see
|
|
10
|
+
[WebGL](./webgl.md)): GLSL ES shaders are translated to SPIR-V by the bundled
|
|
11
|
+
glslang — consumed directly by the Vulkan backend, or cross-compiled to MSL by
|
|
12
|
+
the bundled SPIRV-Cross for Metal — and the drawing buffer is an offscreen
|
|
13
|
+
colour texture that the page composites without a readback. WebGL 2 adds VAOs,
|
|
14
|
+
instancing, integer attributes, sampler objects, `texStorage2D` and buffer
|
|
15
|
+
copies. Uniform blocks, transform feedback, cube maps, 3D textures,
|
|
16
|
+
float/depth textures, compressed textures, multiple render targets,
|
|
17
|
+
`blitFramebuffer`, MSAA and stencil operations are not implemented; `clear`
|
|
18
|
+
ignores the scissor rectangle. On an SDL_GPU backend that accepts neither
|
|
19
|
+
SPIR-V nor MSL (Direct3D 12, which would need DXIL) both context kinds are
|
|
20
|
+
`null`. The `.js` asset loader now patches only three.js's shader unroller;
|
|
21
|
+
`WebGLRenderer` runs on the real backend and there is no Canvas2D fallback.
|
|
22
|
+
Shadow maps (depth textures), cube textures/environment maps and HDR render
|
|
23
|
+
targets remain unsupported.
|
|
24
|
+
|
|
25
|
+
|
|
17
26
|
|
|
18
27
|
- **Intermittent crash at auto-close.** `XT_GUI_AUTOCLOSE_MS` can end a run
|
|
19
28
|
with a native access violation in roughly two runs out of five; a clean exit
|
|
@@ -44,6 +53,23 @@
|
|
|
44
53
|
*class change* on a flex container has also been observed to crash the same
|
|
45
54
|
way; `examples/gui/pelican-bike` reveals its game-over overlay with `opacity`
|
|
46
55
|
instead.
|
|
56
|
+
- **CSS coverage is a deliberate subset.** Grid, `clamp()`/`min()`/`max()`/`env()`,
|
|
57
|
+
`var()` custom properties, the `inset` shorthand, `box-sizing`, `visibility` and
|
|
58
|
+
`pointer-events`, `@media` queries, generated content (`::before`/`::after`),
|
|
59
|
+
multi-layer linear/radial backgrounds, `text-shadow`, `clip-path`
|
|
60
|
+
(`inset`/`circle`/`ellipse`/`polygon`) and `filter` colour functions are
|
|
61
|
+
implemented. Known limits: `mix-blend-mode`, `background-clip`,
|
|
62
|
+
`background-position`/`size`/`repeat`, repeating gradients and `backdrop-filter`
|
|
63
|
+
compositing are not implemented (`backdrop-filter` parses and cascades, but
|
|
64
|
+
sampling the backdrop needs an offscreen layer, so it paints nothing);
|
|
65
|
+
`filter: blur()` is a nine-tap per-shape spread rather than a true group blur,
|
|
66
|
+
so overlapping descendants can darken; `drop-shadow` is approximated from box
|
|
67
|
+
silhouettes; at most two nested `clip-path` shapes are intersected (deeper
|
|
68
|
+
nesting keeps the outer two); and images/canvases are not colour-filtered
|
|
69
|
+
except for the brightness/opacity tint the image shader can carry. Canvas
|
|
70
|
+
textures are sampled nearest-neighbour. Background gradients remain solid
|
|
71
|
+
bands (18 for linear, 32 concentric ellipses for radial), so a soft gradient
|
|
72
|
+
may show slight banding.
|
|
47
73
|
- **SVG is NanoSVG's subset.** SVG *files* (`<img src="logo.svg">`) and inline
|
|
48
74
|
`<svg>` trees share the vendored NanoSVG parser/rasteriser
|
|
49
75
|
(`runtime/ext_gui/svg.cpp`, `inline_svg.cpp`), which renders
|
|
@@ -72,23 +98,30 @@
|
|
|
72
98
|
MSVC-targeting clang as the driver (the LLVM bundled with Visual Studio when
|
|
73
99
|
no newer one is on `PATH`), so a developer prompt is not required.
|
|
74
100
|
- Windows: an MSVC-compatible `gui.lib` (COFF objects + `ar -M`/`llvm-ar`) is
|
|
75
|
-
produced by `scripts/build-gui.ts
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
101
|
+
produced by `scripts/build-gui.ts`. The Windows x64 CI job builds it with the
|
|
102
|
+
Visual Studio toolchain (`.github/actions/vs-toolchain` imports `vcvarsall`
|
|
103
|
+
and uses VS's bundled LLVM), links a `gui,media` program, and ships it in the
|
|
104
|
+
x64 release. *Running* the examples on the hosted runner stays provisional
|
|
105
|
+
because it has no GPU/Vulkan driver (SDL_GPU selects the **Vulkan** backend
|
|
106
|
+
there, so no DXIL/`dxc` toolchain is needed). Windows arm64 still skips both
|
|
107
|
+
archives. Building and running `examples/gui/pelican-svg` and
|
|
108
|
+
`examples/gui/pelican-bike` on a developer machine works.
|
|
109
|
+
- **Windows: x64 builds in CI, arm64 and runtime validation stay provisional.**
|
|
110
|
+
`media.lib` is produced by `scripts/build-media.ts` with FFmpeg's MSVC
|
|
111
|
+
toolchain (`--toolchain=msvc --cc=clang-cl`) so its COFF objects and static CRT
|
|
112
|
+
match `gui.lib`, and `--ext media` links and plays there. Building it needs a
|
|
113
|
+
POSIX shell to run FFmpeg's `configure` and GNU make; the shell comes from Git
|
|
114
|
+
for Windows (already needed to clone SDL3), and make is a native GNU make
|
|
115
|
+
(Chocolatey's `make`, or `xbintsc_MAKE`). CI installs make explicitly,
|
|
116
|
+
builds `gui.lib` + `media.lib` on Windows x64 (using the same Visual Studio
|
|
117
|
+
`vcvarsall` + bundled LLVM as a local build), links a `gui,media` program, and
|
|
118
|
+
ships both archives in the Windows x64 release; the example *run* remains
|
|
119
|
+
provisional because hosted runners have no GPU/Vulkan driver. Windows arm64
|
|
120
|
+
still skips both archives, and `<video controls>` is likewise deferred — the
|
|
121
|
+
intended pattern is TS + a CSS overlay, as in `examples/gui/media.ts`.
|
|
89
122
|
- **D3D12 shaders:** the SPIR-V (Vulkan) and DXIL (Direct3D 12) blobs are built
|
|
90
123
|
and embedded, so the non-Metal path no longer skips geometry. DXIL remains
|
|
91
124
|
unusable on **SDL 3.2.10**: its D3D12 backend rejects any graphics pipeline
|
|
92
125
|
whose shaders declare a uniform buffer, and the engine passes the viewport that
|
|
93
126
|
way. This does not affect Windows in practice because SDL_GPU selects Vulkan
|
|
94
|
-
there; re-check after an SDL upgrade if the D3D12 path is ever forced.
|
|
127
|
+
there; re-check after an SDL upgrade if the D3D12 path is ever forced.
|
package/doc/gui/layout.md
CHANGED
|
@@ -32,6 +32,24 @@ with absolute (viewport-relative) geometry:
|
|
|
32
32
|
Item margins are part of the item's outer size on both axes, so a negative
|
|
33
33
|
`margin-top` pulls an item up instead of being ignored. Whitespace-only text
|
|
34
34
|
between items (source indentation) does not become a flex item.
|
|
35
|
+
- **Grid** — `display: grid` with `grid-template-columns` / `grid-template-rows`
|
|
36
|
+
(fixed lengths, `auto`, `<n>fr`, `minmax(...)`, `repeat(...)`), `gap` /
|
|
37
|
+
`row-gap` / `column-gap`, row-major auto-placement, simple `grid-column` /
|
|
38
|
+
`grid-row` line placement, and `align/justify-items` plus
|
|
39
|
+
`align/justify-self` (including `place-items` / `place-self`). Implicit rows
|
|
40
|
+
and columns grow from the items; a single-cell grid with `place-items: center` centres a card in the whole overlay. Item measurement is a two-pass
|
|
41
|
+
layout (intrinsic size, then final placement), so text fragments are cleared
|
|
42
|
+
between passes.
|
|
43
|
+
- **CSS value functions and custom properties** — `clamp(min, value, max)`,
|
|
44
|
+
`min(...)` and `max(...)` keep their arguments unresolved in the computed style
|
|
45
|
+
and are evaluated at layout time against the element's font size and the
|
|
46
|
+
viewport (`vw`/`vh`); `env(safe-area-inset-*)` resolves to zero in a desktop
|
|
47
|
+
window. `var(--name[, fallback])` is substituted from inherited custom
|
|
48
|
+
properties during the cascade. `inset` is the four-value
|
|
49
|
+
`top/right/bottom/left` shorthand, `box-sizing: border-box` subtracts padding
|
|
50
|
+
and borders from an explicit width/height, `visibility: hidden` skips painting
|
|
51
|
+
and hit testing, and `pointer-events: none` makes a box transparent to input
|
|
52
|
+
(its descendants can opt back in with `auto`).
|
|
35
53
|
- **Positioning** — `position: relative` offsets a box (and its subtree) by
|
|
36
54
|
`top`/`right`/`bottom`/`left` without changing the space it reserved;
|
|
37
55
|
`position: absolute` (and `fixed`, which resolves against the viewport) takes
|
package/doc/gui/media.md
CHANGED
|
@@ -68,21 +68,24 @@ clip paths are not rendered (see [Known issues](./known-issues.md)).
|
|
|
68
68
|
Media playback is split across two extensions so a GUI program does not pay for
|
|
69
69
|
a decoder it never uses:
|
|
70
70
|
|
|
71
|
-
- **`gui`** (`gui.a`) owns the `<video>`/`<audio>` elements, the DOM
|
|
72
|
-
renderer integration and the SDL audio sink, but contains **no
|
|
73
|
-
`runtime/ext_gui/media.{h,cpp}` declares the player interface and
|
|
74
|
-
through a table the media backend installs at startup
|
|
71
|
+
- **`gui`** (`gui.a`/`gui.lib`) owns the `<video>`/`<audio>` elements, the DOM
|
|
72
|
+
API, the renderer integration and the SDL audio sink, but contains **no
|
|
73
|
+
FFmpeg**. `runtime/ext_gui/media.{h,cpp}` declares the player interface and
|
|
74
|
+
dispatches through a table the media backend installs at startup
|
|
75
75
|
(`runtime/ext_gui/media_api.h`).
|
|
76
|
-
- **`media`** (`media.a`, `
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
- **`media`** (`media.a`, or `media.lib` with the MSVC ABI on Windows;
|
|
77
|
+
`runtime/ext_media/`) is the optional decoder backend:
|
|
78
|
+
`runtime/ext_media/media.cpp` wraps a statically vendored **FFmpeg** build,
|
|
79
|
+
and `runtime/ext_media/media_bridge.c` registers it with the engine. Enable it
|
|
80
|
+
with `--ext media` (or `--ext gui,media`). `media` requires `gui`; the
|
|
81
|
+
registry rejects the combination in the wrong order.
|
|
81
82
|
|
|
82
83
|
Without the `media` extension the element still exists and its DOM API is
|
|
83
|
-
callable, but opening a source fails and fires `error`.
|
|
84
|
-
|
|
85
|
-
media
|
|
84
|
+
callable, but opening a source fails and fires `error`. The same happens on any
|
|
85
|
+
host where the archive has not been built (run `npm run media`); Windows is no
|
|
86
|
+
longer special: `media.lib` is FFmpeg compiled with clang-cl for the MSVC ABI,
|
|
87
|
+
so it links against `gui.lib` and plays normally. There is no WebView and no
|
|
88
|
+
platform media framework in the path either way.
|
|
86
89
|
|
|
87
90
|
- **Decoding.** `avformat_open_input` opens the `src` (a path — `file://` is
|
|
88
91
|
accepted, but media paths are *not* percent-decoded, unlike images), the
|
|
@@ -104,7 +107,8 @@ media framework in the path either way.
|
|
|
104
107
|
push mode (`NULL` callback), buffering about 0.25 s ahead at 48 kHz stereo
|
|
105
108
|
`SDL_AUDIO_F32`. `volume` maps to `SDL_SetAudioStreamGain`; audio is
|
|
106
109
|
best-effort and is skipped when no device is available (headless CI). Keeping
|
|
107
|
-
the sink in
|
|
110
|
+
the sink in the GUI archive means `media.a`/`media.lib` depends only on
|
|
111
|
+
FFmpeg.
|
|
108
112
|
- **Threading.** The engine is single-threaded and not thread-aware, so all
|
|
109
113
|
decoding happens on the main thread inside `xt_gui_media_tick` — no decode
|
|
110
114
|
thread, no cross-thread GC exposure.
|
package/doc/gui/rendering.md
CHANGED
|
@@ -10,8 +10,9 @@ emits a backend-agnostic `DisplayList`: a painter-order `ops` list of
|
|
|
10
10
|
**rectangles** (backgrounds and four solid border edges, with `border-radius`),
|
|
11
11
|
**text runs** (each carrying its text, colour and resolved `FontSpec`) and
|
|
12
12
|
**images**, backed by parallel payload arrays. Each op also carries the active
|
|
13
|
-
clip rectangle (the padding box of the nearest `overflow: hidden` ancestor)
|
|
14
|
-
|
|
13
|
+
clip rectangle (the padding box of the nearest `overflow: hidden` ancestor) and
|
|
14
|
+
up to two indices into the display list's triangulated `clip-path` polygons, so
|
|
15
|
+
`overflow`/`clip-path` clipping and `z-index` ordering survive into the renderer.
|
|
15
16
|
`DisplayList::dump()` feeds `paintList()`/`paintCount()`.
|
|
16
17
|
|
|
17
18
|
`opacity` is honoured only at its extremes: a box whose computed `opacity` is
|
|
@@ -73,7 +74,53 @@ divided back into logical units, exactly the way HiDPI scaling already worked.
|
|
|
73
74
|
|
|
74
75
|
The window background (`setBackground`) is the render-pass clear colour.
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
### Backgrounds, generated content and effects (M19)
|
|
78
|
+
|
|
79
|
+
`background-color` and every `background-image` layer are painted. A
|
|
80
|
+
comma-separated layer list is painted bottom-up (the first declaration layer is
|
|
81
|
+
topmost), and both gradient kinds are supported:
|
|
82
|
+
|
|
83
|
+
- a **linear** gradient is sampled at 18 points and emitted as solid rectangles;
|
|
84
|
+
`to <side>`, `deg`/`grad`/`rad`/`turn`, percentage and multi-stop colours work
|
|
85
|
+
(the band walk is axis-aligned, so an oblique angle uses the nearest axis);
|
|
86
|
+
- a **radial** gradient is 32 concentric ellipses. Each is a unit-radius rounded
|
|
87
|
+
rectangle mapped through the shape pipeline's transform slot, so a circle or
|
|
88
|
+
ellipse keeps the distance-field antialiasing. Shape/size keywords
|
|
89
|
+
(`circle`/`ellipse`, `closest-side`/`farthest-side`/`closest-corner`/
|
|
90
|
+
`farthest-corner`, explicit radii) and `at <position>` are parsed.
|
|
91
|
+
|
|
92
|
+
The background colour sits under every layer. Gradients are partially
|
|
93
|
+
transparent if their stops are, and the band approximation can show banding and
|
|
94
|
+
alpha stacking on a very translucent multi-stop gradient.
|
|
95
|
+
|
|
96
|
+
**Generated content** needs no new display-list kind: `::before`/`::after` are
|
|
97
|
+
ordinary layout boxes owned by the per-restyle arena in `style.cpp`, so their
|
|
98
|
+
background, border, text and transforms flow through the same paint walk.
|
|
99
|
+
`content` is resolved from strings, `attr()` and open/close quotes.
|
|
100
|
+
|
|
101
|
+
**`text-shadow`** is emitted as shadow `PaintText` runs *before* the real run, so
|
|
102
|
+
the text pipeline draws them without a new shader. A blurred shadow is nine
|
|
103
|
+
translucent copies spread around the offset (the same approximation `filter:
|
|
104
|
+
blur()` uses).
|
|
105
|
+
|
|
106
|
+
**`clip-path`** is resolved in `paint_clip.cpp` to a device-space polygon (the
|
|
107
|
+
box transform is applied to every point), triangulated with ear clipping, and
|
|
108
|
+
stored on `DisplayList::clip_paths`. Ops carry up to two path indices on their
|
|
109
|
+
`PaintClip`; `renderer_clip.cpp` intersects each convex shape/glyph/image quad
|
|
110
|
+
with those triangles at upload time. The result is exact even for concave
|
|
111
|
+
`polygon()` shapes, needs no stencil or shader change, and the edges are hard
|
|
112
|
+
(no analytic antialiasing). Intersecting two nested paths is supported; deeper
|
|
113
|
+
nesting keeps the outermost two.
|
|
114
|
+
|
|
115
|
+
**`filter`** colour functions (`brightness`, `contrast`, `grayscale`, `sepia`,
|
|
116
|
+
`invert`, `saturate`, `hue-rotate`, `opacity`) are folded into each painted
|
|
117
|
+
colour, so a box and its descendants see the filter. `blur()` and
|
|
118
|
+
`drop-shadow()` are approximations at the display-list level: blur spreads nine
|
|
119
|
+
translucent copies per shape, drop-shadow is a box/text silhouette. This keeps
|
|
120
|
+
the single render pass — there is no offscreen render target — at the cost of
|
|
121
|
+
group semantics: overlapping descendants of a blurred/filtered group can darken,
|
|
122
|
+
and `backdrop-filter` cannot sample what is behind the element, so it parses and
|
|
123
|
+
cascades but paints nothing.
|
|
77
124
|
|
|
78
125
|
## Text stack (M4b)
|
|
79
126
|
|