xbintsc 0.5.32 → 0.5.37
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 +10 -7
- package/README.zh-CN.md +10 -8
- package/dist/scripts/check-version.d.ts +27 -0
- package/dist/scripts/check-version.js +71 -0
- package/dist/scripts/check-version.js.map +1 -0
- package/dist/scripts/package-platform.d.ts +58 -0
- package/dist/scripts/package-platform.js +142 -0
- package/dist/scripts/package-platform.js.map +1 -0
- package/dist/scripts/verify-platform-package.d.ts +34 -0
- package/dist/scripts/verify-platform-package.js +161 -0
- package/dist/scripts/verify-platform-package.js.map +1 -0
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/cli/main.js +3 -1
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/driver/runtime-lib.d.ts +29 -4
- package/dist/src/driver/runtime-lib.js +68 -10
- package/dist/src/driver/runtime-lib.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/index.js +18 -5
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/media/index.js +4 -3
- package/dist/src/extensions/media/index.js.map +1 -1
- package/dist/src/parser/context.d.ts +41 -0
- package/dist/src/parser/context.js +89 -4
- package/dist/src/parser/context.js.map +1 -1
- package/dist/src/parser/literals.js +6 -12
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/driver/platform-package.test.d.ts +1 -0
- package/dist/tests/driver/platform-package.test.js +49 -0
- package/dist/tests/driver/platform-package.test.js.map +1 -0
- package/dist/tests/driver/runtime-lib.test.js +51 -4
- package/dist/tests/driver/runtime-lib.test.js.map +1 -1
- package/dist/tests/e2e/gui-audio.test.d.ts +14 -0
- package/dist/tests/e2e/gui-audio.test.js +287 -0
- package/dist/tests/e2e/gui-audio.test.js.map +1 -0
- package/dist/tests/e2e/gui-browser.test.js +65 -0
- package/dist/tests/e2e/gui-browser.test.js.map +1 -1
- package/dist/tests/e2e/gui-canvas-args.test.d.ts +6 -0
- package/dist/tests/e2e/gui-canvas-args.test.js +217 -0
- package/dist/tests/e2e/gui-canvas-args.test.js.map +1 -0
- package/dist/tests/e2e/gui-canvas.test.js.map +1 -1
- package/dist/tests/e2e/gui-dom.test.js +215 -0
- package/dist/tests/e2e/gui-dom.test.js.map +1 -1
- package/dist/tests/e2e/gui-events.test.js +112 -0
- package/dist/tests/e2e/gui-events.test.js.map +1 -1
- package/dist/tests/e2e/gui-helpers.d.ts +7 -0
- package/dist/tests/e2e/gui-helpers.js +1 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.js +78 -0
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-style.test.js +55 -0
- package/dist/tests/e2e/gui-style.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl.test.js +258 -0
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl2-3d.test.d.ts +4 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.js +264 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.js +262 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.d.ts +6 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.js +395 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.d.ts +4 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.js +105 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.d.ts +8 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.js +112 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2.test.js +45 -1
- package/dist/tests/e2e/gui-webgl2.test.js.map +1 -1
- package/dist/tests/extensions/gui-index.test.js +1 -0
- package/dist/tests/extensions/gui-index.test.js.map +1 -1
- package/dist/tests/extensions/media.test.js +1 -0
- package/dist/tests/extensions/media.test.js.map +1 -1
- package/dist/tests/parser/expressions.test.js +30 -0
- package/dist/tests/parser/expressions.test.js.map +1 -1
- package/dist/tests/platform-tarball.test.d.ts +1 -0
- package/dist/tests/platform-tarball.test.js +111 -0
- package/dist/tests/platform-tarball.test.js.map +1 -0
- package/dist/tests/version.test.js +6 -0
- package/dist/tests/version.test.js.map +1 -1
- package/doc/ai/contributing.md +11 -0
- package/doc/ai/extensions.md +7 -4
- package/doc/ai/troubleshooting.md +7 -5
- package/doc/ai/zh-CN/contributing.md +9 -0
- package/doc/ai/zh-CN/extensions.md +4 -2
- package/doc/ai/zh-CN/troubleshooting.md +5 -3
- package/doc/gui/api.md +99 -22
- package/doc/gui/build.md +11 -4
- package/doc/gui/canvas.md +49 -18
- package/doc/gui/dom.md +57 -7
- package/doc/gui/media.md +4 -0
- package/doc/gui/webgl.md +105 -46
- package/doc/gui.md +7 -3
- package/doc/npm-package.md +55 -27
- package/doc/requirements.md +6 -2
- package/doc/zh-CN/gui/api.md +84 -14
- package/doc/zh-CN/gui/build.md +7 -2
- package/doc/zh-CN/gui/canvas.md +44 -19
- package/doc/zh-CN/gui/dom.md +48 -4
- package/doc/zh-CN/gui/media.md +3 -0
- package/doc/zh-CN/gui/webgl.md +22 -16
- package/doc/zh-CN/gui.md +3 -2
- package/doc/zh-CN/npm-package.md +44 -23
- package/doc/zh-CN/requirements.md +4 -1
- package/package.json +17 -1
- package/runtime/ext_gui/audio.cpp +365 -153
- package/runtime/ext_gui/audio_buffer.cpp +166 -0
- package/runtime/ext_gui/audio_buffer.h +37 -0
- package/runtime/ext_gui/audio_decode.cpp +219 -0
- package/runtime/ext_gui/audio_decode.h +39 -0
- package/runtime/ext_gui/audio_device.cpp +87 -0
- package/runtime/ext_gui/audio_effects.cpp +163 -0
- package/runtime/ext_gui/audio_effects.h +25 -0
- package/runtime/ext_gui/audio_internal.h +30 -0
- package/runtime/ext_gui/audio_mixer.cpp +494 -0
- package/runtime/ext_gui/audio_mixer.h +238 -0
- package/runtime/ext_gui/audio_param.cpp +104 -0
- package/runtime/ext_gui/audio_param_object.cpp +155 -0
- package/runtime/ext_gui/browser.cpp +45 -50
- package/runtime/ext_gui/browser_abort.cpp +249 -0
- package/runtime/ext_gui/browser_dialogs.cpp +76 -0
- package/runtime/ext_gui/browser_media.cpp +176 -0
- package/runtime/ext_gui/browser_navigation.cpp +130 -0
- package/runtime/ext_gui/canvas.cpp +88 -30
- package/runtime/ext_gui/canvas.h +74 -9
- package/runtime/ext_gui/canvas_image_data.cpp +143 -0
- package/runtime/ext_gui/canvas_internal.h +8 -5
- package/runtime/ext_gui/canvas_pattern.cpp +90 -0
- package/runtime/ext_gui/canvas_raster.cpp +31 -9
- package/runtime/ext_gui/canvas_style.cpp +4 -2
- package/runtime/ext_gui/css_selector.cpp +21 -3
- package/runtime/ext_gui/dom.h +4 -0
- package/runtime/ext_gui/dom_api.cpp +1 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +120 -114
- package/runtime/ext_gui/dom_api_canvas_extra.cpp +57 -2
- package/runtime/ext_gui/dom_api_canvas_image.cpp +239 -0
- package/runtime/ext_gui/dom_api_canvas_paths.cpp +179 -0
- package/runtime/ext_gui/dom_api_computed_style.cpp +124 -0
- package/runtime/ext_gui/dom_api_dataset.cpp +154 -0
- package/runtime/ext_gui/dom_api_document.cpp +58 -5
- package/runtime/ext_gui/dom_api_events.cpp +93 -17
- package/runtime/ext_gui/dom_api_internal.h +71 -2
- package/runtime/ext_gui/dom_api_mutation.cpp +159 -0
- package/runtime/ext_gui/dom_api_node.cpp +40 -19
- package/runtime/ext_gui/dom_api_node_read.cpp +37 -1
- package/runtime/ext_gui/dom_api_path2d.cpp +358 -0
- package/runtime/ext_gui/dom_api_proto.cpp +35 -0
- package/runtime/ext_gui/dom_api_style.cpp +223 -13
- package/runtime/ext_gui/dom_api_webgl.cpp +7 -0
- package/runtime/ext_gui/dom_api_webgl2.cpp +151 -36
- package/runtime/ext_gui/dom_api_webgl2_draw.cpp +3 -3
- package/runtime/ext_gui/dom_api_webgl_buffer.cpp +6 -2
- package/runtime/ext_gui/dom_api_webgl_compressed.cpp +167 -0
- package/runtime/ext_gui/dom_api_webgl_framebuffer.cpp +160 -0
- package/runtime/ext_gui/dom_api_webgl_shader.cpp +4 -4
- package/runtime/ext_gui/dom_api_webgl_source.cpp +161 -0
- package/runtime/ext_gui/dom_api_webgl_state.cpp +169 -23
- package/runtime/ext_gui/dom_api_webgl_texture.cpp +276 -236
- package/runtime/ext_gui/dom_api_webgl_ubo.cpp +81 -0
- package/runtime/ext_gui/gui.cpp +103 -14
- package/runtime/ext_gui/gui_engine.h +56 -4
- package/runtime/ext_gui/gui_events.cpp +80 -9
- package/runtime/ext_gui/image_bitmap.cpp +28 -0
- package/runtime/ext_gui/image_bitmap.h +26 -0
- package/runtime/ext_gui/image_bitmap_browser.cpp +136 -0
- package/runtime/ext_gui/listener_options.h +43 -0
- package/runtime/ext_gui/media.cpp +32 -0
- package/runtime/ext_gui/media.h +13 -0
- package/runtime/ext_gui/media_api.h +23 -0
- package/runtime/ext_gui/paint.cpp +28 -0
- package/runtime/ext_gui/paint.h +4 -0
- package/runtime/ext_gui/webgl.h +152 -18
- package/runtime/ext_gui/webgl_blit.cpp +95 -0
- package/runtime/ext_gui/webgl_buffer.cpp +178 -263
- package/runtime/ext_gui/webgl_buffer_objects.cpp +270 -0
- package/runtime/ext_gui/webgl_clear.cpp +142 -0
- package/runtime/ext_gui/webgl_compressed.cpp +180 -0
- package/runtime/ext_gui/webgl_context.cpp +241 -156
- package/runtime/ext_gui/webgl_draw.cpp +68 -3
- package/runtime/ext_gui/webgl_draw_buffers.cpp +75 -0
- package/runtime/ext_gui/webgl_glsl.h +40 -0
- package/runtime/ext_gui/webgl_glsl_compile.cpp +6 -0
- package/runtime/ext_gui/webgl_glsl_rewrite.cpp +18 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +20 -11
- package/runtime/ext_gui/webgl_glsl_scan_block.cpp +126 -0
- package/runtime/ext_gui/webgl_glsl_tokens.h +28 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +71 -19
- package/runtime/ext_gui/webgl_program_blocks.cpp +58 -0
- package/runtime/ext_gui/webgl_program_internal.h +6 -0
- package/runtime/ext_gui/webgl_shader.cpp +13 -1
- package/runtime/ext_gui/webgl_state.cpp +228 -0
- package/runtime/ext_gui/webgl_texture.cpp +144 -17
- package/runtime/ext_gui/webgl_texture_3d.cpp +215 -0
- package/runtime/ext_gui/webgl_uniform_block.h +31 -0
- package/runtime/ext_gui/webgl_webgl2.cpp +58 -5
- package/runtime/ext_gui/window.cpp +14 -65
- package/runtime/ext_gui/window_events.cpp +125 -0
- package/runtime/ext_media/decode_audio.cpp +308 -0
- package/runtime/ext_media/media_bridge.c +2 -0
- package/runtime/rt.h +43 -0
- package/runtime/rt_internal.h +4 -0
- package/runtime/xt_array_buffer.c +30 -0
- package/runtime/xt_builtins.c +0 -21
- package/runtime/xt_containers/access.inc +94 -2
- package/runtime/xt_containers/objects.inc +29 -31
- package/runtime/xt_typed_array/elements.inc +13 -0
- package/scripts/build-media.ts +14 -6
- package/scripts/build-runtime.ts +21 -16
- package/scripts/check-version.ts +39 -9
- package/scripts/package-platform.ts +183 -0
- package/scripts/set-platform-version.ts +62 -0
- package/scripts/verify-platform-package.ts +182 -0
- package/src/cli/main.ts +5 -1
- package/src/driver/runtime-lib.ts +73 -9
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/index.ts +18 -5
- package/src/extensions/media/index.ts +4 -3
- package/src/parser/context.ts +99 -4
- package/src/parser/literals.ts +6 -12
package/doc/gui.md
CHANGED
|
@@ -25,7 +25,10 @@ engine bounded memory: see [Node lifetime](./gui/dom.md#node-lifetime) and
|
|
|
25
25
|
thread with a vendored minimal FFmpeg, video frames go through the image texture
|
|
26
26
|
path and audio to an SDL stream, with the DOM media API exposing
|
|
27
27
|
`play`/`pause`/`currentTime`/… and media events. Enabling `gui` alone does not
|
|
28
|
-
link FFmpeg.
|
|
28
|
+
link FFmpeg. The browser globals also get a real `AudioContext`: a 48 kHz mixer
|
|
29
|
+
in `runtime/ext_gui/audio_mixer.cpp` plus `decodeAudioData` (WAV in-engine,
|
|
30
|
+
compressed formats through `media`) — see
|
|
31
|
+
[GUI API](./gui/api.md#web-audio).
|
|
29
32
|
**M14** adds `<canvas>` with a self-written 2D software rasteriser (anti-aliased
|
|
30
33
|
fills, paths, text and `drawImage`) uploaded through the image texture path —
|
|
31
34
|
see [Canvas](./gui/canvas.md). **M15** adds CSS `transform` /
|
|
@@ -188,8 +191,9 @@ engine were Rust.
|
|
|
188
191
|
annotating the run.
|
|
189
192
|
- The `package` job builds `gui.a`/`gui.lib` and `media.a`/`media.lib` before
|
|
190
193
|
assembling the release, so both ship inside the existing runtime archive
|
|
191
|
-
(`package-release` copies all of `runtime/`)
|
|
192
|
-
Windows
|
|
194
|
+
(`package-release` copies all of `runtime/`) and inside the optional
|
|
195
|
+
`@xbintsc/<os>-<arch>` npm package. Windows x64 is included; Windows arm64
|
|
196
|
+
still skips them.
|
|
193
197
|
- `vendor/` (SDL3/FreeType/HarfBuzz for the GUI archive, FFmpeg for `media`)
|
|
194
198
|
is cached per OS/arch, keyed by `scripts/build-gui.ts` /
|
|
195
199
|
`scripts/build-media.ts`. Windows x64 gets its own source cache plus the
|
package/doc/npm-package.md
CHANGED
|
@@ -36,8 +36,9 @@ If you are an agent asked to build a project that already depends on `xbintsc`:
|
|
|
36
36
|
4. Run the artifact (`./build/<name>`, `.exe` on Windows) and report its path.
|
|
37
37
|
5. If the build reports unsupported syntax, read the installed subset guide at
|
|
38
38
|
`node_modules/xbintsc/doc/ai/language-support.md`; do not assume
|
|
39
|
-
Node-compatible TypeScript.
|
|
40
|
-
|
|
39
|
+
Node-compatible TypeScript. With the optional platform package installed the
|
|
40
|
+
first build links a prebuilt runtime; without it, the C runtime is compiled
|
|
41
|
+
from source and that build is noticeably slower.
|
|
41
42
|
|
|
42
43
|
Do not run `npm install` inside `node_modules/xbintsc`, and do not substitute
|
|
43
44
|
`tsc`/`esbuild` for xbintsc: the native artifact must come from `npx xbintsc`.
|
|
@@ -54,15 +55,22 @@ The package contains:
|
|
|
54
55
|
It runs the compiler through Node.js. The binary it produces is still
|
|
55
56
|
standalone: it does not embed Node, V8 or a TypeScript compiler.
|
|
56
57
|
|
|
58
|
+
Installing it also installs the optional `@xbintsc/<os>-<arch>` package for the
|
|
59
|
+
host (for example `@xbintsc/linux-x64`). That package contains the prebuilt
|
|
60
|
+
runtime archives under `runtime/lib/<os>-<arch>/`: `core`, `ext_node` and, where
|
|
61
|
+
the release publishes them, `gui` and `media`. The driver links those archives
|
|
62
|
+
in place, so the first build does not compile the C runtime and needs no extra
|
|
63
|
+
download from the release page.
|
|
64
|
+
|
|
57
65
|
The package does **not** contain:
|
|
58
66
|
|
|
59
|
-
- a C compiler — you need clang 16+ on the machine that builds
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
- a C compiler — you need clang 16+ on the machine that builds.
|
|
68
|
+
|
|
69
|
+
If npm skips the optional package (`--omit=optional`, a package manager that
|
|
70
|
+
does not install optional dependencies, or a host the release does not build
|
|
71
|
+
for), the driver falls back to compiling the C runtime from the shipped sources
|
|
72
|
+
and caches the objects; that build works but is slower, and `--ext gui` /
|
|
73
|
+
`--ext media` need the archive to be present.
|
|
66
74
|
|
|
67
75
|
## Requirements
|
|
68
76
|
|
|
@@ -182,7 +190,7 @@ npm run build:native
|
|
|
182
190
|
./build/main # .\build\main.exe on Windows
|
|
183
191
|
```
|
|
184
192
|
|
|
185
|
-
Expected output
|
|
193
|
+
Expected output:
|
|
186
194
|
|
|
187
195
|
```text
|
|
188
196
|
xbintsc: wrote /absolute/path/my-app/build/main
|
|
@@ -195,17 +203,38 @@ pass the file explicitly: `xbintsc build src/main.ts --out build`.
|
|
|
195
203
|
|
|
196
204
|
## The first build and the cache
|
|
197
205
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
206
|
+
With the platform package installed, the first build links the prebuilt
|
|
207
|
+
`runtime/lib/<os>-<arch>/core.a` (`.lib` on Windows) and does not compile C at
|
|
208
|
+
all, so it takes about as long as an incremental build.
|
|
209
|
+
|
|
210
|
+
If the optional package is missing — `npm install --omit=optional`, a package
|
|
211
|
+
manager that does not install optional dependencies, or a host the release does
|
|
212
|
+
not build for — the driver compiles the C runtime from the shipped sources
|
|
213
|
+
instead. The runtime objects are cached by source/header content hash. The
|
|
214
|
+
default cache is `.xbintsc/` **in the directory you run the command from** (not
|
|
215
|
+
necessarily next to the config file); set `xbintsc_CACHE_DIR` to put it
|
|
216
|
+
elsewhere. Expect that fallback build to take noticeably longer than the ones
|
|
217
|
+
after it.
|
|
218
|
+
|
|
219
|
+
To ignore the platform archive on purpose and compile the runtime from the
|
|
220
|
+
sources shipped in the package — for example after patching `runtime/`, or when
|
|
221
|
+
the prebuilt archive does not match the environment — set:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
xbintsc_PREFER_PREBUILT=0 npx xbintsc build src/main.ts --out build
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
The objects are still cached in `.xbintsc/`; point `xbintsc_CACHE_DIR` at an
|
|
228
|
+
empty directory (or delete `.xbintsc/`) for a full rebuild. `--force` alone
|
|
229
|
+
does not bypass a prebuilt archive. The archive files themselves are produced
|
|
230
|
+
by `npm run runtime` in a source checkout; users never need to regenerate them
|
|
231
|
+
just to compile.
|
|
201
232
|
|
|
202
|
-
|
|
203
|
-
`core.a`, the first build compiles each runtime translation unit. Expect that
|
|
204
|
-
build to take noticeably longer than the ones after it. `--time` shows where the
|
|
205
|
-
time went:
|
|
233
|
+
`--time` shows where the time went:
|
|
206
234
|
|
|
207
235
|
```bash
|
|
208
236
|
npx xbintsc build src/main.ts --out build --time
|
|
237
|
+
# fallback without the platform package:
|
|
209
238
|
# xbintsc: timing (frontend 4ms, codegen 7ms, clang 1089ms, runtime 37770ms, link 1966ms)
|
|
210
239
|
```
|
|
211
240
|
|
|
@@ -220,7 +249,7 @@ Practical consequences:
|
|
|
220
249
|
|
|
221
250
|
- add `.xbintsc/` to `.gitignore`;
|
|
222
251
|
- keep `.xbintsc/` between CI runs (or point `xbintsc_CACHE_DIR` at a persistent
|
|
223
|
-
directory)
|
|
252
|
+
directory) so a fallback build does not recompile the runtime every time;
|
|
224
253
|
- deleting `.xbintsc/` is safe — the next build recreates it;
|
|
225
254
|
- `--force` ignores the build freshness record, but cached runtime objects are
|
|
226
255
|
still reused. Delete `.xbintsc/` if you want to force a full C rebuild.
|
|
@@ -368,17 +397,16 @@ jobs:
|
|
|
368
397
|
| | npm package (`xbintsc`) | Prebuilt release archive |
|
|
369
398
|
| --- | --- | --- |
|
|
370
399
|
| Needs Node.js | Yes, 22+ | No |
|
|
371
|
-
| First build |
|
|
372
|
-
| GUI / media extensions |
|
|
400
|
+
| First build | Links the prebuilt runtime from the optional platform package | Links the prebuilt runtime |
|
|
401
|
+
| GUI / media extensions | Included on Linux/macOS and Windows x64 (the hosts the release builds them for) | Included in Linux/macOS and Windows x64 archives |
|
|
373
402
|
| Installation | `npm install` + lockfile / provenance | Download, verify `.sha256`, unpack |
|
|
374
403
|
| Programmatic API | Yes | No (CLI only) |
|
|
375
404
|
| Cross-compiles | No — host only | No — host only |
|
|
376
|
-
| Best for | Node projects and CI, familiar npm workflow | Machines without Node,
|
|
405
|
+
| Best for | Node projects and CI, familiar npm workflow | Machines without Node, GUI apps, a fully self-contained install |
|
|
377
406
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
development).
|
|
407
|
+
The npm package gets the same prebuilt runtime through its optional platform
|
|
408
|
+
package, so the cold-build penalty only applies when that package is skipped.
|
|
409
|
+
Use a release archive when Node is not available.
|
|
382
410
|
|
|
383
411
|
## Things that differ from a regular Node build
|
|
384
412
|
|
|
@@ -408,10 +436,10 @@ the same file under `node_modules/xbintsc/doc/ai/`.
|
|
|
408
436
|
| `npx xbintsc` uses an unexpected version | Run `npx --no-install xbintsc version` and `npm ls xbintsc`; pin the version in `package.json` and use `npm ci` in CI. |
|
|
409
437
|
| `requires Node.js 22` / engine error | Upgrade Node; the compiler uses modern Node APIs. |
|
|
410
438
|
| `No C compiler found` or `requires clang 16 or newer` | Install clang 16+ and run `npx xbintsc doctor`; set `xbintsc_CLANG` to a specific clang if needed. |
|
|
411
|
-
| The first build takes a long time |
|
|
439
|
+
| The first build takes a long time | The optional `@xbintsc/<os>-<arch>` package was skipped (or this host has no prebuilt package), so the runtime C sources are compiled and cached. Check `npm ls @xbintsc/<os>-<arch>` and reinstall without `--omit=optional`; `--time` confirms. |
|
|
412
440
|
| Permission errors writing `.xbintsc/` | Set `xbintsc_CACHE_DIR` to a writable directory, or run from a writable working directory. |
|
|
413
441
|
| `module 'fs' is provided by the 'node' extension` | Add `--ext node`, or `"extensions": ["node"]` in the config. |
|
|
414
|
-
| `GUI native library not found` / `media native library not found` | The
|
|
442
|
+
| `GUI native library not found` / `media native library not found` | The optional platform package that ships `gui.a`/`gui.lib` or `media.a`/`media.lib` was skipped, or this host has no prebuilt GUI/media archive (Windows arm64). Reinstall without `--omit=optional`, use a Linux/macOS/Windows x64 release archive, or build the archive from a source checkout. |
|
|
415
443
|
| `require("xbintsc")` fails | The package is ESM-only; use `import` (or dynamic `import()`). |
|
|
416
444
|
| Windows link errors about missing MSVC libraries | Run from a Native Tools prompt, install the VS C++ build tools, and check `npx xbintsc doctor`. |
|
|
417
445
|
| `npm ci --omit=dev` then the build cannot find `xbintsc` | Install devDependencies for the build stage, or move `xbintsc` to `dependencies`. |
|
package/doc/requirements.md
CHANGED
|
@@ -81,8 +81,12 @@ xbintsc-<os>-<arch>/
|
|
|
81
81
|
runtime/ C runtime sources + prebuilt runtime/lib/<os>-<arch>/
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
runtime
|
|
84
|
+
Every archive carries the prebuilt runtime for its host under
|
|
85
|
+
`runtime/lib/<os>-<arch>/`: `core` and `ext_node` on all platforms (`.lib`
|
|
86
|
+
instead of `.a` with the MSVC ABI on Windows), plus `gui`/`media` where the
|
|
87
|
+
release builds them. The npm package receives the same archives from its
|
|
88
|
+
optional `@xbintsc/<os>-<arch>` dependency, so an npm install does not compile
|
|
89
|
+
the C runtime either.
|
|
86
90
|
|
|
87
91
|
Unpack it, put `bin/` on `PATH` (or call `bin/xbintsc` directly), and install the
|
|
88
92
|
toolchain for your platform below. Verify the download against the checksum
|
package/doc/zh-CN/gui/api.md
CHANGED
|
@@ -22,14 +22,48 @@ run(); // 驱动主循环,直到所有窗口
|
|
|
22
22
|
`getHTML` / `setBackground` / `close` / `isOpen` / `on` / `off`,以及
|
|
23
23
|
`driver()`——它报告当前使用的 SDL_GPU 后端(`"vulkan"`、`"direct3d12"`、
|
|
24
24
|
`"metal"` 等,由 SDL 挑选设备支持的最佳后端)。同时也提供 Web 写法:
|
|
25
|
-
`addEventListener` / `removeEventListener`
|
|
26
|
-
`
|
|
25
|
+
`addEventListener` / `removeEventListener` 接受标准的选项对象(`capture`、
|
|
26
|
+
`once`、`passive`、`signal`),`closed` getter 对应 `isOpen()`,因此按浏览器
|
|
27
27
|
API 编写的文档可以原样运行。
|
|
28
28
|
|
|
29
|
+
元素监听器支持同一组选项:`{ once }` 在首次调用后移除监听器,`{ passive: true }`
|
|
30
|
+
使 `preventDefault()` 变成无操作,`{ signal }`(来自 `new AbortController()` 的
|
|
31
|
+
`AbortSignal`)在 abort 时移除监听器,包括添加时就已经 abort 的信号。
|
|
32
|
+
`element.dispatchEvent(event)` 派发的就是**同一个**事件对象(身份可观察),并填充
|
|
33
|
+
`target` / `currentTarget` / `eventPhase`、记录路径供 `event.composedPath()` 使用。
|
|
34
|
+
`new Event(...)`、`new CustomEvent(...)`、`new MouseEvent(...)`、
|
|
35
|
+
`new KeyboardEvent(...)`、`new PointerEvent(...)`、`new WheelEvent(...)`、
|
|
36
|
+
`new FocusEvent(...)`、`new InputEvent(...)` 与 `new SubmitEvent(...)` 会保留 `init`
|
|
37
|
+
对象的全部字段(`detail`、`composed`、鼠标/键盘成员等)。窗口监听器接受同一组
|
|
38
|
+
选项(`capture` 参与监听器身份匹配;窗口投递没有捕获阶段)。
|
|
39
|
+
|
|
40
|
+
窗口导航是真实实现的:`scrollTo(x, y)` / `scrollTo({ left, top })` /
|
|
41
|
+
`scrollBy(...)` 移动页面视口(会按内容边界夹取,绘制与命中测试随之偏移),
|
|
42
|
+
`scrollX` / `scrollY` / `pageXOffset` / `pageYOffset` 报告偏移量。`focus()`
|
|
43
|
+
提升操作系统窗口并置位 `document.hasFocus()`,`blur()` 清除它。事件:
|
|
44
|
+
`ready`(首帧呈现后)、`load`、`close`、`resize`、`scroll`、`focus`、`blur`,
|
|
45
|
+
以及输入事件 `mousemove`、`mousedown`、`mouseup`、`click`、`wheel`、
|
|
46
|
+
`keydown`、`keyup`。
|
|
47
|
+
|
|
48
|
+
`createWindow(options)` 除标题与尺寸外还支持:`{ title, width, height,
|
|
49
|
+
highDensity, resizable, borderless, alwaysOnTop, hidden, fullscreen, x, y,
|
|
50
|
+
opacity, maximized, minimized }`,它们会映射到对应的 SDL 窗口标志/调用,而不是
|
|
51
|
+
被忽略。
|
|
52
|
+
|
|
53
|
+
`window.confirm(message)` / `window.prompt(message, defaultValue)` 不会再丢弃
|
|
54
|
+
参数:设置 `XT_GUI_DIALOGS=1` 且存在窗口时显示原生消息框;否则把消息写到 stderr
|
|
55
|
+
并返回文档化的默认值(`confirm` → `false`,`prompt` → `defaultValue` 或 `""`)。
|
|
56
|
+
|
|
29
57
|
在 Windows 上,GUI 程序会被链接为 **Windows 子系统**可执行文件,因此启动时不会闪出控制台
|
|
30
58
|
窗口;这也意味着从资源管理器启动时 stdout/stderr 无处可去,调试时可在
|
|
31
59
|
`xbintsc.config.json` 里设置 `app.console: true` 保留控制台子系统。
|
|
32
60
|
|
|
61
|
+
没有可用 GPU 的宿主无法运行 GUI。当 SDL 无法打开视频驱动,或无法创建
|
|
62
|
+
Metal/Vulkan/D3D12 设备时,引擎会打印原因并以状态码 **77** 退出——这是 autotools
|
|
63
|
+
的“跳过”约定,CI 与脚本因此可以区分“这台机器没有 GUI”和“程序失败”。此后若窗口仍
|
|
64
|
+
无法打开(SDL 窗口或 GPU claim 错误),`createWindow` 会抛出 JavaScript `Error`,
|
|
65
|
+
而不再返回 `undefined` 句柄、让下一行以 `Cannot read properties of undefined` 失败。
|
|
66
|
+
|
|
33
67
|
触发的事件:
|
|
34
68
|
`ready`(首个呈现帧之后)、`load`、`close`、`resize`,以及输入事件
|
|
35
69
|
`mousemove`、`mousedown`、`mouseup`、`click`、`wheel`、`keydown`、`keyup`。
|
|
@@ -53,12 +87,14 @@ requestAnimationFrame(frame);
|
|
|
53
87
|
| `document` | 该窗口的 document 句柄 |
|
|
54
88
|
| `navigator` | `userAgent`(以 `xbintsc` 结尾的桌面 Chrome 字符串)、`platform`、`vendor`、`language(s)`、`hardwareConcurrency`、`maxTouchPoints`、`onLine`、`vibrate()` |
|
|
55
89
|
| `localStorage` | 内存中的 `getItem` / `setItem` / `removeItem` / `clear` / `key` / `length` |
|
|
56
|
-
| `AudioContext`、`webkitAudioContext` | Web Audio
|
|
57
|
-
| `Event`、`CustomEvent`、`ProgressEvent`
|
|
90
|
+
| `AudioContext`、`webkitAudioContext` | 带真实混音器与解码器的 Web Audio 图(见下) |
|
|
91
|
+
| `Event`、`CustomEvent`、`ProgressEvent`、`MouseEvent`、`KeyboardEvent`、`PointerEvent`、`WheelEvent`、`FocusEvent`、`InputEvent`、`SubmitEvent` | 事件构造器;`init` 参数按原样保留(`detail`、`composed`、鼠标/键盘字段等) |
|
|
92
|
+
| `AbortController`、`AbortSignal` | 真实的 controller/signal 对,用于 `{ signal }` 移除监听器,支持 `abort()`、`aborted`、`reason`、`onabort` 与 `throwIfAborted()` |
|
|
58
93
|
| `HTMLCanvasElement`、`HTMLImageElement`、`WebGLRenderingContext`、`WebGL2RenderingContext`、`WebGLBuffer`/`WebGLTexture`/`WebGLShader`/`WebGLProgram`/`WebGLFramebuffer`/`WebGLRenderbuffer`/`WebGLUniformLocation`/`WebGLActiveInfo`/`WebGLVertexArrayObject`/`WebGLSampler`/`WebGLQuery`/`WebGLSync`/`WebGLTransformFeedback` | 真实的构造函数值。`canvas.getContext("webgl")` 与 `getContext("webgl2")` 返回 GPU 上下文(见 [WebGL](./webgl.md))。 |
|
|
59
|
-
| `ImageBitmap`、`
|
|
94
|
+
| `ImageBitmap`、`createImageBitmap(source)` | 由已解码像素支撑的不可变位图(`<img>`、`<canvas>`、`<video>` 帧与 `ImageData` 形状);promise 立即 settle,`texImage2D` 可直接接受该对象 |
|
|
95
|
+
| `ImageData`、`OffscreenCanvas`、`XRWebGL*`、`Request`、`Headers`、`Response`、`ReadableStream`、`DOMParser` | `typeof` 探测返回 `"undefined"`(没有 XR/fetch/流式后端),让页面走自己的“不支持”分支,而不是调用空壳。Three.js 页面在本后端上使用真实渲染器(见[已知问题](./known-issues.md))。 |
|
|
60
96
|
| `requestAnimationFrame` / `cancelAnimationFrame` | 排入窗口的动画帧列表,见[运行时集成](./runtime.md) |
|
|
61
|
-
| `alert` / `confirm` / `prompt`、`matchMedia`、`getComputedStyle`、`escape` |
|
|
97
|
+
| `alert` / `confirm` / `prompt`、`matchMedia`、`getComputedStyle`、`escape` | 宿主实现。`matchMedia` 返回**实时**列表(按查询缓存):`matches` 在窗口尺寸变化时重新求值,翻转时触发 `change` 监听器。`confirm`/`prompt` 仅在 `XT_GUI_DIALOGS=1` 时使用原生对话框,否则把消息写到 stderr 并返回文档化的默认值(Annex B `escape` 按 UTF-16 码元编码,与 `decodeURIComponent(escape(bytes))` 一致) |
|
|
62
98
|
|
|
63
99
|
`getElementById` / `querySelector` 在 `loadHTML` 之前也能回答:此时得到的是**挂起**句柄,
|
|
64
100
|
首次使用时才绑定到真实节点,因此在模块初始化阶段缓存 `document.querySelector("#id")`
|
|
@@ -66,15 +102,49 @@ requestAnimationFrame(frame);
|
|
|
66
102
|
|
|
67
103
|
### Web Audio
|
|
68
104
|
|
|
69
|
-
`new AudioContext()`
|
|
70
|
-
|
|
71
|
-
`
|
|
72
|
-
|
|
73
|
-
|
|
105
|
+
`new AudioContext()` 会构建**真正参与混音的音频图**:`runtime/ext_gui/audio_mixer.cpp`
|
|
106
|
+
以 48 kHz 立体声 float、128 帧为一个渲染量子进行混音,每个节点对多路输入求和;
|
|
107
|
+
首次 `start()`/`resume()` 会尽力打开默认 SDL 播放设备(无头环境下保持静音但仍在渲染)。
|
|
108
|
+
音频在 SDL 音频线程上基于原生状态渲染,页面无须自行驱动,音频线程也不会触碰任何运行时值。
|
|
109
|
+
|
|
110
|
+
已实现的节点:`createGain`、`createOscillator`(sine、square、sawtooth、triangle)、
|
|
111
|
+
`createBufferSource`(buffer、loop、loopStart/loopEnd、playbackRate/detune)、
|
|
112
|
+
`createBiquadFilter`(lowpass、highpass、bandpass、lowshelf、highshelf、peaking、notch、allpass)、
|
|
113
|
+
`createDynamicsCompressor`、`createStereoPanner`、`createConstantSource` 与
|
|
114
|
+
`createDelay(maxDelayTime)`。`connect` 返回目标节点,因此可链式连接
|
|
115
|
+
(`src.connect(gain).connect(ctx.destination)`);`disconnect()` / `disconnect(target)`
|
|
116
|
+
会更新原生图;`start(when, offset, duration)` / `stop(when)` 按图的时钟生效。
|
|
117
|
+
列表之外的节点(`createAnalyser`、`createConvolver`、`createWaveShaper`、
|
|
118
|
+
`createChannelSplitter`、`createPeriodicWave` 等)不提供,其方法就是缺失的。
|
|
119
|
+
|
|
120
|
+
每个 `AudioParam` 都有实时 `value`,以及 `setValueAtTime` / `linearRampToValueAtTime` /
|
|
74
121
|
`exponentialRampToValueAtTime` / `setTargetAtTime` / `cancelScheduledValues` /
|
|
75
|
-
`cancelAndHoldAtTime
|
|
76
|
-
`
|
|
77
|
-
|
|
122
|
+
`cancelAndHoldAtTime`。自动化时间线**逐采样**求值,因此页面空闲时斜坡仍会继续推进;
|
|
123
|
+
`currentTime` 随渲染量子前进。
|
|
124
|
+
|
|
125
|
+
`createBuffer(channels, length, sampleRate)` 返回的 AudioBuffer 的
|
|
126
|
+
`getChannelData(i)` 是真正的 `Float32Array`,可以用代码逐样本填充。
|
|
127
|
+
`decodeAudioData(bytes)` 返回解码后的 AudioBuffer Promise:WAV(PCM 8/16/24/32 位、
|
|
128
|
+
IEEE float 32/64、A-law 与 µ-law)由引擎自身解码;MP3、AAC/M4A、Vorbis、Opus 与 FLAC
|
|
129
|
+
需要可选的 `media` 扩展(`--ext gui,media`),以其中的 FFmpeg 解码器作为回退。
|
|
130
|
+
`bytes` 可以是 ArrayBuffer、类型化数组、Node `Buffer`,或 `fs.readFileSync`
|
|
131
|
+
返回的原始字节字符串(本运行时没有专门的二进制类型,而该字符串的存储正是文件字节)。
|
|
132
|
+
解码结果会重采样到上下文的 48 kHz,因此 `buffer.sampleRate` 与
|
|
133
|
+
`context.sampleRate` 一致;若没有可用的解码器,Promise 会以 `EncodingError` 拒绝。
|
|
134
|
+
|
|
135
|
+
`resume()` / `suspend()` / `close()` 控制设备与 `state` 属性;`sampleRate` 为 48000,
|
|
136
|
+
与媒体解码器一致。
|
|
137
|
+
|
|
138
|
+
测试与诊断可以创建**离线**上下文同步渲染:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
const ctx = new AudioContext({ __offline: true });
|
|
142
|
+
// … 构建音频图并启动音源 …
|
|
143
|
+
const samples = ctx.__render(480); // 交错立体声 Float32Array
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
这个私有钩子不会打开设备,也不属于 Web Audio API;`tests/e2e/gui-audio.test.ts`
|
|
147
|
+
用它来固定混音数学。
|
|
78
148
|
|
|
79
149
|
输入处理器接收单个负载对象(生命周期处理器不接收任何参数):
|
|
80
150
|
|
package/doc/zh-CN/gui/build.md
CHANGED
|
@@ -52,10 +52,15 @@
|
|
|
52
52
|
`vendor/ffmpeg-build-msvc/dist`,而不是执行 `make install`。
|
|
53
53
|
- CI 在组装发布归档之前构建 `gui.a`/`gui.lib` 与 `media.a`/`media.lib`,因此它们
|
|
54
54
|
会随 `runtime/lib/<slug>/` 一起发布(发布 tarball 会复制整个 `runtime/` 树)。
|
|
55
|
-
|
|
55
|
+
同一批目录还会打进可选的 `@xbintsc/<slug>` npm 包,因此发布覆盖的宿主平台从
|
|
56
|
+
npm 安装后也能使用 `--ext gui`/`--ext media`。归档在 Linux(Xvfb 下,使用
|
|
57
|
+
lavapipe 软件 Vulkan 驱动)与 macOS 上构建并运行
|
|
56
58
|
示例;Windows x64 也会构建两个归档并链接一个 `gui,media` 程序,因此 MSVC
|
|
57
59
|
构建在 CI 中得到验证,只是*运行*示例仍为试验性(托管 runner 没有 GPU/Vulkan
|
|
58
|
-
驱动)。
|
|
60
|
+
驱动)。macOS 的运行同样是试验性的:Intel runner 的虚拟 GPU 缺少
|
|
61
|
+
`MTLGPUFamilyMac2`,引擎会以 **77**(“此机器无法运行 GUI”)退出,任务记录为跳过,
|
|
62
|
+
而不是去编译一套无法呈现的测试。Windows arm64 仍跳过两个归档(FFmpeg 的
|
|
63
|
+
MSVC arm64 构建尚未验证)。
|
|
59
64
|
- Windows CI 通过 `.github/actions/vs-toolchain` →
|
|
60
65
|
`scripts/setup-vs-toolchain.ps1` 使用与本地构建相同的 Visual Studio
|
|
61
66
|
`vcvarsall` 环境和自带的 LLVM(不再单独安装 Chocolatey LLVM)。媒体构建时该
|
package/doc/zh-CN/gui/canvas.md
CHANGED
|
@@ -31,12 +31,19 @@ const ctx = canvas.getContext("2d"); // 或 "webgl" 取得 GPU 上下文
|
|
|
31
31
|
元素上,因此每次都返回**同一个**对象,绘制状态(变换、样式、路径)按 canvas 而非按调用
|
|
32
32
|
保存。`ctx.canvas` 是所属元素的句柄。
|
|
33
33
|
|
|
34
|
+
`getContext("2d", attributes)` 在首次调用时会尊重 `alpha`:传入 `{ alpha: false }`
|
|
35
|
+
时位图以不透明黑色初始化(清除也回到不透明黑)。其余属性由
|
|
36
|
+
`getContextAttributes()` 按规范默认值报告(`antialias: true`、`depth: true`、
|
|
37
|
+
`stencil: false`、`premultipliedAlpha: true`、`preserveDrawingBuffer: false`、
|
|
38
|
+
`colorSpace: "srgb"` 等),特性探测因此能得到诚实的答案。
|
|
39
|
+
|
|
34
40
|
## 绘制模型
|
|
35
41
|
|
|
36
42
|
光栅器刻意保持精简且为自研(不依赖 Skia/Cairo)。它按每条像素行 **4 条垂直子扫描线**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
进行抗锯齿,并做一次**水平解析覆盖率**计算;路径默认采用**非零环绕规则**填充(因此当弧线
|
|
44
|
+
以相反方向环绕时能形成空洞),`fill("evenodd")` 则改用奇偶规则。轴对齐矩形(变换中
|
|
45
|
+
`b == 0 && c == 0`)走直接的覆盖率快速路径。混合为非预乘 source-over,并按
|
|
46
|
+
`globalAlpha` 缩放。
|
|
40
47
|
|
|
41
48
|
填充或描边可以使用纯色,也可以使用 **`CanvasGradient`**。渐变的坐标属于用户空间,
|
|
42
49
|
因此光栅器会先用当前变换的逆矩阵把每个设备像素映射回用户空间再采样——形状被平移、
|
|
@@ -50,9 +57,11 @@ Canvas 像素**不参与垃圾回收**:canvas 由窗口拥有、以 DOM 节点
|
|
|
50
57
|
## 支持的 API
|
|
51
58
|
|
|
52
59
|
状态与变换:`save` / `restore`(会恢复变换、线宽、透明度、字体/文本设置**以及**
|
|
53
|
-
填充/描边样式)、`translate`、`rotate`、`scale`、`transform(a,b,c,d,e,f)
|
|
54
|
-
`setTransform
|
|
55
|
-
|
|
60
|
+
填充/描边样式)、`translate`、`rotate`、`scale`、`transform(a,b,c,d,e,f)` /
|
|
61
|
+
`transform(matrix)`、`setTransform(a,b,c,d,e,f)` / `setTransform(matrix)`、
|
|
62
|
+
`resetTransform`、`getTransform`(返回带 `a`…`f` 与 `is2D` 的对象)。矩阵可以是
|
|
63
|
+
`{ a, b, c, d, e, f }` 对象或六元素数组。变换按 canvas 的顺序组合:
|
|
64
|
+
`translate(x, y); rotate(a)` 围绕平移后的原点旋转。
|
|
56
65
|
|
|
57
66
|
样式与设置:`fillStyle` / `strokeStyle`(层叠所用的颜色解析器能识别的 CSS 颜色,或
|
|
58
67
|
`CanvasGradient`)、`lineWidth`、`globalAlpha`、`lineCap`(`butt`/`round`/`square`)、
|
|
@@ -70,20 +79,27 @@ Canvas 像素**不参与垃圾回收**:canvas 由窗口拥有、以 DOM 节点
|
|
|
70
79
|
会忽略 `x0`/`y0`——请使用同心圆(`x0 == x1`、`y0 == y1`)。
|
|
71
80
|
|
|
72
81
|
路径:`beginPath`、`closePath`、`moveTo`、`lineTo`、`rect`、`roundRect`、`arc`、
|
|
73
|
-
`ellipse`、`quadraticCurveTo`、`bezierCurveTo`,然后
|
|
74
|
-
`
|
|
75
|
-
|
|
82
|
+
`ellipse`、`quadraticCurveTo`、`bezierCurveTo`,然后
|
|
83
|
+
`fill(fillRule?)` / `fill(path, fillRule?)`(多环;`"nonzero"` 或 `"evenodd"`)或
|
|
84
|
+
`stroke(path?)`。贝塞尔与二次曲线段会被展平为线段;弧线与椭圆同样被展平。
|
|
85
|
+
`roundRect` 接受单个半径数字,或 CSS 半径列表(`[all]`、`[tl, br]`、
|
|
86
|
+
`[tl, tr, br]`、`[tl, tr, br, bl]`,元素为数字或 `{ x, y }` 对;圆角按圆弧绘制)。
|
|
87
|
+
|
|
88
|
+
`Path2D` 支持同一组路径命令(`moveTo`、`lineTo`、`closePath`、`rect`、
|
|
89
|
+
`roundRect`、`arc`、`ellipse`、`quadraticCurveTo`、`bezierCurveTo`、`addPath`),
|
|
90
|
+
并可传给 `fill`/`stroke`,因此一次构建的路径可以在不同变换下重复使用。
|
|
76
91
|
|
|
77
92
|
矩形:`clearRect`、`fillRect`、`strokeRect`。
|
|
78
93
|
|
|
79
94
|
虚线:`setLineDash(segments)` / `getLineDash()` / `lineDashOffset` 实现标准规则
|
|
80
95
|
(奇数长度列表会复制一遍,负数/非有限值会被忽略,全零列表表示实线)。
|
|
81
96
|
|
|
82
|
-
文本:`measureText(text)`(返回 `{ width }`)、`fillText(text, x, y)` 与
|
|
83
|
-
`strokeText(text, x, y)`。文本经 HarfBuzz 排版、FreeType 光栅化(与 HTML
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
97
|
+
文本:`measureText(text)`(返回 `{ width }`)、`fillText(text, x, y, maxWidth?)` 与
|
|
98
|
+
`strokeText(text, x, y, maxWidth?)`。文本经 HarfBuzz 排版、FreeType 光栅化(与 HTML
|
|
99
|
+
文本相同的技术栈),按变换的近似缩放绘制。正的 `maxWidth` 会按比例压缩步进与字形位图,
|
|
100
|
+
使文本宽度不超过该值(与 canvas API 一致),而不是忽略该参数。**仅支持平移与均匀
|
|
101
|
+
缩放**——旋转或斜切变换仍会把每个字形放到其变换后的基线点,但不会旋转字形位图。
|
|
102
|
+
`strokeText` 目前用描边样式执行填充,而非生成轮廓。
|
|
87
103
|
|
|
88
104
|
图像:`drawImage(source, …)` 支持 3 参数(`dx, dy`)、5 参数(`dx, dy, dw, dh`)与
|
|
89
105
|
9 参数(本引擎为**目标优先**:`dx, dy, dw, dh, sx, sy, sw, sh`)。完整的仿射变换
|
|
@@ -95,12 +111,21 @@ Canvas 像素**不参与垃圾回收**:canvas 由窗口拥有、以 DOM 节点
|
|
|
95
111
|
测试钩子:`getImageData(x, y, w, h)` 把区域复制为 `{ width, height, data }`,其中
|
|
96
112
|
`data` 是按行主序的 RGBA8 字节数组。越界像素为透明。
|
|
97
113
|
|
|
114
|
+
图案:`createPattern(source, repetition?)` 接受 `<img>` 或另一个 `<canvas>`,在用户
|
|
115
|
+
空间中平铺(`repeat`、`repeat-x`、`repeat-y`、`no-repeat`),因此平铺会跟随当前
|
|
116
|
+
变换。把结果赋给 `fillStyle`/`strokeStyle`;重新赋颜色会替换掉图案。
|
|
117
|
+
|
|
118
|
+
图像数据与导出:`createImageData(width, height)` 分配一个空的
|
|
119
|
+
`{ width, height, data }`,`putImageData(imageData, dx, dy[, dirtyX, dirtyY,
|
|
120
|
+
dirtyWidth, dirtyHeight])` 直接把字节写入位图(不受变换、混合或 `globalAlpha`
|
|
121
|
+
影响)。`canvas.toDataURL(type?)` 导出 PNG data URL,`canvas.toBlob(callback,
|
|
122
|
+
type?)` 从微任务中交付 Blob 形状的 `{ type, size }`(字节在
|
|
123
|
+
`__xt_gui_blob_data` 上;本运行时没有 `URL.createObjectURL`)。
|
|
124
|
+
|
|
98
125
|
## 尚未实现
|
|
99
126
|
|
|
100
|
-
|
|
101
|
-
`
|
|
102
|
-
|
|
103
|
-
CSS `background-image`,以及离屏画布(`OffscreenCanvas`、
|
|
104
|
-
`transferControlToOffscreen`)。`roundRect` 只接受单个半径,径向渐变会忽略内圆偏移。
|
|
127
|
+
阴影、`clip()`、`globalCompositeOperation`、`isPointInPath`、可切换图像平滑的
|
|
128
|
+
`drawImage`、把 `<canvas>` 用作 CSS `background-image`,以及离屏画布
|
|
129
|
+
(`OffscreenCanvas`、`transferControlToOffscreen`)。径向渐变会忽略内圆偏移。
|
|
105
130
|
|
|
106
131
|
另见[媒体](./media.md):`drawImage` 与纹理上传所共享的图像/视频/音频解码栈。
|
package/doc/zh-CN/gui/dom.md
CHANGED
|
@@ -14,7 +14,9 @@ doctype 跳过,实体解码(命名 + 十进制/十六进制),空元素
|
|
|
14
14
|
|
|
15
15
|
**CSS 解析器**(`runtime/ext_gui/css.{h,cpp}`):会剥离注释;`@media` 块递归解析
|
|
16
16
|
(嵌套查询用 `and` 合并,逗号列表会分配到内层查询),其他 at-rule 跳过。规则支持
|
|
17
|
-
|
|
17
|
+
多选择器与声明;选择器列表可以跨任意多行书写(换行就是普通空白,换行后的
|
|
18
|
+
组合器仍按组合器处理),引号内的属性值即使包含逗号、方括号或圆括号也不会
|
|
19
|
+
拆开列表。选择器:类型、`.class`、`#id`、属性
|
|
18
20
|
(`=`、`~=`、`|=`、`^=`、`$=`、`*=`)、四种组合器(后代、子、相邻兄弟与
|
|
19
21
|
通用兄弟)、伪类 `:first-child`、`:last-child`、`:only-child`、`:empty`、
|
|
20
22
|
`:root`、`:not(...)`、`:nth-child(an+b)`、`:disabled`、`:checked`、有状态的
|
|
@@ -66,17 +68,59 @@ created.textContent = "added";
|
|
|
66
68
|
box.appendChild(created);
|
|
67
69
|
box.removeChild(created);
|
|
68
70
|
|
|
71
|
+
// 父子变更辅助方法可在同一次调用中混用节点与字符串。
|
|
72
|
+
box.append("text", doc.createElement("span"));
|
|
73
|
+
box.prepend(doc.createElement("b"));
|
|
74
|
+
box.insertAdjacentHTML("beforeend", "<i>tail</i>"); // beforebegin/afterbegin/beforeend/afterend
|
|
75
|
+
box.replaceChildren("fresh", doc.createElement("em"));
|
|
76
|
+
|
|
77
|
+
// 命名空间会被记录;外部(SVG)元素名保留大小写。
|
|
78
|
+
const gradient = doc.createElementNS("http://www.w3.org/2000/svg", "svg:linearGradient");
|
|
79
|
+
console.log(gradient.namespaceURI, gradient.localName, gradient.prefix);
|
|
80
|
+
|
|
69
81
|
inner.addEventListener("click", (e) => console.log(e.target.id, e.currentTarget.id));
|
|
70
82
|
inner.click(); // 在该元素处合成一次点击
|
|
71
83
|
console.log(box.offsetWidth, box.offsetHeight); // 取整后的边框盒
|
|
72
84
|
console.log(box.contains(inner)); // 后代判断
|
|
73
85
|
```
|
|
74
86
|
|
|
87
|
+
### style 属性、dataset、计算样式与几何
|
|
88
|
+
|
|
89
|
+
内联 `style` 对象是一个 CSSOM 声明块。以属性名赋值/读取的是与 `setProperty`
|
|
90
|
+
相同的声明块(`el.style.display = "none"`、`el.style.backgroundColor = "#f00"`,
|
|
91
|
+
驼峰名会映射到 CSS 拼写,`el.style["--accent"]` 用于自定义属性);
|
|
92
|
+
`setProperty(name, value, priority)` 在 `priority` 为 `"important"` 时以
|
|
93
|
+
`!important` 保存该声明(其他优先级值会让本次调用成为无操作,空值则移除该属性)。
|
|
94
|
+
`getPropertyValue` / `getPropertyPriority` 读回声明,`removeProperty` 返回旧值,
|
|
95
|
+
`cssText` 读取或整体替换声明块,`style.length` / `style.item(i)` 枚举声明块,
|
|
96
|
+
未设置的属性返回 `""`。
|
|
97
|
+
|
|
98
|
+
`el.dataset` 是元素 `data-*` 属性之上的实时 `DOMStringMap`:
|
|
99
|
+
`dataset.fooBar` 读取 `data-foo-bar`,赋值写入属性,`delete` 移除属性,
|
|
100
|
+
`Object.keys(dataset)` / `for...in` 只列出 data 键。
|
|
101
|
+
|
|
102
|
+
`getComputedStyle(el, pseudoElt)` 从**层叠结果**读取——UA 样式表、作者规则、
|
|
103
|
+
继承和内联声明——而不是回显内联块,因此写在样式表里的规则同样可见。它支持
|
|
104
|
+
`getPropertyValue`、`getPropertyPriority` 与命名属性(`cs.width`、
|
|
105
|
+
`cs.backgroundColor`、`cs["--accent"]`)。传入 `"::before"` 或 `"::after"`
|
|
106
|
+
可读取生成内容盒;其他伪元素返回空值。每次读取都会先结算待处理的重新样式,
|
|
107
|
+
因此早先创建的句柄在后续变更后仍然有效。
|
|
108
|
+
|
|
109
|
+
`getBoundingClientRect()` 在 `x` / `y` / `width` / `height` 之外还带有旧式的
|
|
110
|
+
`top` / `right` / `bottom` / `left` 成员;`document.title = …` 写入文档的
|
|
111
|
+
`<title>`(页面没有该元素时会创建它以及 `<head>`)。
|
|
112
|
+
|
|
75
113
|
变更操作会把文档标记为脏;引擎会延迟地(在下一次读取或下一帧之前)重新计算
|
|
76
114
|
样式并重新布局。`inner = …`/`innerHTML = …` **不会**执行脚本。元素事件支持
|
|
77
|
-
捕获与冒泡阶段、`stopPropagation`、`once
|
|
78
|
-
|
|
79
|
-
|
|
115
|
+
捕获与冒泡阶段、`stopPropagation`、`once`、`passive` 与 `signal`(`AbortController`
|
|
116
|
+
的信号会在 abort 时移除监听器),并向上冒泡到 `document`/`window`。
|
|
117
|
+
`dispatchEvent` 派发同一个事件对象,并填充 `target`/`currentTarget`/`eventPhase`/
|
|
118
|
+
`composedPath()`。旧式 `win.on(type, fn)` 负载保留其**字符串** `e.target`
|
|
119
|
+
(`div#id.class`);元素 `Event.target` 是一个句柄,其描述符与同一字符串匹配。
|
|
120
|
+
|
|
121
|
+
`element.focus()` 会把元素滚动到可见区域(传入 `{ preventScroll: true }` 则保持
|
|
122
|
+
当前页面偏移);`document.hasFocus()` 报告由 `window.focus()` / `window.blur()`
|
|
123
|
+
切换的窗口焦点状态。
|
|
80
124
|
|
|
81
125
|
### 节点生命周期
|
|
82
126
|
|
package/doc/zh-CN/gui/media.md
CHANGED
|
@@ -91,6 +91,9 @@ Windows 已不再特殊:`media.lib` 是用 clang-cl 为 MSVC ABI 编译的 FFm
|
|
|
91
91
|
`media.a`/`media.lib` 只依赖 FFmpeg。
|
|
92
92
|
- **线程。** 引擎是单线程且非线程感知,因此所有解码都在主线程的
|
|
93
93
|
`xt_gui_media_tick` 内完成——没有解码线程,也没有跨线程 GC 暴露。
|
|
94
|
+
- **`decodeAudioData`。** 同一套 FFmpeg 还会为 `AudioContext.decodeAudioData`
|
|
95
|
+
解码内存中的音频文件(`runtime/ext_media/decode_audio.cpp`,经媒体表分发);
|
|
96
|
+
WAV 由 GUI 引擎自身处理(`audio_decode.cpp`),因此只有压缩格式需要该扩展。
|
|
94
97
|
- **DOM API。** 元素句柄直接暴露媒体接口(见
|
|
95
98
|
`runtime/ext_gui/dom_api_media.cpp` 与 `dom_api_proto.cpp` 中的原型):
|
|
96
99
|
`play()` / `pause()` / `load()`,以及 `paused` / `ended` / `duration` /
|