Use compact image references in grid cells

This commit is contained in:
Michael Grant
2026-08-06 22:34:49 +01:00
parent ba2dc2cfb6
commit fb931f1676
3 changed files with 50 additions and 8 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

44
image.c
View File

@@ -48,6 +48,7 @@ struct image_cell {
/* Immutable image data and cell geometry. */
struct image {
u_int id;
u_short grid_id;
u_int references;
u_int flags;
u_int parent_id;
@@ -83,6 +84,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
@@ -356,6 +359,16 @@ image_create1(u_int width, u_int height, u_int canvas_width,
u_int canvas_height, u_int sx, u_int sy, size_t stride, u_char *pixels)
{
struct image *im;
u_int i;
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 {
@@ -365,6 +378,7 @@ image_create1(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->source_id = im->id;
im->width = width;
im->height = height;
@@ -377,6 +391,7 @@ image_create1(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);
@@ -394,7 +409,8 @@ image_create(u_int width, u_int height, u_int canvas_width,
return (NULL);
if ((uint64_t)width * height * 4 > SIZE_MAX)
return (NULL);
if ((uint64_t)sx * sy > SIZE_MAX / sizeof *im->cells)
if ((uint64_t)sx * sy > SIZE_MAX / sizeof *im->cells ||
sx > USHRT_MAX || sy > USHRT_MAX)
return (NULL);
im = image_create1(width, height, canvas_width, canvas_height, sx, sy,
(size_t)width * 4, pixels);
@@ -413,18 +429,41 @@ image_create_view(struct image *source, u_int x, u_int y, u_int width,
height > source->height - y || canvas_width < width ||
canvas_height < height || sx == 0 || sy == 0)
return (NULL);
if ((uint64_t)sx * sy > SIZE_MAX / sizeof *im->cells)
if ((uint64_t)sx * sy > SIZE_MAX / sizeof *im->cells ||
sx > USHRT_MAX || sy > USHRT_MAX)
return (NULL);
im = image_create1(width, height, canvas_width, canvas_height, sx, sy,
source->stride, source->pixels + (size_t)y * source->stride +
(size_t)x * 4);
if (im == NULL)
return (NULL);
im->parent_id = source->id;
im->source_id = source->source_id;
image_ref(source->id);
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)
{
@@ -449,6 +488,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;
if (im->parent_id == 0)
free(im->pixels);
else

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;
@@ -4241,6 +4241,8 @@ struct image *image_create_view(struct image *, u_int, u_int, u_int,
u_int, u_int, u_int, u_int, u_int);
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 *);