Commit 19d20afc51f96ae42d5ff03600a0a73d85961f80

Thomas de Grivel 2023-11-23T11:41:27

demo

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 &&