From 6eded1bc85f16fd68527d61087e1859dd1a9a7b6 Mon Sep 17 00:00:00 2001 From: Michael Grant Date: Thu, 6 Aug 2026 22:34:49 +0100 Subject: [PATCH] Use compact image references in grid cells --- grid.c | 6 +++--- image.c | 37 +++++++++++++++++++++++++++++++++++++ tmux.h | 8 +++++--- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/grid.c b/grid.c index 2f8b7dccd..62dc67a1e 100644 --- a/grid.c +++ b/grid.c @@ -80,7 +80,7 @@ grid_entry_image(struct grid_line *gl, struct grid_cell_entry *gce) gee = &gl->extddata[gce->offset]; if (~gee->flags & GRID_FLAG_IMAGE) return (0); - return (gee->image_id); + return (image_get_id_by_grid_id(gee->image_id)); } #endif @@ -211,7 +211,7 @@ grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce, gee->us = gc->us; gee->link = gc->link; #ifdef ENABLE_IMAGES - gee->image_id = gc->image_id; + gee->image_id = image_get_grid_id(gc->image_id); gee->image_x = gc->image_x; gee->image_y = gc->image_y; #endif @@ -684,7 +684,7 @@ grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc) gc->us = gee->us; gc->link = gee->link; #ifdef ENABLE_IMAGES - gc->image_id = gee->image_id; + gc->image_id = image_get_id_by_grid_id(gee->image_id); gc->image_x = gee->image_x; gc->image_y = gee->image_y; #endif diff --git a/image.c b/image.c index e243d66d5..f6fd2fa5e 100644 --- a/image.c +++ b/image.c @@ -45,6 +45,7 @@ struct image_cell { /* Immutable image data and cell geometry. */ struct image { u_int id; + u_short grid_id; u_int references; u_int width; u_int height; @@ -77,6 +78,8 @@ struct image_rectangle { static struct images images = RB_INITIALIZER(&images); static u_int image_next_id; +static u_short image_next_grid_id; +static struct image *image_grid_ids[USHRT_MAX + 1]; #define IMAGE_BACKEND_GRAPHICAL 0x1 #define IMAGE_BACKEND_SCROLLS 0x2 @@ -332,6 +335,7 @@ image_create(u_int width, u_int height, u_int canvas_width, u_int canvas_height, u_int sx, u_int sy, u_char *pixels) { struct image *im; + u_int i; if (width == 0 || height == 0 || canvas_width < width || canvas_height < height || sx == 0 || sy == 0 || pixels == NULL) @@ -340,6 +344,16 @@ image_create(u_int width, u_int height, u_int canvas_width, return (NULL); if ((uint64_t)sx * sy > SIZE_MAX / sizeof *im->cells) return (NULL); + if (sx > USHRT_MAX || sy > USHRT_MAX) + return (NULL); + for (i = 0; i < USHRT_MAX; i++) { + if (++image_next_grid_id == 0) + image_next_grid_id++; + if (image_grid_ids[image_next_grid_id] == NULL) + break; + } + if (i == USHRT_MAX) + return (NULL); im = xcalloc(1, sizeof *im); do { @@ -349,6 +363,7 @@ image_create(u_int width, u_int height, u_int canvas_width, } while (image_find(im->id) != NULL); im->references = 1; + im->grid_id = image_next_grid_id; im->width = width; im->height = height; im->canvas_width = canvas_width; @@ -360,12 +375,33 @@ image_create(u_int width, u_int height, u_int canvas_width, im->pixels = pixels; RB_INSERT(images, &images, im); + image_grid_ids[im->grid_id] = im; log_debug("%s: image %u is %ux%u pixels on %ux%u canvas, " "%ux%u cells", __func__, im->id, width, height, canvas_width, canvas_height, sx, sy); return (im); } +u_short +image_get_grid_id(u_int id) +{ + struct image *im = image_find(id); + + if (im == NULL) + return (0); + return (im->grid_id); +} + +u_int +image_get_id_by_grid_id(u_short grid_id) +{ + struct image *im; + + if (grid_id == 0 || (im = image_grid_ids[grid_id]) == NULL) + return (0); + return (im->id); +} + void image_ref(u_int id) { @@ -390,6 +426,7 @@ image_free(u_int id) log_debug("%s: freeing image %u", __func__, id); RB_REMOVE(images, &images, im); + image_grid_ids[im->grid_id] = NULL; free(im->pixels); if (im->sixel != NULL) sixel_free(im->sixel); diff --git a/tmux.h b/tmux.h index 8234fecf1..1eee02f6b 100644 --- a/tmux.h +++ b/tmux.h @@ -886,9 +886,9 @@ struct grid_extd_entry { int us; u_int link; #ifdef ENABLE_IMAGES - u_int image_id; - u_int image_x; - u_int image_y; + u_short image_id; + u_short image_x; + u_short image_y; #endif } __packed; @@ -4212,6 +4212,8 @@ struct image *image_create(u_int, u_int, u_int, u_int, u_int, u_int, u_char *); struct image *image_find(u_int); u_int image_get_id(const struct image *); +u_short image_get_grid_id(u_int); +u_int image_get_id_by_grid_id(u_short); void image_get_dimensions(const struct image *, u_int *, u_int *); void image_get_canvas_dimensions(const struct image *, u_int *, u_int *); void image_get_cell_dimensions(const struct image *, u_int *, u_int *);