xbintsc 0.5.32 → 0.5.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -7
- package/README.zh-CN.md +10 -8
- package/dist/scripts/check-version.d.ts +27 -0
- package/dist/scripts/check-version.js +71 -0
- package/dist/scripts/check-version.js.map +1 -0
- package/dist/scripts/package-platform.d.ts +58 -0
- package/dist/scripts/package-platform.js +142 -0
- package/dist/scripts/package-platform.js.map +1 -0
- package/dist/scripts/verify-platform-package.d.ts +34 -0
- package/dist/scripts/verify-platform-package.js +161 -0
- package/dist/scripts/verify-platform-package.js.map +1 -0
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/cli/main.js +3 -1
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/driver/runtime-lib.d.ts +29 -4
- package/dist/src/driver/runtime-lib.js +68 -10
- package/dist/src/driver/runtime-lib.js.map +1 -1
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/gui/index.js +18 -5
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/media/index.js +4 -3
- package/dist/src/extensions/media/index.js.map +1 -1
- package/dist/src/parser/context.d.ts +41 -0
- package/dist/src/parser/context.js +89 -4
- package/dist/src/parser/context.js.map +1 -1
- package/dist/src/parser/literals.js +6 -12
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/driver/platform-package.test.d.ts +1 -0
- package/dist/tests/driver/platform-package.test.js +49 -0
- package/dist/tests/driver/platform-package.test.js.map +1 -0
- package/dist/tests/driver/runtime-lib.test.js +51 -4
- package/dist/tests/driver/runtime-lib.test.js.map +1 -1
- package/dist/tests/e2e/gui-audio.test.d.ts +14 -0
- package/dist/tests/e2e/gui-audio.test.js +287 -0
- package/dist/tests/e2e/gui-audio.test.js.map +1 -0
- package/dist/tests/e2e/gui-browser.test.js +65 -0
- package/dist/tests/e2e/gui-browser.test.js.map +1 -1
- package/dist/tests/e2e/gui-canvas-args.test.d.ts +6 -0
- package/dist/tests/e2e/gui-canvas-args.test.js +217 -0
- package/dist/tests/e2e/gui-canvas-args.test.js.map +1 -0
- package/dist/tests/e2e/gui-canvas.test.js.map +1 -1
- package/dist/tests/e2e/gui-dom.test.js +215 -0
- package/dist/tests/e2e/gui-dom.test.js.map +1 -1
- package/dist/tests/e2e/gui-events.test.js +112 -0
- package/dist/tests/e2e/gui-events.test.js.map +1 -1
- package/dist/tests/e2e/gui-helpers.d.ts +7 -0
- package/dist/tests/e2e/gui-helpers.js +1 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.js +78 -0
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-style.test.js +55 -0
- package/dist/tests/e2e/gui-style.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl.test.js +258 -0
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl2-3d.test.d.ts +4 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.js +264 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.js +262 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.d.ts +6 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.js +395 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.d.ts +4 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.js +105 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.d.ts +8 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.js +112 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2.test.js +45 -1
- package/dist/tests/e2e/gui-webgl2.test.js.map +1 -1
- package/dist/tests/extensions/gui-index.test.js +1 -0
- package/dist/tests/extensions/gui-index.test.js.map +1 -1
- package/dist/tests/extensions/media.test.js +1 -0
- package/dist/tests/extensions/media.test.js.map +1 -1
- package/dist/tests/parser/expressions.test.js +30 -0
- package/dist/tests/parser/expressions.test.js.map +1 -1
- package/dist/tests/platform-tarball.test.d.ts +1 -0
- package/dist/tests/platform-tarball.test.js +111 -0
- package/dist/tests/platform-tarball.test.js.map +1 -0
- package/dist/tests/version.test.js +6 -0
- package/dist/tests/version.test.js.map +1 -1
- package/doc/ai/contributing.md +11 -0
- package/doc/ai/extensions.md +7 -4
- package/doc/ai/troubleshooting.md +7 -5
- package/doc/ai/zh-CN/contributing.md +9 -0
- package/doc/ai/zh-CN/extensions.md +4 -2
- package/doc/ai/zh-CN/troubleshooting.md +5 -3
- package/doc/gui/api.md +99 -22
- package/doc/gui/build.md +11 -4
- package/doc/gui/canvas.md +49 -18
- package/doc/gui/dom.md +57 -7
- package/doc/gui/media.md +4 -0
- package/doc/gui/webgl.md +105 -46
- package/doc/gui.md +7 -3
- package/doc/npm-package.md +55 -27
- package/doc/requirements.md +6 -2
- package/doc/zh-CN/gui/api.md +84 -14
- package/doc/zh-CN/gui/build.md +7 -2
- package/doc/zh-CN/gui/canvas.md +44 -19
- package/doc/zh-CN/gui/dom.md +48 -4
- package/doc/zh-CN/gui/media.md +3 -0
- package/doc/zh-CN/gui/webgl.md +22 -16
- package/doc/zh-CN/gui.md +3 -2
- package/doc/zh-CN/npm-package.md +44 -23
- package/doc/zh-CN/requirements.md +4 -1
- package/package.json +17 -1
- package/runtime/ext_gui/audio.cpp +365 -153
- package/runtime/ext_gui/audio_buffer.cpp +166 -0
- package/runtime/ext_gui/audio_buffer.h +37 -0
- package/runtime/ext_gui/audio_decode.cpp +219 -0
- package/runtime/ext_gui/audio_decode.h +39 -0
- package/runtime/ext_gui/audio_device.cpp +87 -0
- package/runtime/ext_gui/audio_effects.cpp +163 -0
- package/runtime/ext_gui/audio_effects.h +25 -0
- package/runtime/ext_gui/audio_internal.h +30 -0
- package/runtime/ext_gui/audio_mixer.cpp +494 -0
- package/runtime/ext_gui/audio_mixer.h +238 -0
- package/runtime/ext_gui/audio_param.cpp +104 -0
- package/runtime/ext_gui/audio_param_object.cpp +155 -0
- package/runtime/ext_gui/browser.cpp +45 -50
- package/runtime/ext_gui/browser_abort.cpp +249 -0
- package/runtime/ext_gui/browser_dialogs.cpp +76 -0
- package/runtime/ext_gui/browser_media.cpp +176 -0
- package/runtime/ext_gui/browser_navigation.cpp +130 -0
- package/runtime/ext_gui/canvas.cpp +88 -30
- package/runtime/ext_gui/canvas.h +74 -9
- package/runtime/ext_gui/canvas_image_data.cpp +143 -0
- package/runtime/ext_gui/canvas_internal.h +8 -5
- package/runtime/ext_gui/canvas_pattern.cpp +90 -0
- package/runtime/ext_gui/canvas_raster.cpp +31 -9
- package/runtime/ext_gui/canvas_style.cpp +4 -2
- package/runtime/ext_gui/css_selector.cpp +21 -3
- package/runtime/ext_gui/dom.h +4 -0
- package/runtime/ext_gui/dom_api.cpp +1 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +120 -114
- package/runtime/ext_gui/dom_api_canvas_extra.cpp +57 -2
- package/runtime/ext_gui/dom_api_canvas_image.cpp +239 -0
- package/runtime/ext_gui/dom_api_canvas_paths.cpp +179 -0
- package/runtime/ext_gui/dom_api_computed_style.cpp +124 -0
- package/runtime/ext_gui/dom_api_dataset.cpp +154 -0
- package/runtime/ext_gui/dom_api_document.cpp +58 -5
- package/runtime/ext_gui/dom_api_events.cpp +93 -17
- package/runtime/ext_gui/dom_api_internal.h +71 -2
- package/runtime/ext_gui/dom_api_mutation.cpp +159 -0
- package/runtime/ext_gui/dom_api_node.cpp +40 -19
- package/runtime/ext_gui/dom_api_node_read.cpp +37 -1
- package/runtime/ext_gui/dom_api_path2d.cpp +358 -0
- package/runtime/ext_gui/dom_api_proto.cpp +35 -0
- package/runtime/ext_gui/dom_api_style.cpp +223 -13
- package/runtime/ext_gui/dom_api_webgl.cpp +7 -0
- package/runtime/ext_gui/dom_api_webgl2.cpp +151 -36
- package/runtime/ext_gui/dom_api_webgl2_draw.cpp +3 -3
- package/runtime/ext_gui/dom_api_webgl_buffer.cpp +6 -2
- package/runtime/ext_gui/dom_api_webgl_compressed.cpp +167 -0
- package/runtime/ext_gui/dom_api_webgl_framebuffer.cpp +160 -0
- package/runtime/ext_gui/dom_api_webgl_shader.cpp +4 -4
- package/runtime/ext_gui/dom_api_webgl_source.cpp +161 -0
- package/runtime/ext_gui/dom_api_webgl_state.cpp +169 -23
- package/runtime/ext_gui/dom_api_webgl_texture.cpp +276 -236
- package/runtime/ext_gui/dom_api_webgl_ubo.cpp +81 -0
- package/runtime/ext_gui/gui.cpp +103 -14
- package/runtime/ext_gui/gui_engine.h +56 -4
- package/runtime/ext_gui/gui_events.cpp +80 -9
- package/runtime/ext_gui/image_bitmap.cpp +28 -0
- package/runtime/ext_gui/image_bitmap.h +26 -0
- package/runtime/ext_gui/image_bitmap_browser.cpp +136 -0
- package/runtime/ext_gui/listener_options.h +43 -0
- package/runtime/ext_gui/media.cpp +32 -0
- package/runtime/ext_gui/media.h +13 -0
- package/runtime/ext_gui/media_api.h +23 -0
- package/runtime/ext_gui/paint.cpp +28 -0
- package/runtime/ext_gui/paint.h +4 -0
- package/runtime/ext_gui/webgl.h +152 -18
- package/runtime/ext_gui/webgl_blit.cpp +95 -0
- package/runtime/ext_gui/webgl_buffer.cpp +178 -263
- package/runtime/ext_gui/webgl_buffer_objects.cpp +270 -0
- package/runtime/ext_gui/webgl_clear.cpp +142 -0
- package/runtime/ext_gui/webgl_compressed.cpp +180 -0
- package/runtime/ext_gui/webgl_context.cpp +241 -156
- package/runtime/ext_gui/webgl_draw.cpp +68 -3
- package/runtime/ext_gui/webgl_draw_buffers.cpp +75 -0
- package/runtime/ext_gui/webgl_glsl.h +40 -0
- package/runtime/ext_gui/webgl_glsl_compile.cpp +6 -0
- package/runtime/ext_gui/webgl_glsl_rewrite.cpp +18 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +20 -11
- package/runtime/ext_gui/webgl_glsl_scan_block.cpp +126 -0
- package/runtime/ext_gui/webgl_glsl_tokens.h +28 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +71 -19
- package/runtime/ext_gui/webgl_program_blocks.cpp +58 -0
- package/runtime/ext_gui/webgl_program_internal.h +6 -0
- package/runtime/ext_gui/webgl_shader.cpp +13 -1
- package/runtime/ext_gui/webgl_state.cpp +228 -0
- package/runtime/ext_gui/webgl_texture.cpp +144 -17
- package/runtime/ext_gui/webgl_texture_3d.cpp +215 -0
- package/runtime/ext_gui/webgl_uniform_block.h +31 -0
- package/runtime/ext_gui/webgl_webgl2.cpp +58 -5
- package/runtime/ext_gui/window.cpp +14 -65
- package/runtime/ext_gui/window_events.cpp +125 -0
- package/runtime/ext_media/decode_audio.cpp +308 -0
- package/runtime/ext_media/media_bridge.c +2 -0
- package/runtime/rt.h +43 -0
- package/runtime/rt_internal.h +4 -0
- package/runtime/xt_array_buffer.c +30 -0
- package/runtime/xt_builtins.c +0 -21
- package/runtime/xt_containers/access.inc +94 -2
- package/runtime/xt_containers/objects.inc +29 -31
- package/runtime/xt_typed_array/elements.inc +13 -0
- package/scripts/build-media.ts +14 -6
- package/scripts/build-runtime.ts +21 -16
- package/scripts/check-version.ts +39 -9
- package/scripts/package-platform.ts +183 -0
- package/scripts/set-platform-version.ts +62 -0
- package/scripts/verify-platform-package.ts +182 -0
- package/src/cli/main.ts +5 -1
- package/src/driver/runtime-lib.ts +73 -9
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/index.ts +18 -5
- package/src/extensions/media/index.ts +4 -3
- package/src/parser/context.ts +99 -4
- package/src/parser/literals.ts +6 -12
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
#include "dom_api_internal.h"
|
|
7
|
+
#include "listener_options.h"
|
|
7
8
|
|
|
8
9
|
#include <algorithm>
|
|
9
10
|
#include <cmath>
|
|
@@ -217,13 +218,19 @@ METHOD(node_get_bounding_rect) {
|
|
|
217
218
|
if (node == nullptr || win == nullptr || win->document == nullptr) return XT_UNDEFINED;
|
|
218
219
|
const xtgui::LayoutBox *box = win->document->boxOf(node);
|
|
219
220
|
if (box == nullptr) return XT_UNDEFINED;
|
|
220
|
-
/* Like the DOM: the rectangle of the *transformed* border box.
|
|
221
|
+
/* Like the DOM: the rectangle of the *transformed* border box. The legacy
|
|
222
|
+
* `top`/`right`/`bottom`/`left` members are the same rectangle in the other
|
|
223
|
+
* spelling; libraries read both. */
|
|
221
224
|
xtgui::LayoutRect rect = xtgui::xt_layout_transformed_bounds(box);
|
|
222
225
|
xt_value object = xt_object_new();
|
|
223
226
|
xt_object_set(object, xt_string_from_cstr("x"), xt_number(rect.x));
|
|
224
227
|
xt_object_set(object, xt_string_from_cstr("y"), xt_number(rect.y));
|
|
225
228
|
xt_object_set(object, xt_string_from_cstr("width"), xt_number(rect.width));
|
|
226
229
|
xt_object_set(object, xt_string_from_cstr("height"), xt_number(rect.height));
|
|
230
|
+
xt_object_set(object, xt_string_from_cstr("top"), xt_number(rect.y));
|
|
231
|
+
xt_object_set(object, xt_string_from_cstr("right"), xt_number(rect.x + rect.width));
|
|
232
|
+
xt_object_set(object, xt_string_from_cstr("bottom"), xt_number(rect.y + rect.height));
|
|
233
|
+
xt_object_set(object, xt_string_from_cstr("left"), xt_number(rect.x));
|
|
227
234
|
return object;
|
|
228
235
|
}
|
|
229
236
|
|
|
@@ -252,12 +259,30 @@ METHOD(node_contains) {
|
|
|
252
259
|
|
|
253
260
|
METHOD(node_focus) {
|
|
254
261
|
(void)env;
|
|
255
|
-
(void)argc;
|
|
256
|
-
(void)argv;
|
|
257
262
|
XtGuiWindow *win = nullptr;
|
|
258
263
|
xtgui::Node *node = resolve_node(self, &win);
|
|
259
264
|
if (node == nullptr || win == nullptr || win->document == nullptr) return XT_UNDEFINED;
|
|
265
|
+
/* `{ preventScroll: true }` keeps the current page offset; otherwise the
|
|
266
|
+
* focused box is scrolled into view, like the browser default. */
|
|
267
|
+
bool prevent_scroll = false;
|
|
268
|
+
xt_value options = xt_arg(argc, argv, 0);
|
|
269
|
+
if (XT_IS_OBJECT(options)) {
|
|
270
|
+
prevent_scroll = value_truthy(xt_object_get_cstr(options, "preventScroll"));
|
|
271
|
+
}
|
|
260
272
|
if (win->document->setFocus(node)) win->geometry.dirty = 1;
|
|
273
|
+
const xtgui::LayoutBox *box = win->document->boxOf(node);
|
|
274
|
+
if (!prevent_scroll && box != nullptr) {
|
|
275
|
+
float viewport_width = 0;
|
|
276
|
+
float viewport_height = 0;
|
|
277
|
+
xt_gui_window_viewport(win, &viewport_width, &viewport_height);
|
|
278
|
+
float x = win->scroll_x;
|
|
279
|
+
float y = win->scroll_y;
|
|
280
|
+
if (box->x < x) x = box->x;
|
|
281
|
+
else if (box->x + box->width > x + viewport_width) x = box->x + box->width - viewport_width;
|
|
282
|
+
if (box->y < y) y = box->y;
|
|
283
|
+
else if (box->y + box->height > y + viewport_height) y = box->y + box->height - viewport_height;
|
|
284
|
+
xt_gui_scroll_to(win, x, y);
|
|
285
|
+
}
|
|
261
286
|
return XT_UNDEFINED;
|
|
262
287
|
}
|
|
263
288
|
|
|
@@ -290,20 +315,18 @@ METHOD(node_add_event_listener) {
|
|
|
290
315
|
if (node == nullptr || win == nullptr || argc < 2) return self;
|
|
291
316
|
xt_value fn = xt_arg(argc, argv, 1);
|
|
292
317
|
if (!XT_IS_FUNCTION(fn)) return self;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
once = value_truthy(xt_object_get_cstr(options, "once"));
|
|
299
|
-
} else if (XT_IS_BOOL(options)) {
|
|
300
|
-
capture = value_truthy(options);
|
|
301
|
-
}
|
|
318
|
+
XtGuiListenerOptions options = xt_gui_listener_options(xt_arg(argc, argv, 2));
|
|
319
|
+
/* `{ signal: controller.signal }` removes the listener: an already-aborted
|
|
320
|
+
* signal means it was never installed, and a later abort is honoured at
|
|
321
|
+
* dispatch time (see `call_node_listeners`). */
|
|
322
|
+
if (xt_gui_signal_aborted(options.signal)) return self;
|
|
302
323
|
XtGuiNodeListener listener;
|
|
303
324
|
listener.type = to_string_value(xt_arg(argc, argv, 0));
|
|
304
325
|
listener.fn = fn;
|
|
305
|
-
listener.once = once;
|
|
306
|
-
listener.capture = capture;
|
|
326
|
+
listener.once = options.once;
|
|
327
|
+
listener.capture = options.capture;
|
|
328
|
+
listener.passive = options.passive;
|
|
329
|
+
listener.signal = options.signal;
|
|
307
330
|
win->node_listeners[node].push_back(listener);
|
|
308
331
|
return self;
|
|
309
332
|
}
|
|
@@ -313,11 +336,9 @@ METHOD(node_remove_event_listener) {
|
|
|
313
336
|
XtGuiWindow *win = nullptr;
|
|
314
337
|
xtgui::Node *node = resolve_node(self, &win);
|
|
315
338
|
if (node == nullptr || win == nullptr || argc < 2) return self;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
else if (XT_IS_BOOL(options)) capture = value_truthy(options);
|
|
320
|
-
remove_listener(win, node, to_string_value(xt_arg(argc, argv, 0)), xt_arg(argc, argv, 1), capture);
|
|
339
|
+
XtGuiListenerOptions options = xt_gui_listener_options(xt_arg(argc, argv, 2));
|
|
340
|
+
remove_listener(win, node, to_string_value(xt_arg(argc, argv, 0)), xt_arg(argc, argv, 1),
|
|
341
|
+
options.capture);
|
|
321
342
|
return self;
|
|
322
343
|
}
|
|
323
344
|
|
|
@@ -34,7 +34,10 @@ METHOD(node_tag_name_get) {
|
|
|
34
34
|
XtGuiWindow *win = nullptr;
|
|
35
35
|
xtgui::Node *node = resolve_node(self, &win);
|
|
36
36
|
if (node == nullptr || !node->isElement()) return XT_UNDEFINED;
|
|
37
|
-
|
|
37
|
+
/* `tagName` uppercases HTML element names but keeps the authored case in a
|
|
38
|
+
* foreign namespace (SVG's `linearGradient`, `clipPath`, …). */
|
|
39
|
+
const bool html = node->ns.empty() || node->ns == "http://www.w3.org/1999/xhtml";
|
|
40
|
+
return xt_string_from_cstr(html ? to_upper(node->tag).c_str() : node->tag.c_str());
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
METHOD(node_node_type_get) {
|
|
@@ -58,6 +61,38 @@ METHOD(node_id_get) {
|
|
|
58
61
|
return xt_string_from_cstr(value != nullptr ? value->c_str() : "");
|
|
59
62
|
}
|
|
60
63
|
|
|
64
|
+
/** `namespaceURI`: the namespace passed to `createElementNS`, or the HTML
|
|
65
|
+
* namespace for an ordinary element. */
|
|
66
|
+
METHOD(node_namespace_uri_get) {
|
|
67
|
+
(void)env;
|
|
68
|
+
(void)argc;
|
|
69
|
+
(void)argv;
|
|
70
|
+
xtgui::Node *node = resolve_node(self, nullptr);
|
|
71
|
+
if (node == nullptr || !node->isElement()) return XT_NULL;
|
|
72
|
+
if (!node->ns.empty()) return xt_string_from_cstr(node->ns.c_str());
|
|
73
|
+
return xt_string_from_cstr("http://www.w3.org/1999/xhtml");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
METHOD(node_local_name_get) {
|
|
77
|
+
(void)env;
|
|
78
|
+
(void)argc;
|
|
79
|
+
(void)argv;
|
|
80
|
+
xtgui::Node *node = resolve_node(self, nullptr);
|
|
81
|
+
if (node == nullptr) return XT_UNDEFINED;
|
|
82
|
+
if (!node->isElement()) return XT_NULL;
|
|
83
|
+
return xt_string_from_cstr(node->tag.c_str());
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
METHOD(node_prefix_get) {
|
|
87
|
+
(void)env;
|
|
88
|
+
(void)argc;
|
|
89
|
+
(void)argv;
|
|
90
|
+
xtgui::Node *node = resolve_node(self, nullptr);
|
|
91
|
+
if (node == nullptr) return XT_UNDEFINED;
|
|
92
|
+
if (node->ns_prefix.empty()) return XT_NULL;
|
|
93
|
+
return xt_string_from_cstr(node->ns_prefix.c_str());
|
|
94
|
+
}
|
|
95
|
+
|
|
61
96
|
METHOD(node_id_set) {
|
|
62
97
|
(void)env;
|
|
63
98
|
XtGuiWindow *win = nullptr;
|
|
@@ -295,6 +330,7 @@ METHOD(node_style_get) {
|
|
|
295
330
|
if (XT_IS_OBJECT(cached)) return cached;
|
|
296
331
|
xt_value style = xt_object_new_with_proto(style_proto());
|
|
297
332
|
xt_object_set(style, xt_string_from_cstr("__xt_gui_node"), self);
|
|
333
|
+
install_style_hooks(style);
|
|
298
334
|
xt_object_set(self, xt_string_from_cstr("__xt_gui_style"), style);
|
|
299
335
|
return style;
|
|
300
336
|
}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc GUI engine — `Path2D`.
|
|
3
|
+
*
|
|
4
|
+
* A path is stored on the runtime object itself as an array of subpaths, each a
|
|
5
|
+
* flat number list `[x0, y0, x1, y1, …]` (user space). Keeping the geometry in
|
|
6
|
+
* the JS heap means the collector owns it: a page that builds a path per frame
|
|
7
|
+
* does not grow a native registry. `ctx.fill(path)` / `ctx.stroke(path)` read it
|
|
8
|
+
* back with `path2d_subpaths` and draw it under the current transform.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#include "dom_api_internal.h"
|
|
12
|
+
|
|
13
|
+
#include <cmath>
|
|
14
|
+
#include <string>
|
|
15
|
+
#include <vector>
|
|
16
|
+
|
|
17
|
+
#include "canvas.h"
|
|
18
|
+
|
|
19
|
+
namespace domapi {
|
|
20
|
+
|
|
21
|
+
namespace {
|
|
22
|
+
|
|
23
|
+
xt_value g_path2d_proto = XT_UNDEFINED;
|
|
24
|
+
constexpr float kPi = 3.14159265358979323846f;
|
|
25
|
+
|
|
26
|
+
#define METHOD(name) xt_value name(xt_value self, xt_value env, int32_t argc, xt_value *argv)
|
|
27
|
+
|
|
28
|
+
xt_value path_data(xt_value self, bool create) {
|
|
29
|
+
xt_value data = xt_object_get_cstr(self, "__xt_gui_path_data");
|
|
30
|
+
if (XT_IS_ARRAY(data) || !create) return data;
|
|
31
|
+
data = xt_array_new(0, nullptr);
|
|
32
|
+
xt_object_set(self, xt_string_from_cstr("__xt_gui_path_data"), data);
|
|
33
|
+
return data;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
xt_value current_subpath(xt_value self, bool create) {
|
|
37
|
+
xt_value data = path_data(self, create);
|
|
38
|
+
if (!XT_IS_ARRAY(data)) return XT_UNDEFINED;
|
|
39
|
+
int32_t count = (int32_t)xt_to_number(xt_array_length(data));
|
|
40
|
+
if (count > 0) return xt_array_get(data, xt_number((double)(count - 1)));
|
|
41
|
+
if (!create) return XT_UNDEFINED;
|
|
42
|
+
xt_value subpath = xt_array_new(0, nullptr);
|
|
43
|
+
xt_array_push(data, subpath);
|
|
44
|
+
return subpath;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void push_point(xt_value subpath, float x, float y) {
|
|
48
|
+
xt_array_push(subpath, xt_number(x));
|
|
49
|
+
xt_array_push(subpath, xt_number(y));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
float number_arg(int32_t argc, xt_value *argv, int32_t index, double fallback) {
|
|
53
|
+
if (index >= argc) return (float)fallback;
|
|
54
|
+
return (float)xt_to_number(xt_arg(argc, argv, index));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
bool last_point(xt_value subpath, float *x, float *y) {
|
|
58
|
+
int32_t count = (int32_t)xt_to_number(xt_array_length(subpath));
|
|
59
|
+
if (count < 2) return false;
|
|
60
|
+
*x = (float)xt_to_number(xt_array_get(subpath, xt_number((double)(count - 2))));
|
|
61
|
+
*y = (float)xt_to_number(xt_array_get(subpath, xt_number((double)(count - 1))));
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Append a flattened polyline, starting a new subpath when none is open. */
|
|
66
|
+
void append_points(xt_value self, const std::vector<float> &flat) {
|
|
67
|
+
if (flat.size() < 2) return;
|
|
68
|
+
xt_value subpath = current_subpath(self, true);
|
|
69
|
+
float lx = 0.0f, ly = 0.0f;
|
|
70
|
+
size_t start = 0;
|
|
71
|
+
if (last_point(subpath, &lx, &ly)) {
|
|
72
|
+
if (lx != flat[0] || ly != flat[1]) push_point(subpath, flat[0], flat[1]);
|
|
73
|
+
start = 2;
|
|
74
|
+
}
|
|
75
|
+
for (size_t i = start; i + 1 < flat.size(); i += 2) push_point(subpath, flat[i], flat[i + 1]);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
void flatten_arc(std::vector<float> *out, float cx, float cy, float rx, float ry, float rotation,
|
|
79
|
+
float start, float sweep) {
|
|
80
|
+
if (sweep == 0.0f) return;
|
|
81
|
+
int segments = (int)std::ceil(std::fabs(sweep) / (kPi / 32.0f));
|
|
82
|
+
if (segments < 1) segments = 1;
|
|
83
|
+
if (segments > 2048) segments = 2048;
|
|
84
|
+
const float cosRotation = std::cos(rotation);
|
|
85
|
+
const float sinRotation = std::sin(rotation);
|
|
86
|
+
for (int i = 0; i <= segments; i++) {
|
|
87
|
+
float angle = start + sweep * ((float)i / (float)segments);
|
|
88
|
+
float px = rx * std::cos(angle);
|
|
89
|
+
float py = ry * std::sin(angle);
|
|
90
|
+
out->push_back(cx + px * cosRotation - py * sinRotation);
|
|
91
|
+
out->push_back(cy + px * sinRotation + py * cosRotation);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
void normalize_sweep(float *sweep, bool counterclockwise) {
|
|
96
|
+
if (counterclockwise) {
|
|
97
|
+
while (*sweep > 0.0f) *sweep -= 2.0f * kPi;
|
|
98
|
+
while (*sweep < -2.0f * kPi) *sweep += 2.0f * kPi;
|
|
99
|
+
} else {
|
|
100
|
+
while (*sweep < 0.0f) *sweep += 2.0f * kPi;
|
|
101
|
+
while (*sweep > 2.0f * kPi) *sweep -= 2.0f * kPi;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
METHOD(path2d_move_to) {
|
|
106
|
+
(void)env;
|
|
107
|
+
xt_value data = path_data(self, true);
|
|
108
|
+
xt_value subpath = xt_array_new(0, nullptr);
|
|
109
|
+
push_point(subpath, number_arg(argc, argv, 0, 0.0), number_arg(argc, argv, 1, 0.0));
|
|
110
|
+
xt_array_push(data, subpath);
|
|
111
|
+
return XT_UNDEFINED;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
METHOD(path2d_line_to) {
|
|
115
|
+
(void)env;
|
|
116
|
+
xt_value subpath = current_subpath(self, true);
|
|
117
|
+
push_point(subpath, number_arg(argc, argv, 0, 0.0), number_arg(argc, argv, 1, 0.0));
|
|
118
|
+
return XT_UNDEFINED;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
METHOD(path2d_close_path) {
|
|
122
|
+
(void)env;
|
|
123
|
+
(void)argc;
|
|
124
|
+
(void)argv;
|
|
125
|
+
xt_value subpath = current_subpath(self, false);
|
|
126
|
+
if (!XT_IS_ARRAY(subpath)) return XT_UNDEFINED;
|
|
127
|
+
int32_t count = (int32_t)xt_to_number(xt_array_length(subpath));
|
|
128
|
+
if (count < 4) return XT_UNDEFINED;
|
|
129
|
+
float firstX = (float)xt_to_number(xt_array_get(subpath, xt_number(0)));
|
|
130
|
+
float firstY = (float)xt_to_number(xt_array_get(subpath, xt_number(1)));
|
|
131
|
+
float lx = 0.0f, ly = 0.0f;
|
|
132
|
+
if (last_point(subpath, &lx, &ly) && (lx != firstX || ly != firstY)) {
|
|
133
|
+
push_point(subpath, firstX, firstY);
|
|
134
|
+
}
|
|
135
|
+
return XT_UNDEFINED;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
METHOD(path2d_rect) {
|
|
139
|
+
(void)env;
|
|
140
|
+
float x = number_arg(argc, argv, 0, 0.0);
|
|
141
|
+
float y = number_arg(argc, argv, 1, 0.0);
|
|
142
|
+
float w = number_arg(argc, argv, 2, 0.0);
|
|
143
|
+
float h = number_arg(argc, argv, 3, 0.0);
|
|
144
|
+
xt_value data = path_data(self, true);
|
|
145
|
+
xt_value subpath = xt_array_new(0, nullptr);
|
|
146
|
+
push_point(subpath, x, y);
|
|
147
|
+
push_point(subpath, x + w, y);
|
|
148
|
+
push_point(subpath, x + w, y + h);
|
|
149
|
+
push_point(subpath, x, y + h);
|
|
150
|
+
push_point(subpath, x, y);
|
|
151
|
+
xt_array_push(data, subpath);
|
|
152
|
+
return XT_UNDEFINED;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
METHOD(path2d_round_rect) {
|
|
156
|
+
(void)env;
|
|
157
|
+
float x = number_arg(argc, argv, 0, 0.0);
|
|
158
|
+
float y = number_arg(argc, argv, 1, 0.0);
|
|
159
|
+
float w = number_arg(argc, argv, 2, 0.0);
|
|
160
|
+
float h = number_arg(argc, argv, 3, 0.0);
|
|
161
|
+
float radius = number_arg(argc, argv, 4, 0.0);
|
|
162
|
+
if (w < 0.0f) {
|
|
163
|
+
x += w;
|
|
164
|
+
w = -w;
|
|
165
|
+
}
|
|
166
|
+
if (h < 0.0f) {
|
|
167
|
+
y += h;
|
|
168
|
+
h = -h;
|
|
169
|
+
}
|
|
170
|
+
float maxRadius = std::min(w, h) * 0.5f;
|
|
171
|
+
if (radius < 0.0f) radius = 0.0f;
|
|
172
|
+
if (radius > maxRadius) radius = maxRadius;
|
|
173
|
+
xt_value data = path_data(self, true);
|
|
174
|
+
xt_value subpath = xt_array_new(0, nullptr);
|
|
175
|
+
std::vector<float> points;
|
|
176
|
+
flatten_arc(&points, x + w - radius, y + radius, radius, radius, 0.0f, -kPi * 0.5f, kPi * 0.5f);
|
|
177
|
+
flatten_arc(&points, x + w - radius, y + h - radius, radius, radius, 0.0f, 0.0f, kPi * 0.5f);
|
|
178
|
+
flatten_arc(&points, x + radius, y + h - radius, radius, radius, 0.0f, kPi * 0.5f, kPi * 0.5f);
|
|
179
|
+
flatten_arc(&points, x + radius, y + radius, radius, radius, 0.0f, kPi, kPi * 0.5f);
|
|
180
|
+
push_point(subpath, x + radius, y);
|
|
181
|
+
for (size_t i = 0; i + 1 < points.size(); i += 2) push_point(subpath, points[i], points[i + 1]);
|
|
182
|
+
push_point(subpath, x + radius, y);
|
|
183
|
+
xt_array_push(data, subpath);
|
|
184
|
+
return XT_UNDEFINED;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
METHOD(path2d_arc) {
|
|
188
|
+
(void)env;
|
|
189
|
+
float sweep = number_arg(argc, argv, 4, 0.0) - number_arg(argc, argv, 3, 0.0);
|
|
190
|
+
normalize_sweep(&sweep, value_truthy(xt_arg(argc, argv, 5)));
|
|
191
|
+
std::vector<float> points;
|
|
192
|
+
flatten_arc(&points, number_arg(argc, argv, 0, 0.0), number_arg(argc, argv, 1, 0.0),
|
|
193
|
+
number_arg(argc, argv, 2, 0.0), number_arg(argc, argv, 2, 0.0), 0.0f,
|
|
194
|
+
number_arg(argc, argv, 3, 0.0), sweep);
|
|
195
|
+
append_points(self, points);
|
|
196
|
+
return XT_UNDEFINED;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
METHOD(path2d_ellipse) {
|
|
200
|
+
(void)env;
|
|
201
|
+
float sweep = number_arg(argc, argv, 6, 0.0) - number_arg(argc, argv, 5, 0.0);
|
|
202
|
+
normalize_sweep(&sweep, value_truthy(xt_arg(argc, argv, 7)));
|
|
203
|
+
std::vector<float> points;
|
|
204
|
+
flatten_arc(&points, number_arg(argc, argv, 0, 0.0), number_arg(argc, argv, 1, 0.0),
|
|
205
|
+
number_arg(argc, argv, 2, 0.0), number_arg(argc, argv, 3, 0.0),
|
|
206
|
+
number_arg(argc, argv, 4, 0.0), number_arg(argc, argv, 5, 0.0), sweep);
|
|
207
|
+
append_points(self, points);
|
|
208
|
+
return XT_UNDEFINED;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
METHOD(path2d_quadratic_curve_to) {
|
|
212
|
+
(void)env;
|
|
213
|
+
xt_value subpath = current_subpath(self, true);
|
|
214
|
+
float lx = 0.0f, ly = 0.0f;
|
|
215
|
+
if (!last_point(subpath, &lx, &ly)) {
|
|
216
|
+
lx = number_arg(argc, argv, 0, 0.0);
|
|
217
|
+
ly = number_arg(argc, argv, 1, 0.0);
|
|
218
|
+
push_point(subpath, lx, ly);
|
|
219
|
+
}
|
|
220
|
+
float cpx = number_arg(argc, argv, 0, 0.0);
|
|
221
|
+
float cpy = number_arg(argc, argv, 1, 0.0);
|
|
222
|
+
float tx = number_arg(argc, argv, 2, 0.0);
|
|
223
|
+
float ty = number_arg(argc, argv, 3, 0.0);
|
|
224
|
+
for (int i = 1; i <= 16; i++) {
|
|
225
|
+
float t = (float)i / 16.0f;
|
|
226
|
+
float a = 1.0f - t;
|
|
227
|
+
push_point(subpath, a * a * lx + 2.0f * a * t * cpx + t * t * tx,
|
|
228
|
+
a * a * ly + 2.0f * a * t * cpy + t * t * ty);
|
|
229
|
+
}
|
|
230
|
+
return XT_UNDEFINED;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
METHOD(path2d_bezier_curve_to) {
|
|
234
|
+
(void)env;
|
|
235
|
+
xt_value subpath = current_subpath(self, true);
|
|
236
|
+
float lx = 0.0f, ly = 0.0f;
|
|
237
|
+
if (!last_point(subpath, &lx, &ly)) {
|
|
238
|
+
lx = number_arg(argc, argv, 0, 0.0);
|
|
239
|
+
ly = number_arg(argc, argv, 1, 0.0);
|
|
240
|
+
push_point(subpath, lx, ly);
|
|
241
|
+
}
|
|
242
|
+
float c1x = number_arg(argc, argv, 0, 0.0);
|
|
243
|
+
float c1y = number_arg(argc, argv, 1, 0.0);
|
|
244
|
+
float c2x = number_arg(argc, argv, 2, 0.0);
|
|
245
|
+
float c2y = number_arg(argc, argv, 3, 0.0);
|
|
246
|
+
float tx = number_arg(argc, argv, 4, 0.0);
|
|
247
|
+
float ty = number_arg(argc, argv, 5, 0.0);
|
|
248
|
+
for (int i = 1; i <= 24; i++) {
|
|
249
|
+
float t = (float)i / 24.0f;
|
|
250
|
+
float u = 1.0f - t;
|
|
251
|
+
push_point(subpath,
|
|
252
|
+
u * u * u * lx + 3.0f * u * u * t * c1x + 3.0f * u * t * t * c2x + t * t * t * tx,
|
|
253
|
+
u * u * u * ly + 3.0f * u * u * t * c1y + 3.0f * u * t * t * c2y + t * t * t * ty);
|
|
254
|
+
}
|
|
255
|
+
return XT_UNDEFINED;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** `path.addPath(other, matrix?)` copies another path, optionally transformed. */
|
|
259
|
+
METHOD(path2d_add_path) {
|
|
260
|
+
(void)env;
|
|
261
|
+
std::vector<xtgui::CanvasSubpath> source = path2d_subpaths(xt_arg(argc, argv, 0));
|
|
262
|
+
if (source.empty()) return XT_UNDEFINED;
|
|
263
|
+
xtgui::CanvasTransform transform;
|
|
264
|
+
if (argc >= 2 && XT_IS_OBJECT(xt_arg(argc, argv, 1))) {
|
|
265
|
+
xt_value matrix = xt_arg(argc, argv, 1);
|
|
266
|
+
static const char *const names[6] = {"a", "b", "c", "d", "e", "f"};
|
|
267
|
+
float values[6] = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
|
|
268
|
+
for (int i = 0; i < 6; i++) {
|
|
269
|
+
xt_value member = xt_object_get_cstr(matrix, names[i]);
|
|
270
|
+
if (XT_IS_NUMBER(member)) values[i] = (float)xt_to_number(member);
|
|
271
|
+
}
|
|
272
|
+
transform = xtgui::CanvasTransform{values[0], values[1], values[2],
|
|
273
|
+
values[3], values[4], values[5]};
|
|
274
|
+
}
|
|
275
|
+
xt_value data = path_data(self, true);
|
|
276
|
+
for (const xtgui::CanvasSubpath &subpath : source) {
|
|
277
|
+
xt_value copy = xt_array_new(0, nullptr);
|
|
278
|
+
for (const xtgui::CanvasPoint &point : subpath) {
|
|
279
|
+
float x = point.x, y = point.y;
|
|
280
|
+
transform.apply(point.x, point.y, &x, &y);
|
|
281
|
+
push_point(copy, x, y);
|
|
282
|
+
}
|
|
283
|
+
xt_array_push(data, copy);
|
|
284
|
+
}
|
|
285
|
+
return XT_UNDEFINED;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
#undef METHOD
|
|
289
|
+
|
|
290
|
+
} // namespace
|
|
291
|
+
|
|
292
|
+
bool path2d_is(xt_value value) { return XT_IS_OBJECT(value) && value_truthy(xt_object_get_cstr(value, "__xt_gui_path2d")); }
|
|
293
|
+
|
|
294
|
+
std::vector<xtgui::CanvasSubpath> path2d_subpaths(xt_value value) {
|
|
295
|
+
std::vector<xtgui::CanvasSubpath> result;
|
|
296
|
+
if (!path2d_is(value)) return result;
|
|
297
|
+
xt_value data = xt_object_get_cstr(value, "__xt_gui_path_data");
|
|
298
|
+
if (!XT_IS_ARRAY(data)) return result;
|
|
299
|
+
int32_t count = (int32_t)xt_to_number(xt_array_length(data));
|
|
300
|
+
for (int32_t i = 0; i < count; i++) {
|
|
301
|
+
xt_value item = xt_array_get(data, xt_number((double)i));
|
|
302
|
+
if (!XT_IS_ARRAY(item)) continue;
|
|
303
|
+
xtgui::CanvasSubpath subpath;
|
|
304
|
+
int32_t numbers = (int32_t)xt_to_number(xt_array_length(item));
|
|
305
|
+
for (int32_t j = 0; j + 1 < numbers; j += 2) {
|
|
306
|
+
subpath.push_back(xtgui::CanvasPoint{
|
|
307
|
+
(float)xt_to_number(xt_array_get(item, xt_number((double)j))),
|
|
308
|
+
(float)xt_to_number(xt_array_get(item, xt_number((double)(j + 1))))});
|
|
309
|
+
}
|
|
310
|
+
if (!subpath.empty()) result.push_back(std::move(subpath));
|
|
311
|
+
}
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
xt_value path2d_proto() {
|
|
316
|
+
if (XT_IS_OBJECT(g_path2d_proto)) return g_path2d_proto;
|
|
317
|
+
g_path2d_proto = xt_object_new();
|
|
318
|
+
xt_gc_add_root(&g_path2d_proto);
|
|
319
|
+
struct Entry {
|
|
320
|
+
const char *name;
|
|
321
|
+
void *fn;
|
|
322
|
+
};
|
|
323
|
+
const Entry methods[] = {
|
|
324
|
+
{"moveTo", (void *)path2d_move_to},
|
|
325
|
+
{"lineTo", (void *)path2d_line_to},
|
|
326
|
+
{"closePath", (void *)path2d_close_path},
|
|
327
|
+
{"rect", (void *)path2d_rect},
|
|
328
|
+
{"roundRect", (void *)path2d_round_rect},
|
|
329
|
+
{"arc", (void *)path2d_arc},
|
|
330
|
+
{"ellipse", (void *)path2d_ellipse},
|
|
331
|
+
{"quadraticCurveTo", (void *)path2d_quadratic_curve_to},
|
|
332
|
+
{"bezierCurveTo", (void *)path2d_bezier_curve_to},
|
|
333
|
+
{"addPath", (void *)path2d_add_path},
|
|
334
|
+
};
|
|
335
|
+
for (const Entry &method : methods) {
|
|
336
|
+
xt_object_set(g_path2d_proto, xt_string_from_cstr(method.name),
|
|
337
|
+
xt_closure_new(method.fn, 0, nullptr));
|
|
338
|
+
}
|
|
339
|
+
return g_path2d_proto;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** `new Path2D()` and `new Path2D(otherPath)`; a string (SVG path data) is not
|
|
343
|
+
* parsed, so it yields an empty path instead of silently drawing nonsense. */
|
|
344
|
+
xt_value path2d_create(xt_value source) {
|
|
345
|
+
xt_value path = xt_object_new_with_proto(path2d_proto());
|
|
346
|
+
xt_object_set(path, xt_string_from_cstr("__xt_gui_path2d"), XT_TRUE);
|
|
347
|
+
xt_object_set(path, xt_string_from_cstr("__xt_gui_path_data"), xt_array_new(0, nullptr));
|
|
348
|
+
if (path2d_is(source)) {
|
|
349
|
+
xt_value data = xt_object_get_cstr(source, "__xt_gui_path_data");
|
|
350
|
+
xt_value copy = xt_array_new(0, nullptr);
|
|
351
|
+
int32_t count = XT_IS_ARRAY(data) ? (int32_t)xt_to_number(xt_array_length(data)) : 0;
|
|
352
|
+
for (int32_t i = 0; i < count; i++) xt_array_push(copy, xt_array_get(data, xt_number((double)i)));
|
|
353
|
+
xt_object_set(path, xt_string_from_cstr("__xt_gui_path_data"), copy);
|
|
354
|
+
}
|
|
355
|
+
return path;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
} // namespace domapi
|
|
@@ -27,6 +27,9 @@ xt_value node_proto() {
|
|
|
27
27
|
define_getter(proto, "tagName", (void *)node_tag_name_get);
|
|
28
28
|
define_getter(proto, "nodeName", (void *)node_tag_name_get);
|
|
29
29
|
define_getter(proto, "nodeType", (void *)node_node_type_get);
|
|
30
|
+
define_getter(proto, "namespaceURI", (void *)node_namespace_uri_get);
|
|
31
|
+
define_getter(proto, "localName", (void *)node_local_name_get);
|
|
32
|
+
define_getter(proto, "prefix", (void *)node_prefix_get);
|
|
30
33
|
define_getter(proto, "id", (void *)node_id_get);
|
|
31
34
|
define_getter(proto, "className", (void *)node_class_name_get);
|
|
32
35
|
define_getter(proto, "textContent", (void *)node_text_content_get);
|
|
@@ -44,6 +47,7 @@ xt_value node_proto() {
|
|
|
44
47
|
define_getter(proto, "isConnected", (void *)node_is_connected_get);
|
|
45
48
|
define_getter(proto, "classList", (void *)node_class_list_get);
|
|
46
49
|
define_getter(proto, "style", (void *)node_style_get);
|
|
50
|
+
define_getter(proto, "dataset", (void *)node_dataset_get);
|
|
47
51
|
define_getter(proto, "offsetWidth", (void *)node_offset_width_get);
|
|
48
52
|
define_getter(proto, "offsetHeight", (void *)node_offset_height_get);
|
|
49
53
|
/* Media element properties (`<video>`/`<audio>`; harmless on any element). */
|
|
@@ -86,6 +90,10 @@ xt_value node_proto() {
|
|
|
86
90
|
define_method(proto, "querySelectorAll", (void *)node_query_selector_all);
|
|
87
91
|
define_method(proto, "matches", (void *)node_matches);
|
|
88
92
|
define_method(proto, "appendChild", (void *)node_append_child);
|
|
93
|
+
define_method(proto, "append", (void *)node_append);
|
|
94
|
+
define_method(proto, "prepend", (void *)node_prepend);
|
|
95
|
+
define_method(proto, "replaceChildren", (void *)node_replace_children);
|
|
96
|
+
define_method(proto, "insertAdjacentHTML", (void *)node_insert_adjacent_html);
|
|
89
97
|
define_method(proto, "insertBefore", (void *)node_insert_before);
|
|
90
98
|
define_method(proto, "removeChild", (void *)node_remove_child);
|
|
91
99
|
define_method(proto, "replaceChild", (void *)node_replace_child);
|
|
@@ -103,6 +111,9 @@ xt_value node_proto() {
|
|
|
103
111
|
define_method(proto, "pause", (void *)node_pause);
|
|
104
112
|
define_method(proto, "load", (void *)node_load);
|
|
105
113
|
define_method(proto, "getContext", (void *)node_get_context);
|
|
114
|
+
/* `toDataURL`/`toBlob` belong to the canvas *element*, as in the DOM. */
|
|
115
|
+
define_method(proto, "toDataURL", (void *)canvas_to_data_url);
|
|
116
|
+
define_method(proto, "toBlob", (void *)canvas_to_blob);
|
|
106
117
|
g_node_proto = proto;
|
|
107
118
|
return proto;
|
|
108
119
|
}
|
|
@@ -121,7 +132,9 @@ xt_value document_proto() {
|
|
|
121
132
|
define_getter(proto, "hidden", (void *)doc_hidden_get);
|
|
122
133
|
define_getter(proto, "visibilityState", (void *)doc_visibility_state_get);
|
|
123
134
|
define_getter(proto, "readyState", (void *)doc_ready_state_get);
|
|
135
|
+
define_method(proto, "hasFocus", (void *)doc_has_focus);
|
|
124
136
|
define_getter(proto, "title", (void *)doc_title_get);
|
|
137
|
+
define_setter(proto, "title", (void *)doc_title_set);
|
|
125
138
|
define_getter(proto, "defaultView", (void *)doc_default_view_get);
|
|
126
139
|
define_method(proto, "createTextNode", (void *)doc_create_text_node);
|
|
127
140
|
/* `document.addEventListener` / element listener plumbing come from the node
|
|
@@ -140,6 +153,7 @@ xt_value event_proto() {
|
|
|
140
153
|
define_method(proto, "preventDefault", (void *)event_prevent_default);
|
|
141
154
|
define_method(proto, "stopPropagation", (void *)event_stop_propagation);
|
|
142
155
|
define_method(proto, "stopImmediatePropagation", (void *)event_stop_immediate_propagation);
|
|
156
|
+
define_method(proto, "composedPath", (void *)event_composed_path);
|
|
143
157
|
g_event_proto = proto;
|
|
144
158
|
return proto;
|
|
145
159
|
}
|
|
@@ -162,11 +176,26 @@ xt_value style_proto() {
|
|
|
162
176
|
xt_value proto = xt_object_new();
|
|
163
177
|
define_method(proto, "setProperty", (void *)style_set_property);
|
|
164
178
|
define_method(proto, "getPropertyValue", (void *)style_get_property_value);
|
|
179
|
+
define_method(proto, "getPropertyPriority", (void *)style_get_property_priority);
|
|
165
180
|
define_method(proto, "removeProperty", (void *)style_remove_property);
|
|
181
|
+
define_getter(proto, "cssText", (void *)style_css_text_get);
|
|
182
|
+
define_setter(proto, "cssText", (void *)style_css_text_set);
|
|
183
|
+
define_method(proto, "item", (void *)style_item);
|
|
184
|
+
define_getter(proto, "length", (void *)style_length_get);
|
|
166
185
|
g_style_proto = proto;
|
|
167
186
|
return proto;
|
|
168
187
|
}
|
|
169
188
|
|
|
189
|
+
xt_value computed_style_proto() {
|
|
190
|
+
xt_gc_add_root(&g_computed_style_proto);
|
|
191
|
+
if (XT_IS_OBJECT(g_computed_style_proto)) return g_computed_style_proto;
|
|
192
|
+
xt_value proto = xt_object_new();
|
|
193
|
+
define_method(proto, "getPropertyValue", (void *)computed_style_get_property_value);
|
|
194
|
+
define_method(proto, "getPropertyPriority", (void *)computed_style_get_property_priority);
|
|
195
|
+
g_computed_style_proto = proto;
|
|
196
|
+
return proto;
|
|
197
|
+
}
|
|
198
|
+
|
|
170
199
|
xt_value canvas_proto() {
|
|
171
200
|
xt_gc_add_root(&g_canvas_proto);
|
|
172
201
|
if (XT_IS_OBJECT(g_canvas_proto)) return g_canvas_proto;
|
|
@@ -224,6 +253,12 @@ xt_value canvas_proto() {
|
|
|
224
253
|
define_method(proto, "strokeText", (void *)canvas_stroke_text);
|
|
225
254
|
define_method(proto, "drawImage", (void *)canvas_draw_image);
|
|
226
255
|
define_method(proto, "getImageData", (void *)canvas_get_image_data);
|
|
256
|
+
define_method(proto, "getContextAttributes", (void *)canvas_get_context_attributes);
|
|
257
|
+
define_method(proto, "putImageData", (void *)canvas_put_image_data);
|
|
258
|
+
define_method(proto, "createImageData", (void *)canvas_create_image_data);
|
|
259
|
+
define_method(proto, "createPattern", (void *)canvas_create_pattern);
|
|
260
|
+
define_method(proto, "toDataURL", (void *)canvas_to_data_url);
|
|
261
|
+
define_method(proto, "toBlob", (void *)canvas_to_blob);
|
|
227
262
|
define_method(proto, "setLineDash", (void *)canvas_line_dash_set);
|
|
228
263
|
define_method(proto, "getLineDash", (void *)canvas_line_dash_get);
|
|
229
264
|
define_method(proto, "getTransform", (void *)canvas_get_transform);
|