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
|
@@ -51,17 +51,18 @@ static void write_declarations(xtgui::Node *node, const std::vector<xtgui::Decla
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
static void set_style_property(XtGuiWindow *win, xtgui::Node *node, const std::string &name,
|
|
54
|
-
const std::string &value) {
|
|
54
|
+
const std::string &value, bool important) {
|
|
55
55
|
std::vector<xtgui::Declaration> decls = xtgui::xt_css_parse_declarations(inline_style_of(node));
|
|
56
56
|
bool found = false;
|
|
57
57
|
for (xtgui::Declaration &decl : decls) {
|
|
58
58
|
if (decl.property == name) {
|
|
59
59
|
decl.value = value;
|
|
60
|
-
decl.important =
|
|
60
|
+
decl.important = important;
|
|
61
61
|
found = true;
|
|
62
|
+
break;
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
|
-
if (!found) decls.push_back({name, value,
|
|
65
|
+
if (!found) decls.push_back({name, value, important});
|
|
65
66
|
write_declarations(node, decls);
|
|
66
67
|
mark_dirty(win);
|
|
67
68
|
}
|
|
@@ -75,6 +76,26 @@ static std::string get_style_property(const xtgui::Node *node, const std::string
|
|
|
75
76
|
return value;
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
static std::string get_style_priority(const xtgui::Node *node, const std::string &name) {
|
|
80
|
+
std::vector<xtgui::Declaration> decls = xtgui::xt_css_parse_declarations(inline_style_of(node));
|
|
81
|
+
for (const xtgui::Declaration &decl : decls) {
|
|
82
|
+
if (decl.property == name) return decl.important ? "important" : "";
|
|
83
|
+
}
|
|
84
|
+
return "";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static std::string serialize_declarations(const xtgui::Node *node) {
|
|
88
|
+
std::vector<xtgui::Declaration> decls = xtgui::xt_css_parse_declarations(inline_style_of(node));
|
|
89
|
+
std::string out;
|
|
90
|
+
for (const xtgui::Declaration &decl : decls) {
|
|
91
|
+
if (!out.empty()) out += " ";
|
|
92
|
+
out += decl.property + ": " + decl.value;
|
|
93
|
+
if (decl.important) out += " !important";
|
|
94
|
+
out += ";";
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
|
|
78
99
|
static void remove_style_property(XtGuiWindow *win, xtgui::Node *node, const std::string &name) {
|
|
79
100
|
std::vector<xtgui::Declaration> decls = xtgui::xt_css_parse_declarations(inline_style_of(node));
|
|
80
101
|
std::vector<xtgui::Declaration> kept;
|
|
@@ -133,17 +154,36 @@ METHOD(class_list_toggle) {
|
|
|
133
154
|
xtgui::Node *node = class_list_node(self, &win);
|
|
134
155
|
if (node == nullptr || argc < 1) return XT_FALSE;
|
|
135
156
|
std::string name = to_string_value(xt_arg(argc, argv, 0));
|
|
157
|
+
if (name.empty()) return XT_FALSE;
|
|
136
158
|
std::vector<std::string> names = split_classes(class_name_of(node));
|
|
137
159
|
auto it = std::find(names.begin(), names.end(), name);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
160
|
+
bool present = it != names.end();
|
|
161
|
+
/* `toggle(name, force)`: with `force` the call is idempotent — it adds when
|
|
162
|
+
* the second argument is truthy and removes when it is falsy, instead of
|
|
163
|
+
* flipping. The argument is optional, so `undefined` still means "flip". */
|
|
164
|
+
bool forceProvided = argc >= 2 && !XT_IS_UNDEFINED(xt_arg(argc, argv, 1));
|
|
165
|
+
bool force = forceProvided && value_truthy(xt_arg(argc, argv, 1));
|
|
166
|
+
if (forceProvided) {
|
|
167
|
+
if (force) {
|
|
168
|
+
if (!present) {
|
|
169
|
+
names.push_back(name);
|
|
170
|
+
set_class_name(win, node, join_classes(names));
|
|
171
|
+
}
|
|
172
|
+
return XT_TRUE;
|
|
173
|
+
}
|
|
174
|
+
if (present) {
|
|
175
|
+
names.erase(it);
|
|
176
|
+
set_class_name(win, node, join_classes(names));
|
|
177
|
+
}
|
|
141
178
|
return XT_FALSE;
|
|
142
179
|
}
|
|
143
|
-
if (
|
|
144
|
-
names.
|
|
180
|
+
if (present) {
|
|
181
|
+
names.erase(it);
|
|
145
182
|
set_class_name(win, node, join_classes(names));
|
|
183
|
+
return XT_FALSE;
|
|
146
184
|
}
|
|
185
|
+
names.push_back(name);
|
|
186
|
+
set_class_name(win, node, join_classes(names));
|
|
147
187
|
return XT_TRUE;
|
|
148
188
|
}
|
|
149
189
|
|
|
@@ -165,8 +205,19 @@ METHOD(style_set_property) {
|
|
|
165
205
|
XtGuiWindow *win = nullptr;
|
|
166
206
|
xtgui::Node *node = style_node(self, &win);
|
|
167
207
|
if (node == nullptr || argc < 2) return XT_UNDEFINED;
|
|
168
|
-
|
|
169
|
-
|
|
208
|
+
std::string name = xtgui::xt_css_lower(xtgui::xt_css_trim(to_string_value(xt_arg(argc, argv, 0))));
|
|
209
|
+
if (name.empty()) return XT_UNDEFINED;
|
|
210
|
+
/* `priority` is "" or "important"; any other value makes the whole call a
|
|
211
|
+
* no-op, exactly as in the CSSOM. */
|
|
212
|
+
std::string priority;
|
|
213
|
+
if (argc >= 3) priority = xtgui::xt_css_lower(xtgui::xt_css_trim(to_string_value(xt_arg(argc, argv, 2))));
|
|
214
|
+
if (!priority.empty() && priority != "important") return XT_UNDEFINED;
|
|
215
|
+
std::string value = to_string_value(xt_arg(argc, argv, 1));
|
|
216
|
+
if (xtgui::xt_css_trim(value).empty()) {
|
|
217
|
+
remove_style_property(win, node, name);
|
|
218
|
+
return XT_UNDEFINED;
|
|
219
|
+
}
|
|
220
|
+
set_style_property(win, node, name, value, priority == "important");
|
|
170
221
|
return XT_UNDEFINED;
|
|
171
222
|
}
|
|
172
223
|
|
|
@@ -175,18 +226,177 @@ METHOD(style_get_property_value) {
|
|
|
175
226
|
xtgui::Node *node = style_node(self, nullptr);
|
|
176
227
|
if (node == nullptr || argc < 1) return xt_string_from_cstr("");
|
|
177
228
|
return xt_string_from_cstr(
|
|
178
|
-
get_style_property(node, to_string_value(xt_arg(argc, argv, 0)))
|
|
229
|
+
get_style_property(node, xtgui::xt_css_lower(xtgui::xt_css_trim(to_string_value(xt_arg(argc, argv, 0)))))
|
|
230
|
+
.c_str());
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
METHOD(style_get_property_priority) {
|
|
234
|
+
(void)env;
|
|
235
|
+
xtgui::Node *node = style_node(self, nullptr);
|
|
236
|
+
if (node == nullptr || argc < 1) return xt_string_from_cstr("");
|
|
237
|
+
return xt_string_from_cstr(
|
|
238
|
+
get_style_priority(node, xtgui::xt_css_lower(xtgui::xt_css_trim(to_string_value(xt_arg(argc, argv, 0)))))
|
|
239
|
+
.c_str());
|
|
179
240
|
}
|
|
180
241
|
|
|
181
242
|
METHOD(style_remove_property) {
|
|
182
243
|
(void)env;
|
|
183
244
|
XtGuiWindow *win = nullptr;
|
|
184
245
|
xtgui::Node *node = style_node(self, &win);
|
|
185
|
-
if (node == nullptr || argc < 1) return
|
|
186
|
-
|
|
246
|
+
if (node == nullptr || argc < 1) return xt_string_from_cstr("");
|
|
247
|
+
std::string name = xtgui::xt_css_lower(xtgui::xt_css_trim(to_string_value(xt_arg(argc, argv, 0))));
|
|
248
|
+
std::string previous = get_style_property(node, name);
|
|
249
|
+
remove_style_property(win, node, name);
|
|
250
|
+
return xt_string_from_cstr(previous.c_str());
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
METHOD(style_css_text_get) {
|
|
254
|
+
(void)env;
|
|
255
|
+
(void)argc;
|
|
256
|
+
(void)argv;
|
|
257
|
+
xtgui::Node *node = style_node(self, nullptr);
|
|
258
|
+
if (node == nullptr) return xt_string_from_cstr("");
|
|
259
|
+
return xt_string_from_cstr(serialize_declarations(node).c_str());
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
METHOD(style_css_text_set) {
|
|
263
|
+
(void)env;
|
|
264
|
+
XtGuiWindow *win = nullptr;
|
|
265
|
+
xtgui::Node *node = style_node(self, &win);
|
|
266
|
+
if (node == nullptr) return XT_UNDEFINED;
|
|
267
|
+
std::vector<xtgui::Declaration> decls =
|
|
268
|
+
xtgui::xt_css_parse_declarations(to_string_value(xt_arg(argc, argv, 0)));
|
|
269
|
+
write_declarations(node, decls);
|
|
270
|
+
mark_dirty(win);
|
|
187
271
|
return XT_UNDEFINED;
|
|
188
272
|
}
|
|
189
273
|
|
|
274
|
+
/* -- named properties (`style.width = "50%"`) -----------------------------
|
|
275
|
+
*
|
|
276
|
+
* A CSSStyleDeclaration exposes every supported CSS property as a camel-cased
|
|
277
|
+
* property (`style.width`, `style.backgroundColor`) as well as through
|
|
278
|
+
* `setProperty`. There are hundreds of them, so instead of enumerating
|
|
279
|
+
* accessors the style object installs the runtime's dynamic-property hooks:
|
|
280
|
+
* a miss on the prototype is answered from the inline declaration block, and
|
|
281
|
+
* an assignment writes it back there. That is what makes the common
|
|
282
|
+
* `el.style.display = "none"` idiom affect layout instead of silently parking
|
|
283
|
+
* a field on the JS object.
|
|
284
|
+
*/
|
|
285
|
+
|
|
286
|
+
namespace {
|
|
287
|
+
|
|
288
|
+
bool property_key(xt_value key, std::string *out) {
|
|
289
|
+
if (!XT_IS_STRING(key)) return false;
|
|
290
|
+
/* Named style properties are camel-cased (`style.backgroundColor`); the
|
|
291
|
+
* declaration block stores the CSS spelling (`background-color`). Custom
|
|
292
|
+
* properties keep their leading `--`, and internal bookkeeping keys stay
|
|
293
|
+
* out of the view (looking one up must not re-enter it). */
|
|
294
|
+
std::string raw = to_string_value(key);
|
|
295
|
+
if (raw.compare(0, 6, "__xt_") == 0) return false;
|
|
296
|
+
std::string mapped;
|
|
297
|
+
for (char c : raw) {
|
|
298
|
+
if (c >= 'A' && c <= 'Z') {
|
|
299
|
+
mapped.push_back('-');
|
|
300
|
+
mapped.push_back((char)std::tolower((unsigned char)c));
|
|
301
|
+
} else {
|
|
302
|
+
mapped.push_back(c);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
*out = xtgui::xt_css_lower(xtgui::xt_css_trim(mapped));
|
|
306
|
+
return !out->empty();
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
xt_value style_view_get(xt_value self, xt_value key, void *data) {
|
|
310
|
+
(void)data;
|
|
311
|
+
std::string name;
|
|
312
|
+
if (!property_key(key, &name)) return XT_UNDEFINED;
|
|
313
|
+
xtgui::Node *node = style_node(self, nullptr);
|
|
314
|
+
if (node == nullptr) return xt_string_from_cstr("");
|
|
315
|
+
return xt_string_from_cstr(get_style_property(node, name).c_str());
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
int style_view_set(xt_value self, xt_value key, xt_value value, void *data) {
|
|
319
|
+
(void)data;
|
|
320
|
+
std::string name;
|
|
321
|
+
if (!property_key(key, &name)) return 0;
|
|
322
|
+
XtGuiWindow *win = nullptr;
|
|
323
|
+
xtgui::Node *node = style_node(self, &win);
|
|
324
|
+
if (node == nullptr) return 1;
|
|
325
|
+
std::string text = to_string_value(value);
|
|
326
|
+
if (text.empty()) {
|
|
327
|
+
remove_style_property(win, node, name);
|
|
328
|
+
} else {
|
|
329
|
+
set_style_property(win, node, name, text, false);
|
|
330
|
+
}
|
|
331
|
+
return 1;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
int style_view_has(xt_value self, xt_value key, void *data) {
|
|
335
|
+
(void)data;
|
|
336
|
+
std::string name;
|
|
337
|
+
if (!property_key(key, &name)) return 0;
|
|
338
|
+
xtgui::Node *node = style_node(self, nullptr);
|
|
339
|
+
if (node == nullptr) return 0;
|
|
340
|
+
std::vector<xtgui::Declaration> decls = xtgui::xt_css_parse_declarations(inline_style_of(node));
|
|
341
|
+
for (const xtgui::Declaration &decl : decls) {
|
|
342
|
+
if (decl.property == name) return 1;
|
|
343
|
+
}
|
|
344
|
+
return 0;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
int style_view_remove(xt_value self, xt_value key, void *data) {
|
|
348
|
+
(void)data;
|
|
349
|
+
std::string name;
|
|
350
|
+
if (!property_key(key, &name)) return 0;
|
|
351
|
+
XtGuiWindow *win = nullptr;
|
|
352
|
+
xtgui::Node *node = style_node(self, &win);
|
|
353
|
+
if (node == nullptr) return 1;
|
|
354
|
+
remove_style_property(win, node, name);
|
|
355
|
+
return 1;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
xt_value style_view_keys(xt_value self, void *data) {
|
|
359
|
+
(void)data;
|
|
360
|
+
xtgui::Node *node = style_node(self, nullptr);
|
|
361
|
+
xt_value result = xt_array_new(0, nullptr);
|
|
362
|
+
if (node == nullptr) return result;
|
|
363
|
+
std::vector<xtgui::Declaration> decls = xtgui::xt_css_parse_declarations(inline_style_of(node));
|
|
364
|
+
for (const xtgui::Declaration &decl : decls) {
|
|
365
|
+
xt_array_push(result, xt_string_from_cstr(decl.property.c_str()));
|
|
366
|
+
}
|
|
367
|
+
return result;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const xt_object_hooks kStyleViewHooks = {style_view_get, style_view_set, style_view_has,
|
|
371
|
+
style_view_remove, style_view_keys};
|
|
372
|
+
|
|
373
|
+
} // namespace
|
|
374
|
+
|
|
375
|
+
void install_style_hooks(xt_value style) {
|
|
376
|
+
xt_object_set_hooks(style, &kStyleViewHooks, nullptr);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
METHOD(style_length_get) {
|
|
380
|
+
(void)env;
|
|
381
|
+
(void)argc;
|
|
382
|
+
(void)argv;
|
|
383
|
+
xtgui::Node *node = style_node(self, nullptr);
|
|
384
|
+
if (node == nullptr) return xt_number(0);
|
|
385
|
+
return xt_number(
|
|
386
|
+
(double)xtgui::xt_css_parse_declarations(inline_style_of(node)).size());
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/** `style.item(index)`: the property name at `index`, or "" past the end. */
|
|
390
|
+
METHOD(style_item) {
|
|
391
|
+
(void)env;
|
|
392
|
+
xtgui::Node *node = style_node(self, nullptr);
|
|
393
|
+
if (node == nullptr || argc < 1) return xt_string_from_cstr("");
|
|
394
|
+
std::vector<xtgui::Declaration> decls = xtgui::xt_css_parse_declarations(inline_style_of(node));
|
|
395
|
+
double index = xt_to_number(xt_arg(argc, argv, 0));
|
|
396
|
+
if (index < 0 || index >= (double)decls.size()) return xt_string_from_cstr("");
|
|
397
|
+
return xt_string_from_cstr(decls[(size_t)index].property.c_str());
|
|
398
|
+
}
|
|
399
|
+
|
|
190
400
|
#undef METHOD
|
|
191
401
|
|
|
192
402
|
} // namespace domapi
|
|
@@ -159,6 +159,8 @@ const MethodEntry kMethods[] = {
|
|
|
159
159
|
{"getTexParameter", (void *)webgl_get_tex_parameter},
|
|
160
160
|
{"texImage2D", (void *)webgl_tex_image_2d},
|
|
161
161
|
{"texSubImage2D", (void *)webgl_tex_sub_image_2d},
|
|
162
|
+
{"compressedTexImage2D", (void *)webgl_compressed_tex_image_2d},
|
|
163
|
+
{"compressedTexSubImage2D", (void *)webgl_compressed_tex_sub_image_2d},
|
|
162
164
|
{"generateMipmap", (void *)webgl_generate_mipmap},
|
|
163
165
|
{"createFramebuffer", (void *)webgl_create_framebuffer},
|
|
164
166
|
{"deleteFramebuffer", (void *)webgl_delete_framebuffer},
|
|
@@ -238,6 +240,11 @@ xtgui::WebGLContext *webgl_from_context(xt_value self) {
|
|
|
238
240
|
return id != 0 ? xtgui::xt_webgl_by_id(id) : nullptr;
|
|
239
241
|
}
|
|
240
242
|
|
|
243
|
+
xtgui::WebGLContext *webgl_live_context(xt_value self) {
|
|
244
|
+
xtgui::WebGLContext *context = webgl_from_context(self);
|
|
245
|
+
return context != nullptr && !context->lost() ? context : nullptr;
|
|
246
|
+
}
|
|
247
|
+
|
|
241
248
|
xt_value webgl_context_handle(xt_value element, xtgui::WebGLContext *context) {
|
|
242
249
|
xt_value cached = xt_object_get_cstr(element, "__xt_gui_gl");
|
|
243
250
|
if (XT_IS_OBJECT(cached)) return cached;
|
|
@@ -81,12 +81,13 @@ const MethodEntry kMethods[] = {
|
|
|
81
81
|
{"getActiveUniformBlockParameter", (void *)webgl2_get_active_uniform_block_parameter},
|
|
82
82
|
{"getActiveUniformBlockName", (void *)webgl2_get_active_uniform_block_name},
|
|
83
83
|
{"uniformBlockBinding", (void *)webgl2_uniform_block_binding},
|
|
84
|
+
{"drawingBufferStorage", (void *)webgl2_drawing_buffer_storage},
|
|
84
85
|
{"texStorage2D", (void *)webgl2_tex_storage_2d},
|
|
85
86
|
{"texStorage3D", (void *)webgl2_tex_storage_3d},
|
|
86
87
|
{"texImage3D", (void *)webgl2_tex_image_3d},
|
|
87
88
|
{"texSubImage3D", (void *)webgl2_tex_sub_image_3d},
|
|
88
|
-
{"compressedTexImage2D", (void *)
|
|
89
|
-
{"compressedTexSubImage2D", (void *)
|
|
89
|
+
{"compressedTexImage2D", (void *)webgl_compressed_tex_image_2d},
|
|
90
|
+
{"compressedTexSubImage2D", (void *)webgl_compressed_tex_sub_image_2d},
|
|
90
91
|
{"compressedTexImage3D", (void *)webgl2_compressed_tex_image3d},
|
|
91
92
|
{"compressedTexSubImage3D", (void *)webgl2_compressed_tex_sub_image3d},
|
|
92
93
|
{"clearBufferfi", (void *)webgl2_clear_buffer_fi},
|
|
@@ -107,7 +108,7 @@ void define_method(xt_value proto, const char *name, void *fn) {
|
|
|
107
108
|
xt_object_set(proto, xt_string_from_cstr(name), xt_closure_new(fn, 0, NULL));
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
xtgui::WebGLContext *context_of(xt_value self) { return
|
|
111
|
+
xtgui::WebGLContext *context_of(xt_value self) { return webgl_live_context(self); }
|
|
111
112
|
|
|
112
113
|
xt_value uint_array(const unsigned int *values, int count) {
|
|
113
114
|
xt_value array = xt_array_new(0, nullptr);
|
|
@@ -202,14 +203,66 @@ WEBGL2_NOOP(webgl2_end_transform_feedback)
|
|
|
202
203
|
WEBGL2_NOOP(webgl2_pause_transform_feedback)
|
|
203
204
|
WEBGL2_NOOP(webgl2_resume_transform_feedback)
|
|
204
205
|
WEBGL2_NOOP(webgl2_transform_feedback_varyings)
|
|
205
|
-
WEBGL2_NOOP(webgl2_bind_buffer_base)
|
|
206
|
-
WEBGL2_NOOP(webgl2_bind_buffer_range)
|
|
207
|
-
WEBGL2_NOOP(webgl2_uniform_block_binding)
|
|
208
|
-
WEBGL2_NOOP(webgl2_blit_framebuffer)
|
|
209
|
-
WEBGL2_NOOP(webgl2_framebuffer_texture_layer)
|
|
210
206
|
WEBGL2_NOOP(webgl2_invalidate_framebuffer)
|
|
211
207
|
WEBGL2_NOOP(webgl2_invalidate_sub_framebuffer)
|
|
212
|
-
|
|
208
|
+
|
|
209
|
+
METHOD(webgl2_blit_framebuffer) {
|
|
210
|
+
(void)env;
|
|
211
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
212
|
+
if (context == nullptr) return XT_UNDEFINED;
|
|
213
|
+
const int source[4] = {webgl_int(argc, argv, 0, 0), webgl_int(argc, argv, 1, 0),
|
|
214
|
+
webgl_int(argc, argv, 2, 0), webgl_int(argc, argv, 3, 0)};
|
|
215
|
+
const int destination[4] = {webgl_int(argc, argv, 4, 0), webgl_int(argc, argv, 5, 0),
|
|
216
|
+
webgl_int(argc, argv, 6, 0), webgl_int(argc, argv, 7, 0)};
|
|
217
|
+
context->blit_framebuffer(source, destination, webgl_int(argc, argv, 8, GL_COLOR_BUFFER_BIT),
|
|
218
|
+
webgl_int(argc, argv, 9, GL_NEAREST));
|
|
219
|
+
return XT_UNDEFINED;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
METHOD(webgl2_tex_sub_image_3d) {
|
|
223
|
+
(void)env;
|
|
224
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
225
|
+
if (context == nullptr) return XT_UNDEFINED;
|
|
226
|
+
const uint32_t texture = context->bound_texture(0);
|
|
227
|
+
if (texture == 0 || webgl_int(argc, argv, 1, 0) != 0) return XT_UNDEFINED;
|
|
228
|
+
const int x = webgl_int(argc, argv, 2, 0);
|
|
229
|
+
const int y = webgl_int(argc, argv, 3, 0);
|
|
230
|
+
const int z = webgl_int(argc, argv, 4, 0);
|
|
231
|
+
const int width = webgl_int(argc, argv, 5, 0);
|
|
232
|
+
const int height = webgl_int(argc, argv, 6, 0);
|
|
233
|
+
const int depth = webgl_int(argc, argv, 7, 0);
|
|
234
|
+
const int format = webgl_int(argc, argv, 8, GL_RGBA);
|
|
235
|
+
const int type = webgl_int(argc, argv, 9, GL_UNSIGNED_BYTE);
|
|
236
|
+
if (type != GL_UNSIGNED_BYTE) {
|
|
237
|
+
context->set_error(GL_INVALID_ENUM);
|
|
238
|
+
return XT_UNDEFINED;
|
|
239
|
+
}
|
|
240
|
+
int channels = 1;
|
|
241
|
+
if (format == GL_RGBA) channels = 4;
|
|
242
|
+
else if (format == GL_RGB) channels = 3;
|
|
243
|
+
else if (format == GL_LUMINANCE_ALPHA) channels = 2;
|
|
244
|
+
const std::vector<uint8_t> bytes = webgl_bytes(xt_arg(argc, argv, 10));
|
|
245
|
+
const size_t count = (size_t)width * height * depth;
|
|
246
|
+
if (bytes.size() < count * (size_t)channels) {
|
|
247
|
+
context->set_error(GL_INVALID_VALUE);
|
|
248
|
+
return XT_UNDEFINED;
|
|
249
|
+
}
|
|
250
|
+
std::vector<uint8_t> rgba;
|
|
251
|
+
webgl_convert_pixels(bytes.data(), (int)count, format, false, &rgba);
|
|
252
|
+
context->tex_sub_image_3d(texture, x, y, z, width, height, depth, rgba.data());
|
|
253
|
+
return XT_UNDEFINED;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
METHOD(webgl2_framebuffer_texture_layer) {
|
|
257
|
+
(void)env;
|
|
258
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
259
|
+
if (context == nullptr) return XT_UNDEFINED;
|
|
260
|
+
context->framebuffer_texture_layer(
|
|
261
|
+
context->bound_framebuffer_id(),
|
|
262
|
+
webgl_object_id(xt_arg(argc, argv, 2), "__xt_gl_texture"),
|
|
263
|
+
webgl_int(argc, argv, 1, GL_COLOR_ATTACHMENT0), webgl_int(argc, argv, 4, 0));
|
|
264
|
+
return XT_UNDEFINED;
|
|
265
|
+
}
|
|
213
266
|
|
|
214
267
|
METHOD(webgl2_get_transform_feedback_varying) {
|
|
215
268
|
(void)env;
|
|
@@ -259,12 +312,6 @@ METHOD(webgl2_get_sync_parameter) {
|
|
|
259
312
|
|
|
260
313
|
/* -- uniform blocks and indexed queries ---------------------------------- */
|
|
261
314
|
|
|
262
|
-
METHOD(webgl2_get_indexed_parameter) {
|
|
263
|
-
(void)env;
|
|
264
|
-
(void)argc;
|
|
265
|
-
(void)argv;
|
|
266
|
-
return XT_NULL;
|
|
267
|
-
}
|
|
268
315
|
|
|
269
316
|
METHOD(webgl2_get_uniform_indices) {
|
|
270
317
|
(void)env;
|
|
@@ -290,19 +337,7 @@ METHOD(webgl2_get_uniform_block_index) {
|
|
|
290
337
|
return xt_number((double)index);
|
|
291
338
|
}
|
|
292
339
|
|
|
293
|
-
METHOD(webgl2_get_active_uniform_block_parameter) {
|
|
294
|
-
(void)env;
|
|
295
|
-
(void)argc;
|
|
296
|
-
(void)argv;
|
|
297
|
-
return xt_number(0);
|
|
298
|
-
}
|
|
299
340
|
|
|
300
|
-
METHOD(webgl2_get_active_uniform_block_name) {
|
|
301
|
-
(void)env;
|
|
302
|
-
(void)argc;
|
|
303
|
-
(void)argv;
|
|
304
|
-
return XT_NULL;
|
|
305
|
-
}
|
|
306
341
|
|
|
307
342
|
/* -- buffers ------------------------------------------------------------- */
|
|
308
343
|
|
|
@@ -340,22 +375,80 @@ METHOD(webgl2_get_buffer_sub_data) {
|
|
|
340
375
|
|
|
341
376
|
/* -- textures ------------------------------------------------------------ */
|
|
342
377
|
|
|
378
|
+
METHOD(webgl2_drawing_buffer_storage) {
|
|
379
|
+
(void)env;
|
|
380
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
381
|
+
if (context != nullptr) {
|
|
382
|
+
context->drawing_buffer_storage(webgl_int(argc, argv, 0, 0),
|
|
383
|
+
webgl_int(argc, argv, 1, 0));
|
|
384
|
+
}
|
|
385
|
+
return XT_UNDEFINED;
|
|
386
|
+
}
|
|
387
|
+
|
|
343
388
|
METHOD(webgl2_tex_storage_2d) {
|
|
344
389
|
(void)env;
|
|
345
390
|
xtgui::WebGLContext *context = context_of(self);
|
|
346
391
|
if (context != nullptr) {
|
|
347
392
|
const uint32_t texture = context->bound_texture(0);
|
|
348
|
-
|
|
349
|
-
|
|
393
|
+
const int internalformat = webgl_int(argc, argv, 2, 0x8058); // GL_RGBA8
|
|
394
|
+
context->tex_storage_format(texture, webgl_int(argc, argv, 1, 1),
|
|
395
|
+
webgl_int(argc, argv, 3, 0), webgl_int(argc, argv, 4, 0),
|
|
396
|
+
xtgui::webgl_storage_format(internalformat));
|
|
397
|
+
}
|
|
398
|
+
return XT_UNDEFINED;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
METHOD(webgl2_tex_storage_3d) {
|
|
402
|
+
(void)env;
|
|
403
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
404
|
+
if (context == nullptr) return XT_UNDEFINED;
|
|
405
|
+
const int internalformat = webgl_int(argc, argv, 2, 0x8058); // GL_RGBA8
|
|
406
|
+
context->tex_storage_3d(context->bound_texture(0), webgl_int(argc, argv, 1, 1),
|
|
407
|
+
webgl_int(argc, argv, 3, 0), webgl_int(argc, argv, 4, 0),
|
|
408
|
+
webgl_int(argc, argv, 5, 0),
|
|
409
|
+
xtgui::webgl_storage_format(internalformat),
|
|
410
|
+
webgl_int(argc, argv, 0, GL_TEXTURE_2D_ARRAY));
|
|
411
|
+
return XT_UNDEFINED;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
METHOD(webgl2_tex_image_3d) {
|
|
415
|
+
(void)env;
|
|
416
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
417
|
+
if (context == nullptr) return XT_UNDEFINED;
|
|
418
|
+
const uint32_t texture = context->bound_texture(0);
|
|
419
|
+
if (texture == 0) return XT_UNDEFINED;
|
|
420
|
+
if (webgl_int(argc, argv, 1, 0) != 0) return XT_UNDEFINED;
|
|
421
|
+
const int internalformat = webgl_int(argc, argv, 2, GL_RGBA);
|
|
422
|
+
const int width = webgl_int(argc, argv, 3, 0);
|
|
423
|
+
const int height = webgl_int(argc, argv, 4, 0);
|
|
424
|
+
const int depth = webgl_int(argc, argv, 5, 0);
|
|
425
|
+
const int format = webgl_int(argc, argv, 7, GL_RGBA);
|
|
426
|
+
const int type = webgl_int(argc, argv, 8, GL_UNSIGNED_BYTE);
|
|
427
|
+
if (type != GL_UNSIGNED_BYTE || width <= 0 || height <= 0 || depth <= 0) {
|
|
428
|
+
context->set_error(GL_INVALID_VALUE);
|
|
429
|
+
return XT_UNDEFINED;
|
|
430
|
+
}
|
|
431
|
+
int channels = 1;
|
|
432
|
+
if (format == GL_RGBA) channels = 4;
|
|
433
|
+
else if (format == GL_RGB) channels = 3;
|
|
434
|
+
else if (format == GL_LUMINANCE_ALPHA) channels = 2;
|
|
435
|
+
const std::vector<uint8_t> bytes = webgl_bytes(xt_arg(argc, argv, 9));
|
|
436
|
+
const size_t count = (size_t)width * height * depth;
|
|
437
|
+
std::vector<uint8_t> rgba;
|
|
438
|
+
if (bytes.empty()) {
|
|
439
|
+
rgba.assign(count * 4, 0);
|
|
440
|
+
} else if (bytes.size() < count * (size_t)channels) {
|
|
441
|
+
context->set_error(GL_INVALID_VALUE);
|
|
442
|
+
return XT_UNDEFINED;
|
|
443
|
+
} else {
|
|
444
|
+
webgl_convert_pixels(bytes.data(), (int)count, format, false, &rgba);
|
|
350
445
|
}
|
|
446
|
+
context->tex_image_3d(texture, width, height, depth,
|
|
447
|
+
xtgui::webgl_storage_format(internalformat), rgba.data(),
|
|
448
|
+
webgl_int(argc, argv, 0, GL_TEXTURE_2D_ARRAY));
|
|
351
449
|
return XT_UNDEFINED;
|
|
352
450
|
}
|
|
353
451
|
|
|
354
|
-
WEBGL2_NOOP(webgl2_tex_storage_3d)
|
|
355
|
-
WEBGL2_NOOP(webgl2_tex_image_3d)
|
|
356
|
-
WEBGL2_NOOP(webgl2_tex_sub_image_3d)
|
|
357
|
-
WEBGL2_NOOP(webgl2_compressed_tex_image2d)
|
|
358
|
-
WEBGL2_NOOP(webgl2_compressed_tex_sub_image2d)
|
|
359
452
|
WEBGL2_NOOP(webgl2_compressed_tex_image3d)
|
|
360
453
|
WEBGL2_NOOP(webgl2_compressed_tex_sub_image3d)
|
|
361
454
|
|
|
@@ -410,8 +503,30 @@ METHOD(webgl2_clear_buffer_fi) {
|
|
|
410
503
|
|
|
411
504
|
METHOD(webgl2_draw_buffers) {
|
|
412
505
|
(void)env;
|
|
413
|
-
(
|
|
414
|
-
(
|
|
506
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
507
|
+
if (context == nullptr) return XT_UNDEFINED;
|
|
508
|
+
const xt_value list = xt_arg(argc, argv, 0);
|
|
509
|
+
std::vector<double> values = webgl_numbers(list);
|
|
510
|
+
if (values.empty()) {
|
|
511
|
+
/* `webgl_numbers` only walks typed arrays; plain WebGL argument arrays
|
|
512
|
+
* (`drawBuffers([gl.COLOR_ATTACHMENT0, ...])`) need the element accessor. */
|
|
513
|
+
const double length = xt_to_number(xt_get(list, xt_string_from_cstr("length")));
|
|
514
|
+
if (length > 0.0 && length <= 16.0) {
|
|
515
|
+
for (int i = 0; i < (int)length; i++) {
|
|
516
|
+
values.push_back(xt_to_number(xt_get(list, xt_number((double)i))));
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
std::vector<int> buffers(values.size());
|
|
521
|
+
for (size_t i = 0; i < values.size(); i++) buffers[i] = (int)values[i];
|
|
522
|
+
context->draw_buffers((int)buffers.size(), buffers.data());
|
|
523
|
+
return XT_UNDEFINED;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
METHOD(webgl2_read_buffer) {
|
|
527
|
+
(void)env;
|
|
528
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
529
|
+
if (context != nullptr) context->read_buffer(webgl_int(argc, argv, 0, GL_BACK));
|
|
415
530
|
return XT_UNDEFINED;
|
|
416
531
|
}
|
|
417
532
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
namespace domapi {
|
|
19
19
|
namespace {
|
|
20
20
|
|
|
21
|
-
xtgui::WebGLContext *context_of(xt_value self) { return
|
|
21
|
+
xtgui::WebGLContext *context_of(xt_value self) { return webgl_live_context(self); }
|
|
22
22
|
|
|
23
23
|
uint32_t vertex_array_argument(xt_value value) {
|
|
24
24
|
return webgl_object_id(value, "__xt_gl_vertex_array");
|
|
@@ -81,7 +81,7 @@ METHOD(webgl2_vertex_attrib_ipointer) {
|
|
|
81
81
|
namespace {
|
|
82
82
|
|
|
83
83
|
void attrib_integer(xt_value self, int32_t argc, xt_value *argv, bool is_unsigned) {
|
|
84
|
-
xtgui::WebGLContext *context =
|
|
84
|
+
xtgui::WebGLContext *context = webgl_live_context(self);
|
|
85
85
|
if (context == nullptr) return;
|
|
86
86
|
float values[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
|
87
87
|
const std::vector<double> numbers = webgl_numbers(xt_arg(argc, argv, 1));
|
|
@@ -162,7 +162,7 @@ METHOD(webgl2_draw_range_elements) {
|
|
|
162
162
|
namespace {
|
|
163
163
|
|
|
164
164
|
void uniform_unsigned(xt_value self, int32_t argc, xt_value *argv, int components, bool vector) {
|
|
165
|
-
xtgui::WebGLContext *context =
|
|
165
|
+
xtgui::WebGLContext *context = webgl_live_context(self);
|
|
166
166
|
if (context == nullptr) return;
|
|
167
167
|
xt_value handle = xt_arg(argc, argv, 0);
|
|
168
168
|
if (!XT_IS_OBJECT(handle)) return;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
namespace domapi {
|
|
15
15
|
namespace {
|
|
16
16
|
|
|
17
|
-
xtgui::WebGLContext *context_of(xt_value self) { return
|
|
17
|
+
xtgui::WebGLContext *context_of(xt_value self) { return webgl_live_context(self); }
|
|
18
18
|
|
|
19
19
|
uint32_t buffer_argument(xt_value value) { return webgl_object_id(value, "__xt_gl_buffer"); }
|
|
20
20
|
|
|
@@ -85,6 +85,10 @@ METHOD(webgl_get_buffer_parameter) {
|
|
|
85
85
|
const int pname = webgl_int(argc, argv, 1, 0);
|
|
86
86
|
const uint32_t buffer = context->bound_buffer(target);
|
|
87
87
|
if (pname == GL_BUFFER_SIZE) return xt_number((double)context->buffer_size(buffer));
|
|
88
|
+
if (pname == 0x8765) { // GL_BUFFER_USAGE
|
|
89
|
+
xtgui::WebGLBuffer *record = context->buffer(buffer);
|
|
90
|
+
return xt_number(record != nullptr ? (double)record->usage : 0.0);
|
|
91
|
+
}
|
|
88
92
|
return xt_number(0);
|
|
89
93
|
}
|
|
90
94
|
|
|
@@ -116,7 +120,7 @@ METHOD(webgl_vertex_attrib_pointer) {
|
|
|
116
120
|
namespace {
|
|
117
121
|
|
|
118
122
|
void attrib_value(xt_value self, int32_t argc, xt_value *argv, int components) {
|
|
119
|
-
xtgui::WebGLContext *context =
|
|
123
|
+
xtgui::WebGLContext *context = webgl_live_context(self);
|
|
120
124
|
if (context == nullptr) return;
|
|
121
125
|
float values[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
|
122
126
|
for (int i = 0; i < components; i++) values[i] = (float)webgl_number(argc, argv, i + 1, 0.0);
|