Use compact image references in grid cells

This commit is contained in:
Michael Grant
2026-08-06 22:34:49 +01:00
parent 09250ea86f
commit 35b856652d
3 changed files with 45 additions and 6 deletions

6
grid.c
View File

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

37
image.c
View File

@@ -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;
@@ -78,6 +79,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
@@ -345,6 +348,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)
@@ -353,6 +357,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 {
@@ -362,6 +376,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;
@@ -373,12 +388,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)
{
@@ -403,6 +439,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);

8
tmux.h
View File

@@ -887,9 +887,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;
@@ -4242,6 +4242,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 *);