xbintsc 0.5.45 → 0.5.52
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/AGENTS.md +1 -1
- package/README.md +5 -4
- package/README.zh-CN.md +4 -3
- package/dist/src/cli/extensions.d.ts +24 -0
- package/dist/src/cli/extensions.js +62 -0
- package/dist/src/cli/extensions.js.map +1 -0
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/cli/help.js +3 -1
- package/dist/src/cli/help.js.map +1 -1
- package/dist/src/cli/hints.js +8 -3
- package/dist/src/cli/hints.js.map +1 -1
- package/dist/src/cli/main.js +21 -28
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/diagnostics/diagnostic.d.ts +3 -1
- package/dist/src/diagnostics/diagnostic.js +2 -0
- package/dist/src/diagnostics/diagnostic.js.map +1 -1
- package/dist/src/driver/build-key.d.ts +2 -0
- package/dist/src/driver/build-key.js +1 -0
- package/dist/src/driver/build-key.js.map +1 -1
- package/dist/src/driver/compiler.js +61 -8
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/config.d.ts +4 -0
- package/dist/src/driver/config.js +2 -0
- package/dist/src/driver/config.js.map +1 -1
- package/dist/src/driver/link-features.d.ts +37 -0
- package/dist/src/driver/link-features.js +123 -0
- package/dist/src/driver/link-features.js.map +1 -0
- package/dist/src/driver/options.d.ts +10 -0
- package/dist/src/driver/runtime-objects.d.ts +5 -0
- package/dist/src/driver/runtime-objects.js +20 -1
- package/dist/src/driver/runtime-objects.js.map +1 -1
- package/dist/src/driver/usage.d.ts +23 -0
- package/dist/src/driver/usage.js +353 -0
- package/dist/src/driver/usage.js.map +1 -0
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/catalog.js +1 -2
- package/dist/src/extensions/catalog.js.map +1 -1
- package/dist/src/extensions/gui/features.d.ts +34 -0
- package/dist/src/extensions/gui/features.js +165 -0
- package/dist/src/extensions/gui/features.js.map +1 -0
- package/dist/src/extensions/gui/index.js +10 -4
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/link-feature.d.ts +70 -0
- package/dist/src/extensions/link-feature.js +18 -0
- package/dist/src/extensions/link-feature.js.map +1 -0
- package/dist/src/extensions/registry.d.ts +24 -4
- package/dist/src/extensions/registry.js +26 -3
- package/dist/src/extensions/registry.js.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.js +0 -1
- package/dist/src/index.js.map +1 -1
- package/dist/tests/cli/hints.test.js +5 -7
- package/dist/tests/cli/hints.test.js.map +1 -1
- package/dist/tests/driver/link-features.test.js +105 -0
- package/dist/tests/driver/link-features.test.js.map +1 -0
- package/dist/tests/driver/usage.test.d.ts +1 -0
- package/dist/tests/driver/usage.test.js +88 -0
- package/dist/tests/driver/usage.test.js.map +1 -0
- package/dist/tests/e2e/gui-audio.test.js +4 -4
- package/dist/tests/e2e/gui-audio.test.js.map +1 -1
- package/dist/tests/e2e/gui-css-coverage.test.d.ts +9 -0
- package/dist/tests/e2e/gui-css-coverage.test.js +333 -0
- package/dist/tests/e2e/gui-css-coverage.test.js.map +1 -0
- package/dist/tests/e2e/gui-css-features.test.d.ts +6 -0
- package/dist/tests/e2e/gui-css-features.test.js +270 -0
- package/dist/tests/e2e/gui-css-features.test.js.map +1 -0
- package/dist/tests/e2e/gui-effects.test.js +92 -11
- package/dist/tests/e2e/gui-effects.test.js.map +1 -1
- package/dist/tests/e2e/gui-feature-linking.test.d.ts +9 -0
- package/dist/tests/e2e/gui-feature-linking.test.js +68 -0
- package/dist/tests/e2e/gui-feature-linking.test.js.map +1 -0
- package/dist/tests/e2e/gui-font-face.test.d.ts +10 -0
- package/dist/tests/e2e/gui-font-face.test.js +142 -0
- package/dist/tests/e2e/gui-font-face.test.js.map +1 -0
- package/dist/tests/e2e/gui-fonts.test.d.ts +10 -0
- package/dist/tests/e2e/gui-fonts.test.js +150 -0
- package/dist/tests/e2e/gui-fonts.test.js.map +1 -0
- package/dist/tests/e2e/gui-helpers.d.ts +10 -1
- package/dist/tests/e2e/gui-helpers.js +6 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-layout.test.js +7 -3
- package/dist/tests/e2e/gui-layout.test.js.map +1 -1
- package/dist/tests/e2e/gui-media-disabled.test.d.ts +5 -4
- package/dist/tests/e2e/gui-media-disabled.test.js +7 -6
- package/dist/tests/e2e/gui-media-disabled.test.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.d.ts +5 -4
- package/dist/tests/e2e/gui-media.test.js +9 -9
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-paint.test.js +5 -2
- package/dist/tests/e2e/gui-paint.test.js.map +1 -1
- package/dist/tests/e2e/gui-shaping.test.d.ts +5 -0
- package/dist/tests/e2e/gui-shaping.test.js +47 -0
- package/dist/tests/e2e/gui-shaping.test.js.map +1 -0
- package/dist/tests/e2e/gui-track-sizing.test.d.ts +6 -0
- package/dist/tests/e2e/gui-track-sizing.test.js +173 -0
- package/dist/tests/e2e/gui-track-sizing.test.js.map +1 -0
- package/dist/tests/e2e/gui-transform.test.js +3 -2
- package/dist/tests/e2e/gui-transform.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl-pipeline-cache.test.d.ts +18 -0
- package/dist/tests/e2e/gui-webgl-pipeline-cache.test.js +120 -0
- package/dist/tests/e2e/gui-webgl-pipeline-cache.test.js.map +1 -0
- package/dist/tests/extensions/gui-features.test.d.ts +1 -0
- package/dist/tests/extensions/gui-features.test.js +175 -0
- package/dist/tests/extensions/gui-features.test.js.map +1 -0
- package/doc/ai/cli.md +5 -1
- package/doc/ai/extensions.md +56 -26
- package/doc/ai/troubleshooting.md +10 -7
- package/doc/ai/zh-CN/cli.md +5 -1
- package/doc/ai/zh-CN/extensions.md +48 -22
- package/doc/ai/zh-CN/troubleshooting.md +6 -5
- package/doc/gui/animation.md +39 -9
- package/doc/gui/api.md +2 -1
- package/doc/gui/build.md +137 -19
- package/doc/gui/canvas.md +1 -1
- package/doc/gui/dom.md +20 -4
- package/doc/gui/known-issues.md +63 -26
- package/doc/gui/layout.md +31 -8
- package/doc/gui/media.md +13 -7
- package/doc/gui/rendering.md +114 -39
- package/doc/gui/runtime.md +5 -0
- package/doc/gui/webgl.md +24 -6
- package/doc/gui.md +110 -47
- package/doc/implemented/cli.md +2 -0
- package/doc/implemented/extensions.md +9 -3
- package/doc/npm-package.md +4 -4
- package/doc/xbintsc.config.schema.json +10 -0
- package/doc/zh-CN/gui/animation.md +33 -10
- package/doc/zh-CN/gui/api.md +2 -1
- package/doc/zh-CN/gui/build.md +110 -16
- package/doc/zh-CN/gui/canvas.md +1 -1
- package/doc/zh-CN/gui/dom.md +16 -3
- package/doc/zh-CN/gui/known-issues.md +45 -15
- package/doc/zh-CN/gui/layout.md +23 -6
- package/doc/zh-CN/gui/media.md +11 -6
- package/doc/zh-CN/gui/rendering.md +84 -26
- package/doc/zh-CN/gui/runtime.md +3 -0
- package/doc/zh-CN/gui/webgl.md +3 -3
- package/doc/zh-CN/gui.md +92 -41
- package/doc/zh-CN/implemented/cli.md +2 -0
- package/doc/zh-CN/implemented/extensions.md +9 -3
- package/doc/zh-CN/npm-package.md +4 -3
- package/package.json +7 -7
- package/runtime/ext_gui/animation_values.cpp +425 -0
- package/runtime/ext_gui/animation_values.h +64 -0
- package/runtime/ext_gui/browser.cpp +22 -15
- package/runtime/ext_gui/browser_loop.cpp +13 -1
- package/runtime/ext_gui/canvas.h +1 -1
- package/runtime/ext_gui/canvas_raster.cpp +1 -1
- package/runtime/ext_gui/canvas_text.cpp +1 -1
- package/runtime/ext_gui/css.cpp +172 -21
- package/runtime/ext_gui/css.h +75 -4
- package/runtime/ext_gui/css_match.cpp +4 -0
- package/runtime/ext_gui/css_sheet.cpp +218 -2
- package/runtime/ext_gui/document.cpp +42 -192
- package/runtime/ext_gui/document.h +25 -12
- package/runtime/ext_gui/document_animation.cpp +428 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +15 -8
- package/runtime/ext_gui/dom_api_canvas_extra.cpp +44 -20
- package/runtime/ext_gui/dom_api_canvas_image.cpp +3 -1
- package/runtime/ext_gui/dom_api_node_read.cpp +10 -0
- package/runtime/ext_gui/dom_api_offscreen.cpp +3 -1
- package/runtime/ext_gui/dom_api_style.cpp +7 -0
- package/runtime/ext_gui/dom_api_webgl_internal.h +4 -0
- package/runtime/ext_gui/dom_api_webgl_source.cpp +5 -2
- package/runtime/ext_gui/effect_values.cpp +245 -21
- package/runtime/ext_gui/gpu_bridge.c +28 -0
- package/runtime/ext_gui/gpu_feature.cpp +30 -0
- package/runtime/ext_gui/gpu_shader.cpp +22 -0
- package/runtime/ext_gui/gpu_shader_api.h +50 -0
- package/runtime/ext_gui/gradient_values.cpp +24 -0
- package/runtime/ext_gui/grid_values.cpp +23 -0
- package/runtime/ext_gui/gui.cpp +6 -37
- package/runtime/ext_gui/gui_canvas.cpp +14 -6
- package/runtime/ext_gui/gui_cursor.cpp +50 -0
- package/runtime/ext_gui/gui_engine.h +1 -18
- package/runtime/ext_gui/gui_events.cpp +19 -6
- package/runtime/ext_gui/gui_internal.h +3 -0
- package/runtime/ext_gui/gui_webgl.cpp +25 -10
- package/runtime/ext_gui/image_api.cpp +18 -0
- package/runtime/ext_gui/image_api.h +43 -0
- package/runtime/ext_gui/image_bitmap_browser.cpp +20 -11
- package/runtime/ext_gui/image_bridge.c +22 -0
- package/runtime/ext_gui/image_feature.cpp +107 -0
- package/runtime/ext_gui/inline_svg.cpp +95 -8
- package/runtime/ext_gui/inline_svg.h +5 -1
- package/runtime/ext_gui/layout.cpp +15 -9
- package/runtime/ext_gui/layout.h +8 -2
- package/runtime/ext_gui/layout_flex.cpp +134 -29
- package/runtime/ext_gui/layout_flow.cpp +58 -7
- package/runtime/ext_gui/layout_flow_internal.h +39 -4
- package/runtime/ext_gui/layout_grid.cpp +31 -0
- package/runtime/ext_gui/layout_inline.cpp +26 -2
- package/runtime/ext_gui/layout_vertical.cpp +196 -0
- package/runtime/ext_gui/media.cpp +4 -2
- package/runtime/ext_gui/media.h +3 -3
- package/runtime/ext_gui/media_api.h +7 -6
- package/runtime/ext_gui/paint.cpp +67 -9
- package/runtime/ext_gui/paint.h +61 -8
- package/runtime/ext_gui/paint_backdrop.cpp +211 -0
- package/runtime/ext_gui/paint_background.cpp +175 -97
- package/runtime/ext_gui/paint_effects.cpp +12 -6
- package/runtime/ext_gui/paint_internal.h +27 -0
- package/runtime/ext_gui/paint_outline.cpp +44 -0
- package/runtime/ext_gui/paint_shadow.cpp +368 -0
- package/runtime/ext_gui/renderer.cpp +15 -7
- package/runtime/ext_gui/renderer.h +11 -2
- package/runtime/ext_gui/renderer_backdrop.cpp +374 -0
- package/runtime/ext_gui/renderer_bitmap.cpp +82 -0
- package/runtime/ext_gui/renderer_gradient.cpp +51 -17
- package/runtime/ext_gui/renderer_image.cpp +19 -7
- package/runtime/ext_gui/renderer_internal.h +21 -0
- package/runtime/ext_gui/renderer_layer.cpp +37 -6
- package/runtime/ext_gui/renderer_text.cpp +2 -1
- package/runtime/ext_gui/stb_truetype.h +5077 -0
- package/runtime/ext_gui/style.cpp +62 -8
- package/runtime/ext_gui/style.h +111 -4
- package/runtime/ext_gui/style_cascade.cpp +83 -0
- package/runtime/ext_gui/style_internal.h +13 -1
- package/runtime/ext_gui/style_length.cpp +92 -0
- package/runtime/ext_gui/style_print.cpp +83 -2
- package/runtime/ext_gui/style_svg.cpp +40 -0
- package/runtime/ext_gui/style_text.cpp +302 -0
- package/runtime/ext_gui/style_ui.cpp +150 -0
- package/runtime/ext_gui/style_values.cpp +76 -62
- package/runtime/ext_gui/style_values_internal.h +23 -0
- package/runtime/ext_gui/text.cpp +27 -499
- package/runtime/ext_gui/text.h +18 -9
- package/runtime/ext_gui/text_api.h +45 -0
- package/runtime/ext_gui/text_bridge.c +23 -0
- package/runtime/ext_gui/text_cache.cpp +12 -3
- package/runtime/ext_gui/text_font_db.cpp +427 -0
- package/runtime/ext_gui/text_font_paths.cpp +250 -0
- package/runtime/ext_gui/text_font_paths.h +39 -0
- package/runtime/ext_gui/text_font_sfnt.cpp +396 -0
- package/runtime/ext_gui/text_font_sfnt.h +44 -0
- package/runtime/ext_gui/text_fonts.cpp +348 -0
- package/runtime/ext_gui/text_fonts.h +78 -0
- package/runtime/ext_gui/text_fonts_internal.h +77 -0
- package/runtime/ext_gui/text_glyph_cache.cpp +2 -2
- package/runtime/ext_gui/text_hb.cpp +438 -0
- package/runtime/ext_gui/text_stb.cpp +369 -0
- package/runtime/ext_gui/transform.cpp +107 -9
- package/runtime/ext_gui/transform.h +5 -0
- package/runtime/ext_gui/webgl_api.cpp +19 -0
- package/runtime/ext_gui/webgl_api.h +53 -0
- package/runtime/ext_gui/webgl_bridge.c +25 -0
- package/runtime/ext_gui/webgl_draw_setup.cpp +42 -1
- package/runtime/ext_gui/webgl_feature.cpp +82 -0
- package/runtime/ext_gui/webgl_feature.h +28 -0
- package/runtime/ext_gui/webgl_msl.cpp +41 -0
- package/runtime/ext_gui/webgl_msl.h +6 -0
- package/runtime/ext_gui/webgl_shader.cpp +40 -32
- package/runtime/ext_gui/window.cpp +7 -7
- package/runtime/ext_media/decode_audio.cpp +1 -1
- package/runtime/ext_media/media.cpp +1 -1
- package/runtime/ext_media/media_bridge.c +7 -7
- package/scripts/build-gui.ts +97 -98
- package/scripts/check-file-length.ts +1 -0
- package/scripts/gui-build-options.ts +122 -0
- package/src/cli/extensions.ts +72 -0
- package/src/cli/help.ts +3 -1
- package/src/cli/hints.ts +9 -3
- package/src/cli/main.ts +21 -27
- package/src/diagnostics/diagnostic.ts +2 -0
- package/src/driver/build-key.ts +3 -0
- package/src/driver/compiler.ts +63 -8
- package/src/driver/config.ts +6 -0
- package/src/driver/link-features.ts +163 -0
- package/src/driver/options.ts +10 -0
- package/src/driver/runtime-objects.ts +26 -1
- package/src/driver/usage.ts +376 -0
- package/src/driver/version.ts +1 -1
- package/src/extensions/catalog.ts +1 -2
- package/src/extensions/gui/features.ts +166 -0
- package/src/extensions/gui/index.ts +10 -4
- package/src/extensions/link-feature.ts +72 -0
- package/src/extensions/registry.ts +45 -4
- package/src/index.ts +3 -2
- package/dist/src/extensions/media/index.d.ts +0 -28
- package/dist/src/extensions/media/index.js +0 -59
- package/dist/src/extensions/media/index.js.map +0 -1
- package/dist/tests/extensions/media.test.js +0 -63
- package/dist/tests/extensions/media.test.js.map +0 -1
- package/src/extensions/media/index.ts +0 -65
- /package/dist/tests/{extensions/media.test.d.ts → driver/link-features.test.d.ts} +0 -0
package/doc/gui/layout.md
CHANGED
|
@@ -22,10 +22,13 @@ with absolute (viewport-relative) geometry:
|
|
|
22
22
|
Each line shrinks to the band left free by any floats (`float: left|right`)
|
|
23
23
|
that overlap it, so later lines wrap around them.
|
|
24
24
|
Each text fragment remembers the run it covers, so paint can shape it. Text is
|
|
25
|
-
measured with the
|
|
25
|
+
measured with the stb_truetype stack (see [Text stack](./rendering.md#text-stack-m4b)).
|
|
26
26
|
- **Flexbox** — `row`/`column` (and the `-reverse` variants) with `gap`,
|
|
27
27
|
`flex-basis`/`flex-grow`/`flex-shrink`, `justify-content` and `align-items`
|
|
28
|
-
(including `stretch` when the cross size is definite).
|
|
28
|
+
(including `stretch` when the cross size is definite). On both axes the main
|
|
29
|
+
size comes from `flex-basis` (or the measured size when it is `auto`), positive
|
|
30
|
+
free space is split by `flex-grow` and a deficit by `flex-shrink`, and an
|
|
31
|
+
item's `align-self` overrides the container's `align-items`. `flex-wrap: wrap`
|
|
29
32
|
breaks items into several lines, `align-content`
|
|
30
33
|
(`stretch`/`flex-start`/`flex-end`/`center`/`space-between`/`space-around`)
|
|
31
34
|
distributes the lines on the cross axis and `wrap-reverse` flips that axis.
|
|
@@ -37,14 +40,34 @@ with absolute (viewport-relative) geometry:
|
|
|
37
40
|
`row-gap` / `column-gap`, row-major auto-placement, simple `grid-column` /
|
|
38
41
|
`grid-row` line placement, and `align/justify-items` plus
|
|
39
42
|
`align/justify-self` (including `place-items` / `place-self`). Implicit rows
|
|
40
|
-
and columns grow from the items; a
|
|
43
|
+
and columns grow from the items; a definite grid height is shared across `fr`
|
|
44
|
+
rows after the fixed and auto rows are sized, so `aspect-ratio` can drive a
|
|
45
|
+
`repeat(n, 1fr)` grid. A single-cell grid with `place-items: center` centres a
|
|
46
|
+
card in the whole overlay. Item measurement is a two-pass
|
|
41
47
|
layout (intrinsic size, then final placement), so text fragments are cleared
|
|
42
48
|
between passes.
|
|
43
|
-
- **
|
|
44
|
-
`
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
- **Inline-level containers, auto margins and aspect ratio** — `display:
|
|
50
|
+
inline-flex`/`inline-grid` lay their children out with the flex/grid algorithm
|
|
51
|
+
but participate in the parent line as one atomic inline box (`vertical-align`
|
|
52
|
+
shifts it by its length value). A block-level box with `margin-left: auto` /
|
|
53
|
+
`margin-right: auto` absorbs the leftover inline space (both auto → centred);
|
|
54
|
+
a flex item's auto main-axis margins absorb the line's free space before
|
|
55
|
+
`justify-content`, which is what pushes a footer or button hint to the end.
|
|
56
|
+
`aspect-ratio` derives a `height: auto` box from its used width (the
|
|
57
|
+
width-from-height direction is not implemented). `border-radius` accepts a
|
|
58
|
+
percentage and resolves against the smaller border-box side.
|
|
59
|
+
- **Vertical writing mode** — `writing-mode: vertical-rl|vertical-lr` lays text
|
|
60
|
+
out one character per column step: CJK/kana/Hangul glyphs stay upright and
|
|
61
|
+
other scripts are rotated 90° at paint time. A definite height starts a new
|
|
62
|
+
column; a flex container's row/column axes swap with the writing mode. This is
|
|
63
|
+
a text-focused implementation: nested blocks and mixed horizontal content in a
|
|
64
|
+
vertical container still fall back to horizontal layout.
|
|
65
|
+
- **CSS value functions and custom properties** — `calc()` arithmetic (including
|
|
66
|
+
nested `calc()` and `calc()` inside the other functions), `clamp(min, value,
|
|
67
|
+
max)`, `min(...)` and `max(...)` keep their expression unresolved in the
|
|
68
|
+
computed style and are evaluated at layout time against the element's font
|
|
69
|
+
size and the viewport (`vw`/`vh`); `env(safe-area-inset-*)` resolves to zero in
|
|
70
|
+
a desktop window. `var(--name[, fallback])` is substituted from inherited custom
|
|
48
71
|
properties during the cascade. `inset` is the four-value
|
|
49
72
|
`top/right/bottom/left` shorthand, `box-sizing: border-box` subtracts padding
|
|
50
73
|
and borders from an explicit width/height, `visibility: hidden` skips painting
|
package/doc/gui/media.md
CHANGED
|
@@ -74,8 +74,9 @@ clip paths are not rendered (see [Known issues](./known-issues.md)).
|
|
|
74
74
|
|
|
75
75
|
## Video & audio (M13)
|
|
76
76
|
|
|
77
|
-
Media playback is split
|
|
78
|
-
a decoder it never uses
|
|
77
|
+
Media playback is split inside the `gui` extension so a GUI program does not pay
|
|
78
|
+
for a decoder it never uses. Decoding is an optional **`media` link feature**,
|
|
79
|
+
not a separate extension:
|
|
79
80
|
|
|
80
81
|
- **`gui`** (`gui.a`/`gui.lib`) owns the `<video>`/`<audio>` elements, the DOM
|
|
81
82
|
API, the renderer integration and the SDL audio sink, but contains **no
|
|
@@ -85,13 +86,18 @@ a decoder it never uses:
|
|
|
85
86
|
- **`media`** (`media.a`, or `media.lib` with the MSVC ABI on Windows;
|
|
86
87
|
`runtime/ext_media/`) is the optional decoder backend:
|
|
87
88
|
`runtime/ext_media/media.cpp` wraps a statically vendored **FFmpeg** build,
|
|
88
|
-
and `runtime/ext_media/media_bridge.c` registers it with the engine.
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
and `runtime/ext_media/media_bridge.c` registers it with the engine. The
|
|
90
|
+
compiler selects the feature when the program may use it (a `<video>`/`<audio>`
|
|
91
|
+
element in imported HTML, `createElement("video"/"audio")`, `new Audio()`,
|
|
92
|
+
`decodeAudioData`, or runtime-built markup) and only then compiles the bridge
|
|
93
|
+
and links `media.a`. `--feature media` forces it and `--no-feature media`
|
|
94
|
+
keeps it out; see [Link features](./build.md#link-features).
|
|
91
95
|
|
|
92
|
-
Without the
|
|
96
|
+
Without the feature the element still exists and its DOM API is
|
|
93
97
|
callable, but opening a source fails and fires `error`. The same happens on any
|
|
94
|
-
host where the archive has not been built (run `npm run media`)
|
|
98
|
+
host where the archive has not been built (run `npm run media`) — an
|
|
99
|
+
auto-detected feature with no archive produces a build warning and degrades this
|
|
100
|
+
way, while `--feature media` fails the build. Windows is no
|
|
95
101
|
longer special: `media.lib` is FFmpeg compiled with clang-cl for the MSVC ABI,
|
|
96
102
|
so it links against `gui.lib` and plays normally. There is no WebView and no
|
|
97
103
|
platform media framework in the path either way.
|
package/doc/gui/rendering.md
CHANGED
|
@@ -76,17 +76,27 @@ divided back into logical units, exactly the way HiDPI scaling already worked.
|
|
|
76
76
|
|
|
77
77
|
The window background (`setBackground`) is the render-pass clear colour.
|
|
78
78
|
|
|
79
|
+
`background-size` on a `url()` layer emits one image quad per tile (default
|
|
80
|
+
`repeat`, 4096-tile cap) instead of stretching the picture to the box;
|
|
81
|
+
percentage sizes resolve against the box, `auto` keeps the box dimension.
|
|
82
|
+
`outline` paints four edge rectangles outside the border box (offset included)
|
|
83
|
+
after the border and before the content. A vertical-writing-mode text run is
|
|
84
|
+
painted by rotating its glyph quads 90° (CJK glyphs stay upright and are centred
|
|
85
|
+
in their column).
|
|
86
|
+
|
|
79
87
|
### Backgrounds, generated content and effects (M19)
|
|
80
88
|
|
|
81
89
|
`background-color` and every `background-image` layer are painted. A
|
|
82
90
|
comma-separated layer list is painted bottom-up (the first declaration layer is
|
|
83
91
|
topmost), and both gradient kinds are supported:
|
|
84
92
|
|
|
85
|
-
- a **linear** gradient
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
- a **linear** gradient follows the CSS gradient line (through the box centre,
|
|
94
|
+
at the declared angle, with the box extent projected onto it as its length, so
|
|
95
|
+
`%` and `%`-inside-`calc()` offsets resolve against that length) and is
|
|
96
|
+
resolved per pixel like a radial one. The ramp only varies along the line, so
|
|
97
|
+
the texture is one row (or one column) of device pixels. `to <side>`,
|
|
98
|
+
`deg`/`grad`/`rad`/`turn`, percentage or length (`px`/`em`/…) offsets, the
|
|
99
|
+
`color <start> <end>` shorthand and multi-stop colours work;
|
|
90
100
|
- a **radial** gradient is resolved per pixel in `renderer_gradient.cpp` into one
|
|
91
101
|
RGBA texture that is drawn as a single image quad (`PaintGradient`). Nesting the
|
|
92
102
|
bands instead would composite their alpha once per band — since every band
|
|
@@ -98,6 +108,14 @@ topmost), and both gradient kinds are supported:
|
|
|
98
108
|
the side or corner, as CSS does. Stops interpolate in premultiplied alpha, and
|
|
99
109
|
the last stop extends past the ending shape over the rest of the box.
|
|
100
110
|
|
|
111
|
+
Both kinds share that per-pixel path: a walk of solid rectangles composites a
|
|
112
|
+
translucent stop once per band and cannot place a stop narrower than a band, so a
|
|
113
|
+
`transparent … calc(100% - 1px), rgba(…) calc(100% - 1px)` divider line either
|
|
114
|
+
fell between two samples (and vanished) or widened into a full band. A stop
|
|
115
|
+
position given as `calc()` keeps its percentage relative to the gradient line,
|
|
116
|
+
and a stop whose resolved offset is negative stays where the declaration put it
|
|
117
|
+
instead of being treated as "no offset declared".
|
|
118
|
+
|
|
101
119
|
`repeating-linear-gradient()` and `repeating-radial-gradient()` tile the stop
|
|
102
120
|
pattern from 0 to the last stop's offset across the whole box; the stop list is
|
|
103
121
|
not forced to end at 100%, so `red 0%, blue 10%` repeats every 10%. A normal
|
|
@@ -105,18 +123,34 @@ gradient whose last stop is below 100% holds that colour for the rest of the box
|
|
|
105
123
|
as in CSS.
|
|
106
124
|
|
|
107
125
|
The background colour sits under every layer. Gradients are partially
|
|
108
|
-
transparent if their stops are;
|
|
109
|
-
|
|
126
|
+
transparent if their stops are; both kinds are exact per pixel, so hard stops and
|
|
127
|
+
1px details stay hard instead of banding.
|
|
110
128
|
|
|
111
129
|
**Generated content** needs no new display-list kind: `::before`/`::after` are
|
|
112
130
|
ordinary layout boxes owned by the per-restyle arena in `style.cpp`, so their
|
|
113
131
|
background, border, text and transforms flow through the same paint walk.
|
|
114
132
|
`content` is resolved from strings, `attr()` and open/close quotes.
|
|
115
133
|
|
|
116
|
-
**`text-shadow`** is emitted as shadow `PaintText` runs *before* the
|
|
117
|
-
the text pipeline draws
|
|
118
|
-
|
|
119
|
-
|
|
134
|
+
**`text-shadow`** with no blur is emitted as shadow `PaintText` runs *before* the
|
|
135
|
+
real run, so the text pipeline draws it crisply. A blurred shadow is a real
|
|
136
|
+
Gaussian: `paint_shadow.cpp` rasterises the glyph coverage, convolves it with a
|
|
137
|
+
separable kernel (`sigma = blur / 2`, cropped at ±3σ), and emits one tinted image
|
|
138
|
+
quad. The mask is cached by text/font/blur, so an animated colour only changes
|
|
139
|
+
the quad's tint.
|
|
140
|
+
|
|
141
|
+
**`box-shadow`** uses the same Gaussian mask: the rounded-rectangle silhouette is
|
|
142
|
+
rasterised (spread expands or shrinks it), convolved, and composited behind the
|
|
143
|
+
background; `inset` shadows invert the mask, crop it to the padding box and paint
|
|
144
|
+
above the background. A zero-blur outer shadow stays an exact rounded rect. The
|
|
145
|
+
declaration list is painted last-layer-first, matching CSS.
|
|
146
|
+
|
|
147
|
+
**`backdrop-filter`** is composited by the same offscreen machinery as
|
|
148
|
+
`mix-blend-mode`: when the painter reaches the box, the renderer copies the
|
|
149
|
+
scene painted so far into a scratch texture, applies the Gaussian and one
|
|
150
|
+
combined colour matrix (brightness/contrast/grayscale/sepia/invert/saturate/
|
|
151
|
+
hue-rotate/opacity multiplied together) in a full-screen shader, and composites
|
|
152
|
+
the result back through the box's rounded border-box mask. A `backdrop-filter`
|
|
153
|
+
therefore shows as a `backdrop …` op in `paintList()`.
|
|
120
154
|
|
|
121
155
|
**`clip-path`** is resolved in `paint_clip.cpp` to a device-space polygon (the
|
|
122
156
|
box transform is applied to every point), triangulated with ear clipping, and
|
|
@@ -133,8 +167,8 @@ colour, so a box and its descendants see the filter. `blur()` and
|
|
|
133
167
|
`drop-shadow()` are approximations at the display-list level: blur spreads nine
|
|
134
168
|
translucent copies per shape, drop-shadow is a box/text silhouette. This keeps
|
|
135
169
|
the ordinary painter single-pass at the cost of group semantics: overlapping
|
|
136
|
-
descendants of a blurred/filtered group can darken
|
|
137
|
-
|
|
170
|
+
descendants of a blurred/filtered group can darken. `backdrop-filter` is the
|
|
171
|
+
exception — it has its own offscreen snapshot/filter pass (see above).
|
|
138
172
|
|
|
139
173
|
**`mix-blend-mode`** is the exception that does need an offscreen layer. A box
|
|
140
174
|
with a non-`normal` mode is wrapped in `LayerBegin`/`LayerEnd` markers (visible
|
|
@@ -149,37 +183,59 @@ SPIRV-Cross (Metal); the two scene textures per nesting level are reused across
|
|
|
149
183
|
frames and ping-pong so the backdrop stays sampleable while it is written.
|
|
150
184
|
Backends that consume neither format — the D3D12/DXIL path, which has no shader
|
|
151
185
|
compiler here — keep painting the group with ordinary source-over blending.
|
|
152
|
-
`backdrop-filter`
|
|
186
|
+
`backdrop-filter` uses the same runtime-compiled path; when the shader backend is
|
|
187
|
+
unavailable it is skipped while the rest of the page still paints.
|
|
153
188
|
|
|
154
189
|
## Text stack (M4b)
|
|
155
190
|
|
|
156
|
-
`runtime/ext_gui/text.{h,cpp}`
|
|
157
|
-
|
|
158
|
-
`
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
191
|
+
`runtime/ext_gui/text.{h,cpp}` is the front-end; it dispatches through a small
|
|
192
|
+
backend table. The default backend is the bundled **stb_truetype**
|
|
193
|
+
(`text_stb.cpp`, `runtime/ext_gui/stb_truetype.h`). The optional **`shaping`**
|
|
194
|
+
link feature installs `text_hb.cpp`, a HarfBuzz + FreeType backend, and is
|
|
195
|
+
selected automatically for non-ASCII text or an author `@font-face` rule. Both
|
|
196
|
+
backends share the font database in `text_font_db.cpp` (discovery and indexing)
|
|
197
|
+
and the CSS matcher in `text_fonts.cpp`, plus the sfnt metadata reader in
|
|
198
|
+
`text_font_sfnt.cpp`, so a CSS style resolves to the same real face whichever
|
|
199
|
+
shaper is linked.
|
|
200
|
+
|
|
201
|
+
- Fonts are resolved from the installed system faces. The `font-family` list is
|
|
202
|
+
matched case-insensitively; `sans-serif`, `serif`, `monospace` (and the
|
|
203
|
+
`system-ui`/`ui-*` aliases) map to platform defaults, while any other family
|
|
204
|
+
name discovers the platform font directories once. `font-weight` (1–1000) and
|
|
205
|
+
`font-style: italic` select that family's real bold/italic face using the CSS
|
|
206
|
+
Fonts weight-matching order; a missing weight picks the nearest face and a
|
|
207
|
+
family without an italic face uses its upright face — there is no synthetic
|
|
208
|
+
bold or oblique. Faces are cached per `(file, collection index, size)`.
|
|
209
|
+
`XT_GUI_FONT` / `XT_GUI_FONT_MONO` still override the generic defaults.
|
|
210
|
+
- Author **`@font-face`** rules load local sfnt faces (`.ttf`, `.ttc`, `.otf`,
|
|
211
|
+
`.otc`). The `src` list is tried from left to right; `local(...)`, remote and
|
|
212
|
+
`data:` entries are skipped. A relative URL is a local `file:` path resolved
|
|
213
|
+
against the process working directory — the same policy as image sources — and
|
|
214
|
+
`file://` URLs (including percent-encoded paths) are accepted. The
|
|
215
|
+
`font-weight`/`font-style` descriptors select the face; a weight range
|
|
216
|
+
(`font-weight: 100 900`) is honoured, and later rules with the same family and
|
|
217
|
+
descriptors replace earlier ones. CSS matches the declared family name even
|
|
218
|
+
when it differs from the font file's internal name. When no source is
|
|
219
|
+
readable the family simply falls through to the next family in the CSS list.
|
|
220
|
+
- The default candidates prefer a **CJK-capable TrueType/TTC** face (Microsoft
|
|
221
|
+
YaHei on Windows, PingFang/STHeiti on macOS, Noto Sans CJK/WenQuanYi on Linux)
|
|
222
|
+
before the Latin-only ones. A family's weight/style variants are resolved
|
|
223
|
+
across its files, and a candidate stb_truetype cannot parse (for example a
|
|
224
|
+
CFF/OTF collection) is skipped in favour of the next one; the `shaping`
|
|
225
|
+
backend loads it instead.
|
|
169
226
|
- **Codepoints the primary face lacks fall back to another face.** The engine
|
|
170
227
|
keeps a small fallback chain — the platform's symbol face (Segoe UI Symbol,
|
|
171
|
-
Apple Symbols, Noto Sans Symbols, DejaVu Sans) first, then the
|
|
172
|
-
|
|
173
|
-
glyph. The run is shaped in segments, one per face, so a mixed
|
|
228
|
+
Apple Symbols, Noto Sans Symbols, DejaVu Sans) first, then the default sans,
|
|
229
|
+
serif and monospace faces — and resolves each codepoint to the first face in
|
|
230
|
+
it that has the glyph. The run is shaped in segments, one per face, so a mixed
|
|
231
|
+
run (Latin
|
|
174
232
|
plus an arrow, box-drawing or geometric shape, or Latin inside CJK) draws
|
|
175
|
-
every glyph instead of dropping the missing ones as `.notdef`.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
- `xt_text_measure_width` shapes the run with HarfBuzz (so kerning and
|
|
182
|
-
ligatures are honoured), `xt_text_metrics` returns FreeType's ascent /
|
|
233
|
+
every glyph instead of dropping the missing ones as `.notdef`. Each shaped
|
|
234
|
+
glyph carries its face (`ShapedGlyph::font`) so the renderer rasterises it
|
|
235
|
+
from the right atlas entry; `xt_text_scale` maps a face to the display's scale
|
|
236
|
+
factor.
|
|
237
|
+
- `xt_text_measure_width` maps each codepoint to a glyph and adds its advance
|
|
238
|
+
plus the font's `kern` table; `xt_text_metrics` returns stb_truetype's ascent /
|
|
183
239
|
descent / normal line height. When no font file can be found the module falls
|
|
184
240
|
back to a deterministic per-byte approximation, so layout still works.
|
|
185
241
|
- `xt_text_shape_run` returns positioned glyphs and `xt_text_rasterize` renders
|
|
@@ -189,6 +245,15 @@ compiler here — keep painting the group with ordinary source-over blending.
|
|
|
189
245
|
- Layout uses these real metrics for text widths, line breaking and
|
|
190
246
|
`line-height: normal`; `measureText`/`fontMetrics` expose them to tests.
|
|
191
247
|
|
|
248
|
+
Shape trade-off: the default is a simple shaper, not a full OpenType engine. It
|
|
249
|
+
handles Latin/CJK/Cyrillic/Greek, basic kerning and per-codepoint fallback, but
|
|
250
|
+
it does not run ligatures or complex-script shaping (Arabic/Indic/Thai), and
|
|
251
|
+
stb_truetype only accepts TrueType outlines, not CFF/OTF or variable fonts. The
|
|
252
|
+
choice keeps a DOM-only binary near 3 MiB. The optional **`shaping`** link
|
|
253
|
+
feature installs the HarfBuzz + FreeType backend instead (about 1.2 MiB) and
|
|
254
|
+
restores full OpenType shaping and CFF/OTF/variable-font support; it is selected
|
|
255
|
+
automatically for non-ASCII text and can be forced with `--feature shaping`.
|
|
256
|
+
|
|
192
257
|
## Performance (M20)
|
|
193
258
|
|
|
194
259
|
The engine is a retained-mode pipeline: a DOM mutation restyles the document,
|
|
@@ -210,7 +275,17 @@ is what `tests/e2e/gui-perf.test.ts` asserts on.
|
|
|
210
275
|
glyphs / 8,192 entries; when a generation is full the *spare* one is dropped
|
|
211
276
|
and becomes current, so the hot path has no LRU bookkeeping. A word is shaped
|
|
212
277
|
once and reused by every later layout pass and repaint that draws it. Primary
|
|
213
|
-
face lookups are cached by (family
|
|
278
|
+
face lookups are cached by (family, weight, style, size) as well; the font
|
|
279
|
+
database itself scans the platform directories only once, on the first
|
|
280
|
+
non-generic family request.
|
|
281
|
+
- **No-op writes.** `textContent` and `style.<property>` do nothing when the
|
|
282
|
+
node already shows that value: the document is not dirtied, so no restyle,
|
|
283
|
+
relayout, repaint or upload follows. A HUD that assigns the same clock string,
|
|
284
|
+
the same bar width or the same transform every frame therefore costs nothing —
|
|
285
|
+
before this each assignment rebuilt a text node (an allocation, and one the
|
|
286
|
+
collector then had to sweep) or re-serialized the inline style, and dirtied
|
|
287
|
+
the document for a full restyle. `classList` and `removeAttribute` already
|
|
288
|
+
behaved this way; `setAttribute` still dirties unconditionally.
|
|
214
289
|
- **Frame loop.** The media/canvas tables are reconciled with the DOM only when
|
|
215
290
|
the document changed (or on the first frame) instead of walking the tree every
|
|
216
291
|
frame. A frame presents only when something happened — a mutation, a scroll,
|
package/doc/gui/runtime.md
CHANGED
|
@@ -55,6 +55,11 @@ that case with a single 16 ms `xt_set_timeout` tick:
|
|
|
55
55
|
queued animation-frame callbacks before layout, so a page can stop itself),
|
|
56
56
|
- it re-arms **only while callbacks remain**, so an idle page lets the event
|
|
57
57
|
loop drain and the process exit — the browser-tab lifecycle;
|
|
58
|
+
- it schedules the next tick for *frame start + 16 ms*, not 16 ms after the
|
|
59
|
+
frame finished: the frame's own duration is not added to the interval, so a
|
|
60
|
+
10 ms frame runs at a 16 ms period instead of 26 ms, and a page slower than
|
|
61
|
+
16 ms runs as fast as it can instead of falling a frame's worth of time
|
|
62
|
+
further behind on every frame;
|
|
58
63
|
- it stands aside while `xt_gui_run_active()` is set (the program called
|
|
59
64
|
`run()`), so the same window is not rendered twice per tick;
|
|
60
65
|
- `XT_GUI_AUTOCLOSE_MS=n` makes the pump quit after `n` milliseconds, which is
|
package/doc/gui/webgl.md
CHANGED
|
@@ -48,8 +48,19 @@ reports the type as well.
|
|
|
48
48
|
`readPixels` flips rows back, and the compositor sees an upright texture.
|
|
49
49
|
- A fixed-function state change (`blendFunc`, `depthFunc`, `cullFace`,
|
|
50
50
|
`colorMask`, …) changes which `SDL_GPUGraphicsPipeline` is needed, so
|
|
51
|
-
pipelines are created lazily
|
|
52
|
-
the program
|
|
51
|
+
pipelines are created lazily and cached on the program. The key is the
|
|
52
|
+
*content* of the draw: the program, the primitive mode, a hash of the vertex
|
|
53
|
+
layout (attribute locations, formats, offsets, buffer pitches and input rates),
|
|
54
|
+
the reflected fixed-function state and the attachment formats. It deliberately
|
|
55
|
+
excludes the context's monotonic version counters (`attribs_version_`,
|
|
56
|
+
`framebuffer_version_`) and the GPU buffer handles: those advance on every VAO
|
|
57
|
+
bind, framebuffer switch or buffer re-creation without changing the pipeline,
|
|
58
|
+
and keying on them re-created every pipeline once per frame in a scene that
|
|
59
|
+
binds several layouts per frame — three.js does, and measured 248
|
|
60
|
+
`SDL_CreateGPUGraphicsPipeline` calls per frame while the per-program cache
|
|
61
|
+
grew without bound. `tests/e2e/gui-webgl-pipeline-cache.test.ts` pins the
|
|
62
|
+
steady state: two draws with the same layout and different buffers create no
|
|
63
|
+
pipeline after the first frame.
|
|
53
64
|
|
|
54
65
|
## Shaders: GLSL ES to SPIR-V (and on to MSL)
|
|
55
66
|
|
|
@@ -283,9 +294,15 @@ format — Direct3D 12, which would need DXIL — `getContext("webgl")` and
|
|
|
283
294
|
`getContext("webgl2")` both answer `null`; the 2D canvas and the rest of the page
|
|
284
295
|
still work.
|
|
285
296
|
|
|
286
|
-
glslang
|
|
287
|
-
`gui.
|
|
288
|
-
|
|
297
|
+
glslang is fetched and built by `npm run gui` and merged into `gui.a` /
|
|
298
|
+
`gui.lib`; SPIRV-Cross is merged **on macOS only**, because no other SDL_GPU
|
|
299
|
+
backend consumes MSL (see [Packaging and build](./build.md)). Both are reached
|
|
300
|
+
through the optional **`gpu` link feature**: the compiler selects it when the
|
|
301
|
+
program may call `getContext("webgl…")` or use `mix-blend-mode`, and only then
|
|
302
|
+
does the feature bridge pull the translator members out of `gui.a`. The WebGL
|
|
303
|
+
context and DOM bindings are the separate **`webgl` feature**, which requires
|
|
304
|
+
`gpu`; a program that only uses the 2D canvas or the DOM links neither glslang,
|
|
305
|
+
SPIRV-Cross, nor any `webgl_*` member (see [Link features](./build.md#link-features)).
|
|
289
306
|
|
|
290
307
|
## Testing
|
|
291
308
|
|
|
@@ -339,6 +356,7 @@ Canvas2D fallback is bundled any more**. Verified with three.js r160 through SDL
|
|
|
339
356
|
Features outside this engine's subset still cannot be emulated: transform
|
|
340
357
|
feedback and MSAA. Depth textures, float render targets and compressed textures
|
|
341
358
|
are available, and comparative `sampler2DShadow` sampling is translated, so
|
|
342
|
-
three.js shadow maps can use the hardware depth compare on both backends
|
|
359
|
+
three.js shadow maps can use the hardware depth compare on both backends (see
|
|
360
|
+
[known issues](./known-issues.md) for an Intel-Mac driver caveat). A
|
|
343
361
|
scene that needs transform feedback or MSAA will not render correctly;
|
|
344
362
|
everything the previous Canvas2D fallback could show now goes through the GPU.
|