diff --git a/libc3/c3.c b/libc3/c3.c
index 7f45d23..7d02020 100644
--- a/libc3/c3.c
+++ b/libc3/c3.c
@@ -42,6 +42,11 @@ void c3_clean (s_env *env)
sym_delete_all();
}
+void c3_exit (sw code)
+{
+ exit((int) code);
+}
+
void c3_init (s_env *env)
{
if (! env)
diff --git a/libc3/sequence.c b/libc3/sequence.c
index 6f44e99..60f22c1 100644
--- a/libc3/sequence.c
+++ b/libc3/sequence.c
@@ -14,11 +14,13 @@
#include "sequence.h"
s_sequence * sequence_init (s_sequence *sequence, f64 duration,
- const s8 *title)
+ const s8 *title,
+ f_sequence_render render)
{
assert(sequence);
sequence->t = 0.0;
sequence->duration = duration;
sequence->title = title;
+ sequence->render = render;
return sequence;
}
diff --git a/libc3/sequence.h b/libc3/sequence.h
index ba07dbc..dbccd4b 100644
--- a/libc3/sequence.h
+++ b/libc3/sequence.h
@@ -16,6 +16,7 @@
#include "types.h"
s_sequence * sequence_init (s_sequence *sequence, f64 duration,
- const s8 *title);
+ const s8 *title,
+ f_sequence_render render);
#endif /* LIBC3_SEQUENCE_H */
diff --git a/libc3/tag.c b/libc3/tag.c
index c9bde05..203a31f 100644
--- a/libc3/tag.c
+++ b/libc3/tag.c
@@ -3804,6 +3804,24 @@ s_tag * tag_init_list_1 (s_tag *tag, const s8 *p)
return tag;
}
+s_tag * tag_init_map (s_tag *tag, uw count)
+{
+ assert(tag);
+ tag->type = TAG_MAP;
+ if (! map_init(&tag->data.map, count))
+ return NULL;
+ return tag;
+}
+
+s_tag * tag_init_map_1 (s_tag *tag, const s8 *p)
+{
+ assert(tag);
+ tag->type = TAG_MAP;
+ if (! map_init_1(&tag->data.map, p))
+ return NULL;
+ return tag;
+}
+
s_tag * tag_init_s8 (s_tag *tag, s8 i)
{
assert(tag);
diff --git a/libc3/tag.h b/libc3/tag.h
index 1712a8e..84ef805 100644
--- a/libc3/tag.h
+++ b/libc3/tag.h
@@ -44,6 +44,8 @@ s_tag * tag_init_integer_1 (s_tag *tag, const s8 *p);
s_tag * tag_init_integer_zero (s_tag *tag);
s_tag * tag_init_list (s_tag *tag, s_list *list);
s_tag * tag_init_list_1 (s_tag *tag, const s8 *p);
+s_tag * tag_init_map (s_tag *tag, uw count);
+s_tag * tag_init_map_1 (s_tag *tag, const s8 *p);
s_tag * tag_init_str (s_tag *tag, s8 *free, uw size, const s8 *p);
s_tag * tag_init_str_1 (s_tag *tag, s8 *free, const s8 *p);
s_tag * tag_init_sym (s_tag *tag, const s_sym *p);
diff --git a/libc3/types.h b/libc3/types.h
index cc26265..c9e31f4 100644
--- a/libc3/types.h
+++ b/libc3/types.h
@@ -181,6 +181,8 @@ typedef sw (* f_buf_inspect) (s_buf *buf, const void *x);
typedef sw (* f_buf_inspect_size) (const void *x);
typedef sw (* f_buf_parse) (s_buf *buf, void *dest);
typedef void * (* f_copy) (const void *a, void *b);
+typedef void (* f_sequence_render) (void *window, void *render_context,
+ s_sequence *seq);
#define CHARACTER_MAX S32_MAX
#define SKIPLIST_HEIGHT_MAX U64_MAX
@@ -255,14 +257,6 @@ struct quote {
s_tag *tag;
};
-struct sequence {
- f64 t;
- f64 duration;
- s_time t0;
- const s8 *title;
- void *data;
-};
-
struct struct_ {
void *data;
uw count;
@@ -459,6 +453,16 @@ struct list {
s_tag next;
};
+struct sequence {
+ s_tag data;
+ f64 dt;
+ f64 duration;
+ f_sequence_render render;
+ f64 t;
+ s_time t0;
+ const s8 *title;
+};
+
#define TYPEDEF_SET_ITEM(name, type) \
typedef struct set_item__##name s_set_item__##name; \
\
diff --git a/libc3/window/cairo/c3_window_cairo_demo.c b/libc3/window/cairo/c3_window_cairo_demo.c
index 78c1d06..732857b 100644
--- a/libc3/window/cairo/c3_window_cairo_demo.c
+++ b/libc3/window/cairo/c3_window_cairo_demo.c
@@ -13,11 +13,13 @@
#include <assert.h>
#include <math.h>
#include <stdio.h>
+#include <stdlib.h>
#include <time.h>
#include <libc3/c3.h>
#include <cairo/cairo.h>
#include <xkbcommon/xkbcommon.h>
#include "../window.h"
+#include "window_cairo.h"
#include "c3_window_cairo_demo.h"
#include "types.h"
@@ -64,7 +66,12 @@ bool c3_window_cairo_demo_load (s_window_cairo *window)
{
assert(window->sequence_count ==
LIBC3_WINDOW_CAIRO_DEMO_SEQUENCE_COUNT);
- sequence_init(window->sequence, 8.0, "01. Background rectangles");
+ window_cairo_sequence_init(window->sequence, 8.0,
+ "01. Background rectangles",
+ c3_window_cairo_demo_render_bg_rect);
+ window_cairo_sequence_init(window->sequence + 1, 30.0,
+ "02. Lightspeed",
+ c3_window_cairo_demo_render_lightspeed);
window_set_sequence_pos((s_window *) window, 0);
return true;
}
@@ -79,16 +86,7 @@ bool c3_window_cairo_demo_render (s_window_cairo *window,
if (! window_animate((s_window *) window))
return false;
seq = window->sequence + window->sequence_pos;
- /* background */
- switch (window->sequence_pos) {
- case 0:
- c3_window_cairo_demo_render_bg_rect(window, cr, seq);
- break;
- default:
- cairo_set_source_rgb(cr, 1, 1, 1);
- cairo_rectangle(cr, 0, 0, window->w, window->h);
- cairo_fill(cr);
- }
+ seq->render(window, cr, seq);
/* text */
cairo_set_font_size(cr, 20);
cairo_select_font_face(cr, "Courier New",
@@ -162,6 +160,76 @@ void c3_window_cairo_demo_render_bg_rect (s_window_cairo *window,
cairo_fill(cr);
}
+f64 frandom (void)
+{
+ return (double) random() / (((sw) 1 << 31) - 1);
+}
+
+static void star_init (s_tag *star)
+{
+ tag_init_map(star, 3);
+ tag_init_sym(star->data.map.keys, sym_1("speed"));
+ tag_init_f64(star->data.map.values, 0.0);
+ tag_init_sym(star->data.map.keys + 1, sym_1("x"));
+ tag_init_f64(star->data.map.values + 1, 2.0 * frandom() - 1.0);
+ tag_init_sym(star->data.map.keys + 2, sym_1("y"));
+ tag_init_f64(star->data.map.values + 2, 2.0 * frandom() - 1.0);
+}
+
+static void star_render (s_tag *star, s_window_cairo *window,
+ cairo_t *cr, s_sequence *seq)
+{
+ f64 q;
+ f64 *speed;
+ f64 *x;
+ f64 *y;
+ (void) window;
+ speed = &star->data.map.values[0].data.f64;
+ x = &star->data.map.values[1].data.f64;
+ y = &star->data.map.values[2].data.f64;
+ cairo_set_line_width(cr, 0.01);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_move_to(cr, *x, *y);
+ q = (1 + *speed / 10);
+ cairo_line_to(cr, *x * q, *y * q);
+ cairo_stroke(cr);
+ q = (1 + *speed / 1000);
+ printf("%%{speed: %f, x: %f, y: %f}\n", *speed, *x, *y);
+ *x = *x * q;
+ *y = *y * q;
+ *speed += seq->dt;
+ if (*x < -1.0 || *x > 1.0 || *y < -1.0 || *y > 1.0)
+ star_init(star);
+}
+
+void c3_window_cairo_demo_render_lightspeed (s_window_cairo *window,
+ cairo_t *cr,
+ s_sequence *seq)
+{
+ uw i;
+ cairo_matrix_t matrix;
+ cairo_get_matrix(cr, &matrix);
+ cairo_scale(cr, window->w / 2.0, window->h / 2.0);
+ cairo_translate(cr, 1.0, 1.0);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_rectangle(cr, -1, -1, 2, 2);
+ cairo_fill(cr);
+ if (seq->data.type == TAG_VOID) {
+ tag_init_tuple(&seq->data, C3_WINDOW_CAIRO_DEMO_LIGHTSPEED_STARS);
+ i = 0;
+ while (i < C3_WINDOW_CAIRO_DEMO_LIGHTSPEED_STARS) {
+ star_init(seq->data.data.tuple.tag + i);
+ i++;
+ }
+ }
+ i = 0;
+ while (i < C3_WINDOW_CAIRO_DEMO_LIGHTSPEED_STARS) {
+ star_render(seq->data.data.tuple.tag + i, window, cr, seq);
+ i++;
+ }
+ cairo_set_matrix(cr, &matrix);
+}
+
bool c3_window_cairo_demo_resize (s_window_cairo *window,
uw w, uw h)
{
diff --git a/libc3/window/cairo/c3_window_cairo_demo.h b/libc3/window/cairo/c3_window_cairo_demo.h
index 6b1d25b..121546d 100644
--- a/libc3/window/cairo/c3_window_cairo_demo.h
+++ b/libc3/window/cairo/c3_window_cairo_demo.h
@@ -16,7 +16,8 @@
#include <libc3/types.h>
#include "types.h"
-#define LIBC3_WINDOW_CAIRO_DEMO_SEQUENCE_COUNT 1
+#define C3_WINDOW_CAIRO_DEMO_SEQUENCE_COUNT 2
+#define C3_WINDOW_CAIRO_DEMO_LIGHTSPEED_STARS 100
bool c3_window_cairo_demo_button (s_window_cairo *window, u8 button,
sw x, sw y);
@@ -26,6 +27,9 @@ bool c3_window_cairo_demo_render (s_window_cairo *window, cairo_t *cr);
void c3_window_cairo_demo_render_bg_rect (s_window_cairo *window,
cairo_t *cr,
s_sequence *seq);
+void c3_window_cairo_demo_render_lightspeed (s_window_cairo *window,
+ cairo_t *cr,
+ s_sequence *seq);
bool c3_window_cairo_demo_resize (s_window_cairo *window, uw w, uw h);
#endif /* LIBC3_WINDOW_CAIRO_DEMO_H */
diff --git a/libc3/window/cairo/quartz/demo/c3_window_cairo_quartz_demo.c b/libc3/window/cairo/quartz/demo/c3_window_cairo_quartz_demo.c
index 52bc4e9..26ee3ee 100644
--- a/libc3/window/cairo/quartz/demo/c3_window_cairo_quartz_demo.c
+++ b/libc3/window/cairo/quartz/demo/c3_window_cairo_quartz_demo.c
@@ -23,7 +23,7 @@ int main (void)
s_window_cairo window;
window_cairo_init(&window, 0, 0, 800, 600,
"C3.Window.Cairo.Quartz demo",
- LIBC3_WINDOW_CAIRO_DEMO_SEQUENCE_COUNT);
+ C3_WINDOW_CAIRO_DEMO_SEQUENCE_COUNT);
window.button = c3_window_cairo_demo_button;
window.key = c3_window_cairo_demo_key;
window.load = c3_window_cairo_demo_load;
diff --git a/libc3/window/cairo/types.h b/libc3/window/cairo/types.h
index eebc778..4fbd360 100644
--- a/libc3/window/cairo/types.h
+++ b/libc3/window/cairo/types.h
@@ -44,6 +44,10 @@ typedef bool (*f_window_cairo_motion) (s_window_cairo *window, sw x,
typedef bool (*f_window_cairo_render) (s_window_cairo *window,
cairo_t *cr);
+typedef void (*f_window_cairo_render_sequence) (s_window_cairo *window,
+ cairo_t *cr,
+ s_sequence *seq);
+
/* return false to break event loop */
typedef bool (*f_window_cairo_resize) (s_window_cairo *window,
uw w, uw h);
diff --git a/libc3/window/cairo/window_cairo.c b/libc3/window/cairo/window_cairo.c
index fa64378..ca9d276 100644
--- a/libc3/window/cairo/window_cairo.c
+++ b/libc3/window/cairo/window_cairo.c
@@ -98,3 +98,15 @@ bool window_cairo_resize_default (s_window_cairo *window, uw w, uw h)
printf("window_cairo_resize_default: %lu x %lu\n", w, h);
return true;
}
+
+s_sequence * window_cairo_sequence_init
+(s_sequence *sequence, f64 duration, const s8 *title,
+ f_window_cairo_render_sequence render)
+{
+ assert(sequence);
+ sequence->t = 0.0;
+ sequence->duration = duration;
+ sequence->title = title;
+ sequence->render = (f_sequence_render) render;
+ return sequence;
+}
diff --git a/libc3/window/cairo/window_cairo.h b/libc3/window/cairo/window_cairo.h
index c7e0745..70b0b34 100644
--- a/libc3/window/cairo/window_cairo.h
+++ b/libc3/window/cairo/window_cairo.h
@@ -21,6 +21,10 @@ s_window_cairo * window_cairo_init (s_window_cairo *window,
uw sequence_count);
bool window_cairo_run (s_window_cairo *window);
+s_sequence * window_cairo_sequence_init
+(s_sequence *sequence, f64 duration, const s8 *title,
+ f_window_cairo_render_sequence render);
+
/* callbacks */
bool window_cairo_button_default (s_window_cairo *window, u8 button,
sw x, sw y);
diff --git a/libc3/window/cairo/xcb/demo/c3_window_cairo_xcb_demo.c b/libc3/window/cairo/xcb/demo/c3_window_cairo_xcb_demo.c
index a145c6d..ec4e6db 100644
--- a/libc3/window/cairo/xcb/demo/c3_window_cairo_xcb_demo.c
+++ b/libc3/window/cairo/xcb/demo/c3_window_cairo_xcb_demo.c
@@ -22,7 +22,7 @@ int main (void)
s_window_cairo window;
window_cairo_init(&window, 0, 0, 800, 600,
"C3.Window.Cairo.XCB demo",
- LIBC3_WINDOW_CAIRO_DEMO_SEQUENCE_COUNT);
+ C3_WINDOW_CAIRO_DEMO_SEQUENCE_COUNT);
window.button = c3_window_cairo_demo_button;
window.key = c3_window_cairo_demo_key;
window.load = c3_window_cairo_demo_load;
diff --git a/libc3/window/window.c b/libc3/window/window.c
index b5714cf..10102c1 100644
--- a/libc3/window/window.c
+++ b/libc3/window/window.c
@@ -33,6 +33,7 @@ bool window_animate (s_window *window)
seq = window->sequence + window->sequence_pos;
time_sub(&clock_monotonic, &seq->t0, &delta);
time_to_f64(&delta, &t);
+ seq->dt = t - seq->t;
seq->t = t;
/* printf("window_animate: %f\n", t); */
if (t > seq->duration &&