xbintsc 0.5.51 → 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/dist/src/cli/help.d.ts +1 -1
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/gui/features.d.ts +9 -6
- package/dist/src/extensions/gui/features.js +14 -9
- package/dist/src/extensions/gui/features.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-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 +5 -0
- package/dist/tests/e2e/gui-helpers.js +4 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-layout.test.js +3 -2
- package/dist/tests/e2e/gui-layout.test.js.map +1 -1
- 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/extensions/gui-features.test.js +8 -1
- package/dist/tests/extensions/gui-features.test.js.map +1 -1
- package/doc/ai/extensions.md +10 -5
- package/doc/ai/zh-CN/extensions.md +9 -4
- package/doc/gui/animation.md +39 -9
- package/doc/gui/build.md +6 -5
- package/doc/gui/dom.md +20 -4
- package/doc/gui/known-issues.md +31 -23
- package/doc/gui/layout.md +30 -7
- package/doc/gui/rendering.md +84 -26
- package/doc/gui.md +62 -14
- package/doc/zh-CN/gui/animation.md +33 -10
- package/doc/zh-CN/gui/build.md +5 -5
- package/doc/zh-CN/gui/dom.md +16 -3
- package/doc/zh-CN/gui/known-issues.md +21 -12
- package/doc/zh-CN/gui/layout.md +22 -5
- package/doc/zh-CN/gui/rendering.md +61 -20
- package/doc/zh-CN/gui.md +53 -15
- 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/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/effect_values.cpp +245 -21
- package/runtime/ext_gui/gradient_values.cpp +24 -0
- package/runtime/ext_gui/grid_values.cpp +23 -0
- package/runtime/ext_gui/gui_cursor.cpp +50 -0
- package/runtime/ext_gui/gui_events.cpp +16 -4
- package/runtime/ext_gui/gui_internal.h +3 -0
- package/runtime/ext_gui/image_api.h +3 -1
- package/runtime/ext_gui/image_feature.cpp +4 -2
- package/runtime/ext_gui/inline_svg.cpp +95 -8
- package/runtime/ext_gui/inline_svg.h +5 -1
- package/runtime/ext_gui/layout.cpp +3 -2
- package/runtime/ext_gui/layout.h +6 -0
- 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/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 +10 -1
- 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 +6 -1
- package/runtime/ext_gui/renderer_internal.h +21 -0
- package/runtime/ext_gui/renderer_layer.cpp +27 -1
- package/runtime/ext_gui/renderer_text.cpp +2 -1
- 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 +4 -2
- package/runtime/ext_gui/text.h +11 -4
- package/runtime/ext_gui/text_cache.cpp +11 -2
- 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_hb.cpp +63 -179
- package/runtime/ext_gui/text_stb.cpp +49 -193
- package/runtime/ext_gui/transform.cpp +107 -9
- package/runtime/ext_gui/transform.h +5 -0
- package/runtime/ext_gui/window.cpp +1 -1
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/features.ts +13 -9
package/doc/gui/animation.md
CHANGED
|
@@ -30,21 +30,27 @@ running transition is recorded and re-applied every frame until it finishes;
|
|
|
30
30
|
the engine advances the clock with real frame deltas (`XtDocument::advance`),
|
|
31
31
|
and `win.advance(ms)` lets tests step it deterministically.
|
|
32
32
|
|
|
33
|
-
- Supported properties: `background-color`, `color`, `border-color`,
|
|
34
|
-
`border-radius
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
- Supported properties: `background-color`, `color`, `border-color`, `opacity`,
|
|
34
|
+
`border-radius`, `transform`, `text-shadow`, `box-shadow`, every box offset
|
|
35
|
+
and size length (`width`/`height`/`top`/`left`/`margin-*`/`padding-*`/…), the
|
|
36
|
+
gap/flex-basis lengths and `filter` (matching filter lists interpolate their
|
|
37
|
+
blur lengths, amounts and drop-shadow colours). `transition: all` covers the
|
|
38
|
+
whole list. Lengths
|
|
39
|
+
interpolate when their units line up (a mixed-unit change is CSS's discrete
|
|
40
|
+
fallback); `opacity`, colours and `transform` interpolate normally.
|
|
38
41
|
- Both the `transition` shorthand and the `transition-property` / `-duration` /
|
|
39
42
|
`-delay` / `-timing-function` longhands are parsed; time values accept `s` and
|
|
40
|
-
`ms`;
|
|
41
|
-
|
|
43
|
+
`ms`; `calc()` is accepted inside the shorthand and longhands.
|
|
44
|
+
- Timing functions are `linear`, `ease`, `ease-in`, `ease-out`, `ease-in-out`,
|
|
45
|
+
`cubic-bezier(x1, y1, x2, y2)`, `steps(n, start|end)` and their `jump-*`
|
|
46
|
+
spellings. The engine solves the cubic Bézier numerically; keyword curves use
|
|
47
|
+
the CSS control points.
|
|
42
48
|
- Retargeting mid-flight starts a new transition from the current interpolated
|
|
43
49
|
value, so reversing a hover animates smoothly from wherever it was.
|
|
44
50
|
- `computedStyle()` reports the displayed (interpolated) value, so transitions
|
|
45
51
|
are directly observable in tests.
|
|
46
52
|
|
|
47
|
-
`transform` lists interpolate **element-wise** (`
|
|
53
|
+
`transform` lists interpolate **element-wise** (`animation_values.cpp`,
|
|
48
54
|
`xt_transform_interpolate`), which is what makes the common pair
|
|
49
55
|
`translateY(-4px) rotate(-0.35deg)` <-> `none` glide instead of jumping: the
|
|
50
56
|
missing side is filled with identity ops of the same kind. Two lists whose shapes
|
|
@@ -52,6 +58,29 @@ or units do not line up (`rotate(10deg)` vs `rotate(10rad)`, or a different numb
|
|
|
52
58
|
of functions) are not interpolated at all — the transition snaps to the target,
|
|
53
59
|
which is CSS's discrete fallback rather than a wrong-looking sweep.
|
|
54
60
|
|
|
61
|
+
## CSS animations (`@keyframes`)
|
|
62
|
+
|
|
63
|
+
`@keyframes` rules are parsed into `StyleSheet::keyframes` (offsets from
|
|
64
|
+
`from`/`to`/percent selectors, sorted). `animation` and every `animation-*`
|
|
65
|
+
longhand are supported: name, duration, delay, timing function, iteration count
|
|
66
|
+
(including `infinite`), direction (`normal`/`reverse`/`alternate`/
|
|
67
|
+
`alternate-reverse`), fill mode (`none`/`forwards`/`backwards`/`both`) and
|
|
68
|
+
`paused`/`running`.
|
|
69
|
+
|
|
70
|
+
`XtDocument` starts one active animation per element/name when the computed
|
|
71
|
+
style first declares it, restarts it when the shorthand changes, and leaves it
|
|
72
|
+
alone across unrelated restyles. Each frame it resolves the local time to an
|
|
73
|
+
iteration progress, applies the timing function **per keyframe interval**, and
|
|
74
|
+
interpolates every animatable property. A property that a middle keyframe does
|
|
75
|
+
not mention keeps interpolating between the nearest keyframes that do declare
|
|
76
|
+
it (so a transform declared at 0% and 100% runs straight through a 50% step that
|
|
77
|
+
only changes `opacity`). Missing 0%/100% steps use the element's underlying
|
|
78
|
+
style. `forwards`/`backwards` hold the edge value outside the active time, and
|
|
79
|
+
`computedStyle()` reports the animated value.
|
|
80
|
+
|
|
81
|
+
Animations and transitions share `animation_values.cpp`, so both understand the
|
|
82
|
+
same property set, shadow lists and `transform` identity filling.
|
|
83
|
+
|
|
55
84
|
## CSS transforms (M15)
|
|
56
85
|
|
|
57
86
|
`transform` and `transform-origin` are supported as *paint-time* effects
|
|
@@ -93,5 +122,6 @@ Both are exercised by `examples/gui/pelican-svg` (per-frame sway plus a
|
|
|
93
122
|
hover transition on the caption) and pinned by
|
|
94
123
|
`tests/e2e/gui-transform.test.ts`.
|
|
95
124
|
|
|
96
|
-
|
|
125
|
+
`calc()` can be used in any animated length (for example
|
|
126
|
+
`transition: width 300ms ease-out; width: calc(100% - 20px)`).
|
|
97
127
|
|
package/doc/gui/build.md
CHANGED
|
@@ -131,7 +131,7 @@ features** selected per program:
|
|
|
131
131
|
| `media` | `media_bridge.c` + `media.a` (FFmpeg) | an HTML `<video>`/`<audio>` tag, `createElement("video"/"audio")`, `new Audio()`, `decodeAudioData`, or runtime-built markup |
|
|
132
132
|
| `gpu` | `gpu_bridge.c` (the implementation is already in `gui.a`) | a `getContext("webgl"/"webgl2"/"experimental-webgl")` (or a kind decided at run time), any `webgl` string, `mix-blend-mode`/`mixBlendMode`, or runtime-built markup |
|
|
133
133
|
| `images` | `image_bridge.c` (the implementation is already in `gui.a`) | `<img>`, inline `<svg>`, `background-image`/`url(...)`, a `.svg` path, `drawImage`/`createImageBitmap`/`Image`, or runtime-built markup |
|
|
134
|
-
| `shaping` | `text_bridge.c` (the implementation is already in `gui.a`) | non-ASCII text (CJK/Cyrillic/Greek/…), an escaped/entity codepoint, or runtime-built markup |
|
|
134
|
+
| `shaping` | `text_bridge.c` (the implementation is already in `gui.a`) | non-ASCII text (CJK/Cyrillic/Greek/…), an escaped/entity codepoint, an author `@font-face` rule (custom fonts may be CFF/OTF), or runtime-built markup |
|
|
135
135
|
| `webgl` | `webgl_bridge.c` (the implementation is already in `gui.a`; requires `gpu`) | a WebGL `getContext(...)`, a `webgl` string, or runtime-built markup |
|
|
136
136
|
|
|
137
137
|
The driver scans the bundled AST (`src/driver/usage.ts`): every string literal
|
|
@@ -206,10 +206,11 @@ TrueType outlines and a per-codepoint mapping plus the font's `kern` table, so
|
|
|
206
206
|
CFF/OTF and variable fonts, OpenType ligatures and complex-script shaping
|
|
207
207
|
(Arabic/Indic/Thai) are not available. The fallback chain still selects another
|
|
208
208
|
face for codepoints the primary lacks. Selecting the optional **`shaping`**
|
|
209
|
-
feature (automatically for non-ASCII text
|
|
210
|
-
HarfBuzz + FreeType back in (~1.2 MiB) and
|
|
211
|
-
CFF/OTF/variable-font support. A Latin-only
|
|
212
|
-
3.1 MiB; a Chinese/complex-script page is closer
|
|
209
|
+
feature (automatically for non-ASCII text or an author `@font-face` rule, or
|
|
210
|
+
with `--feature shaping`) links HarfBuzz + FreeType back in (~1.2 MiB) and
|
|
211
|
+
restores full OpenType shaping and CFF/OTF/variable-font support. A Latin-only
|
|
212
|
+
DOM page therefore stays near 3.1 MiB; a Chinese/complex-script page is closer
|
|
213
|
+
to 4.3 MiB.
|
|
213
214
|
|
|
214
215
|
## Running the example
|
|
215
216
|
|
package/doc/gui/dom.md
CHANGED
|
@@ -21,11 +21,26 @@ commas, brackets or parentheses without splitting the list. Selectors: type,
|
|
|
21
21
|
`.class`, `#id`, attribute (`=`, `~=`, `|=`, `^=`, `$=`, `*=`), the four
|
|
22
22
|
combinators (descendant, child, adjacent and general sibling), the pseudo-classes
|
|
23
23
|
`:first-child`, `:last-child`, `:only-child`, `:empty`, `:root`, `:not(...)`,
|
|
24
|
-
`:nth-child(an+b)`, `:disabled`, `:checked`, plus the stateful `:hover
|
|
25
|
-
`:focus` (
|
|
24
|
+
`:nth-child(an+b)`, `:disabled`, `:checked`, plus the stateful `:hover`,
|
|
25
|
+
`:focus`, `:focus-visible` (currently an alias of `:focus`) and `:active` (see
|
|
26
|
+
[Input](./input.md)), and the pseudo-elements `::before`/`::after`
|
|
26
27
|
(legacy `:before`/`:after` too). Values: lengths (`px`, `%`, `em`, `rem`, `vw`,
|
|
27
28
|
`vh`, `pt`, `pc`, `in`, `cm`, `mm`, `q`), colors (hex, `rgb()`/`rgba()`, a named
|
|
28
|
-
subset), numbers, keywords and shorthands (`margin`/`padding`/`border`/`flex
|
|
29
|
+
subset), numbers, keywords and shorthands (`margin`/`padding`/`border`/`flex`/
|
|
30
|
+
`font`/`outline`). `display: inline-flex`/`inline-grid` make a flex/grid
|
|
31
|
+
container inline-level; `grid-area`, `aspect-ratio`, `letter-spacing`,
|
|
32
|
+
`text-transform`, `writing-mode` (`vertical-rl`/`vertical-lr` text),
|
|
33
|
+
`vertical-align` (length form), percentage `border-radius`, `background-size`
|
|
34
|
+
(size + default repeat for `url()` layers) and `currentColor` are parsed too.
|
|
35
|
+
`font-variant-numeric`, `text-wrap`, `text-rendering`, `touch-action`,
|
|
36
|
+
`user-select`, `overscroll-behavior`, `scroll-behavior`, `isolation` and
|
|
37
|
+
`vector-effect` are accepted but have no engine behaviour (the text stack exposes no OpenType features and the engine
|
|
38
|
+
has no touch/selection/smooth-scroll subsystem); `cursor` maps to the SDL system
|
|
39
|
+
cursor. A document rule may style SVG children with the presentation properties
|
|
40
|
+
`fill`, `fill-opacity`, `fill-rule`, `stroke`, `stroke-opacity`, `stroke-width`,
|
|
41
|
+
`stroke-dasharray`, `stroke-dashoffset`, `stroke-linecap` and `stroke-linejoin`;
|
|
42
|
+
the serializer writes them into the inline `<svg>` markup as NanoSVG-readable
|
|
43
|
+
inline styles. `skewX()`/`skewY()`/`skew()` transform functions are supported.
|
|
29
44
|
`transform` (`translate`/`translate3d`/`translateX`/`translateY`, `scale`/
|
|
30
45
|
`scale3d`/`scaleX`/`scaleY`, `rotate`/`rotateZ`, `matrix`; the `3d` spellings'
|
|
31
46
|
`z` argument is dropped) and `transform-origin` are parsed into the computed
|
|
@@ -33,7 +48,8 @@ style as a list of operations plus two (unresolved) origin lengths; an
|
|
|
33
48
|
unsupported function invalidates the whole declaration
|
|
34
49
|
([Layout](./layout.md#transforms-m15)). M19 adds `background-image` layer lists
|
|
35
50
|
(linear/radial), `clip-path` (`inset`/`circle`/`ellipse`/`polygon`), the
|
|
36
|
-
`filter`/`backdrop-filter` function lists, `text-shadow` and
|
|
51
|
+
`filter`/`backdrop-filter` function lists, `text-shadow`, `box-shadow` and
|
|
52
|
+
`content`.
|
|
37
53
|
|
|
38
54
|
**Cascade & computed style** (`runtime/ext_gui/style.{h,cpp}`): a small built-in
|
|
39
55
|
UA stylesheet, author rules sorted by `(!important, specificity, source order)`,
|
package/doc/gui/known-issues.md
CHANGED
|
@@ -64,29 +64,37 @@
|
|
|
64
64
|
*class change* on a flex container has also been observed to crash the same
|
|
65
65
|
way; `examples/gui/pelican-bike` reveals its game-over overlay with `opacity`
|
|
66
66
|
instead.
|
|
67
|
-
- **CSS coverage is a deliberate subset.** Grid, `
|
|
68
|
-
`
|
|
69
|
-
`
|
|
70
|
-
|
|
71
|
-
(`
|
|
72
|
-
|
|
73
|
-
`
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
`
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
67
|
+
- **CSS coverage is a deliberate subset.** Grid, `calc()` (including
|
|
68
|
+
nested arithmetic and `calc()` inside `min()`/`max()`/`clamp()`),
|
|
69
|
+
`clamp()`/`min()`/`max()`/`env()`, `var()` custom properties, the `inset`
|
|
70
|
+
shorthand, `box-sizing`, `visibility` and `pointer-events`, `@media` queries,
|
|
71
|
+
generated content (`::before`/`::after`), multi-layer linear/radial
|
|
72
|
+
backgrounds, `text-shadow` (true Gaussian), `box-shadow` (outer/inset, spread,
|
|
73
|
+
multiple layers), `clip-path` (`inset`/`circle`/`ellipse`/`polygon`),
|
|
74
|
+
`filter` colour functions, `@keyframes` animations, the full `transition`
|
|
75
|
+
timing-function set, `letter-spacing`, `text-transform`, inline-level
|
|
76
|
+
`flex`/`grid`, `grid-area`, `aspect-ratio`, auto margins, percentage
|
|
77
|
+
`border-radius`, `outline`, `background-size` tiling for `url()` layers and
|
|
78
|
+
document CSS on SVG children (`fill`/`stroke`/…) are implemented. Known
|
|
79
|
+
limits: `background-clip`, `background-position` and `background-repeat`
|
|
80
|
+
remain unimplemented (`background-size` covers the tiled default);
|
|
81
|
+
`font-variant-numeric`, `text-wrap`, `text-rendering`, `touch-action`,
|
|
82
|
+
`user-select`, `overscroll-behavior`, `scroll-behavior`, `isolation` and
|
|
83
|
+
`vector-effect` are parsed but inert; vertical writing mode is text-only (nested/mixed content falls back to
|
|
84
|
+
horizontal); group `opacity` is
|
|
85
|
+
a per-shape alpha rather than a true group composite; the blend and
|
|
86
|
+
`backdrop-filter` compositors are unavailable on the D3D12/DXIL backend, where
|
|
87
|
+
groups fall back to normal source-over painting and the backdrop filter is
|
|
88
|
+
skipped. `filter: blur()` is still a nine-tap per-shape spread rather than a
|
|
89
|
+
true group blur, so overlapping descendants can darken; `drop-shadow` is
|
|
90
|
+
approximated from box silhouettes; at most two nested `clip-path` shapes are
|
|
91
|
+
intersected (deeper nesting keeps the outer two); and images/canvases are not
|
|
92
|
+
colour-filtered except for the brightness/opacity tint the image shader can
|
|
93
|
+
carry. Canvas textures are sampled nearest-neighbour. Background gradients
|
|
94
|
+
(linear and radial) are rasterised per pixel into a texture and then stretched
|
|
95
|
+
when the box is larger than the texture (1024 px per edge for a radial ramp,
|
|
96
|
+
4096 px along the line for a linear one, which is only one texel thick across
|
|
97
|
+
it), so a hard stop in a very large box can come out slightly soft.
|
|
90
98
|
- **SVG is NanoSVG's subset.** SVG *files* (`<img src="logo.svg">`) and inline
|
|
91
99
|
`<svg>` trees share the vendored NanoSVG parser/rasteriser
|
|
92
100
|
(`runtime/ext_gui/svg.cpp`, `inline_svg.cpp`), which renders
|
package/doc/gui/layout.md
CHANGED
|
@@ -25,7 +25,10 @@ with absolute (viewport-relative) geometry:
|
|
|
25
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/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,7 +183,8 @@ 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
|
|
|
@@ -157,22 +192,43 @@ compiler here — keep painting the group with ordinary source-over blending.
|
|
|
157
192
|
backend table. The default backend is the bundled **stb_truetype**
|
|
158
193
|
(`text_stb.cpp`, `runtime/ext_gui/stb_truetype.h`). The optional **`shaping`**
|
|
159
194
|
link feature installs `text_hb.cpp`, a HarfBuzz + FreeType backend, and is
|
|
160
|
-
selected automatically for non-ASCII text.
|
|
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.
|
|
161
200
|
|
|
162
|
-
- Fonts are resolved from
|
|
163
|
-
|
|
164
|
-
`
|
|
165
|
-
|
|
166
|
-
|
|
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.
|
|
167
220
|
- The default candidates prefer a **CJK-capable TrueType/TTC** face (Microsoft
|
|
168
221
|
YaHei on Windows, PingFang/STHeiti on macOS, Noto Sans CJK/WenQuanYi on Linux)
|
|
169
|
-
before the Latin-only ones. A
|
|
170
|
-
|
|
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.
|
|
171
226
|
- **Codepoints the primary face lacks fall back to another face.** The engine
|
|
172
227
|
keeps a small fallback chain — the platform's symbol face (Segoe UI Symbol,
|
|
173
|
-
Apple Symbols, Noto Sans Symbols, DejaVu Sans) first, then the
|
|
174
|
-
|
|
175
|
-
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
|
|
176
232
|
plus an arrow, box-drawing or geometric shape, or Latin inside CJK) draws
|
|
177
233
|
every glyph instead of dropping the missing ones as `.notdef`. Each shaped
|
|
178
234
|
glyph carries its face (`ShapedGlyph::font`) so the renderer rasterises it
|
|
@@ -219,7 +275,9 @@ is what `tests/e2e/gui-perf.test.ts` asserts on.
|
|
|
219
275
|
glyphs / 8,192 entries; when a generation is full the *spare* one is dropped
|
|
220
276
|
and becomes current, so the hot path has no LRU bookkeeping. A word is shaped
|
|
221
277
|
once and reused by every later layout pass and repaint that draws it. Primary
|
|
222
|
-
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.
|
|
223
281
|
- **No-op writes.** `textContent` and `style.<property>` do nothing when the
|
|
224
282
|
node already shows that value: the document is not dirtied, so no restyle,
|
|
225
283
|
relayout, repaint or upload follows. A HUD that assigns the same clock string,
|
package/doc/gui.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# xbintsc GUI extension (self-hosted HTML/CSS renderer)
|
|
2
2
|
|
|
3
|
-
Status: **
|
|
3
|
+
Status: **M22** — features (M1–M15) are complete: HTML parsing, CSS selector
|
|
4
4
|
matching, the cascade, computed styles and layout (block, inline, Flexbox and
|
|
5
5
|
CSS positioning) are
|
|
6
6
|
in place, and the engine *paints*: it builds a display list of rectangles, images
|
|
@@ -44,13 +44,17 @@ them) can be translated, scaled and rotated without reflowing anything — and
|
|
|
44
44
|
**M19** fills in the decorative CSS layer: `@media` queries, generated content
|
|
45
45
|
(`::before`/`::after`), multi-layer linear/radial/repeating backgrounds,
|
|
46
46
|
`text-shadow`, `clip-path`, `mix-blend-mode` (through an offscreen compositor)
|
|
47
|
-
and the `filter` colour
|
|
48
|
-
snapshot, and true group blur remains an approximation — see
|
|
47
|
+
and the `filter` colour effects. See
|
|
49
48
|
[Rendering](./gui/rendering.md#backgrounds-generated-content-and-effects-m19).
|
|
50
49
|
**M20** makes large documents interactive: `@media` is evaluated once per rule,
|
|
51
50
|
layout and paint share a bounded shaping cache, and a frame only does (and
|
|
52
51
|
presents) the work a change requires — see
|
|
53
52
|
[Performance](./gui/rendering.md#performance-m20).
|
|
53
|
+
**M21** completes the value/animation gaps: `calc()` arithmetic everywhere a
|
|
54
|
+
length is accepted, true Gaussian `text-shadow`/`box-shadow`, backdrop
|
|
55
|
+
compositing, `@keyframes` and the full transition timing-function set. See
|
|
56
|
+
[Rendering](./gui/rendering.md#backgrounds-generated-content-and-effects-m19)
|
|
57
|
+
and [Animation](./gui/animation.md#css-animations-keyframes).
|
|
54
58
|
This overview records the locked decisions, the architecture, the milestone plan
|
|
55
59
|
and the current progress; the engine itself is documented by function in the
|
|
56
60
|
pages above.
|
|
@@ -179,8 +183,10 @@ engine were Rust.
|
|
|
179
183
|
rounded-rect SDL_GPU pipeline (`paint.*`, `renderer.*`).
|
|
180
184
|
- **M4b-1 — text stack + metrics** ✅ the text module (`text.*`) with font
|
|
181
185
|
resolution/caching and shaping-based metrics used by layout
|
|
182
|
-
(`measureText`/`fontMetrics`);
|
|
183
|
-
|
|
186
|
+
(`measureText`/`fontMetrics`); the CSS family list, weight and italic style
|
|
187
|
+
select real installed faces, and author `@font-face` rules load local font
|
|
188
|
+
files (relative URLs resolve as `file:` paths against the process working
|
|
189
|
+
directory). Originally HarfBuzz + FreeType, now the bundled stb_truetype.
|
|
184
190
|
- **M4b-2 — glyph rendering** ✅ stb_truetype rasterisation, a shared shelf-packed
|
|
185
191
|
glyph atlas, textured text quads in the display list and HiDPI-aware raster
|
|
186
192
|
scaling. Gradients remain.
|
|
@@ -195,8 +201,8 @@ engine were Rust.
|
|
|
195
201
|
per-file GPU textures and textured quads (`image.*`, `svg.*`, `paint.*`,
|
|
196
202
|
`renderer.*`).
|
|
197
203
|
- **M6b — transitions/animations** ✅ `transition` shorthand + longhands,
|
|
198
|
-
|
|
199
|
-
|
|
204
|
+
retargeting, `cubic-bezier()`/`steps()`, `win.advance(ms)` and (M21)
|
|
205
|
+
`@keyframes` with every animation longhand.
|
|
200
206
|
7. **M7 — CI & releases** ✅ (Linux/macOS/Windows x64 build) / 🚧 (run + Windows arm64)
|
|
201
207
|
- `compile-examples` builds `gui.a` and `media.a` on Linux and macOS
|
|
202
208
|
(required), then runs the examples and `tests/e2e/gui-*.test.ts` under
|
|
@@ -348,16 +354,18 @@ engine were Rust.
|
|
|
348
354
|
- Generated content: `::before`/`::after` selectors, inherited pseudo styles,
|
|
349
355
|
`content` strings/escapes/`attr()`, and synthetic layout boxes that never
|
|
350
356
|
leak into DOM traversal.
|
|
351
|
-
- Multi-layer `background-image` with linear
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
- `text-shadow`
|
|
357
|
+
- Multi-layer `background-image` with linear and radial gradients rasterised
|
|
358
|
+
per pixel into one image texture (`renderer_gradient.cpp`), so hard stops
|
|
359
|
+
and sub-pixel details (a 1px divider) are exact.
|
|
360
|
+
- `text-shadow` and `box-shadow` (outer/inset, spread, multiple layers),
|
|
361
|
+
blurred with a true separable Gaussian over the shape mask (M21).
|
|
355
362
|
- `clip-path` polygons (`inset`/`circle`/`ellipse`/`polygon`) resolved to
|
|
356
363
|
device space, ear-clipped and intersected with shape geometry in
|
|
357
364
|
`renderer_clip.cpp` — no stencil/shader change.
|
|
358
365
|
- `filter` colour functions, nine-tap `blur()` and silhouette
|
|
359
|
-
`drop-shadow()`; `backdrop-filter`
|
|
360
|
-
|
|
366
|
+
`drop-shadow()`; `backdrop-filter` snapshots the scene, applies a Gaussian
|
|
367
|
+
and one combined colour matrix, and composites through the border-box mask
|
|
368
|
+
(M21).
|
|
361
369
|
- E2E coverage in `tests/e2e/gui-effects.test.ts`; see
|
|
362
370
|
[Rendering](./gui/rendering.md#backgrounds-generated-content-and-effects-m19).
|
|
363
371
|
20. **M20 — rendering performance** ✅
|
|
@@ -372,6 +380,28 @@ engine were Rust.
|
|
|
372
380
|
dirty frame, and redundant render-state binds removed.
|
|
373
381
|
- `win.stats()`/`XT_GUI_PERF` counters and `tests/e2e/gui-perf.test.ts`; see
|
|
374
382
|
[Performance](./gui/rendering.md#performance-m20).
|
|
383
|
+
21. **M21 — CSS value/animation completeness** ✅
|
|
384
|
+
- `calc()` is parsed as an unresolved expression tree and resolved by both
|
|
385
|
+
layout (`toPx`) and paint; nested arithmetic, `calc()` inside
|
|
386
|
+
`min`/`max`/`clamp`, and calc in shadows/transforms/filters are covered.
|
|
387
|
+
- `box-shadow` (outer/inset, spread, multiple layers) and blurred
|
|
388
|
+
`text-shadow` are rasterised into a Gaussian mask, cached and composited
|
|
389
|
+
as one tinted image quad.
|
|
390
|
+
- `backdrop-filter` snapshots the painted scene and composites a Gaussian +
|
|
391
|
+
colour matrix through the border-box mask in a runtime-compiled shader.
|
|
392
|
+
- `@keyframes` plus every `animation-*` longhand (delay, iterations,
|
|
393
|
+
direction, fill mode, paused/running) share the property interpolator with
|
|
394
|
+
transitions; transitions now cover opacity, layout lengths, box shadows
|
|
395
|
+
and `cubic-bezier()`/`steps()`/`step-start`/`step-end`.
|
|
396
|
+
- E2E: `tests/e2e/gui-css-features.test.ts`.
|
|
397
|
+
22. **M22 — CSS coverage for the boxing UI** ✅
|
|
398
|
+
- `letter-spacing`, `text-transform`, the `font` shorthand, length-form
|
|
399
|
+
`vertical-align`, `writing-mode` (text-only vertical layout), percentage
|
|
400
|
+
`border-radius`, `inline-flex`/`inline-grid`, `grid-area`, `aspect-ratio`,
|
|
401
|
+
auto margins, `outline` + `:focus-visible`/`:active`, `currentColor`,
|
|
402
|
+
`skewX()`/`skewY()`, `background-size` tiling for `url()` layers and
|
|
403
|
+
document CSS on SVG children (`fill`/`stroke`/…) are now honoured.
|
|
404
|
+
- E2E: `tests/e2e/gui-css-coverage.test.ts`.
|
|
375
405
|
|
|
376
406
|
## Progress log
|
|
377
407
|
|
|
@@ -522,9 +552,27 @@ engine were Rust.
|
|
|
522
552
|
`paint_background.cpp` resolves and paints it (radial layers become one
|
|
523
553
|
`PaintGradient`, which `renderer_gradient.cpp` rasterises into a texture),
|
|
524
554
|
`paint_effects.cpp` applies filter colour functions plus nine-tap
|
|
525
|
-
blur/drop-shadow
|
|
555
|
+
blur/drop-shadow, `paint_shadow.cpp` rasterises Gaussian text/box shadows,
|
|
556
|
+
`paint_backdrop.cpp` + `renderer_layer.cpp` composite `backdrop-filter`, and
|
|
526
557
|
`paint_clip.cpp`/`renderer_clip.cpp` clip geometry against triangulated
|
|
527
558
|
`clip-path` polygons. E2E: `tests/e2e/gui-effects.test.ts`.
|
|
559
|
+
- **M22** ✅ CSS coverage for the boxing UI. The cascade/declaration parser
|
|
560
|
+
gained `letter-spacing`, `text-transform`, the `font` shorthand,
|
|
561
|
+
`vertical-align`, `writing-mode`, percentage `border-radius`, `outline`,
|
|
562
|
+
`background-size`, `currentColor` and the SVG presentation properties;
|
|
563
|
+
layout gained inline-level flex/grid, `grid-area`, `aspect-ratio`, auto
|
|
564
|
+
margins and text-only vertical writing mode; paint gained outline edges,
|
|
565
|
+
sized/tiled image backgrounds and rotated vertical text; `:focus-visible` is
|
|
566
|
+
an alias of `:focus` and `:active` is tracked from pointer down/up. E2E:
|
|
567
|
+
`tests/e2e/gui-css-coverage.test.ts`.
|
|
568
|
+
- **M21** ✅ CSS value/animation completeness. `calc()` is parsed as an
|
|
569
|
+
unresolved expression tree and resolved by layout/paint; `box-shadow` and
|
|
570
|
+
blurred `text-shadow` use a separable Gaussian mask cached as a texture;
|
|
571
|
+
`backdrop-filter` gets an offscreen snapshot pass; `@keyframes` (plus every
|
|
572
|
+
`animation-*` longhand, delay, iteration, direction and fill mode) shares the
|
|
573
|
+
property interpolator with transitions, which now also cover opacity, layout
|
|
574
|
+
lengths, box shadows and `cubic-bezier()`/`steps()`. E2E:
|
|
575
|
+
`tests/e2e/gui-css-features.test.ts`.
|
|
528
576
|
- **M20** ✅ rendering performance. `@media` is evaluated once per rule per
|
|
529
577
|
restyle, generated content is skipped for sheets without `::before`/`::after`,
|
|
530
578
|
and `:hover`/`:focus` only restyle when the sheet tracks them
|