xbintsc 0.5.45 → 0.5.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/README.md +5 -4
- package/README.zh-CN.md +4 -3
- package/dist/src/cli/extensions.d.ts +24 -0
- package/dist/src/cli/extensions.js +62 -0
- package/dist/src/cli/extensions.js.map +1 -0
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/cli/help.js +3 -1
- package/dist/src/cli/help.js.map +1 -1
- package/dist/src/cli/hints.js +8 -3
- package/dist/src/cli/hints.js.map +1 -1
- package/dist/src/cli/main.js +21 -28
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/diagnostics/diagnostic.d.ts +3 -1
- package/dist/src/diagnostics/diagnostic.js +2 -0
- package/dist/src/diagnostics/diagnostic.js.map +1 -1
- package/dist/src/driver/build-key.d.ts +2 -0
- package/dist/src/driver/build-key.js +1 -0
- package/dist/src/driver/build-key.js.map +1 -1
- package/dist/src/driver/compiler.js +61 -8
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/config.d.ts +4 -0
- package/dist/src/driver/config.js +2 -0
- package/dist/src/driver/config.js.map +1 -1
- package/dist/src/driver/link-features.d.ts +37 -0
- package/dist/src/driver/link-features.js +123 -0
- package/dist/src/driver/link-features.js.map +1 -0
- package/dist/src/driver/options.d.ts +10 -0
- package/dist/src/driver/runtime-objects.d.ts +5 -0
- package/dist/src/driver/runtime-objects.js +20 -1
- package/dist/src/driver/runtime-objects.js.map +1 -1
- package/dist/src/driver/usage.d.ts +23 -0
- package/dist/src/driver/usage.js +353 -0
- package/dist/src/driver/usage.js.map +1 -0
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/catalog.js +1 -2
- package/dist/src/extensions/catalog.js.map +1 -1
- package/dist/src/extensions/gui/features.d.ts +34 -0
- package/dist/src/extensions/gui/features.js +165 -0
- package/dist/src/extensions/gui/features.js.map +1 -0
- package/dist/src/extensions/gui/index.js +10 -4
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/link-feature.d.ts +70 -0
- package/dist/src/extensions/link-feature.js +18 -0
- package/dist/src/extensions/link-feature.js.map +1 -0
- package/dist/src/extensions/registry.d.ts +24 -4
- package/dist/src/extensions/registry.js +26 -3
- package/dist/src/extensions/registry.js.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.js +0 -1
- package/dist/src/index.js.map +1 -1
- package/dist/tests/cli/hints.test.js +5 -7
- package/dist/tests/cli/hints.test.js.map +1 -1
- package/dist/tests/driver/link-features.test.js +105 -0
- package/dist/tests/driver/link-features.test.js.map +1 -0
- package/dist/tests/driver/usage.test.d.ts +1 -0
- package/dist/tests/driver/usage.test.js +88 -0
- package/dist/tests/driver/usage.test.js.map +1 -0
- package/dist/tests/e2e/gui-audio.test.js +4 -4
- package/dist/tests/e2e/gui-audio.test.js.map +1 -1
- package/dist/tests/e2e/gui-css-coverage.test.d.ts +9 -0
- package/dist/tests/e2e/gui-css-coverage.test.js +333 -0
- package/dist/tests/e2e/gui-css-coverage.test.js.map +1 -0
- package/dist/tests/e2e/gui-css-features.test.d.ts +6 -0
- package/dist/tests/e2e/gui-css-features.test.js +270 -0
- package/dist/tests/e2e/gui-css-features.test.js.map +1 -0
- package/dist/tests/e2e/gui-effects.test.js +92 -11
- package/dist/tests/e2e/gui-effects.test.js.map +1 -1
- package/dist/tests/e2e/gui-feature-linking.test.d.ts +9 -0
- package/dist/tests/e2e/gui-feature-linking.test.js +68 -0
- package/dist/tests/e2e/gui-feature-linking.test.js.map +1 -0
- package/dist/tests/e2e/gui-font-face.test.d.ts +10 -0
- package/dist/tests/e2e/gui-font-face.test.js +142 -0
- package/dist/tests/e2e/gui-font-face.test.js.map +1 -0
- package/dist/tests/e2e/gui-fonts.test.d.ts +10 -0
- package/dist/tests/e2e/gui-fonts.test.js +150 -0
- package/dist/tests/e2e/gui-fonts.test.js.map +1 -0
- package/dist/tests/e2e/gui-helpers.d.ts +10 -1
- package/dist/tests/e2e/gui-helpers.js +6 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-layout.test.js +7 -3
- package/dist/tests/e2e/gui-layout.test.js.map +1 -1
- package/dist/tests/e2e/gui-media-disabled.test.d.ts +5 -4
- package/dist/tests/e2e/gui-media-disabled.test.js +7 -6
- package/dist/tests/e2e/gui-media-disabled.test.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.d.ts +5 -4
- package/dist/tests/e2e/gui-media.test.js +9 -9
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-paint.test.js +5 -2
- package/dist/tests/e2e/gui-paint.test.js.map +1 -1
- package/dist/tests/e2e/gui-shaping.test.d.ts +5 -0
- package/dist/tests/e2e/gui-shaping.test.js +47 -0
- package/dist/tests/e2e/gui-shaping.test.js.map +1 -0
- package/dist/tests/e2e/gui-track-sizing.test.d.ts +6 -0
- package/dist/tests/e2e/gui-track-sizing.test.js +173 -0
- package/dist/tests/e2e/gui-track-sizing.test.js.map +1 -0
- package/dist/tests/e2e/gui-transform.test.js +3 -2
- package/dist/tests/e2e/gui-transform.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl-pipeline-cache.test.d.ts +18 -0
- package/dist/tests/e2e/gui-webgl-pipeline-cache.test.js +120 -0
- package/dist/tests/e2e/gui-webgl-pipeline-cache.test.js.map +1 -0
- package/dist/tests/extensions/gui-features.test.d.ts +1 -0
- package/dist/tests/extensions/gui-features.test.js +175 -0
- package/dist/tests/extensions/gui-features.test.js.map +1 -0
- package/doc/ai/cli.md +5 -1
- package/doc/ai/extensions.md +56 -26
- package/doc/ai/troubleshooting.md +10 -7
- package/doc/ai/zh-CN/cli.md +5 -1
- package/doc/ai/zh-CN/extensions.md +48 -22
- package/doc/ai/zh-CN/troubleshooting.md +6 -5
- package/doc/gui/animation.md +39 -9
- package/doc/gui/api.md +2 -1
- package/doc/gui/build.md +137 -19
- package/doc/gui/canvas.md +1 -1
- package/doc/gui/dom.md +20 -4
- package/doc/gui/known-issues.md +63 -26
- package/doc/gui/layout.md +31 -8
- package/doc/gui/media.md +13 -7
- package/doc/gui/rendering.md +114 -39
- package/doc/gui/runtime.md +5 -0
- package/doc/gui/webgl.md +24 -6
- package/doc/gui.md +110 -47
- package/doc/implemented/cli.md +2 -0
- package/doc/implemented/extensions.md +9 -3
- package/doc/npm-package.md +4 -4
- package/doc/xbintsc.config.schema.json +10 -0
- package/doc/zh-CN/gui/animation.md +33 -10
- package/doc/zh-CN/gui/api.md +2 -1
- package/doc/zh-CN/gui/build.md +110 -16
- package/doc/zh-CN/gui/canvas.md +1 -1
- package/doc/zh-CN/gui/dom.md +16 -3
- package/doc/zh-CN/gui/known-issues.md +45 -15
- package/doc/zh-CN/gui/layout.md +23 -6
- package/doc/zh-CN/gui/media.md +11 -6
- package/doc/zh-CN/gui/rendering.md +84 -26
- package/doc/zh-CN/gui/runtime.md +3 -0
- package/doc/zh-CN/gui/webgl.md +3 -3
- package/doc/zh-CN/gui.md +92 -41
- package/doc/zh-CN/implemented/cli.md +2 -0
- package/doc/zh-CN/implemented/extensions.md +9 -3
- package/doc/zh-CN/npm-package.md +4 -3
- package/package.json +7 -7
- package/runtime/ext_gui/animation_values.cpp +425 -0
- package/runtime/ext_gui/animation_values.h +64 -0
- package/runtime/ext_gui/browser.cpp +22 -15
- package/runtime/ext_gui/browser_loop.cpp +13 -1
- package/runtime/ext_gui/canvas.h +1 -1
- package/runtime/ext_gui/canvas_raster.cpp +1 -1
- package/runtime/ext_gui/canvas_text.cpp +1 -1
- package/runtime/ext_gui/css.cpp +172 -21
- package/runtime/ext_gui/css.h +75 -4
- package/runtime/ext_gui/css_match.cpp +4 -0
- package/runtime/ext_gui/css_sheet.cpp +218 -2
- package/runtime/ext_gui/document.cpp +42 -192
- package/runtime/ext_gui/document.h +25 -12
- package/runtime/ext_gui/document_animation.cpp +428 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +15 -8
- package/runtime/ext_gui/dom_api_canvas_extra.cpp +44 -20
- package/runtime/ext_gui/dom_api_canvas_image.cpp +3 -1
- package/runtime/ext_gui/dom_api_node_read.cpp +10 -0
- package/runtime/ext_gui/dom_api_offscreen.cpp +3 -1
- package/runtime/ext_gui/dom_api_style.cpp +7 -0
- package/runtime/ext_gui/dom_api_webgl_internal.h +4 -0
- package/runtime/ext_gui/dom_api_webgl_source.cpp +5 -2
- package/runtime/ext_gui/effect_values.cpp +245 -21
- package/runtime/ext_gui/gpu_bridge.c +28 -0
- package/runtime/ext_gui/gpu_feature.cpp +30 -0
- package/runtime/ext_gui/gpu_shader.cpp +22 -0
- package/runtime/ext_gui/gpu_shader_api.h +50 -0
- package/runtime/ext_gui/gradient_values.cpp +24 -0
- package/runtime/ext_gui/grid_values.cpp +23 -0
- package/runtime/ext_gui/gui.cpp +6 -37
- package/runtime/ext_gui/gui_canvas.cpp +14 -6
- package/runtime/ext_gui/gui_cursor.cpp +50 -0
- package/runtime/ext_gui/gui_engine.h +1 -18
- package/runtime/ext_gui/gui_events.cpp +19 -6
- package/runtime/ext_gui/gui_internal.h +3 -0
- package/runtime/ext_gui/gui_webgl.cpp +25 -10
- package/runtime/ext_gui/image_api.cpp +18 -0
- package/runtime/ext_gui/image_api.h +43 -0
- package/runtime/ext_gui/image_bitmap_browser.cpp +20 -11
- package/runtime/ext_gui/image_bridge.c +22 -0
- package/runtime/ext_gui/image_feature.cpp +107 -0
- package/runtime/ext_gui/inline_svg.cpp +95 -8
- package/runtime/ext_gui/inline_svg.h +5 -1
- package/runtime/ext_gui/layout.cpp +15 -9
- package/runtime/ext_gui/layout.h +8 -2
- package/runtime/ext_gui/layout_flex.cpp +134 -29
- package/runtime/ext_gui/layout_flow.cpp +58 -7
- package/runtime/ext_gui/layout_flow_internal.h +39 -4
- package/runtime/ext_gui/layout_grid.cpp +31 -0
- package/runtime/ext_gui/layout_inline.cpp +26 -2
- package/runtime/ext_gui/layout_vertical.cpp +196 -0
- package/runtime/ext_gui/media.cpp +4 -2
- package/runtime/ext_gui/media.h +3 -3
- package/runtime/ext_gui/media_api.h +7 -6
- package/runtime/ext_gui/paint.cpp +67 -9
- package/runtime/ext_gui/paint.h +61 -8
- package/runtime/ext_gui/paint_backdrop.cpp +211 -0
- package/runtime/ext_gui/paint_background.cpp +175 -97
- package/runtime/ext_gui/paint_effects.cpp +12 -6
- package/runtime/ext_gui/paint_internal.h +27 -0
- package/runtime/ext_gui/paint_outline.cpp +44 -0
- package/runtime/ext_gui/paint_shadow.cpp +368 -0
- package/runtime/ext_gui/renderer.cpp +15 -7
- package/runtime/ext_gui/renderer.h +11 -2
- package/runtime/ext_gui/renderer_backdrop.cpp +374 -0
- package/runtime/ext_gui/renderer_bitmap.cpp +82 -0
- package/runtime/ext_gui/renderer_gradient.cpp +51 -17
- package/runtime/ext_gui/renderer_image.cpp +19 -7
- package/runtime/ext_gui/renderer_internal.h +21 -0
- package/runtime/ext_gui/renderer_layer.cpp +37 -6
- package/runtime/ext_gui/renderer_text.cpp +2 -1
- package/runtime/ext_gui/stb_truetype.h +5077 -0
- package/runtime/ext_gui/style.cpp +62 -8
- package/runtime/ext_gui/style.h +111 -4
- package/runtime/ext_gui/style_cascade.cpp +83 -0
- package/runtime/ext_gui/style_internal.h +13 -1
- package/runtime/ext_gui/style_length.cpp +92 -0
- package/runtime/ext_gui/style_print.cpp +83 -2
- package/runtime/ext_gui/style_svg.cpp +40 -0
- package/runtime/ext_gui/style_text.cpp +302 -0
- package/runtime/ext_gui/style_ui.cpp +150 -0
- package/runtime/ext_gui/style_values.cpp +76 -62
- package/runtime/ext_gui/style_values_internal.h +23 -0
- package/runtime/ext_gui/text.cpp +27 -499
- package/runtime/ext_gui/text.h +18 -9
- package/runtime/ext_gui/text_api.h +45 -0
- package/runtime/ext_gui/text_bridge.c +23 -0
- package/runtime/ext_gui/text_cache.cpp +12 -3
- package/runtime/ext_gui/text_font_db.cpp +427 -0
- package/runtime/ext_gui/text_font_paths.cpp +250 -0
- package/runtime/ext_gui/text_font_paths.h +39 -0
- package/runtime/ext_gui/text_font_sfnt.cpp +396 -0
- package/runtime/ext_gui/text_font_sfnt.h +44 -0
- package/runtime/ext_gui/text_fonts.cpp +348 -0
- package/runtime/ext_gui/text_fonts.h +78 -0
- package/runtime/ext_gui/text_fonts_internal.h +77 -0
- package/runtime/ext_gui/text_glyph_cache.cpp +2 -2
- package/runtime/ext_gui/text_hb.cpp +438 -0
- package/runtime/ext_gui/text_stb.cpp +369 -0
- package/runtime/ext_gui/transform.cpp +107 -9
- package/runtime/ext_gui/transform.h +5 -0
- package/runtime/ext_gui/webgl_api.cpp +19 -0
- package/runtime/ext_gui/webgl_api.h +53 -0
- package/runtime/ext_gui/webgl_bridge.c +25 -0
- package/runtime/ext_gui/webgl_draw_setup.cpp +42 -1
- package/runtime/ext_gui/webgl_feature.cpp +82 -0
- package/runtime/ext_gui/webgl_feature.h +28 -0
- package/runtime/ext_gui/webgl_msl.cpp +41 -0
- package/runtime/ext_gui/webgl_msl.h +6 -0
- package/runtime/ext_gui/webgl_shader.cpp +40 -32
- package/runtime/ext_gui/window.cpp +7 -7
- package/runtime/ext_media/decode_audio.cpp +1 -1
- package/runtime/ext_media/media.cpp +1 -1
- package/runtime/ext_media/media_bridge.c +7 -7
- package/scripts/build-gui.ts +97 -98
- package/scripts/check-file-length.ts +1 -0
- package/scripts/gui-build-options.ts +122 -0
- package/src/cli/extensions.ts +72 -0
- package/src/cli/help.ts +3 -1
- package/src/cli/hints.ts +9 -3
- package/src/cli/main.ts +21 -27
- package/src/diagnostics/diagnostic.ts +2 -0
- package/src/driver/build-key.ts +3 -0
- package/src/driver/compiler.ts +63 -8
- package/src/driver/config.ts +6 -0
- package/src/driver/link-features.ts +163 -0
- package/src/driver/options.ts +10 -0
- package/src/driver/runtime-objects.ts +26 -1
- package/src/driver/usage.ts +376 -0
- package/src/driver/version.ts +1 -1
- package/src/extensions/catalog.ts +1 -2
- package/src/extensions/gui/features.ts +166 -0
- package/src/extensions/gui/index.ts +10 -4
- package/src/extensions/link-feature.ts +72 -0
- package/src/extensions/registry.ts +45 -4
- package/src/index.ts +3 -2
- package/dist/src/extensions/media/index.d.ts +0 -28
- package/dist/src/extensions/media/index.js +0 -59
- package/dist/src/extensions/media/index.js.map +0 -1
- package/dist/tests/extensions/media.test.js +0 -63
- package/dist/tests/extensions/media.test.js.map +0 -1
- package/src/extensions/media/index.ts +0 -65
- /package/dist/tests/{extensions/media.test.d.ts → driver/link-features.test.d.ts} +0 -0
|
@@ -4,7 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
#include "document.h"
|
|
6
6
|
|
|
7
|
+
#include <cmath>
|
|
8
|
+
#include <string>
|
|
9
|
+
#include <utility>
|
|
10
|
+
#include <vector>
|
|
11
|
+
|
|
7
12
|
#include "perf.h"
|
|
13
|
+
#include "style_internal.h"
|
|
14
|
+
#include "text_fonts.h"
|
|
8
15
|
|
|
9
16
|
namespace xtgui {
|
|
10
17
|
|
|
@@ -30,15 +37,37 @@ void XtDocument::load(const std::string &html, float viewportWidth, float viewpo
|
|
|
30
37
|
dirty_ = false;
|
|
31
38
|
hover_ = nullptr;
|
|
32
39
|
focus_ = nullptr;
|
|
40
|
+
active_ = nullptr;
|
|
33
41
|
styles_.clear();
|
|
34
42
|
display_.clear();
|
|
35
43
|
transitions_.clear();
|
|
44
|
+
animations_.clear();
|
|
36
45
|
mediaSizes_.clear();
|
|
37
46
|
canvasInfo_.clear();
|
|
38
47
|
clock_ms_ = 0.0;
|
|
39
48
|
std::string css;
|
|
40
49
|
collectStyleText(root_.get(), &css);
|
|
41
50
|
sheet_ = xt_css_parse_stylesheet(css);
|
|
51
|
+
|
|
52
|
+
/* Author `@font-face` families are global to the process's text stack, so a
|
|
53
|
+
* new document replaces the previous set before its first layout. */
|
|
54
|
+
std::vector<UserFontFace> user_faces;
|
|
55
|
+
user_faces.reserve(sheet_.font_faces.size());
|
|
56
|
+
for (const FontFaceRule &rule : sheet_.font_faces) {
|
|
57
|
+
UserFontFace face;
|
|
58
|
+
face.family = rule.family;
|
|
59
|
+
face.sources.reserve(rule.sources.size());
|
|
60
|
+
for (const FontFaceSource &source : rule.sources) {
|
|
61
|
+
face.sources.push_back(UserFontSource{source.url, source.format});
|
|
62
|
+
}
|
|
63
|
+
face.has_weight = rule.has_weight;
|
|
64
|
+
face.weight_min = rule.weight_min;
|
|
65
|
+
face.weight_max = rule.weight_max;
|
|
66
|
+
face.has_italic = rule.has_italic;
|
|
67
|
+
face.italic = rule.italic;
|
|
68
|
+
user_faces.push_back(std::move(face));
|
|
69
|
+
}
|
|
70
|
+
xt_font_set_user_faces(user_faces);
|
|
42
71
|
restyle(viewportWidth, viewportHeight);
|
|
43
72
|
}
|
|
44
73
|
|
|
@@ -50,206 +79,19 @@ void XtDocument::restyle(float viewportWidth, float viewportHeight) {
|
|
|
50
79
|
MatchState state;
|
|
51
80
|
state.hover = hover_;
|
|
52
81
|
state.focus = focus_;
|
|
82
|
+
state.active = active_;
|
|
53
83
|
bool hasTransitions = sheet_.has_transitions;
|
|
84
|
+
bool hasAnimations = sheet_.has_animations;
|
|
54
85
|
xt_style_compute(root_.get(), sheet_, styles_, viewportWidth, viewportHeight, state, &pseudos_,
|
|
55
|
-
&hasTransitions);
|
|
86
|
+
&hasTransitions, &hasAnimations);
|
|
56
87
|
has_transitions_ = hasTransitions;
|
|
88
|
+
has_animations_ = hasAnimations;
|
|
57
89
|
startTransitions();
|
|
90
|
+
startAnimations();
|
|
58
91
|
updateDisplay();
|
|
59
92
|
}
|
|
60
93
|
}
|
|
61
94
|
|
|
62
|
-
namespace {
|
|
63
|
-
|
|
64
|
-
float easeProgress(float t, TimingFunction timing) {
|
|
65
|
-
if (t <= 0.0f) return 0.0f;
|
|
66
|
-
if (t >= 1.0f) return 1.0f;
|
|
67
|
-
switch (timing) {
|
|
68
|
-
case TimingFunction::Linear:
|
|
69
|
-
return t;
|
|
70
|
-
case TimingFunction::EaseIn:
|
|
71
|
-
return t * t * t;
|
|
72
|
-
case TimingFunction::EaseOut: {
|
|
73
|
-
float u = 1.0f - t;
|
|
74
|
-
return 1.0f - u * u * u;
|
|
75
|
-
}
|
|
76
|
-
case TimingFunction::EaseInOut:
|
|
77
|
-
return t < 0.5f ? 4.0f * t * t * t : 1.0f - 4.0f * (1.0f - t) * (1.0f - t) * (1.0f - t);
|
|
78
|
-
case TimingFunction::Ease:
|
|
79
|
-
default:
|
|
80
|
-
return t * t * (3.0f - 2.0f * t); // smoothstep approximation of `ease`
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
float mix(float a, float b, float t) { return a + (b - a) * t; }
|
|
85
|
-
|
|
86
|
-
const float *colorOf(const XtStyle &style, const std::string &property) {
|
|
87
|
-
static const float transparent[4] = {0, 0, 0, 0};
|
|
88
|
-
if (property == "background-color") {
|
|
89
|
-
return style.has_background ? &style.background.r : transparent;
|
|
90
|
-
}
|
|
91
|
-
if (property == "border-color") {
|
|
92
|
-
return style.has_border_color ? &style.border_color.r : transparent;
|
|
93
|
-
}
|
|
94
|
-
return &style.color.r;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
float numberOf(const XtStyle &style, const std::string &property) {
|
|
98
|
-
if (property == "border-radius") return style.border_radius;
|
|
99
|
-
return 0.0f;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
bool isNumberProperty(const std::string &property) { return property == "border-radius"; }
|
|
103
|
-
|
|
104
|
-
bool specMatches(const std::string &spec, const std::string &property) {
|
|
105
|
-
return spec == "all" || spec == property;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
void applyColor(XtStyle *style, const std::string &property, const float *rgba) {
|
|
109
|
-
if (property == "background-color") {
|
|
110
|
-
style->background = Color{rgba[0], rgba[1], rgba[2], rgba[3], true};
|
|
111
|
-
style->has_background = rgba[3] > 0.0f;
|
|
112
|
-
} else if (property == "border-color") {
|
|
113
|
-
style->border_color = Color{rgba[0], rgba[1], rgba[2], rgba[3], true};
|
|
114
|
-
style->has_border_color = rgba[3] > 0.0f;
|
|
115
|
-
} else {
|
|
116
|
-
style->color = Color{rgba[0], rgba[1], rgba[2], rgba[3], true};
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
void applyNumber(XtStyle *style, const std::string &property, float value) {
|
|
121
|
-
if (property == "border-radius") style->border_radius = value;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
} // namespace
|
|
125
|
-
|
|
126
|
-
void XtDocument::startTransitions() {
|
|
127
|
-
if (display_.empty()) return; // first style computation: nothing to animate from
|
|
128
|
-
/* Without a `transition` declaration anywhere in the sheet (or in an inline
|
|
129
|
-
* style) no transition can start, so skip the O(nodes) scan `restyle` would
|
|
130
|
-
* otherwise do every time. */
|
|
131
|
-
if (!has_transitions_) return;
|
|
132
|
-
static const char *const kProperties[] = {"background-color", "color", "border-color",
|
|
133
|
-
"border-radius", "transform"};
|
|
134
|
-
for (auto &entry : styles_) {
|
|
135
|
-
const Node *node = entry.first;
|
|
136
|
-
const XtStyle &target = entry.second;
|
|
137
|
-
/* Generated boxes are rebuilt on every restyle; a transition keyed by one
|
|
138
|
-
* would address a node that no longer exists. */
|
|
139
|
-
if (node->is_pseudo) continue;
|
|
140
|
-
if (target.transitions.empty()) continue;
|
|
141
|
-
auto prev_it = display_.find(node);
|
|
142
|
-
if (prev_it == display_.end()) continue;
|
|
143
|
-
const XtStyle ¤t = prev_it->second;
|
|
144
|
-
for (const TransitionSpec &spec : target.transitions) {
|
|
145
|
-
if (spec.duration <= 0.0f) continue;
|
|
146
|
-
for (const char *property : kProperties) {
|
|
147
|
-
if (!specMatches(spec.property, property)) continue;
|
|
148
|
-
ActiveTransition running;
|
|
149
|
-
running.node = node;
|
|
150
|
-
running.property = property;
|
|
151
|
-
running.timing = spec.timing;
|
|
152
|
-
running.duration_ms = spec.duration * 1000.0f;
|
|
153
|
-
running.delay_ms = spec.delay * 1000.0f;
|
|
154
|
-
running.start_ms = (float)clock_ms_ + running.delay_ms;
|
|
155
|
-
if (std::string(property) == "transform") {
|
|
156
|
-
if (xt_transform_equal(current.transform, target.transform)) continue;
|
|
157
|
-
std::vector<TransformOp> probe;
|
|
158
|
-
/* Lists of a different shape (or with clashing units) cannot be
|
|
159
|
-
* mixed; such a change snaps instead of animating. */
|
|
160
|
-
if (!xt_transform_interpolate(current.transform, target.transform, 0.5f, &probe)) {
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
running.is_transform = true;
|
|
164
|
-
running.from_transform = current.transform;
|
|
165
|
-
running.to_transform = target.transform;
|
|
166
|
-
} else if (isNumberProperty(property)) {
|
|
167
|
-
float from = numberOf(current, property);
|
|
168
|
-
float to = numberOf(target, property);
|
|
169
|
-
if (from == to) continue;
|
|
170
|
-
running.is_color = false;
|
|
171
|
-
running.from_number = from;
|
|
172
|
-
running.to_number = to;
|
|
173
|
-
} else {
|
|
174
|
-
const float *from = colorOf(current, property);
|
|
175
|
-
const float *to = colorOf(target, property);
|
|
176
|
-
if (from[0] == to[0] && from[1] == to[1] && from[2] == to[2] && from[3] == to[3]) continue;
|
|
177
|
-
running.is_color = true;
|
|
178
|
-
for (int i = 0; i < 4; i++) {
|
|
179
|
-
running.from_color[i] = from[i];
|
|
180
|
-
running.to_color[i] = to[i];
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
/* Retarget an existing transition (mid-flight) instead of stacking. */
|
|
184
|
-
bool replaced = false;
|
|
185
|
-
for (ActiveTransition &existing : transitions_) {
|
|
186
|
-
if (existing.node == node && existing.property == property) {
|
|
187
|
-
existing = running;
|
|
188
|
-
replaced = true;
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
if (!replaced) transitions_.push_back(running);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
void XtDocument::updateDisplay() {
|
|
199
|
-
/* Without a `transition` declaration in the sheet (or an inline style) no
|
|
200
|
-
* transition can ever start, so the displayed style *is* the cascade result:
|
|
201
|
-
* skip the per-node deep copy of the whole style map (and keep `display_`
|
|
202
|
-
* empty, which `styleOf` already falls back from). */
|
|
203
|
-
if (!has_transitions_) {
|
|
204
|
-
if (!transitions_.empty()) transitions_.clear();
|
|
205
|
-
if (!display_.empty()) display_.clear();
|
|
206
|
-
layout_.compute(root_.get(), styles_, viewportWidth_, viewportHeight_, &mediaSizes_,
|
|
207
|
-
&canvasInfo_);
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
display_ = styles_;
|
|
211
|
-
for (size_t i = 0; i < transitions_.size();) {
|
|
212
|
-
ActiveTransition &transition = transitions_[i];
|
|
213
|
-
auto node_it = display_.find(transition.node);
|
|
214
|
-
if (node_it == display_.end()) {
|
|
215
|
-
transitions_.erase(transitions_.begin() + (long)i);
|
|
216
|
-
continue;
|
|
217
|
-
}
|
|
218
|
-
float elapsed = (float)clock_ms_ - transition.start_ms;
|
|
219
|
-
float progress = transition.duration_ms > 0.0f ? elapsed / transition.duration_ms : 1.0f;
|
|
220
|
-
if (progress > 1.0f) progress = 1.0f;
|
|
221
|
-
float eased = easeProgress(progress, transition.timing);
|
|
222
|
-
XtStyle &style = node_it->second;
|
|
223
|
-
if (transition.is_transform) {
|
|
224
|
-
std::vector<TransformOp> mixed;
|
|
225
|
-
if (xt_transform_interpolate(transition.from_transform, transition.to_transform, eased,
|
|
226
|
-
&mixed)) {
|
|
227
|
-
style.transform = mixed;
|
|
228
|
-
}
|
|
229
|
-
} else if (transition.is_color) {
|
|
230
|
-
float rgba[4];
|
|
231
|
-
for (int c = 0; c < 4; c++) rgba[c] = mix(transition.from_color[c], transition.to_color[c], eased);
|
|
232
|
-
applyColor(&style, transition.property, rgba);
|
|
233
|
-
} else {
|
|
234
|
-
applyNumber(&style, transition.property, mix(transition.from_number, transition.to_number, eased));
|
|
235
|
-
}
|
|
236
|
-
if (progress >= 1.0f) {
|
|
237
|
-
transitions_.erase(transitions_.begin() + (long)i);
|
|
238
|
-
} else {
|
|
239
|
-
i++;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
layout_.compute(root_.get(), display_, viewportWidth_, viewportHeight_, &mediaSizes_,
|
|
243
|
-
&canvasInfo_);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
bool XtDocument::advance(double delta_ms) {
|
|
247
|
-
clock_ms_ += delta_ms;
|
|
248
|
-
if (transitions_.empty()) return false;
|
|
249
|
-
updateDisplay();
|
|
250
|
-
return true;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
95
|
bool XtDocument::setHover(const Node *node) {
|
|
254
96
|
if (hover_ == node) return false;
|
|
255
97
|
hover_ = node;
|
|
@@ -267,6 +109,14 @@ bool XtDocument::setFocus(const Node *node) {
|
|
|
267
109
|
return true;
|
|
268
110
|
}
|
|
269
111
|
|
|
112
|
+
bool XtDocument::setActive(const Node *node) {
|
|
113
|
+
if (active_ == node) return false;
|
|
114
|
+
active_ = node;
|
|
115
|
+
if (!sheet_.has_active) return false;
|
|
116
|
+
restyle(viewportWidth_, viewportHeight_);
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
|
|
270
120
|
const XtStyle *XtDocument::styleOf(const Node *node) const {
|
|
271
121
|
auto it = display_.find(node);
|
|
272
122
|
if (it != display_.end()) return &it->second;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
#include <unordered_map>
|
|
14
14
|
#include <vector>
|
|
15
15
|
|
|
16
|
+
#include "animation_values.h"
|
|
16
17
|
#include "css.h"
|
|
17
18
|
#include "dom.h"
|
|
18
19
|
#include "layout.h"
|
|
@@ -20,22 +21,24 @@
|
|
|
20
21
|
|
|
21
22
|
namespace xtgui {
|
|
22
23
|
|
|
23
|
-
/** A running CSS transition
|
|
24
|
+
/** A running CSS transition. */
|
|
24
25
|
struct ActiveTransition {
|
|
25
26
|
const Node *node = nullptr;
|
|
26
27
|
std::string property;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
float from_color[4] = {0, 0, 0, 0};
|
|
30
|
-
float to_color[4] = {0, 0, 0, 0};
|
|
31
|
-
float from_number = 0;
|
|
32
|
-
float to_number = 0;
|
|
33
|
-
std::vector<TransformOp> from_transform;
|
|
34
|
-
std::vector<TransformOp> to_transform;
|
|
28
|
+
AnimatableValue from;
|
|
29
|
+
AnimatableValue to;
|
|
35
30
|
float start_ms = 0; // when interpolation begins (after `delay`)
|
|
36
31
|
float duration_ms = 0;
|
|
37
32
|
float delay_ms = 0;
|
|
38
|
-
TimingFunction timing
|
|
33
|
+
TimingFunction timing;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** A running `@keyframes` animation on one element. */
|
|
37
|
+
struct ActiveAnimation {
|
|
38
|
+
const Node *node = nullptr;
|
|
39
|
+
std::string name;
|
|
40
|
+
AnimationSpec spec;
|
|
41
|
+
float start_ms = 0;
|
|
39
42
|
};
|
|
40
43
|
|
|
41
44
|
class XtDocument {
|
|
@@ -48,17 +51,21 @@ class XtDocument {
|
|
|
48
51
|
* and layout when a transition is running. Returns true when anything
|
|
49
52
|
* transitioned (the caller should repaint). */
|
|
50
53
|
bool advance(double delta_ms);
|
|
51
|
-
/** True while at least one transition is running. */
|
|
52
|
-
bool animating() const { return !transitions_.empty(); }
|
|
54
|
+
/** True while at least one transition or animation is running. */
|
|
55
|
+
bool animating() const { return !transitions_.empty() || !animations_.empty(); }
|
|
53
56
|
/** Set the hovered/focused element; restyles when it changed. Returns true
|
|
54
57
|
* when the dynamic state (and therefore the styles) changed. */
|
|
55
58
|
bool setHover(const Node *node);
|
|
56
59
|
bool setFocus(const Node *node);
|
|
60
|
+
/** Element held down by the primary pointer (`:active`). */
|
|
61
|
+
bool setActive(const Node *node);
|
|
57
62
|
const Node *hover() const { return hover_; }
|
|
58
63
|
const Node *focus() const { return focus_; }
|
|
64
|
+
const Node *active() const { return active_; }
|
|
59
65
|
|
|
60
66
|
const Node *root() const { return root_.get(); }
|
|
61
67
|
const StyleSheet &sheet() const { return sheet_; }
|
|
68
|
+
const std::unordered_map<const Node *, XtStyle> &styles() const { return styles_; }
|
|
62
69
|
const XtStyle *styleOf(const Node *node) const;
|
|
63
70
|
const LayoutBox *boxOf(const Node *node) const;
|
|
64
71
|
const LayoutTree &layout() const { return layout_; }
|
|
@@ -117,7 +124,9 @@ class XtDocument {
|
|
|
117
124
|
private:
|
|
118
125
|
void collectStyleText(const Node *node, std::string *out) const;
|
|
119
126
|
void startTransitions();
|
|
127
|
+
void startAnimations();
|
|
120
128
|
void updateDisplay();
|
|
129
|
+
void applyAnimations(std::unordered_map<const Node *, XtStyle> *out);
|
|
121
130
|
|
|
122
131
|
std::unique_ptr<Node> root_;
|
|
123
132
|
/** Detached nodes (created or removed) stay alive here so handles remain valid. */
|
|
@@ -131,14 +140,18 @@ class XtDocument {
|
|
|
131
140
|
MediaSizeMap mediaSizes_; // `<video>` intrinsic sizes
|
|
132
141
|
CanvasInfoMap canvasInfo_; // `<canvas>` sizes + ids
|
|
133
142
|
std::vector<ActiveTransition> transitions_;
|
|
143
|
+
std::vector<ActiveAnimation> animations_;
|
|
134
144
|
/** Whether any computed style declares a `transition` (from the sheet or an
|
|
135
145
|
* inline `style="…"`): when false the document skips the transition snapshot
|
|
136
146
|
* and `display_` stays empty. */
|
|
137
147
|
bool has_transitions_ = false;
|
|
148
|
+
/** Whether any computed style declares an `animation`. */
|
|
149
|
+
bool has_animations_ = false;
|
|
138
150
|
double clock_ms_ = 0.0;
|
|
139
151
|
LayoutTree layout_;
|
|
140
152
|
const Node *hover_ = nullptr;
|
|
141
153
|
const Node *focus_ = nullptr;
|
|
154
|
+
const Node *active_ = nullptr;
|
|
142
155
|
float viewportWidth_ = 0.0f;
|
|
143
156
|
float viewportHeight_ = 0.0f;
|
|
144
157
|
};
|