xbintsc 0.3.69 → 0.3.81
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 +57 -4
- package/README.zh-CN.md +51 -2
- package/dist/src/driver/compiler.js +6 -1
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/extensions/gui/index.js +10 -2
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/tests/e2e/gui-advanced.test.d.ts +6 -0
- package/dist/tests/e2e/gui-advanced.test.js +261 -0
- package/dist/tests/e2e/gui-advanced.test.js.map +1 -0
- package/dist/tests/e2e/gui-canvas.test.d.ts +9 -0
- package/dist/tests/e2e/gui-canvas.test.js +233 -0
- package/dist/tests/e2e/gui-canvas.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-svg.test.d.ts +21 -0
- package/dist/tests/e2e/gui-example-svg.test.js +105 -0
- package/dist/tests/e2e/gui-example-svg.test.js.map +1 -0
- package/dist/tests/e2e/gui-example.test.d.ts +1 -1
- package/dist/tests/e2e/gui-example.test.js +2 -2
- package/dist/tests/e2e/gui-helpers.d.ts +3 -0
- package/dist/tests/e2e/gui-helpers.js +5 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-layout.test.js +73 -0
- package/dist/tests/e2e/gui-layout.test.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.d.ts +8 -0
- package/dist/tests/e2e/gui-media.test.js +119 -0
- package/dist/tests/e2e/gui-media.test.js.map +1 -0
- package/dist/tests/e2e/gui-paint.test.js +40 -0
- package/dist/tests/e2e/gui-paint.test.js.map +1 -1
- package/dist/tests/e2e/gui-transform.test.d.ts +7 -0
- package/dist/tests/e2e/gui-transform.test.js +198 -0
- package/dist/tests/e2e/gui-transform.test.js.map +1 -0
- package/doc/ai/cli.md +5 -0
- package/doc/ai/extensions.md +20 -3
- package/doc/ai/zh-CN/extensions.md +14 -3
- package/doc/gui/animation.md +97 -0
- package/doc/gui/api.md +92 -0
- package/doc/gui/build.md +91 -0
- package/doc/gui/canvas.md +98 -0
- package/doc/gui/dom.md +128 -0
- package/doc/gui/input.md +25 -0
- package/doc/gui/known-issues.md +78 -0
- package/doc/gui/layout.md +108 -0
- package/doc/gui/media.md +87 -0
- package/doc/gui/rendering.md +113 -0
- package/doc/gui/runtime.md +88 -0
- package/doc/gui-scripts.md +7 -3
- package/doc/gui.md +109 -612
- package/doc/implemented.md +1 -0
- package/doc/zh-CN/gui/animation.md +93 -0
- package/doc/zh-CN/gui/api.md +88 -0
- package/doc/zh-CN/gui/build.md +84 -0
- package/doc/zh-CN/gui/canvas.md +80 -0
- package/doc/zh-CN/gui/dom.md +119 -0
- package/doc/zh-CN/gui/input.md +23 -0
- package/doc/zh-CN/gui/known-issues.md +60 -0
- package/doc/zh-CN/gui/layout.md +91 -0
- package/doc/zh-CN/gui/media.md +71 -0
- package/doc/zh-CN/gui/rendering.md +92 -0
- package/doc/zh-CN/gui/runtime.md +76 -0
- package/doc/zh-CN/gui-scripts.md +6 -2
- package/doc/zh-CN/gui.md +89 -532
- package/doc/zh-CN/implemented.md +1 -0
- package/llms.txt +15 -2
- package/package.json +1 -1
- package/runtime/ext_gui/canvas.cpp +580 -0
- package/runtime/ext_gui/canvas.h +170 -0
- package/runtime/ext_gui/canvas_internal.h +59 -0
- package/runtime/ext_gui/canvas_raster.cpp +254 -0
- package/runtime/ext_gui/document.cpp +45 -4
- package/runtime/ext_gui/document.h +15 -1
- package/runtime/ext_gui/dom_api.cpp +3 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +548 -0
- package/runtime/ext_gui/dom_api_internal.h +73 -0
- package/runtime/ext_gui/dom_api_media.cpp +274 -0
- package/runtime/ext_gui/dom_api_node.cpp +6 -4
- package/runtime/ext_gui/dom_api_proto.cpp +80 -0
- package/runtime/ext_gui/gui.cpp +6 -0
- package/runtime/ext_gui/gui_canvas.cpp +95 -0
- package/runtime/ext_gui/gui_engine.h +49 -0
- package/runtime/ext_gui/gui_events.cpp +21 -5
- package/runtime/ext_gui/gui_media.cpp +193 -0
- package/runtime/ext_gui/image.cpp +31 -12
- package/runtime/ext_gui/image.h +20 -7
- package/runtime/ext_gui/layout.cpp +130 -6
- package/runtime/ext_gui/layout.h +54 -1
- package/runtime/ext_gui/layout_flex.cpp +263 -99
- package/runtime/ext_gui/layout_flow.cpp +85 -9
- package/runtime/ext_gui/layout_flow_internal.h +84 -5
- package/runtime/ext_gui/layout_inline.cpp +54 -37
- package/runtime/ext_gui/media.cpp +514 -0
- package/runtime/ext_gui/media.h +104 -0
- package/runtime/ext_gui/nanosvg.h +3278 -0
- package/runtime/ext_gui/nanosvgrast.h +1472 -0
- package/runtime/ext_gui/paint.cpp +156 -38
- package/runtime/ext_gui/paint.h +42 -6
- package/runtime/ext_gui/renderer.cpp +117 -12
- package/runtime/ext_gui/renderer.h +49 -9
- package/runtime/ext_gui/renderer_image.cpp +205 -78
- package/runtime/ext_gui/renderer_internal.h +12 -9
- package/runtime/ext_gui/renderer_text.cpp +46 -39
- package/runtime/ext_gui/style.h +21 -0
- package/runtime/ext_gui/style_print.cpp +17 -0
- package/runtime/ext_gui/style_ua.cpp +7 -0
- package/runtime/ext_gui/style_values.cpp +83 -1
- package/runtime/ext_gui/svg.cpp +182 -0
- package/runtime/ext_gui/svg.h +46 -0
- package/runtime/ext_gui/text.cpp +156 -25
- package/runtime/ext_gui/text.h +11 -2
- package/runtime/ext_gui/transform.cpp +412 -0
- package/runtime/ext_gui/transform.h +112 -0
- package/runtime/ext_gui/window.cpp +10 -5
- package/scripts/build-gui.ts +148 -6
- package/scripts/check-file-length.ts +5 -1
- package/scripts/install-gui-deps.sh +28 -0
- package/src/driver/compiler.ts +6 -1
- package/src/extensions/gui/index.ts +10 -2
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end tests for `<canvas>` support in the `gui` extension.
|
|
3
|
+
*
|
|
4
|
+
* A `<canvas>` is a replaced element laid out like an `<img>`, but its pixels
|
|
5
|
+
* come from a CPU rasteriser instead of a decoder. The script draws through the
|
|
6
|
+
* 2D context and the engine turns the bitmap into a GPU texture through the same
|
|
7
|
+
* image path as `media_id`/`src` (see `renderer_image.cpp`).
|
|
8
|
+
*/
|
|
9
|
+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
10
|
+
import { createGuiHarness, guiAvailable } from "./gui-helpers.js";
|
|
11
|
+
const harness = createGuiHarness();
|
|
12
|
+
describe.skipIf(!guiAvailable)("gui extension — canvas", () => {
|
|
13
|
+
beforeAll(() => harness.setup());
|
|
14
|
+
afterAll(() => harness.cleanup());
|
|
15
|
+
it("lays out a canvas and rasterises fills into pixels", () => {
|
|
16
|
+
const { value, stdout } = harness.compileAndRun("canvas-draw", `
|
|
17
|
+
import { createWindow, run } from "gui";
|
|
18
|
+
|
|
19
|
+
const HTML = \`
|
|
20
|
+
<html><head><style>
|
|
21
|
+
body { margin: 0; }
|
|
22
|
+
#c { width: 100px; height: 50px; }
|
|
23
|
+
</style></head><body>
|
|
24
|
+
<canvas id="c" width="100" height="50"></canvas>
|
|
25
|
+
</body></html>
|
|
26
|
+
\`;
|
|
27
|
+
|
|
28
|
+
const win = createWindow({ title: "canvas", width: 400, height: 300 });
|
|
29
|
+
win.on("ready", () => {
|
|
30
|
+
const canvas: any = win.document.getElementById("c");
|
|
31
|
+
const ctx: any = canvas.getContext("2d");
|
|
32
|
+
ctx.fillStyle = "#ff0000";
|
|
33
|
+
ctx.fillRect(0, 0, 50, 50);
|
|
34
|
+
ctx.fillStyle = "#0000ff";
|
|
35
|
+
ctx.fillRect(50, 0, 50, 50);
|
|
36
|
+
|
|
37
|
+
const left = ctx.getImageData(0, 0, 1, 1).data;
|
|
38
|
+
const right = ctx.getImageData(99, 0, 1, 1).data;
|
|
39
|
+
console.log("left=" + left[0] + "," + left[1] + "," + left[2] + "," + left[3]);
|
|
40
|
+
console.log("right=" + right[0] + "," + right[1] + "," + right[2] + "," + right[3]);
|
|
41
|
+
|
|
42
|
+
console.log("size=" + canvas.width + "x" + canvas.height);
|
|
43
|
+
const rect = win.getBoundingClientRect("#c");
|
|
44
|
+
console.log("rect=" + rect.x + "," + rect.y + "," + rect.width + "," + rect.height);
|
|
45
|
+
console.log("paint-list-start");
|
|
46
|
+
console.log(win.paintList());
|
|
47
|
+
console.log("paint-list-end");
|
|
48
|
+
|
|
49
|
+
// The same context handle is returned on every getContext("2d").
|
|
50
|
+
console.log("same-ctx=" + (canvas.getContext("2d") === ctx));
|
|
51
|
+
win.close();
|
|
52
|
+
});
|
|
53
|
+
win.loadHTML(HTML);
|
|
54
|
+
run();
|
|
55
|
+
`);
|
|
56
|
+
const list = stdout.slice(stdout.indexOf("paint-list-start"), stdout.indexOf("paint-list-end"));
|
|
57
|
+
// The canvas keeps its attribute size and is laid out as a replaced block.
|
|
58
|
+
expect(value("size")).toBe("100x50");
|
|
59
|
+
expect(value("rect")).toBe("0,0,100,50");
|
|
60
|
+
// The rasteriser filled the left half red and the right half blue.
|
|
61
|
+
expect(value("left")).toBe("255,0,0,255");
|
|
62
|
+
expect(value("right")).toBe("0,0,255,255");
|
|
63
|
+
// The canvas reaches the display list as an image keyed by its canvas id.
|
|
64
|
+
expect(list).toMatch(/image x=0\.0 y=0\.0 w=100\.0 h=50\.0 canvas=\d+/);
|
|
65
|
+
expect(value("same-ctx")).toBe("true");
|
|
66
|
+
});
|
|
67
|
+
it("honours attributes, the default size and the width/height setters", () => {
|
|
68
|
+
const { value } = harness.compileAndRun("canvas-size", `
|
|
69
|
+
import { createWindow, run } from "gui";
|
|
70
|
+
|
|
71
|
+
const HTML = \`
|
|
72
|
+
<html><head><style>
|
|
73
|
+
body { margin: 0; }
|
|
74
|
+
</style></head><body>
|
|
75
|
+
<canvas id="a" width="80" height="40"></canvas>
|
|
76
|
+
<canvas id="b"></canvas>
|
|
77
|
+
</body></html>
|
|
78
|
+
\`;
|
|
79
|
+
|
|
80
|
+
const win = createWindow({ title: "canvas-size", width: 400, height: 300 });
|
|
81
|
+
win.on("ready", () => {
|
|
82
|
+
const a: any = win.document.getElementById("a");
|
|
83
|
+
const b: any = win.document.getElementById("b");
|
|
84
|
+
console.log("a=" + a.width + "x" + a.height);
|
|
85
|
+
console.log("b=" + b.width + "x" + b.height);
|
|
86
|
+
|
|
87
|
+
// Without CSS the canvas lays out at its attribute size.
|
|
88
|
+
const rectA = win.getBoundingClientRect("#a");
|
|
89
|
+
console.log("rect-a=" + rectA.width + "x" + rectA.height);
|
|
90
|
+
|
|
91
|
+
b.width = 64;
|
|
92
|
+
b.height = 32;
|
|
93
|
+
console.log("b2=" + b.width + "x" + b.height);
|
|
94
|
+
const rectB = win.getBoundingClientRect("#b");
|
|
95
|
+
console.log("rect-b=" + rectB.width + "x" + rectB.height);
|
|
96
|
+
win.close();
|
|
97
|
+
});
|
|
98
|
+
win.loadHTML(HTML);
|
|
99
|
+
run();
|
|
100
|
+
`);
|
|
101
|
+
expect(value("a")).toBe("80x40");
|
|
102
|
+
// The CSS default canvas size is 300x150.
|
|
103
|
+
expect(value("b")).toBe("300x150");
|
|
104
|
+
expect(value("rect-a")).toBe("80x40");
|
|
105
|
+
expect(value("b2")).toBe("64x32");
|
|
106
|
+
expect(value("rect-b")).toBe("64x32");
|
|
107
|
+
});
|
|
108
|
+
it("applies transforms, paths and text metrics", () => {
|
|
109
|
+
const { value } = harness.compileAndRun("canvas-paths", `
|
|
110
|
+
import { createWindow, run } from "gui";
|
|
111
|
+
|
|
112
|
+
const HTML = \`
|
|
113
|
+
<html><head><style>body { margin: 0; }</style></head><body>
|
|
114
|
+
<canvas id="c" width="100" height="100"></canvas>
|
|
115
|
+
</body></html>
|
|
116
|
+
\`;
|
|
117
|
+
|
|
118
|
+
const win = createWindow({ title: "canvas-paths", width: 400, height: 300 });
|
|
119
|
+
win.on("ready", () => {
|
|
120
|
+
const canvas: any = win.document.getElementById("c");
|
|
121
|
+
const ctx: any = canvas.getContext("2d");
|
|
122
|
+
|
|
123
|
+
// Translate 10px right, then fill a 5x5 square: pixel (10,0) is painted.
|
|
124
|
+
ctx.save();
|
|
125
|
+
ctx.translate(10, 0);
|
|
126
|
+
ctx.fillStyle = "#00ff00";
|
|
127
|
+
ctx.fillRect(0, 0, 5, 5);
|
|
128
|
+
ctx.restore();
|
|
129
|
+
const moved = ctx.getImageData(10, 0, 1, 1).data;
|
|
130
|
+
const origin = ctx.getImageData(0, 0, 1, 1).data;
|
|
131
|
+
console.log("moved=" + moved[0] + "," + moved[1] + "," + moved[2] + "," + moved[3]);
|
|
132
|
+
console.log("origin=" + origin[3]);
|
|
133
|
+
|
|
134
|
+
// A path fill through beginPath + rect.
|
|
135
|
+
ctx.beginPath();
|
|
136
|
+
ctx.fillStyle = "#ff00ff";
|
|
137
|
+
ctx.rect(60, 60, 20, 20);
|
|
138
|
+
ctx.fill();
|
|
139
|
+
const path = ctx.getImageData(70, 70, 1, 1).data;
|
|
140
|
+
console.log("path=" + path[0] + "," + path[1] + "," + path[2] + "," + path[3]);
|
|
141
|
+
|
|
142
|
+
// save/restore also restores the paint style, not just the transform.
|
|
143
|
+
ctx.fillStyle = "#ff0000";
|
|
144
|
+
ctx.save();
|
|
145
|
+
ctx.fillStyle = "#0000ff";
|
|
146
|
+
ctx.restore();
|
|
147
|
+
console.log("fill=" + ctx.fillStyle);
|
|
148
|
+
|
|
149
|
+
console.log("text=" + (ctx.measureText("Hello").width > 0));
|
|
150
|
+
win.close();
|
|
151
|
+
});
|
|
152
|
+
win.loadHTML(HTML);
|
|
153
|
+
run();
|
|
154
|
+
`);
|
|
155
|
+
expect(value("moved")).toBe("0,255,0,255");
|
|
156
|
+
// The transform is undone by `restore`, so the origin stays transparent.
|
|
157
|
+
expect(value("origin")).toBe("0");
|
|
158
|
+
expect(value("path")).toBe("255,0,255,255");
|
|
159
|
+
expect(value("fill")).toBe("#ff0000");
|
|
160
|
+
expect(value("text")).toBe("true");
|
|
161
|
+
});
|
|
162
|
+
it("draws an image onto a canvas with drawImage", () => {
|
|
163
|
+
const src = harness.imageSrc(harness.logoPath);
|
|
164
|
+
const { value } = harness.compileAndRun("canvas-drawimage", `
|
|
165
|
+
import { createWindow, run } from "gui";
|
|
166
|
+
|
|
167
|
+
const HTML = \`
|
|
168
|
+
<html><head><style>body { margin: 0; }</style></head><body>
|
|
169
|
+
<img id="logo" src="${src}" style="display:none">
|
|
170
|
+
<canvas id="c" width="40" height="40"></canvas>
|
|
171
|
+
</body></html>
|
|
172
|
+
\`;
|
|
173
|
+
|
|
174
|
+
const win = createWindow({ title: "canvas-drawimage", width: 400, height: 300 });
|
|
175
|
+
win.on("ready", () => {
|
|
176
|
+
const canvas: any = win.document.getElementById("c");
|
|
177
|
+
const ctx: any = canvas.getContext("2d");
|
|
178
|
+
const logo: any = win.document.getElementById("logo");
|
|
179
|
+
// Blow the 4x4 logo up to 40x40.
|
|
180
|
+
ctx.drawImage(logo, 0, 0, 40, 40);
|
|
181
|
+
// The 4x4 logo is red on the left half, blue on the right half.
|
|
182
|
+
const left = ctx.getImageData(4, 20, 1, 1).data;
|
|
183
|
+
const right = ctx.getImageData(36, 20, 1, 1).data;
|
|
184
|
+
console.log("left=" + left[0] + "," + left[1] + "," + left[2] + "," + left[3]);
|
|
185
|
+
console.log("right=" + right[0] + "," + right[1] + "," + right[2] + "," + right[3]);
|
|
186
|
+
win.close();
|
|
187
|
+
});
|
|
188
|
+
win.loadHTML(HTML);
|
|
189
|
+
run();
|
|
190
|
+
`);
|
|
191
|
+
expect(value("left")).toBe("255,0,0,255");
|
|
192
|
+
expect(value("right")).toBe("0,0,255,255");
|
|
193
|
+
});
|
|
194
|
+
it("releases canvases when the document is replaced", () => {
|
|
195
|
+
const { value } = harness.compileAndRun("canvas-lifecycle", `
|
|
196
|
+
import { createWindow, run } from "gui";
|
|
197
|
+
|
|
198
|
+
const FIRST = \`
|
|
199
|
+
<html><body style="margin:0">
|
|
200
|
+
<canvas id="c" width="20" height="20"></canvas>
|
|
201
|
+
</body></html>
|
|
202
|
+
\`;
|
|
203
|
+
const SECOND = \`
|
|
204
|
+
<html><body style="margin:0">
|
|
205
|
+
<canvas id="c" width="30" height="30"></canvas>
|
|
206
|
+
</body></html>
|
|
207
|
+
\`;
|
|
208
|
+
|
|
209
|
+
const win = createWindow({ title: "canvas-lifecycle", width: 400, height: 300 });
|
|
210
|
+
win.on("ready", () => {
|
|
211
|
+
const oldCtx: any = win.document.getElementById("c").getContext("2d");
|
|
212
|
+
oldCtx.fillStyle = "#ff0000";
|
|
213
|
+
oldCtx.fillRect(0, 0, 20, 20);
|
|
214
|
+
|
|
215
|
+
// Replacing the document drops the old canvas (and its GPU texture).
|
|
216
|
+
win.loadHTML(SECOND);
|
|
217
|
+
const freshCtx: any = win.document.getElementById("c").getContext("2d");
|
|
218
|
+
freshCtx.fillStyle = "#00ff00";
|
|
219
|
+
freshCtx.fillRect(0, 0, 30, 30);
|
|
220
|
+
const px = freshCtx.getImageData(0, 0, 1, 1).data;
|
|
221
|
+
console.log("fresh=" + px[0] + "," + px[1] + "," + px[2] + "," + px[3]);
|
|
222
|
+
// The stale context is inert rather than crashing.
|
|
223
|
+
console.log("stale=" + (oldCtx.getImageData(0, 0, 1, 1).width === undefined));
|
|
224
|
+
win.close();
|
|
225
|
+
});
|
|
226
|
+
win.loadHTML(FIRST);
|
|
227
|
+
run();
|
|
228
|
+
`);
|
|
229
|
+
expect(value("fresh")).toBe("0,255,0,255");
|
|
230
|
+
expect(value("stale")).toBe("true");
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
//# sourceMappingURL=gui-canvas.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gui-canvas.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-canvas.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end test for `examples/gui/pelican-svg` — the SVG gallery page that
|
|
3
|
+
* animates a CSS `transform` from the frame loop.
|
|
4
|
+
*
|
|
5
|
+
* The example's own `main.ts` is compiled here together with its `index.html`
|
|
6
|
+
* (the `gui` extension compiles the document and the `<img>` path it points at),
|
|
7
|
+
* linked against the prebuilt `gui.a`, and run under the `XT_GUI_AUTOCLOSE_MS`
|
|
8
|
+
* hang guard. The assertions read the example's `label=value` report, which is
|
|
9
|
+
* printed from the first presented frame:
|
|
10
|
+
*
|
|
11
|
+
* - the document parsed, the SVG decoded and the image reached the paint list;
|
|
12
|
+
* - the artwork's *layout* box is the 720x520 box CSS asked for;
|
|
13
|
+
* - each frame's pose (a `transform` list parsed by the engine) composed into a
|
|
14
|
+
* matrix that reached the display list, and the reported bounding box moved
|
|
15
|
+
* with it — a paint-time transform does not touch layout;
|
|
16
|
+
* - hit testing still lands on the `<img>` through the transform.
|
|
17
|
+
*
|
|
18
|
+
* The pose values themselves are wall-clock dependent (`requestAnimationFrame`
|
|
19
|
+
* timestamps), so the test matches their *shape*, not their numbers.
|
|
20
|
+
*/
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end test for `examples/gui/pelican-svg` — the SVG gallery page that
|
|
3
|
+
* animates a CSS `transform` from the frame loop.
|
|
4
|
+
*
|
|
5
|
+
* The example's own `main.ts` is compiled here together with its `index.html`
|
|
6
|
+
* (the `gui` extension compiles the document and the `<img>` path it points at),
|
|
7
|
+
* linked against the prebuilt `gui.a`, and run under the `XT_GUI_AUTOCLOSE_MS`
|
|
8
|
+
* hang guard. The assertions read the example's `label=value` report, which is
|
|
9
|
+
* printed from the first presented frame:
|
|
10
|
+
*
|
|
11
|
+
* - the document parsed, the SVG decoded and the image reached the paint list;
|
|
12
|
+
* - the artwork's *layout* box is the 720x520 box CSS asked for;
|
|
13
|
+
* - each frame's pose (a `transform` list parsed by the engine) composed into a
|
|
14
|
+
* matrix that reached the display list, and the reported bounding box moved
|
|
15
|
+
* with it — a paint-time transform does not touch layout;
|
|
16
|
+
* - hit testing still lands on the `<img>` through the transform.
|
|
17
|
+
*
|
|
18
|
+
* The pose values themselves are wall-clock dependent (`requestAnimationFrame`
|
|
19
|
+
* timestamps), so the test matches their *shape*, not their numbers.
|
|
20
|
+
*/
|
|
21
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
22
|
+
import { tmpdir } from "node:os";
|
|
23
|
+
import { dirname, join, resolve } from "node:path";
|
|
24
|
+
import { spawnSync } from "node:child_process";
|
|
25
|
+
import { fileURLToPath } from "node:url";
|
|
26
|
+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
27
|
+
import { build } from "../../src/driver/compiler.js";
|
|
28
|
+
import { createDefaultRegistry } from "../../src/extensions/registry.js";
|
|
29
|
+
import { guiExtension } from "../../src/extensions/gui/index.js";
|
|
30
|
+
import { nodeExtension } from "../../src/extensions/node/index.js";
|
|
31
|
+
import { guiAvailable } from "./gui-helpers.js";
|
|
32
|
+
/** The example lives at <repo>/examples/gui/pelican-svg. */
|
|
33
|
+
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
34
|
+
const exampleDir = join(repoRoot, "examples", "gui", "pelican-svg");
|
|
35
|
+
/** Windows reports an access violation as this NTSTATUS exit code; on POSIX the
|
|
36
|
+
* same documented teardown fault surfaces as a signal (see
|
|
37
|
+
* `doc/gui/known-issues.md`). */
|
|
38
|
+
const ACCESS_VIOLATION = 3221225477;
|
|
39
|
+
const CRASH_SIGNALS = new Set(["SIGSEGV", "SIGBUS", "SIGABRT", "SIGILL", "SIGFPE"]);
|
|
40
|
+
let workdir = "";
|
|
41
|
+
describe.skipIf(!guiAvailable)("gui example — pelican svg", () => {
|
|
42
|
+
beforeAll(() => {
|
|
43
|
+
workdir = mkdtempSync(join(tmpdir(), "xbintsc-pelican-svg-"));
|
|
44
|
+
writeFileSync(join(workdir, "index.html"), readFileSync(join(exampleDir, "index.html"), "utf8"));
|
|
45
|
+
writeFileSync(join(workdir, "pelican-svg.ts"), readFileSync(join(exampleDir, "main.ts"), "utf8"));
|
|
46
|
+
});
|
|
47
|
+
afterAll(() => {
|
|
48
|
+
rmSync(workdir, { recursive: true, force: true });
|
|
49
|
+
});
|
|
50
|
+
it("compiles the gallery and animates the artwork", () => {
|
|
51
|
+
const extensions = createDefaultRegistry().register(guiExtension).register(nodeExtension);
|
|
52
|
+
const result = build(join(workdir, "pelican-svg.ts"), {
|
|
53
|
+
emit: "exe",
|
|
54
|
+
outDir: join(workdir, "out"),
|
|
55
|
+
cacheDir: join(workdir, ".cache"),
|
|
56
|
+
extensions,
|
|
57
|
+
});
|
|
58
|
+
expect(result.diagnostics.filter((diagnostic) => diagnostic.category === "error")).toEqual([]);
|
|
59
|
+
/* The example finds the artwork relative to the working directory, so it is
|
|
60
|
+
spawned from the repository root — the same way the CLI runs it. */
|
|
61
|
+
const executed = spawnSync(result.outputPath, [], {
|
|
62
|
+
cwd: repoRoot,
|
|
63
|
+
encoding: "utf8",
|
|
64
|
+
env: { ...process.env, XT_GUI_AUTOCLOSE_MS: "4000" },
|
|
65
|
+
});
|
|
66
|
+
const crashed = executed.status === ACCESS_VIOLATION ||
|
|
67
|
+
(executed.status === null && executed.signal !== null && CRASH_SIGNALS.has(executed.signal));
|
|
68
|
+
const outcome = executed.signal !== null ? `signal ${executed.signal}` : `exit ${executed.status}`;
|
|
69
|
+
expect(executed.status === 0 || crashed, `unexpected ${outcome}\nstderr:\n${executed.stderr}`).toBe(true);
|
|
70
|
+
const stdout = executed.stdout ?? "";
|
|
71
|
+
const value = (label) => {
|
|
72
|
+
const found = stdout.split("\n").find((entry) => entry.startsWith(`${label}=`));
|
|
73
|
+
expect(found, `missing ${label} in stdout:\n${stdout}\nstderr:\n${executed.stderr}`).toBeDefined();
|
|
74
|
+
return found.slice(label.length + 1).trim();
|
|
75
|
+
};
|
|
76
|
+
// The window, the backend and the document: the artwork laid out at 720x520
|
|
77
|
+
// and the vector source decoded into a single painted image.
|
|
78
|
+
expect(value("window")).toBe("800x640 (gui extension, SDL_GPU)");
|
|
79
|
+
expect(value("art-box")).toBe("x=40 y=35 720x520");
|
|
80
|
+
expect(value("painted-images")).toBe("1");
|
|
81
|
+
expect(value("painted-image")).toMatch(/^image x=40\.0 y=35\.0 w=720\.0 h=520\.0 src=.*pelican-bike\.svg$/);
|
|
82
|
+
expect(value("svg-declares")).toBe("720x520");
|
|
83
|
+
expect(value("svg-has-viewbox")).toBe("true");
|
|
84
|
+
expect(value("svg-paths")).toBe("44");
|
|
85
|
+
// The SVG is `<img>` content, so it is hit-testable like any other element,
|
|
86
|
+
// and `transform-origin` came through the cascade unresolved (`%`), as CSS
|
|
87
|
+
// requires: layout resolves it against the border box.
|
|
88
|
+
expect(value("hit-test")).toBe("img#art");
|
|
89
|
+
expect(value("art-origin")).toBe("50% 92%");
|
|
90
|
+
// The frame loop applied a pose: a `transform` list the engine parsed into a
|
|
91
|
+
// matrix, which is what the renderer received for the image quad.
|
|
92
|
+
/* Match the *shape* only: the values follow the wall clock, and the engine's
|
|
93
|
+
canonical spelling trims trailing zeros (`rotate(0.8deg)`, not `0.80deg`). */
|
|
94
|
+
const pose = /^translateY\(-?[\d.]+px\) rotate\(-?[\d.]+deg\) scale\([\d.]+, [\d.]+\)$/;
|
|
95
|
+
expect(value("art-pose@1")).toMatch(pose);
|
|
96
|
+
expect(value("art-pose@2")).toMatch(pose);
|
|
97
|
+
expect(value("art-matrix")).toMatch(/^matrix\(/);
|
|
98
|
+
// ...and the geometry the DOM reports follows the transform, while the
|
|
99
|
+
// layout box above stayed at 720x520.
|
|
100
|
+
const moved = value("art-moved-box");
|
|
101
|
+
expect(moved).toMatch(/^x=-?\d+ y=-?\d+ \d+x\d+$/);
|
|
102
|
+
expect(moved).not.toBe("x=40 y=35 720x520");
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=gui-example-svg.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gui-example-svg.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-example-svg.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* The example's own `main.ts` is compiled here (with the game document next to
|
|
7
7
|
* it) and run briefly. The game is interactive and never closes its own window,
|
|
8
8
|
* so the engine's auto-close guard ends the run — and that shutdown path has an
|
|
9
|
-
* intermittent native crash (see `doc/gui.md
|
|
9
|
+
* intermittent native crash (see `doc/gui/known-issues.md`), so the
|
|
10
10
|
* deterministic assertions live in `gui-example-browser.test.ts` (which runs the
|
|
11
11
|
* very same inline script against a stub host) while this test covers the
|
|
12
12
|
* native side: it compiles, it links against the gui archive, and it runs.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* The example's own `main.ts` is compiled here (with the game document next to
|
|
7
7
|
* it) and run briefly. The game is interactive and never closes its own window,
|
|
8
8
|
* so the engine's auto-close guard ends the run — and that shutdown path has an
|
|
9
|
-
* intermittent native crash (see `doc/gui.md
|
|
9
|
+
* intermittent native crash (see `doc/gui/known-issues.md`), so the
|
|
10
10
|
* deterministic assertions live in `gui-example-browser.test.ts` (which runs the
|
|
11
11
|
* very same inline script against a stub host) while this test covers the
|
|
12
12
|
* native side: it compiles, it links against the gui archive, and it runs.
|
|
@@ -24,7 +24,7 @@ import { guiAvailable } from "./gui-helpers.js";
|
|
|
24
24
|
/** The example lives at <repo>/examples/gui/pelican-bike. */
|
|
25
25
|
const exampleDir = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "examples", "gui", "pelican-bike");
|
|
26
26
|
/** `0xC0000005`: the known intermittent access violation in the gui engine's
|
|
27
|
-
* auto-close teardown (documented in `doc/gui.md`). Windows reports a crash as
|
|
27
|
+
* auto-close teardown (documented in `doc/gui/known-issues.md`). Windows reports a crash as
|
|
28
28
|
* this NTSTATUS exit code; on POSIX the same fault terminates the process with
|
|
29
29
|
* a signal, so `spawnSync` reports `status: null` plus a `signal` name. */
|
|
30
30
|
const ACCESS_VIOLATION = 3221225477;
|
|
@@ -58,6 +58,9 @@ export interface GuiHarness {
|
|
|
58
58
|
* the engine decodes it again (`xt_image_load`).
|
|
59
59
|
*/
|
|
60
60
|
imageSrc(absolutePath: string): string;
|
|
61
|
+
/** Write `contents` into the work directory and return an embeddable source
|
|
62
|
+
* for it (e.g. an SVG fixture for the image tests). */
|
|
63
|
+
writeAsset(name: string, contents: string): string;
|
|
61
64
|
setup(): void;
|
|
62
65
|
cleanup(): void;
|
|
63
66
|
/** Compile a program and run it with the auto-close hook, returning stdout. */
|
|
@@ -89,6 +89,11 @@ export function createGuiHarness() {
|
|
|
89
89
|
return logoPath;
|
|
90
90
|
},
|
|
91
91
|
imageSrc: toImageSrc,
|
|
92
|
+
writeAsset(name, contents) {
|
|
93
|
+
const path = join(workdir, name);
|
|
94
|
+
writeFileSync(path, contents);
|
|
95
|
+
return toImageSrc(path);
|
|
96
|
+
},
|
|
92
97
|
setup() {
|
|
93
98
|
workdir = mkdtempSync(join(tmpdir(), "xbintsc-gui-"));
|
|
94
99
|
logoPath = join(workdir, "logo.png");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gui-helpers.js","sourceRoot":"","sources":["../../../tests/e2e/gui-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzE,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC,CAAC;AAE3E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GACvB,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;IACjG,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG,CAAC,CAAC;AAyB1E,sFAAsF;AACtF,MAAM,oBAAoB,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"gui-helpers.js","sourceRoot":"","sources":["../../../tests/e2e/gui-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -239,5 +239,78 @@ describe.skipIf(!guiAvailable)("gui extension — layout", () => {
|
|
|
239
239
|
expect(value("empty")).toBe("0");
|
|
240
240
|
expect(value("wide")).toBe("true");
|
|
241
241
|
});
|
|
242
|
+
it("falls back to another face for a codepoint the primary lacks", () => {
|
|
243
|
+
/**
|
|
244
|
+
* Candidate pairs whose members a face which has one often lacks or spaces
|
|
245
|
+
* differently: U+25AE ▮ / U+25AF ▯ (the pelican-bike speed bar), squares,
|
|
246
|
+
* stars, triangles and arrows.
|
|
247
|
+
*
|
|
248
|
+
* The regression is that a codepoint the shaping face does not cover came
|
|
249
|
+
* back as `.notdef` (glyph 0) and was dropped, so a mixed run lost glyphs.
|
|
250
|
+
* That shows up as a run whose width no longer adds up — and, when the host
|
|
251
|
+
* has a face that distinguishes the codepoints, as a pair of advances that
|
|
252
|
+
* differ instead of collapsing onto `.notdef`.
|
|
253
|
+
*
|
|
254
|
+
* The second half cannot be asserted unconditionally: a face can *cover*
|
|
255
|
+
* both codepoints and still give them the same advance, so "different
|
|
256
|
+
* glyphs" does not imply "different widths". Measured from the faces the
|
|
257
|
+
* engine resolves for a minimal Ubuntu host:
|
|
258
|
+
*
|
|
259
|
+
* DejaVu Sans ▮ = ▯ = 1127/2048 em ★ = ☆ = 1836/2048 em
|
|
260
|
+
* Noto Sans Symbols2 ▮ = ▯ = 1000/1000 em ★ = ☆ = 960 vs 1034
|
|
261
|
+
* Symbola ▮ = ▯ = 816/2048 em
|
|
262
|
+
*
|
|
263
|
+
* ▮/▯ are indistinguishable on all three, so that pair alone cannot show
|
|
264
|
+
* the fallback on such a host; the probe below measures every pair and the
|
|
265
|
+
* distinct-advance check is made on whichever pair the host distinguishes.
|
|
266
|
+
*/
|
|
267
|
+
const pairs = [
|
|
268
|
+
["25AE", "25AF"], // ▮ ▯ filled/hollow vertical rectangle
|
|
269
|
+
["25A0", "25A1"], // ■ □ filled/hollow square
|
|
270
|
+
["2605", "2606"], // ★ ☆ filled/hollow star
|
|
271
|
+
["25B2", "25B3"], // ▲ △ filled/hollow triangle
|
|
272
|
+
["2190", "2192"], // ← → left/right arrow
|
|
273
|
+
];
|
|
274
|
+
const measurements = pairs.map(([first, second], index) => [
|
|
275
|
+
` console.log("pair${index}=" + win.measureText("\\u${first}", 16) + "," +`,
|
|
276
|
+
` win.measureText("\\u${second}", 16) + "," +`,
|
|
277
|
+
` win.measureText("\\u${first}\\u${second}", 16));`,
|
|
278
|
+
].join("\n"));
|
|
279
|
+
const { value } = harness.compileAndRun("fallback", `
|
|
280
|
+
import { createWindow, run } from "gui";
|
|
281
|
+
|
|
282
|
+
const win = createWindow({ title: "fallback", width: 200, height: 100 });
|
|
283
|
+
win.on("ready", () => {
|
|
284
|
+
${measurements.join("\n")}
|
|
285
|
+
win.close();
|
|
286
|
+
});
|
|
287
|
+
win.loadHTML("<html><body></body></html>");
|
|
288
|
+
run();
|
|
289
|
+
`);
|
|
290
|
+
// Every pair must add up: two codepoints shaped in one run measure their
|
|
291
|
+
// separate advances only when neither glyph was dropped or duplicated.
|
|
292
|
+
const measured = pairs.map((_, index) => String(value(`pair${index}`)).split(",").map(Number));
|
|
293
|
+
for (const [first, second, mixed] of measured) {
|
|
294
|
+
expect(first).toBeGreaterThan(0);
|
|
295
|
+
expect(second).toBeGreaterThan(0);
|
|
296
|
+
expect(mixed).toBeCloseTo(first + second, 3);
|
|
297
|
+
}
|
|
298
|
+
// On a host whose font stack distinguishes at least one pair, that pair is
|
|
299
|
+
// the regression guard: distinct advances mean each codepoint kept its own
|
|
300
|
+
// glyph from whichever face had it, rather than both becoming `.notdef`.
|
|
301
|
+
const distinctive = measured.find(([first, second]) => first !== second);
|
|
302
|
+
if (distinctive === undefined) {
|
|
303
|
+
// Informational, not a failure: with no distinguishing face on this host
|
|
304
|
+
// the distinct-advance half of the regression is unobservable.
|
|
305
|
+
console.log(`gui-layout: no candidate pair is distinguished by this host's fonts, ` +
|
|
306
|
+
`so only the additive half of the fallback check ran.`);
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
// Both advances were already required to be positive above; what matters
|
|
310
|
+
// here is that they differ.
|
|
311
|
+
const [first, second] = distinctive;
|
|
312
|
+
expect(first).not.toBe(second);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
242
315
|
});
|
|
243
316
|
//# sourceMappingURL=gui-layout.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gui-layout.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-layout.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gui-layout.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-layout.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end tests for `<video>` / `<audio>` support in the `gui` extension.
|
|
3
|
+
*
|
|
4
|
+
* These exercise the real decoding path (vendored FFmpeg + SDL audio) and the
|
|
5
|
+
* DOM media API. The fixtures live in `examples/resources`; when they are
|
|
6
|
+
* absent (a trim checkout) the suite is skipped rather than failing.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|