diff --git a/libc3/c3.h b/libc3/c3.h
index 3474df4..cb1b623 100644
--- a/libc3/c3.h
+++ b/libc3/c3.h
@@ -67,6 +67,7 @@
#include "integer.h"
#include "io.h"
#include "list.h"
+#include "map.h"
#include "ptag.h"
#include "ptr.h"
#include "module.h"
diff --git a/libc3/sym.c b/libc3/sym.c
index d48d11f..561c8cc 100644
--- a/libc3/sym.c
+++ b/libc3/sym.c
@@ -340,6 +340,8 @@ f_clean sym_to_clean (const s_sym *type)
return NULL;
if (type == sym_1("List"))
return (f_clean) list_clean;
+ if (type == sym_1("Map"))
+ return (f_clean) map_clean;
if (type == sym_1("Ptag"))
return NULL;
if (type == sym_1("Ptr"))
diff --git a/libc3/window/cairo/cairo_font.c b/libc3/window/cairo/cairo_font.c
index 2569b51..4eca894 100644
--- a/libc3/window/cairo/cairo_font.c
+++ b/libc3/window/cairo/cairo_font.c
@@ -17,6 +17,14 @@ static FT_Library *g_cairo_font_ft = NULL;
static FT_Library * cairo_font_ft (void);
+void c3_window_cairo_font_clean (void)
+{
+ if (g_cairo_font_ft) {
+ FT_Done_FreeType(*g_cairo_font_ft);
+ free(g_cairo_font_ft);
+ }
+}
+
void cairo_font_clean (s_cairo_font *font)
{
assert(font);
@@ -44,17 +52,17 @@ static FT_Library * cairo_font_ft (void)
return g_cairo_font_ft;
}
-s_cairo_font * cairo_font_init (s_cairo_font *font, const s_str *path)
+s_cairo_font * cairo_font_init (s_cairo_font *font, const s8 *path)
{
FT_Library *ft;
assert(font);
assert(path);
if (! (ft = cairo_font_ft()))
return NULL;
- str_init_copy(&font->path, path);
- if (! file_search(path, sym_1("r"), &font->real_path)) {
+ str_init_copy_1(&font->path, path);
+ if (! file_search(&font->path, sym_1("r"), &font->real_path)) {
err_write_1("cairo_font_init: file not found: ");
- err_puts(path->ptr.ps8);
+ err_puts(path);
str_clean(&font->path);
return NULL;
}
@@ -70,7 +78,7 @@ s_cairo_font * cairo_font_init (s_cairo_font *font, const s_str *path)
return font;
}
-void cairo_font_set (const s_cairo_font *font, cairo_t *cr)
+void cairo_set_font (cairo_t *cr, const s_cairo_font *font)
{
cairo_set_font_face(cr, font->cairo_font_face);
}
diff --git a/libc3/window/cairo/cairo_font.h b/libc3/window/cairo/cairo_font.h
index 573bf6f..5d55775 100644
--- a/libc3/window/cairo/cairo_font.h
+++ b/libc3/window/cairo/cairo_font.h
@@ -20,9 +20,9 @@
/* Stack-allocation compatible functions, call cairo_font_clean after
use. */
void cairo_font_clean (s_cairo_font *font);
-s_cairo_font * cairo_font_init (s_cairo_font *font, const s_str *path);
+s_cairo_font * cairo_font_init (s_cairo_font *font, const s8 *path);
/* Observers */
-void cairo_font_set (const s_cairo_font *font, cairo_t *cr);
+void cairo_set_font (cairo_t *cr, const s_cairo_font *font);
#endif /* LIBC3_WINDOW_CAIRO_CAIRO_FONT_H */
diff --git a/libc3/window/cairo/demo/flies.c b/libc3/window/cairo/demo/flies.c
index 7271e8b..d1ec38b 100644
--- a/libc3/window/cairo/demo/flies.c
+++ b/libc3/window/cairo/demo/flies.c
@@ -12,8 +12,10 @@
*/
#include <math.h>
#include <libc3/c3.h>
-#include "../window_cairo.h"
+#include "../cairo_font.h"
#include "../cairo_sprite.h"
+#include "../window_cairo.h"
+#include "window_cairo_demo.h"
#include "flies.h"
#define BOARD_SIZE 25
@@ -30,8 +32,8 @@ static const u8 g_board_item_space = BOARD_ITEM_SPACE;
static const u8 g_board_item_block = BOARD_ITEM_BLOCK;
static const u8 g_board_item_fly = BOARD_ITEM_FLY;
static const u8 g_board_item_dead_fly = BOARD_ITEM_DEAD_FLY;
-s_cairo_sprite g_dead_fly_sprite = {0};
-s_cairo_sprite g_fly_sprite = {0};
+s_cairo_sprite g_sprite_dead_fly = {0};
+s_cairo_sprite g_sprite_fly = {0};
static const f64 g_xy_ratio = 0.6;
static void fly_init (s_map *map)
@@ -177,16 +179,14 @@ bool flies_render (s_sequence *seq, s_window_cairo *window,
board_w = board_item_w * BOARD_SIZE;
board_h = board_item_h * BOARD_SIZE;
board_x = (window->w - board_w) / 2.0;
- fly_scale = 2.0 * board_item_w / g_fly_sprite.w;
- dead_fly_scale = 2.0 * board_item_w / g_dead_fly_sprite.w;
+ fly_scale = 2.0 * board_item_w / g_sprite_fly.w;
+ dead_fly_scale = 2.0 * board_item_w / g_sprite_dead_fly.w;
cairo_set_source_rgb(cr, 0.6, 0.7, 0.9);
cairo_rectangle(cr, board_x, 0, board_w, board_h);
cairo_fill(cr);
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
cairo_set_font_size(cr, board_item_h);
- cairo_select_font_face(cr, "Courier New",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font(cr, &g_font_courier_new);
buf_init(&buf, false, sizeof(a), a);
buf_write_1(&buf, "In ");
buf_inspect_uw(&buf, fly_in);
@@ -225,7 +225,7 @@ bool flies_render (s_sequence *seq, s_window_cairo *window,
cairo_translate(cr, -board_item_w / 2.0,
-board_item_h / 2.0);
cairo_scale(cr, fly_scale, fly_scale);
- cairo_sprite_blit(&g_fly_sprite, 0,
+ cairo_sprite_blit(&g_sprite_fly, 0,
cr, 0, 0);
if (address[0] == BOARD_SIZE / 2 &&
address[1] == BOARD_SIZE - 1) {
@@ -297,7 +297,7 @@ bool flies_render (s_sequence *seq, s_window_cairo *window,
cairo_translate(cr, -board_item_w / 2.0,
-board_item_h / 2.0);
cairo_scale(cr, dead_fly_scale, dead_fly_scale);
- cairo_sprite_blit(&g_dead_fly_sprite, 0,
+ cairo_sprite_blit(&g_sprite_dead_fly, 0,
cr, 0, 0);
break;
}
diff --git a/libc3/window/cairo/demo/flies.h b/libc3/window/cairo/demo/flies.h
index 9eff323..9695712 100644
--- a/libc3/window/cairo/demo/flies.h
+++ b/libc3/window/cairo/demo/flies.h
@@ -15,8 +15,8 @@
#include "../types.h"
-extern s_cairo_sprite g_dead_fly_sprite;
-extern s_cairo_sprite g_fly_sprite;
+extern s_cairo_sprite g_sprite_dead_fly;
+extern s_cairo_sprite g_sprite_fly;
bool flies_load (s_sequence *seq, s_window_cairo *window);
bool flies_render (s_sequence *seq, s_window_cairo *window,
diff --git a/libc3/window/cairo/demo/lightspeed.c b/libc3/window/cairo/demo/lightspeed.c
index 9416f62..19397dc 100644
--- a/libc3/window/cairo/demo/lightspeed.c
+++ b/libc3/window/cairo/demo/lightspeed.c
@@ -19,7 +19,7 @@ static void star_init (s_tag *star)
f64 y;
f64_random(&x);
f64_random(&y);
- tag_init_map(star, 3);
+ tag_map(star, 3);
tag_init_sym(star->data.map.key, sym_1("speed"));
tag_init_f64(star->data.map.value, 0.0);
tag_init_sym(star->data.map.key + 1, sym_1("x"));
diff --git a/libc3/window/cairo/demo/toasters.c b/libc3/window/cairo/demo/toasters.c
index 5aa0143..13086e1 100644
--- a/libc3/window/cairo/demo/toasters.c
+++ b/libc3/window/cairo/demo/toasters.c
@@ -17,8 +17,8 @@
static const f64 g_speed_x = 80.0;
static const f64 g_speed_y = -40.0;
-s_cairo_sprite g_toast_sprite = {0};
-s_cairo_sprite g_toaster_sprite = {0};
+s_cairo_sprite g_sprite_toast = {0};
+s_cairo_sprite g_sprite_toaster = {0};
static bool toasters_render_toasters (s_list **toasters,
s_window_cairo *window,
@@ -58,7 +58,7 @@ static void toast_render (s_tag *toast, s_window_cairo *window,
}
cairo_get_matrix(cr, &matrix);
cairo_translate(cr, *x, *y);
- cairo_sprite_blit(&g_toast_sprite, 0, cr, 0, 0);
+ cairo_sprite_blit(&g_sprite_toast, 0, cr, 0, 0);
cairo_set_matrix(cr, &matrix);
}
}
@@ -91,9 +91,9 @@ static void toaster_render (s_tag *toaster, s_window_cairo *window,
}
cairo_get_matrix(cr, &matrix);
cairo_translate(cr, *x, *y);
- cairo_sprite_blit(&g_toaster_sprite,
- fmod(seq->t * g_toaster_sprite.frame_count,
- g_toaster_sprite.frame_count),
+ cairo_sprite_blit(&g_sprite_toaster,
+ fmod(seq->t * g_sprite_toaster.frame_count,
+ g_sprite_toaster.frame_count),
cr, 0, 0);
cairo_set_matrix(cr, &matrix);
}
diff --git a/libc3/window/cairo/demo/toasters.h b/libc3/window/cairo/demo/toasters.h
index 630d4e9..b97b4b9 100644
--- a/libc3/window/cairo/demo/toasters.h
+++ b/libc3/window/cairo/demo/toasters.h
@@ -15,8 +15,8 @@
#include "../types.h"
-extern s_cairo_sprite g_toast_sprite;
-extern s_cairo_sprite g_toaster_sprite;
+extern s_cairo_sprite g_sprite_toast;
+extern s_cairo_sprite g_sprite_toaster;
bool toasters_load (s_sequence *seq, s_window_cairo *window);
bool toasters_render (s_sequence *seq, s_window_cairo *window,
diff --git a/libc3/window/cairo/demo/window_cairo_demo.c b/libc3/window/cairo/demo/window_cairo_demo.c
index 3a409ca..b8096b9 100644
--- a/libc3/window/cairo/demo/window_cairo_demo.c
+++ b/libc3/window/cairo/demo/window_cairo_demo.c
@@ -15,14 +15,18 @@
#include <libc3/c3.h>
#include <xkbcommon/xkbcommon.h>
#include "../../window.h"
-#include "../window_cairo.h"
+#include "../cairo_font.h"
#include "../cairo_sprite.h"
+#include "../window_cairo.h"
#include "window_cairo_demo.h"
#include "bg_rect.h"
#include "lightspeed.h"
#include "toasters.h"
#include "flies.h"
+s_cairo_font g_font_computer_modern = {0};
+s_cairo_font g_font_courier_new = {0};
+
bool window_cairo_demo_button (s_window_cairo *window, u8 button,
sw x, sw y)
{
@@ -81,25 +85,28 @@ bool window_cairo_demo_load (s_window_cairo *window)
assert(window->sequence_count == WINDOW_CAIRO_DEMO_SEQUENCE_COUNT);
return false;
}
+ if (! cairo_font_init(&g_font_courier_new,
+ "fonts/Courier New/Courier New.ttf"))
+ return false;
window_cairo_sequence_init(window->sequence, 8.0,
"01. Background rectangles",
bg_rect_load, bg_rect_render);
window_cairo_sequence_init(window->sequence + 1, 20.0,
"02. Lightspeed",
lightspeed_load, lightspeed_render);
- if (! cairo_sprite_init(&g_toaster_sprite, "img/flaps.png",
+ if (! cairo_sprite_init(&g_sprite_toaster, "img/flaps.png",
4, 1, 4))
return false;
- if (! cairo_sprite_init(&g_toast_sprite, "img/toast.png",
+ if (! cairo_sprite_init(&g_sprite_toast, "img/toast.png",
1, 1, 1))
return false;
window_cairo_sequence_init(window->sequence + 2, 60.0,
"03. Toasters",
toasters_load, toasters_render);
- if (! cairo_sprite_init(&g_fly_sprite, "img/fly-noto.png",
+ if (! cairo_sprite_init(&g_sprite_fly, "img/fly-noto.png",
1, 1, 1))
return false;
- if (! cairo_sprite_init(&g_dead_fly_sprite, "img/fly-dead.png",
+ if (! cairo_sprite_init(&g_sprite_dead_fly, "img/fly-dead.png",
1, 1, 1))
return false;
window_cairo_sequence_init(window->sequence + 3, 60.0,
@@ -149,9 +156,7 @@ bool window_cairo_demo_render (s_window_cairo *window,
return false;
/* text */
cairo_set_font_size(cr, 20);
- cairo_select_font_face(cr, "Courier New",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font(cr, &g_font_courier_new);
cairo_text_extents(cr, seq->title, &te);
render_text(cr, 20.0, window->h - te.height - te.y_bearing - 20,
seq->title);
@@ -183,3 +188,14 @@ bool window_cairo_demo_resize (s_window_cairo *window,
(void) h;
return true;
}
+
+void window_cairo_demo_unload (s_window_cairo *window)
+{
+ assert(window);
+ (void) window;
+ cairo_font_clean(&g_font_courier_new);
+ cairo_sprite_clean(&g_sprite_toaster);
+ cairo_sprite_clean(&g_sprite_toast);
+ cairo_sprite_clean(&g_sprite_fly);
+ cairo_sprite_clean(&g_sprite_dead_fly);
+}
diff --git a/libc3/window/cairo/demo/window_cairo_demo.h b/libc3/window/cairo/demo/window_cairo_demo.h
index 8df2e6b..ab2b69a 100644
--- a/libc3/window/cairo/demo/window_cairo_demo.h
+++ b/libc3/window/cairo/demo/window_cairo_demo.h
@@ -17,11 +17,15 @@
#define WINDOW_CAIRO_DEMO_SEQUENCE_COUNT 4
+extern s_cairo_font g_font_computer_modern;
+extern s_cairo_font g_font_courier_new;
+
bool window_cairo_demo_button (s_window_cairo *window, u8 button,
sw x, sw y);
bool window_cairo_demo_key (s_window_cairo *window, uw keysym);
bool window_cairo_demo_load (s_window_cairo *window);
bool window_cairo_demo_render (s_window_cairo *window, cairo_t *cr);
bool window_cairo_demo_resize (s_window_cairo *window, uw w, uw h);
+void window_cairo_demo_unload (s_window_cairo *window);
#endif /* LIBC3_WINDOW_CAIRO_DEMO_H */
diff --git a/libc3/window/cairo/types.h b/libc3/window/cairo/types.h
index 7a1afdd..f7647fe 100644
--- a/libc3/window/cairo/types.h
+++ b/libc3/window/cairo/types.h
@@ -61,6 +61,8 @@ typedef bool (*f_window_cairo_sequence_render) (s_sequence *seq,
s_window_cairo *window,
cairo_t *cr);
+typedef void (*f_window_cairo_unload) (s_window_cairo *window);
+
struct cairo_font {
cairo_font_face_t *cairo_font_face;
FT_Face ft_face;
@@ -112,7 +114,9 @@ struct window_cairo {
s_sequence *sequence;
uw sequence_count;
uw sequence_pos;
+ s_tag tag; // TODO: move sequence to tag
const s8 *title;
+ f_window_cairo_unload unload;
};
#endif /* LIBC3_WINDOW_CAIRO_TYPES_H */
diff --git a/libc3/window/cairo/window_cairo.c b/libc3/window/cairo/window_cairo.c
index 8f7823a..db2dbb5 100644
--- a/libc3/window/cairo/window_cairo.c
+++ b/libc3/window/cairo/window_cairo.c
@@ -35,22 +35,17 @@ s_window_cairo * window_cairo_init (s_window_cairo *window,
const s8 *title,
uw sequence_count)
{
+ s_window_cairo tmp = {0};
assert(window);
- window->x = x;
- window->y = y;
- window->w = w;
- window->h = h;
- window->button = window_cairo_button_default;
- window->key = window_cairo_key_default;
- window->load = window_cairo_load_default;
- window->motion = window_cairo_motion_default;
- window->render = window_cairo_render_default;
- window->resize = window_cairo_resize_default;
- window->cr = NULL;
- window->sequence = calloc(sequence_count, sizeof(s_sequence));
- window->sequence_count = sequence_count;
- window->sequence_pos = 0;
- window->title = title ? title : "C3.Window.Cairo";
+ title = title ? title : "C3.Window.Cairo";
+ window_init((s_window *) &tmp, x, y, w, h, title, sequence_count);
+ tmp.button = window_cairo_button_default;
+ tmp.key = window_cairo_key_default;
+ tmp.load = window_cairo_load_default;
+ tmp.motion = window_cairo_motion_default;
+ tmp.render = window_cairo_render_default;
+ tmp.resize = window_cairo_resize_default;
+ *window = tmp;
return window;
}
diff --git a/libc3/window/cairo/xcb/demo/window_cairo_xcb_demo.c b/libc3/window/cairo/xcb/demo/window_cairo_xcb_demo.c
index 779d09e..b584d5a 100644
--- a/libc3/window/cairo/xcb/demo/window_cairo_xcb_demo.c
+++ b/libc3/window/cairo/xcb/demo/window_cairo_xcb_demo.c
@@ -33,8 +33,10 @@ int main (int argc, char **argv)
window.load = window_cairo_demo_load;
window.render = window_cairo_demo_render;
window.resize = window_cairo_demo_resize;
+ window.unload = window_cairo_demo_unload;
if (! window_cairo_xcb_run(&window)) {
err_puts("window_cairo_xcb_run -> false");
+ window_cairo_clean(&window);
c3_clean(NULL);
return g_c3_exit_code;
}
diff --git a/libc3/window/cairo/xcb/window_cairo_xcb.c b/libc3/window/cairo/xcb/window_cairo_xcb.c
index b20a2b6..111b940 100644
--- a/libc3/window/cairo/xcb/window_cairo_xcb.c
+++ b/libc3/window/cairo/xcb/window_cairo_xcb.c
@@ -150,8 +150,8 @@ bool window_cairo_xcb_run (s_window_cairo *window)
screen->root_visual,
value_mask, value_list);
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, xcb_window,
- XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 12,
- window->title);
+ XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
+ strlen(window->title), window->title);
xcb_map_window(conn, xcb_window);
pixmap = xcb_generate_id(conn);
xcb_create_pixmap(conn, screen->root_depth, pixmap, xcb_window,
@@ -187,6 +187,11 @@ bool window_cairo_xcb_run (s_window_cairo *window)
}
}
clean:
+ cairo_surface_destroy(surface);
+ cairo_destroy(window->cr);
+ xkb_state_unref(xkb_state);
+ xkb_keymap_unref(xkb_keymap);
+ xkb_context_unref(xkb_ctx);
xcb_disconnect(conn);
return r;
}
diff --git a/libc3/window/types.h b/libc3/window/types.h
index c2cb53d..c14b999 100644
--- a/libc3/window/types.h
+++ b/libc3/window/types.h
@@ -43,10 +43,11 @@ typedef bool (*f_window_render) (s_window *window,
typedef bool (*f_window_resize) (s_window *window,
uw w, uw h);
+typedef void (*f_window_unload) (s_window *window);
+
/* To subtype make a copy of this struct while replacing
* pointer types (including pointer to function types).
- * E.g. see libc3/window/cairo/types.h
- */
+ * E.g. see libc3/window/cairo/types.h */
struct window {
sw x;
sw y;
@@ -63,7 +64,9 @@ struct window {
s_sequence *sequence;
uw sequence_count;
uw sequence_pos;
+ s_tag tag; // TODO: move sequence to tag
const s8 *title;
+ f_window_unload unload;
};
#endif /* LIBC3_WINDOW_TYPES_H */
diff --git a/libc3/window/window.c b/libc3/window/window.c
index 76d7cc9..b17178d 100644
--- a/libc3/window/window.c
+++ b/libc3/window/window.c
@@ -52,6 +52,27 @@ void window_clean (s_window *window)
i++;
}
free(window->sequence);
+ tag_clean(&window->tag);
+}
+
+s_window * window_init (s_window *window,
+ sw x, sw y, uw w, uw h,
+ const s8 *title,
+ uw sequence_count)
+{
+ s_window tmp = {0};
+ assert(window);
+ tmp.x = x;
+ tmp.y = y;
+ tmp.w = w;
+ tmp.h = h;
+ tmp.sequence = calloc(sequence_count, sizeof(s_sequence));
+ tmp.sequence_count = sequence_count;
+ tmp.sequence_pos = 0;
+ tag_init_void(&tmp.tag);
+ tmp.title = title ? title : "C3.Window";
+ *window = tmp;
+ return window;
}
bool window_set_sequence_pos (s_window *window, uw sequence_pos)
diff --git a/libc3/window/window.h b/libc3/window/window.h
index 90338ca..cdfeef8 100644
--- a/libc3/window/window.h
+++ b/libc3/window/window.h
@@ -18,8 +18,13 @@
/* Stack-allocation compatible functions, call window_clean
after use. */
-void window_clean (s_window *window);
+void window_clean (s_window *window);
+s_window * window_init (s_window *window,
+ sw x, sw y, uw w, uw h,
+ const s8 *title,
+ uw sequence_count);
+/* Operators. */
bool window_animate (s_window *window);
bool window_set_sequence_pos (s_window *window, uw sequence_pos);