mirror of
https://github.com/tmux/tmux.git
synced 2026-08-29 18:11:36 +00:00
Make image types opaque
This commit is contained in:
124
image-kitty.c
124
image-kitty.c
@@ -219,14 +219,15 @@ kitty_place(struct tty *tty, struct image *im, u_int id)
|
||||
{
|
||||
char control[192];
|
||||
u_int x, y, columns, rows, px, py, pwidth, pheight;
|
||||
u_int placement = 1;
|
||||
u_int placement = 1, sx, sy;
|
||||
|
||||
for (y = 0; y < im->sy; y += nitems(kitty_diacritics)) {
|
||||
rows = im->sy - y;
|
||||
image_get_cell_dimensions(im, &sx, &sy);
|
||||
for (y = 0; y < sy; y += nitems(kitty_diacritics)) {
|
||||
rows = sy - y;
|
||||
if (rows > nitems(kitty_diacritics))
|
||||
rows = nitems(kitty_diacritics);
|
||||
for (x = 0; x < im->sx; x += nitems(kitty_diacritics)) {
|
||||
columns = im->sx - x;
|
||||
for (x = 0; x < sx; x += nitems(kitty_diacritics)) {
|
||||
columns = sx - x;
|
||||
if (columns > nitems(kitty_diacritics))
|
||||
columns = nitems(kitty_diacritics);
|
||||
image_get_pixel_rectangle(im, x, y, columns, rows, &px,
|
||||
@@ -247,12 +248,14 @@ kitty_upload(struct tty *tty, struct image *im)
|
||||
struct kitty_image_cache *cache;
|
||||
char control[128], encoded[4097];
|
||||
u_char raw[3072];
|
||||
size_t offset, size, copied, row, column, available;
|
||||
const u_char *pixels;
|
||||
size_t offset, size, copied, row, column, available, stride;
|
||||
size_t image_size;
|
||||
int encodedlen;
|
||||
u_int id;
|
||||
u_int id, width, height;
|
||||
|
||||
for (cache = ko->images; cache != NULL; cache = cache->next) {
|
||||
if (cache->server_id != im->id)
|
||||
if (cache->server_id != image_get_id(im))
|
||||
continue;
|
||||
if (cache->xpixel == tty->xpixel &&
|
||||
cache->ypixel == tty->ypixel)
|
||||
@@ -269,22 +272,24 @@ kitty_upload(struct tty *tty, struct image *im)
|
||||
do {
|
||||
id = ++ko->next_id & 0xffffff;
|
||||
} while (id == 0);
|
||||
cache->server_id = im->id;
|
||||
cache->server_id = image_get_id(im);
|
||||
cache->kitty_id = id;
|
||||
cache->xpixel = tty->xpixel;
|
||||
cache->ypixel = tty->ypixel;
|
||||
|
||||
for (offset = 0; offset < im->size; offset += size) {
|
||||
size = im->size - offset;
|
||||
pixels = image_get_pixels(im, &stride, &image_size);
|
||||
image_get_dimensions(im, &width, &height);
|
||||
for (offset = 0; offset < image_size; offset += size) {
|
||||
size = image_size - offset;
|
||||
if (size > sizeof raw)
|
||||
size = sizeof raw;
|
||||
for (copied = 0; copied < size; copied += available) {
|
||||
row = (offset + copied) / ((size_t)im->width * 4);
|
||||
column = (offset + copied) % ((size_t)im->width * 4);
|
||||
available = (size_t)im->width * 4 - column;
|
||||
row = (offset + copied) / ((size_t)width * 4);
|
||||
column = (offset + copied) % ((size_t)width * 4);
|
||||
available = (size_t)width * 4 - column;
|
||||
if (available > size - copied)
|
||||
available = size - copied;
|
||||
memcpy(raw + copied, im->pixels + row * im->stride +
|
||||
memcpy(raw + copied, pixels + row * stride +
|
||||
column, available);
|
||||
}
|
||||
encodedlen = b64_ntop(raw, size, encoded,
|
||||
@@ -294,11 +299,10 @@ kitty_upload(struct tty *tty, struct image *im)
|
||||
if (offset == 0) {
|
||||
xsnprintf(control, sizeof control,
|
||||
"\033_Ga=t,f=32,s=%u,v=%u,i=%u,q=2,m=%d;",
|
||||
im->width, im->height, id,
|
||||
offset + size < im->size);
|
||||
width, height, id, offset + size < image_size);
|
||||
} else {
|
||||
xsnprintf(control, sizeof control, "\033_Gm=%d;",
|
||||
offset + size < im->size);
|
||||
offset + size < image_size);
|
||||
}
|
||||
tty_puts(tty, control);
|
||||
tty_putn(tty, encoded, encodedlen, 0);
|
||||
@@ -311,9 +315,10 @@ kitty_upload(struct tty *tty, struct image *im)
|
||||
static u_int
|
||||
kitty_placement(struct image *im, u_int x, u_int y)
|
||||
{
|
||||
u_int across;
|
||||
u_int across, sx;
|
||||
|
||||
across = (im->sx + nitems(kitty_diacritics) - 1) /
|
||||
image_get_cell_dimensions(im, &sx, NULL);
|
||||
across = (sx + nitems(kitty_diacritics) - 1) /
|
||||
nitems(kitty_diacritics);
|
||||
return ((y / nitems(kitty_diacritics)) * across +
|
||||
x / nitems(kitty_diacritics) + 1);
|
||||
@@ -355,30 +360,32 @@ kitty_draw_rectangle(struct tty *tty, const struct image_rectangle *rectangle,
|
||||
{
|
||||
struct grid_cell draw_gc;
|
||||
struct kitty_image_cache *cache;
|
||||
struct image *im = rectangle->image;
|
||||
u_int x, y, run, available;
|
||||
struct image *im;
|
||||
u_int x, y, run, available, source_x, source_y;
|
||||
u_int width, height, destination_x, destination_y;
|
||||
|
||||
im = image_rectangle_get_image(rectangle);
|
||||
kitty_images_collect(tty);
|
||||
cache = kitty_upload(tty, im);
|
||||
if (cache == NULL)
|
||||
return;
|
||||
memcpy(&draw_gc, &rectangle->cell, sizeof draw_gc);
|
||||
memcpy(&draw_gc, image_rectangle_get_cell(rectangle), sizeof draw_gc);
|
||||
image_rectangle_get_coordinates(rectangle, &source_x, &source_y, &width,
|
||||
&height, &destination_x, &destination_y);
|
||||
draw_gc.flags &= ~(GRID_FLAG_IMAGE|GRID_FLAG_SELECTED);
|
||||
utf8_set(&draw_gc.data, ' ');
|
||||
for (y = 0; y < rectangle->height; y++) {
|
||||
for (x = 0; x < rectangle->width; x += run) {
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x += run) {
|
||||
available = nitems(kitty_diacritics) -
|
||||
(rectangle->source_x + x) %
|
||||
(source_x + x) %
|
||||
nitems(kitty_diacritics);
|
||||
run = rectangle->width - x;
|
||||
run = width - x;
|
||||
if (run > available)
|
||||
run = available;
|
||||
tty_cursor(tty, rectangle->destination_x + x,
|
||||
rectangle->destination_y + y);
|
||||
tty_cursor(tty, destination_x + x, destination_y + y);
|
||||
tty_attributes(tty, &draw_gc, style_ctx);
|
||||
kitty_placeholder(tty, cache, im,
|
||||
rectangle->source_x + x,
|
||||
rectangle->source_y + y, run);
|
||||
kitty_placeholder(tty, cache, im, source_x + x,
|
||||
source_y + y, run);
|
||||
tty_reset(tty);
|
||||
}
|
||||
}
|
||||
@@ -569,8 +576,8 @@ kitty_source_set(struct kitty_context *kc, u_int id, struct image *im)
|
||||
}
|
||||
image_free(source->server_id);
|
||||
}
|
||||
image_ref(im->id);
|
||||
source->server_id = im->id;
|
||||
image_ref(image_get_id(im));
|
||||
source->server_id = image_get_id(im);
|
||||
return (old_id);
|
||||
}
|
||||
|
||||
@@ -599,8 +606,8 @@ kitty_placement_set(struct kitty_context *kc, u_int image_id,
|
||||
source->placements = placement;
|
||||
}
|
||||
old_id = placement->server_id;
|
||||
image_ref(im->id);
|
||||
placement->server_id = im->id;
|
||||
image_ref(image_get_id(im));
|
||||
placement->server_id = image_get_id(im);
|
||||
if (old_id != 0)
|
||||
image_free(old_id);
|
||||
return (old_id);
|
||||
@@ -623,7 +630,7 @@ kitty_placement_remove(struct kitty_context *kc, u_int image_id,
|
||||
continue;
|
||||
im = image_find(placement->server_id);
|
||||
if (im != NULL)
|
||||
image_ref(im->id);
|
||||
image_ref(image_get_id(im));
|
||||
*pp = placement->next;
|
||||
image_free(placement->server_id);
|
||||
free(placement);
|
||||
@@ -642,8 +649,8 @@ kitty_virtual_set(struct kitty_context *kc, u_int id, struct image *im)
|
||||
return;
|
||||
if (source->virtual_id != 0)
|
||||
image_free(source->virtual_id);
|
||||
image_ref(im->id);
|
||||
source->virtual_id = im->id;
|
||||
image_ref(image_get_id(im));
|
||||
source->virtual_id = image_get_id(im);
|
||||
}
|
||||
|
||||
static struct image *
|
||||
@@ -657,7 +664,7 @@ kitty_source_remove(struct kitty_context *kc, u_int id)
|
||||
continue;
|
||||
im = image_find(source->server_id);
|
||||
if (im != NULL)
|
||||
image_ref(im->id);
|
||||
image_ref(image_get_id(im));
|
||||
*pp = source->next;
|
||||
kitty_placements_free(source);
|
||||
if (source->virtual_id != 0)
|
||||
@@ -680,7 +687,7 @@ kitty_source_get(struct kitty_context *kc, u_int id)
|
||||
return (NULL);
|
||||
im = image_find(source->server_id);
|
||||
if (im != NULL)
|
||||
image_ref(im->id);
|
||||
image_ref(image_get_id(im));
|
||||
return (im);
|
||||
}
|
||||
|
||||
@@ -748,19 +755,21 @@ kitty_place_image(struct image *source, struct kitty_state *ks, u_int xpixel,
|
||||
{
|
||||
uint64_t numerator, denominator, value;
|
||||
u_int x, y, width, height, sx, sy, canvas_width;
|
||||
u_int canvas_height, cell_width, cell_height;
|
||||
u_int canvas_height, cell_width, cell_height, source_width;
|
||||
u_int source_height;
|
||||
struct image *im;
|
||||
|
||||
x = ks->source_x;
|
||||
y = ks->source_y;
|
||||
if (x >= source->width || y >= source->height)
|
||||
image_get_dimensions(source, &source_width, &source_height);
|
||||
if (x >= source_width || y >= source_height)
|
||||
return (NULL);
|
||||
width = ks->source_width;
|
||||
if (width == 0 || width > source->width - x)
|
||||
width = source->width - x;
|
||||
if (width == 0 || width > source_width - x)
|
||||
width = source_width - x;
|
||||
height = ks->source_height;
|
||||
if (height == 0 || height > source->height - y)
|
||||
height = source->height - y;
|
||||
if (height == 0 || height > source_height - y)
|
||||
height = source_height - y;
|
||||
|
||||
cell_width = (xpixel == 0 ? 8 : xpixel);
|
||||
cell_height = (ypixel == 0 ? 16 : ypixel);
|
||||
@@ -819,7 +828,7 @@ kitty_place_image(struct image *source, struct kitty_state *ks, u_int xpixel,
|
||||
im = image_create_view(source, x, y, width, height, canvas_width,
|
||||
canvas_height, sx, sy);
|
||||
if (im != NULL && ks->no_cursor)
|
||||
im->flags |= IMAGE_FLAG_NO_CURSOR;
|
||||
image_set_no_cursor(im);
|
||||
return (im);
|
||||
}
|
||||
|
||||
@@ -891,17 +900,17 @@ kitty_parse_image(void **state, const u_char *buf, size_t len, u_int xpixel,
|
||||
im = NULL;
|
||||
} else if (ks->virtual) {
|
||||
im = kitty_place_image(source, ks, xpixel, ypixel);
|
||||
image_free(source->id);
|
||||
image_free(image_get_id(source));
|
||||
if (im != NULL) {
|
||||
kitty_virtual_set(kc, ks->image_id, im);
|
||||
image_free(im->id);
|
||||
image_free(image_get_id(im));
|
||||
im = NULL;
|
||||
*action = 'u';
|
||||
*status = KITTY_PARSE_OK;
|
||||
}
|
||||
} else {
|
||||
im = kitty_place_image(source, ks, xpixel, ypixel);
|
||||
image_free(source->id);
|
||||
image_free(image_get_id(source));
|
||||
if (im != NULL) {
|
||||
*replace_id = kitty_placement_set(kc, ks->image_id,
|
||||
ks->placement_id, im);
|
||||
@@ -1014,14 +1023,14 @@ kitty_parse_image(void **state, const u_char *buf, size_t len, u_int xpixel,
|
||||
*status = KITTY_PARSE_ERROR;
|
||||
else {
|
||||
kitty_virtual_set(kc, ks->image_id, im);
|
||||
image_free(im->id);
|
||||
image_free(image_get_id(im));
|
||||
im = NULL;
|
||||
*action = 'u';
|
||||
}
|
||||
} else {
|
||||
im = NULL;
|
||||
}
|
||||
image_free(source->id);
|
||||
image_free(image_get_id(source));
|
||||
}
|
||||
kitty_state_free(ks);
|
||||
return (im);
|
||||
@@ -1094,7 +1103,7 @@ kitty_placeholder_to_cell(void *state, struct grid_cell *gc,
|
||||
struct image *im;
|
||||
uint32_t value;
|
||||
size_t offset = 0;
|
||||
u_int values[3], nvalues = 0, id, x, y;
|
||||
u_int values[3], nvalues = 0, id, x, y, sx, sy;
|
||||
struct utf8_data data;
|
||||
int fg, bg, us;
|
||||
|
||||
@@ -1127,22 +1136,23 @@ kitty_placeholder_to_cell(void *state, struct grid_cell *gc,
|
||||
source->server_id);
|
||||
if (im == NULL)
|
||||
return (0);
|
||||
image_get_cell_dimensions(im, &sx, &sy);
|
||||
|
||||
if (nvalues >= 1)
|
||||
y = values[0];
|
||||
else if (left != NULL && left->flags & GRID_FLAG_IMAGE &&
|
||||
left->image_id == im->id)
|
||||
left->image_id == image_get_id(im))
|
||||
y = left->image_y;
|
||||
else
|
||||
return (0);
|
||||
if (nvalues >= 2)
|
||||
x = values[1];
|
||||
else if (left != NULL && left->flags & GRID_FLAG_IMAGE &&
|
||||
left->image_id == im->id && left->image_x != UINT_MAX)
|
||||
left->image_id == image_get_id(im) && left->image_x != UINT_MAX)
|
||||
x = left->image_x + 1;
|
||||
else
|
||||
return (0);
|
||||
if (x >= im->sx || y >= im->sy)
|
||||
if (x >= sx || y >= sy)
|
||||
return (0);
|
||||
|
||||
utf8_copy(&data, &gc->data);
|
||||
|
||||
119
image-sixel.c
119
image-sixel.c
@@ -88,6 +88,40 @@ struct sixel_output {
|
||||
uint64_t age;
|
||||
};
|
||||
|
||||
struct sixel_histogram {
|
||||
u_int count;
|
||||
uint64_t red;
|
||||
uint64_t green;
|
||||
uint64_t blue;
|
||||
};
|
||||
|
||||
struct sixel_box {
|
||||
u_int red_min;
|
||||
u_int red_max;
|
||||
u_int green_min;
|
||||
u_int green_max;
|
||||
u_int blue_min;
|
||||
u_int blue_max;
|
||||
u_int count;
|
||||
};
|
||||
|
||||
struct sixel_rgb {
|
||||
u_char red;
|
||||
u_char green;
|
||||
u_char blue;
|
||||
};
|
||||
|
||||
struct sixel_source {
|
||||
const u_char *pixels;
|
||||
size_t stride;
|
||||
u_int width;
|
||||
u_int height;
|
||||
u_int canvas_width;
|
||||
u_int canvas_height;
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
};
|
||||
|
||||
static int
|
||||
sixel_parse_expand_lines(struct sixel_image *si, u_int y)
|
||||
{
|
||||
@@ -516,7 +550,7 @@ sixel_to_image(struct sixel_image *si)
|
||||
if (im == NULL)
|
||||
free(pixels);
|
||||
else
|
||||
im->sixel = si;
|
||||
image_set_sixel(im, si);
|
||||
return (im);
|
||||
}
|
||||
#endif
|
||||
@@ -763,26 +797,6 @@ sixel_print(struct sixel_image *si, struct sixel_image *map, size_t *size)
|
||||
return (buf);
|
||||
}
|
||||
|
||||
struct sixel_histogram {
|
||||
u_int count;
|
||||
uint64_t red;
|
||||
uint64_t green;
|
||||
uint64_t blue;
|
||||
};
|
||||
|
||||
struct sixel_box {
|
||||
u_int red_min, red_max;
|
||||
u_int green_min, green_max;
|
||||
u_int blue_min, blue_max;
|
||||
u_int count;
|
||||
};
|
||||
|
||||
struct sixel_rgb {
|
||||
u_char red;
|
||||
u_char green;
|
||||
u_char blue;
|
||||
};
|
||||
|
||||
/* Split a 5-bit RGB histogram into an adaptive palette using median cut. */
|
||||
static void
|
||||
sixel_box_update(struct sixel_box *box, struct sixel_histogram *histogram)
|
||||
@@ -992,7 +1006,8 @@ sixel_clamp_colour(int colour)
|
||||
}
|
||||
|
||||
static const u_char *
|
||||
sixel_from_image_pixel(struct image *im, u_int sourcex0, u_int sourcey0,
|
||||
sixel_from_image_pixel(const struct sixel_source *source, u_int sourcex0,
|
||||
u_int sourcey0,
|
||||
u_int sourcewidth, u_int sourceheight, u_int sx, u_int sy, u_int x,
|
||||
u_int y)
|
||||
{
|
||||
@@ -1000,11 +1015,11 @@ sixel_from_image_pixel(struct image *im, u_int sourcex0, u_int sourcey0,
|
||||
|
||||
sourcex = sourcex0 + (uint64_t)x * sourcewidth / sx;
|
||||
sourcey = sourcey0 + (uint64_t)y * sourceheight / sy;
|
||||
if (sourcex >= im->width)
|
||||
sourcex = im->width - 1;
|
||||
if (sourcey >= im->height)
|
||||
sourcey = im->height - 1;
|
||||
return (im->pixels + sourcey * im->stride + sourcex * 4);
|
||||
if (sourcex >= source->width)
|
||||
sourcex = source->width - 1;
|
||||
if (sourcey >= source->height)
|
||||
sourcey = source->height - 1;
|
||||
return (source->pixels + sourcey * source->stride + sourcex * 4);
|
||||
}
|
||||
|
||||
static struct sixel_image *
|
||||
@@ -1014,6 +1029,7 @@ sixel_from_image(struct image *im, u_int ox, u_int oy, u_int cells_x,
|
||||
struct sixel_image *si;
|
||||
struct sixel_histogram *histogram, *entry;
|
||||
struct sixel_rgb palette[SIXEL_PALETTE_SIZE];
|
||||
struct sixel_source source;
|
||||
const u_char *pixel;
|
||||
uint16_t *cache;
|
||||
int *current, *next, *tmp;
|
||||
@@ -1024,14 +1040,19 @@ sixel_from_image(struct image *im, u_int ox, u_int oy, u_int cells_x,
|
||||
uint64_t destination_width, destination_height;
|
||||
uint64_t content_width, content_height, x0, x1, y0, y1;
|
||||
|
||||
destination_width = (uint64_t)im->sx * xpixel;
|
||||
destination_height = (uint64_t)im->sy * ypixel;
|
||||
source.pixels = image_get_pixels(im, &source.stride, NULL);
|
||||
image_get_dimensions(im, &source.width, &source.height);
|
||||
image_get_canvas_dimensions(im, &source.canvas_width,
|
||||
&source.canvas_height);
|
||||
image_get_cell_dimensions(im, &source.sx, &source.sy);
|
||||
destination_width = (uint64_t)source.sx * xpixel;
|
||||
destination_height = (uint64_t)source.sy * ypixel;
|
||||
if (destination_width > UINT_MAX || destination_height > UINT_MAX)
|
||||
return (NULL);
|
||||
content_width = ((uint64_t)im->width * destination_width +
|
||||
im->canvas_width - 1) / im->canvas_width;
|
||||
content_height = ((uint64_t)im->height * destination_height +
|
||||
im->canvas_height - 1) / im->canvas_height;
|
||||
content_width = ((uint64_t)source.width * destination_width +
|
||||
source.canvas_width - 1) / source.canvas_width;
|
||||
content_height = ((uint64_t)source.height * destination_height +
|
||||
source.canvas_height - 1) / source.canvas_height;
|
||||
x0 = (uint64_t)ox * xpixel;
|
||||
y0 = (uint64_t)oy * ypixel;
|
||||
x1 = ((uint64_t)ox + cells_x) * xpixel;
|
||||
@@ -1055,7 +1076,7 @@ sixel_from_image(struct image *im, u_int ox, u_int oy, u_int cells_x,
|
||||
histogram = xcalloc(SIXEL_HISTOGRAM_SIZE, sizeof *histogram);
|
||||
for (y = 0; y < sy; y++) {
|
||||
for (x = 0; x < sx; x++) {
|
||||
pixel = sixel_from_image_pixel(im, sourcex0, sourcey0,
|
||||
pixel = sixel_from_image_pixel(&source, sourcex0, sourcey0,
|
||||
sourcewidth, sourceheight, sx, sy, x, y);
|
||||
if (pixel[3] < 128)
|
||||
continue;
|
||||
@@ -1095,7 +1116,7 @@ sixel_from_image(struct image *im, u_int ox, u_int oy, u_int cells_x,
|
||||
next = xcalloc(((size_t)sx + 2) * 3, sizeof *next);
|
||||
for (y = 0; y < sy; y++) {
|
||||
for (x = 0; x < sx; x++) {
|
||||
pixel = sixel_from_image_pixel(im, sourcex0, sourcey0,
|
||||
pixel = sixel_from_image_pixel(&source, sourcex0, sourcey0,
|
||||
sourcewidth, sourceheight, sx, sy, x, y);
|
||||
if (pixel[3] < 128)
|
||||
continue;
|
||||
@@ -1223,11 +1244,15 @@ sixel_geometry_changed(struct tty *tty)
|
||||
static struct sixel_image *
|
||||
sixel_render_image(struct image *im, u_int xpixel, u_int ypixel)
|
||||
{
|
||||
struct sixel_image *original;
|
||||
u_int sx, sy;
|
||||
|
||||
image_get_cell_dimensions(im, &sx, &sy);
|
||||
/* Preserve SIXEL's original palette and indexed pixels when possible. */
|
||||
if (im->sixel != NULL)
|
||||
return (sixel_scale(im->sixel, xpixel, ypixel, 0, 0,
|
||||
im->sx, im->sy, 1));
|
||||
return (sixel_from_image(im, 0, 0, im->sx, im->sy, xpixel, ypixel));
|
||||
original = image_get_sixel(im);
|
||||
if (original != NULL)
|
||||
return (sixel_scale(original, xpixel, ypixel, 0, 0, sx, sy, 1));
|
||||
return (sixel_from_image(im, 0, 0, sx, sy, xpixel, ypixel));
|
||||
}
|
||||
|
||||
static struct sixel_image *
|
||||
@@ -1240,7 +1265,8 @@ sixel_get_image(struct tty *tty, struct image *im)
|
||||
|
||||
sixel_collect_images(so);
|
||||
for (cache = so->images; cache != NULL; cache = cache->next) {
|
||||
if (cache->server_id != im->id || cache->xpixel != tty->xpixel ||
|
||||
if (cache->server_id != image_get_id(im) ||
|
||||
cache->xpixel != tty->xpixel ||
|
||||
cache->ypixel != tty->ypixel)
|
||||
continue;
|
||||
cache->age = ++so->age;
|
||||
@@ -1267,7 +1293,7 @@ sixel_get_image(struct tty *tty, struct image *im)
|
||||
sixel_remove_cache(so, oldest);
|
||||
}
|
||||
cache = xcalloc(1, sizeof *cache);
|
||||
cache->server_id = im->id;
|
||||
cache->server_id = image_get_id(im);
|
||||
cache->xpixel = tty->xpixel;
|
||||
cache->ypixel = tty->ypixel;
|
||||
cache->size = size;
|
||||
@@ -1301,13 +1327,16 @@ sixel_draw_rectangle(struct tty *tty, const struct image_rectangle *rectangle,
|
||||
struct sixel_image *si, *crop;
|
||||
char *data;
|
||||
size_t size;
|
||||
u_int source_x, source_y, width, height;
|
||||
u_int destination_x, destination_y;
|
||||
|
||||
si = sixel_get_image(tty, rectangle->image);
|
||||
si = sixel_get_image(tty, image_rectangle_get_image(rectangle));
|
||||
if (si == NULL)
|
||||
return;
|
||||
image_rectangle_get_coordinates(rectangle, &source_x, &source_y, &width,
|
||||
&height, &destination_x, &destination_y);
|
||||
crop = sixel_scale(si, tty->xpixel, tty->ypixel,
|
||||
rectangle->source_x, rectangle->source_y, rectangle->width,
|
||||
rectangle->height, 1);
|
||||
source_x, source_y, width, height, 1);
|
||||
if (!sixel_image_is_cached(tty, si))
|
||||
sixel_free(si);
|
||||
if (crop == NULL)
|
||||
@@ -1318,7 +1347,7 @@ sixel_draw_rectangle(struct tty *tty, const struct image_rectangle *rectangle,
|
||||
return;
|
||||
tty_region_off(tty);
|
||||
tty_margin_off(tty);
|
||||
tty_cursor(tty, rectangle->destination_x, rectangle->destination_y);
|
||||
tty_cursor(tty, destination_x, destination_y);
|
||||
tty->flags |= TTY_NOBLOCK;
|
||||
tty_putn(tty, data, size, 0);
|
||||
tty_invalidate(tty);
|
||||
|
||||
143
image.c
143
image.c
@@ -27,6 +27,60 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/* A protocol-neutral average of part of an image cell. RGB is premultiplied. */
|
||||
struct image_sample {
|
||||
u_char red;
|
||||
u_char green;
|
||||
u_char blue;
|
||||
u_char alpha;
|
||||
u_char brightness;
|
||||
};
|
||||
|
||||
/* Half blocks, quadrants and sextants all divide evenly into a 2 by 6 grid. */
|
||||
#define IMAGE_SAMPLE_COLUMNS 2
|
||||
#define IMAGE_SAMPLE_ROWS 6
|
||||
#define IMAGE_FLAG_NO_CURSOR 0x1
|
||||
struct image_cell {
|
||||
struct image_sample whole;
|
||||
struct image_sample samples[IMAGE_SAMPLE_ROWS][IMAGE_SAMPLE_COLUMNS];
|
||||
};
|
||||
|
||||
/* Immutable protocol-neutral image placement. */
|
||||
struct image {
|
||||
u_int id;
|
||||
u_int references;
|
||||
u_int flags;
|
||||
u_int parent_id;
|
||||
u_int source_id;
|
||||
u_int width;
|
||||
u_int height;
|
||||
u_int canvas_width;
|
||||
u_int canvas_height;
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
size_t stride;
|
||||
size_t size;
|
||||
u_char *pixels;
|
||||
/* Original indexed SIXEL data, if this image arrived as SIXEL. */
|
||||
struct sixel_image *sixel;
|
||||
struct image_cell *cells;
|
||||
|
||||
RB_ENTRY(image) entry;
|
||||
};
|
||||
RB_HEAD(images, image);
|
||||
|
||||
/* A cell-aligned part of an image to draw at a terminal position. */
|
||||
struct image_rectangle {
|
||||
struct image *image;
|
||||
struct grid_cell cell;
|
||||
u_int source_x;
|
||||
u_int source_y;
|
||||
u_int width;
|
||||
u_int height;
|
||||
u_int destination_x;
|
||||
u_int destination_y;
|
||||
};
|
||||
|
||||
static struct images images = RB_INITIALIZER(&images);
|
||||
static u_int image_next_id;
|
||||
|
||||
@@ -210,6 +264,93 @@ image_find(u_int id)
|
||||
return (RB_FIND(images, &images, &find));
|
||||
}
|
||||
|
||||
u_int
|
||||
image_get_id(const struct image *im)
|
||||
{
|
||||
return (im->id);
|
||||
}
|
||||
|
||||
void
|
||||
image_get_dimensions(const struct image *im, u_int *width, u_int *height)
|
||||
{
|
||||
if (width != NULL)
|
||||
*width = im->width;
|
||||
if (height != NULL)
|
||||
*height = im->height;
|
||||
}
|
||||
|
||||
void
|
||||
image_get_canvas_dimensions(const struct image *im, u_int *width,
|
||||
u_int *height)
|
||||
{
|
||||
if (width != NULL)
|
||||
*width = im->canvas_width;
|
||||
if (height != NULL)
|
||||
*height = im->canvas_height;
|
||||
}
|
||||
|
||||
void
|
||||
image_get_cell_dimensions(const struct image *im, u_int *sx, u_int *sy)
|
||||
{
|
||||
if (sx != NULL)
|
||||
*sx = im->sx;
|
||||
if (sy != NULL)
|
||||
*sy = im->sy;
|
||||
}
|
||||
|
||||
const u_char *
|
||||
image_get_pixels(const struct image *im, size_t *stride, size_t *size)
|
||||
{
|
||||
if (stride != NULL)
|
||||
*stride = im->stride;
|
||||
if (size != NULL)
|
||||
*size = im->size;
|
||||
return (im->pixels);
|
||||
}
|
||||
|
||||
void
|
||||
image_set_no_cursor(struct image *im)
|
||||
{
|
||||
im->flags |= IMAGE_FLAG_NO_CURSOR;
|
||||
}
|
||||
|
||||
struct sixel_image *
|
||||
image_get_sixel(const struct image *im)
|
||||
{
|
||||
return (im->sixel);
|
||||
}
|
||||
|
||||
void
|
||||
image_set_sixel(struct image *im, struct sixel_image *si)
|
||||
{
|
||||
im->sixel = si;
|
||||
}
|
||||
|
||||
struct image *
|
||||
image_rectangle_get_image(const struct image_rectangle *rectangle)
|
||||
{
|
||||
return (rectangle->image);
|
||||
}
|
||||
|
||||
const struct grid_cell *
|
||||
image_rectangle_get_cell(const struct image_rectangle *rectangle)
|
||||
{
|
||||
return (&rectangle->cell);
|
||||
}
|
||||
|
||||
void
|
||||
image_rectangle_get_coordinates(const struct image_rectangle *rectangle,
|
||||
u_int *source_x, u_int *source_y, u_int *width, u_int *height,
|
||||
u_int *destination_x, u_int *destination_y)
|
||||
{
|
||||
*source_x = rectangle->source_x;
|
||||
*source_y = rectangle->source_y;
|
||||
*width = rectangle->width;
|
||||
*height = rectangle->height;
|
||||
*destination_x = rectangle->destination_x;
|
||||
*destination_y = rectangle->destination_y;
|
||||
}
|
||||
|
||||
static struct image *
|
||||
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)
|
||||
@@ -318,7 +459,7 @@ image_free(u_int id)
|
||||
free(im);
|
||||
}
|
||||
|
||||
const struct image_cell *
|
||||
static const struct image_cell *
|
||||
image_get_cell(struct image *im, u_int x, u_int y)
|
||||
{
|
||||
if (im == NULL || x >= im->sx || y >= im->sy)
|
||||
|
||||
4
input.c
4
input.c
@@ -2844,10 +2844,10 @@ input_handle_kitty(struct input_ctx *ictx, const u_char *buf, size_t len)
|
||||
image_clear(sctx, replace_id);
|
||||
if (im != NULL) {
|
||||
if (action == 'd')
|
||||
image_clear(sctx, im->id);
|
||||
image_clear(sctx, image_get_id(im));
|
||||
else
|
||||
image_write(sctx, im, ictx->cell.cell.bg);
|
||||
image_free(im->id);
|
||||
image_free(image_get_id(im));
|
||||
if (quiet == 0 && image_id != 0)
|
||||
input_reply(ictx, 0, "\033_Gi=%u;OK\033\\", image_id);
|
||||
} else if (action == 'd' && image_id == 0)
|
||||
|
||||
@@ -3054,7 +3054,7 @@ screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si,
|
||||
return;
|
||||
}
|
||||
image_write(ctx, im, bg);
|
||||
image_free(im->id);
|
||||
image_free(image_get_id(im));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
76
tmux.h
76
tmux.h
@@ -1038,60 +1038,6 @@ struct style {
|
||||
};
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
/* A protocol-neutral average of part of an image cell. RGB is premultiplied. */
|
||||
struct image_sample {
|
||||
u_char red;
|
||||
u_char green;
|
||||
u_char blue;
|
||||
u_char alpha;
|
||||
u_char brightness;
|
||||
};
|
||||
|
||||
/* Half blocks, quadrants and sextants all divide evenly into a 2 by 6 grid. */
|
||||
#define IMAGE_SAMPLE_COLUMNS 2
|
||||
#define IMAGE_SAMPLE_ROWS 6
|
||||
#define IMAGE_FLAG_NO_CURSOR 0x1
|
||||
struct image_cell {
|
||||
struct image_sample whole;
|
||||
struct image_sample samples[IMAGE_SAMPLE_ROWS][IMAGE_SAMPLE_COLUMNS];
|
||||
};
|
||||
|
||||
/* Immutable protocol-neutral image placement. */
|
||||
struct image {
|
||||
u_int id;
|
||||
u_int references;
|
||||
u_int flags;
|
||||
u_int parent_id;
|
||||
u_int source_id;
|
||||
u_int width;
|
||||
u_int height;
|
||||
u_int canvas_width;
|
||||
u_int canvas_height;
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
size_t stride;
|
||||
size_t size;
|
||||
u_char *pixels;
|
||||
/* Original indexed SIXEL data, if this image arrived as SIXEL. */
|
||||
struct sixel_image *sixel;
|
||||
struct image_cell *cells; /* lazily generated text samples */
|
||||
|
||||
RB_ENTRY(image) entry;
|
||||
};
|
||||
RB_HEAD(images, image);
|
||||
|
||||
/* A cell-aligned part of an image to draw at a terminal position. */
|
||||
struct image_rectangle {
|
||||
struct image *image;
|
||||
struct grid_cell cell;
|
||||
u_int source_x;
|
||||
u_int source_y;
|
||||
u_int width;
|
||||
u_int height;
|
||||
u_int destination_x;
|
||||
u_int destination_y;
|
||||
};
|
||||
|
||||
#define IMAGE_SIZE_LIMIT (64 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
@@ -4274,6 +4220,14 @@ struct image *image_create(u_int, u_int, u_int, u_int, u_int, u_int,
|
||||
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 *);
|
||||
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 *);
|
||||
const u_char *image_get_pixels(const struct image *, size_t *, size_t *);
|
||||
void image_set_no_cursor(struct image *);
|
||||
struct sixel_image *image_get_sixel(const struct image *);
|
||||
void image_set_sixel(struct image *, struct sixel_image *);
|
||||
void image_ref(u_int);
|
||||
void image_free(u_int);
|
||||
void image_set_cell(struct grid_cell *, struct image *, u_int,
|
||||
@@ -4297,10 +4251,14 @@ void image_tty_geometry_changed(struct tty *);
|
||||
void image_tty_free(struct tty *, int);
|
||||
void image_draw_line(struct tty *, struct screen *, u_int, u_int,
|
||||
u_int, u_int, u_int, const struct tty_style_ctx *);
|
||||
const struct image_cell *image_get_cell(struct image *, u_int, u_int);
|
||||
void image_get_fallback_cell(struct tty *, struct image *, u_int,
|
||||
u_int, const struct grid_cell *, struct grid_cell *,
|
||||
const struct tty_style_ctx *);
|
||||
struct image *image_rectangle_get_image(const struct image_rectangle *);
|
||||
const struct grid_cell *image_rectangle_get_cell(
|
||||
const struct image_rectangle *);
|
||||
void image_rectangle_get_coordinates(const struct image_rectangle *,
|
||||
u_int *, u_int *, u_int *, u_int *, u_int *, u_int *);
|
||||
void image_clear(struct screen_write_ctx *, u_int);
|
||||
#define KITTY_PARSE_ERROR -1
|
||||
#define KITTY_PARSE_OK 0
|
||||
@@ -4315,15 +4273,15 @@ void kitty_draw_rectangle(struct tty *,
|
||||
const struct image_rectangle *, const struct tty_style_ctx *);
|
||||
void kitty_free_output(struct tty *, int);
|
||||
void kitty_geometry_changed(struct tty *);
|
||||
void sixel_draw_rectangle(struct tty *,
|
||||
const struct image_rectangle *, const struct tty_style_ctx *);
|
||||
void sixel_free_output(struct tty *, int);
|
||||
void sixel_geometry_changed(struct tty *);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SIXEL
|
||||
/* image-sixel.c */
|
||||
#define SIXEL_COLOUR_REGISTERS 1024
|
||||
void sixel_draw_rectangle(struct tty *,
|
||||
const struct image_rectangle *, const struct tty_style_ctx *);
|
||||
void sixel_free_output(struct tty *, int);
|
||||
void sixel_geometry_changed(struct tty *);
|
||||
struct sixel_image *sixel_parse(const char *, size_t, u_int, u_int, u_int);
|
||||
void sixel_free(struct sixel_image *);
|
||||
void sixel_log(struct sixel_image *);
|
||||
|
||||
Reference in New Issue
Block a user