Commit fad65d4858fa61714e6378806087750873b5027c

Thomas de Grivel 2024-02-26T20:46:11

fix segv

diff --git a/libc3/window/sdl2/demo/matrix.c b/libc3/window/sdl2/demo/matrix.c
index 827b089..b91e7a4 100644
--- a/libc3/window/sdl2/demo/matrix.c
+++ b/libc3/window/sdl2/demo/matrix.c
@@ -28,8 +28,11 @@ static s_gl_sprite g_matrix_shade = {0};
 static f64         g_matrix_time;
 
 void matrix_column_clean (s_tag *tag);
-bool matrix_column_init (s_sequence *seq, s_tag *tag, f32 x);
+bool matrix_column_init (s_sequence *seq, s_tag *tag);
 bool matrix_column_render (s_sequence *seq, s_tag *tag);
+void matrix_screen_clean (s_tag *tag);
+bool matrix_screen_init (s_tag *tag);
+bool matrix_screen_render (s_sequence *seq, s_tag *tag);
 void matrix_text_clean (s_tag *tag);
 bool matrix_text_init (s_tag *tag, f32 y);
 bool matrix_text_render (s_sequence *seq, const s_tag *tag, f32 **py);
@@ -50,11 +53,10 @@ void matrix_column_clean (s_tag *tag)
   }
 }
 
-bool matrix_column_init (s_sequence *seq, s_tag *tag, f32 x)
+bool matrix_column_init (s_sequence *seq, s_tag *tag)
 {
   s_list *list;
   s_window_sdl2 *window;
-  (void) x;
   assert(seq);
   window = seq->window;
   assert(window);
@@ -78,7 +80,8 @@ bool matrix_column_render (s_sequence *seq, s_tag *tag)
   assert(glGetError() == GL_NO_ERROR);
   window = seq->window;
   assert(window);
-  if (tag->type != TAG_LIST) {
+  if (!tag ||
+      tag->type != TAG_LIST) {
     err_puts("matrix_column_render: invalid tag");
     assert(! "matrix_column_render: invalid tag");
     return false;
@@ -117,7 +120,7 @@ bool matrix_load (s_sequence *seq)
                      point_per_pixel))
     return false;
   gl_font_set_size(&g_matrix_font, MATRIX_FONT_SIZE);
-  if (! matrix_column_init(seq, &seq->tag, 0))
+  if (! matrix_screen_init(&seq->tag))
     return false;
   if (! gl_sprite_init(&g_matrix_shade,
                        "img/matrix_shade.png",
@@ -133,13 +136,82 @@ bool matrix_render (s_sequence *seq)
   glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
   glClear(GL_COLOR_BUFFER_BIT);
   assert(glGetError() == GL_NO_ERROR);
-  matrix_column_render(seq, &seq->tag);
+  matrix_screen_render(seq, &seq->tag);
   assert(glGetError() == GL_NO_ERROR);
   if (seq->t - g_matrix_time > MATRIX_TIME)
     g_matrix_time = seq->t;
   return true;
 }
 
+void matrix_screen_clean (s_tag *tag)
+{
+  s_list *list;
+  if (! tag ||
+      tag->type != TAG_LIST) {
+    err_puts("matrix_screen_clean: invalid tag");
+    assert(! "matrix_screen_clean: invalid tag");
+    return;
+  }
+  list = tag->data.list;
+  while (list) {
+    matrix_column_clean(&list->tag);
+    list = list_delete(list);
+  }
+}
+
+bool matrix_screen_init (s_tag *tag)
+{
+  tag_init_list(tag, NULL);
+  return true;
+}
+
+bool matrix_screen_render (s_sequence *seq, s_tag *tag)
+{
+  s_list **l;
+  s_list *list;
+  s_mat4 matrix;
+  s_window_sdl2 *window;
+  f32 x;
+  assert(seq);
+  window = seq->window;
+  assert(window);
+  if (! tag ||
+      tag->type != TAG_LIST) {
+    err_puts("matrix_screen_render: invalid tag");
+    assert(! "matrix_screen_render: invalid tag");
+    return false;
+  }
+  x = 0;
+  l = &tag->data.list;
+  while (*l) {
+    if (x > window->w) {
+      matrix_column_clean(&(*l)->tag);
+      *l = list_delete(*l);
+    }
+    else {
+      x += MATRIX_FONT_SIZE;
+      l = &(*l)->next.data.list;
+    }
+  }
+  while (x < window->w) {
+    *l = list_new(NULL);
+    if (! matrix_column_init(seq, &(*l)->tag))
+      return false;
+    x += MATRIX_FONT_SIZE;
+    l = &(*l)->next.data.list;
+  }
+  matrix = g_ortho.model_matrix; {
+    list = tag->data.list;
+    while (list) {
+      if (! matrix_column_render(seq, &list->tag))
+        return false;
+      mat4_translate(&g_ortho.model_matrix, MATRIX_FONT_SIZE, 0, 0);
+      list = list_next(list);
+    }
+  } g_ortho.model_matrix = matrix;
+  return true;
+}
+
 bool matrix_text_init (s_tag *tag, f32 y)
 {
   char a[1024];
@@ -230,21 +302,24 @@ void matrix_text_clean (s_tag *tag)
 {
   s_map *map;
   s_gl_text *text;
-  if (tag->type == TAG_MAP &&
-      (map = &tag->data.map) &&
-      map->count == 3 &&
-      map->key[1].type == TAG_SYM &&
-      map->key[1].data.sym == sym_1("text") &&
-      map->value[1].type == TAG_PTR &&
-      (text = map->value[1].data.ptr.p)) {
-    gl_vtext_clean(text);
+  if (! (tag->type == TAG_MAP &&
+         (map = &tag->data.map) &&
+         map->count == 3 &&
+         map->key[1].type == TAG_SYM &&
+         map->key[1].data.sym == sym_1("text") &&
+         map->value[1].type == TAG_PTR &&
+         (text = map->value[1].data.ptr.p))) {
+    err_puts("matrix_text_clean: invalid tag");
+    assert(! "matrix_text_clean: invalid tag");
+    return;
   }
+  gl_vtext_clean(text);
 }
 
 bool matrix_unload (s_sequence *seq)
 {
   assert(seq);
-  matrix_text_clean(&seq->tag);
+  matrix_screen_clean(&seq->tag);
   tag_void(&seq->tag);
   gl_font_clean(&g_matrix_font);
   return true;
diff --git a/libc3/window/sdl2/gl_vtext.c b/libc3/window/sdl2/gl_vtext.c
index 2603ab2..b12ec93 100644
--- a/libc3/window/sdl2/gl_vtext.c
+++ b/libc3/window/sdl2/gl_vtext.c
@@ -173,7 +173,7 @@ bool gl_vtext_render_to_texture (s_gl_text *text)
     x = (data_w - (glyph->metrics.width >> 6)) / 2;
     i = 0;
     while (i < glyph->bitmap.rows) {
-      data_y = data_h - 1 - (y + i + max_ascent - glyph->bitmap_top);
+      data_y = data_h - line_height - 1 - (y + i + max_ascent - glyph->bitmap_top);
       //printf("\n");
       j = 0;
       while (j < glyph->bitmap.width) {
@@ -210,25 +210,25 @@ bool gl_vtext_render_to_texture_random (s_gl_text *text, uw len)
 {
   FT_UInt *glyphs;
   u8 *data;
-  uw  data_w;
-  uw  data_h;
+  sw  data_w;
+  sw  data_h;
   u8 *data_pixel;
-  uw  data_size;
-  uw  data_x;
-  uw  data_y;
+  sw  data_size;
+  sw  data_x;
+  sw  data_y;
   FT_Face face;
   const s_gl_font *font;
   FT_GlyphSlot glyph;
   FT_UInt glyph_index;
-  uw i;
-  uw j;
-  uw k;
-  uw line_height;
-  uw max_ascent;
-  uw max_descent;
+  sw i;
+  sw j;
+  sw k;
+  sw line_height;
+  sw max_ascent;
+  sw max_descent;
   f32 scale_y;
-  uw x;
-  uw y;
+  sw x;
+  sw y;
   assert(text);
   assert(text->font);
   assert(text->texture);
@@ -245,7 +245,7 @@ bool gl_vtext_render_to_texture_random (s_gl_text *text, uw len)
              " failed to allocate memory");
     return false;
   }
-  for (i = 0; i < len; i++) {
+  for (i = 0; i < (sw) len; i++) {
     do {
       u32_random_uniform(glyphs + i, face->num_glyphs - 2);
       glyphs[i]++;
@@ -262,7 +262,7 @@ bool gl_vtext_render_to_texture_random (s_gl_text *text, uw len)
   data_w = 0;
   data_h = 0;
   x = 0;
-  for (i = 0; i < len; i++) {
+  for (i = 0; i < (sw) len; i++) {
     glyph_index = glyphs[i];
     if (FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER)) {
       err_write_1("gl_vtext_render_to_texture_random: failed to load glyph: ");
@@ -276,11 +276,13 @@ bool gl_vtext_render_to_texture_random (s_gl_text *text, uw len)
       data_w = x;
     data_h += line_height;
   }
+  data_w++;
+  data_h += line_height * 2;
   data_size = data_w * data_h * 4;
   data = calloc(1, data_size);
   x = 0;
   y = 0;
-  for (i = 0; i < len; i++) {
+  for (i = 0; i < (sw) len; i++) {
     glyph_index = glyphs[i];
     if (FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER))
       continue;
@@ -288,7 +290,8 @@ bool gl_vtext_render_to_texture_random (s_gl_text *text, uw len)
     x = (data_w - (glyph->metrics.width >> 6)) / 2;
     j = 0;
     while (j < glyph->bitmap.rows) {
-      data_y = data_h - 1 - (y + j + max_ascent - glyph->bitmap_top);
+      data_y = data_h - line_height - 1 -
+        ((sw) y + j + max_ascent - glyph->bitmap_top);
       //printf("\n");
       k = 0;
       while (k < glyph->bitmap.width) {