mirror of
https://github.com/tmux/tmux.git
synced 2026-10-14 06:44:28 +00:00
SIXEL image placement.
This commit is contained in:
112
image-grid.c
112
image-grid.c
@@ -196,7 +196,7 @@ image_grid_add(struct grid *gd, struct image *im, u_int x, u_int y,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove the covered part of each span, retaining either side. */
|
/* Remove the covered part of a span. */
|
||||||
static void
|
static void
|
||||||
image_line_remove(struct image_line *line, u_int x, u_int w)
|
image_line_remove(struct image_line *line, u_int x, u_int w)
|
||||||
{
|
{
|
||||||
@@ -459,3 +459,113 @@ image_damage_screen(struct screen_write_ctx *ctx, u_int x, u_int y, u_int sx,
|
|||||||
if (ctx->flags & SCREEN_WRITE_INPUT)
|
if (ctx->flags & SCREEN_WRITE_INPUT)
|
||||||
image_grid_remove(s->grid, x, s->grid->hsize + y, sx, sy);
|
image_grid_remove(s->grid, x, s->grid->hsize + y, sx, sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return whether an image cell has any visible pixels. */
|
||||||
|
static int
|
||||||
|
image_cell_has_visible_pixels(struct image *im, u_int x, u_int y)
|
||||||
|
{
|
||||||
|
u_int px, py, sx, sy, xx, yy;
|
||||||
|
const u_char *pixels;
|
||||||
|
size_t stride;
|
||||||
|
|
||||||
|
image_get_pixel_area(im, x, y, 1, 1, &px, &py, &sx, &sy);
|
||||||
|
if (sx == 0 || sy == 0)
|
||||||
|
return (0);
|
||||||
|
pixels = image_get_pixels(im, &stride, NULL);
|
||||||
|
for (yy = py; yy < py + sy; yy++) {
|
||||||
|
for (xx = px; xx < px + sx; xx++) {
|
||||||
|
if (pixels[yy * stride + xx * 4 + 3] != 0)
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach the visible runs from one image row. */
|
||||||
|
static void
|
||||||
|
image_add_row(struct image_line *line, struct image_placement *plmt,
|
||||||
|
u_int cx, u_int src_y, u_int sx)
|
||||||
|
{
|
||||||
|
struct image *im = plmt->image;
|
||||||
|
u_int x, run;
|
||||||
|
|
||||||
|
for (x = 0; x < sx; x += run) {
|
||||||
|
if (!image_cell_has_visible_pixels(im, x, src_y)) {
|
||||||
|
run = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (run = 1; x + run < sx; run++) {
|
||||||
|
if (!image_cell_has_visible_pixels(im, x + run, src_y))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
image_span_add(line, plmt, cx + x, run, x, src_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Place a SIXEL image at the cursor. */
|
||||||
|
void
|
||||||
|
image_write(struct screen_write_ctx *ctx, struct image *im, u_int bg)
|
||||||
|
{
|
||||||
|
struct screen *s = ctx->s;
|
||||||
|
struct grid *gd = s->grid;
|
||||||
|
struct image_placement *plmt;
|
||||||
|
struct grid_line *gl;
|
||||||
|
struct image_line *line;
|
||||||
|
u_int cx = s->cx, cy = s->cy, y, sx, sy, lines;
|
||||||
|
u_int origin_y = 0, h_origin_y, region_height;
|
||||||
|
u_int remaining, n;
|
||||||
|
|
||||||
|
image_get_size_in_cells(im, &sx, &sy);
|
||||||
|
if (sx > screen_size_x(s) - cx)
|
||||||
|
sx = screen_size_x(s) - cx;
|
||||||
|
if (sx == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Scroll images that move the cursor. */
|
||||||
|
if (screen_size_y(s) - cy <= sy) {
|
||||||
|
lines = sy - (screen_size_y(s) - cy) + 1;
|
||||||
|
region_height = s->rlower - s->rupper + 1;
|
||||||
|
|
||||||
|
remaining = lines;
|
||||||
|
while (remaining > 0) {
|
||||||
|
if (remaining < region_height)
|
||||||
|
n = remaining;
|
||||||
|
else
|
||||||
|
n = region_height;
|
||||||
|
screen_write_scrollup(ctx, n, bg);
|
||||||
|
remaining -= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lines > cy) {
|
||||||
|
origin_y = lines - cy;
|
||||||
|
screen_write_cursormove(ctx, -1, 0, 0);
|
||||||
|
} else {
|
||||||
|
origin_y = 0;
|
||||||
|
screen_write_cursormove(ctx, -1, cy - lines, 0);
|
||||||
|
}
|
||||||
|
cy = s->cy;
|
||||||
|
sy -= origin_y;
|
||||||
|
}
|
||||||
|
plmt = image_placement_create(gd, im);
|
||||||
|
|
||||||
|
/* Attach scrolled image rows to the available history lines. */
|
||||||
|
h_origin_y = origin_y;
|
||||||
|
if (h_origin_y > gd->hsize)
|
||||||
|
h_origin_y = gd->hsize;
|
||||||
|
for (y = 0; y < h_origin_y; y++) {
|
||||||
|
gl = &gd->linedata[gd->hsize - h_origin_y + y];
|
||||||
|
line = image_line_get(gl);
|
||||||
|
image_add_row(line, plmt, cx, origin_y - h_origin_y + y, sx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach visible image rows. */
|
||||||
|
for (y = 0; y < sy; y++) {
|
||||||
|
line = image_line_get(&gd->linedata[gd->hsize + cy + y]);
|
||||||
|
image_add_row(line, plmt, cx, origin_y + y, sx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Schedule a redraw and advance the cursor past the image. */
|
||||||
|
image_store_prune(gd->images);
|
||||||
|
image_redraw_area(ctx, cx, cy, sx, sy);
|
||||||
|
screen_write_cursormove(ctx, 0, cy + sy, 0);
|
||||||
|
}
|
||||||
|
|||||||
@@ -515,10 +515,10 @@ sixel_to_image(struct sixel_image *si)
|
|||||||
(uint64_t)sy * si->ypixel > UINT_MAX)
|
(uint64_t)sy * si->ypixel > UINT_MAX)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
pixels = xcalloc((size_t)si->x * si->y, 4);
|
pixels = xcalloc(si->x * si->y, 4);
|
||||||
for (y = 0; y < si->y; y++) {
|
for (y = 0; y < si->y; y++) {
|
||||||
for (x = 0; x < si->x; x++) {
|
for (x = 0; x < si->x; x++) {
|
||||||
pixel = pixels + ((size_t)y * si->x + x) * 4;
|
pixel = pixels + (y * si->x + x) * 4;
|
||||||
|
|
||||||
c = sixel_get_pixel(si, x, y);
|
c = sixel_get_pixel(si, x, y);
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
@@ -545,8 +545,7 @@ sixel_to_image(struct sixel_image *si)
|
|||||||
|
|
||||||
/* Write a SIXEL image. */
|
/* Write a SIXEL image. */
|
||||||
void
|
void
|
||||||
sixel_write(__unused struct screen_write_ctx *ctx, struct sixel_image *si,
|
sixel_write(struct screen_write_ctx *ctx, struct sixel_image *si, u_int bg)
|
||||||
__unused u_int bg)
|
|
||||||
{
|
{
|
||||||
struct image *im;
|
struct image *im;
|
||||||
|
|
||||||
@@ -554,6 +553,6 @@ sixel_write(__unused struct screen_write_ctx *ctx, struct sixel_image *si,
|
|||||||
sixel_free(si);
|
sixel_free(si);
|
||||||
if (im == NULL)
|
if (im == NULL)
|
||||||
return;
|
return;
|
||||||
/* XXX image_write_sixel */
|
image_write(ctx, im, bg);
|
||||||
image_free(im);
|
image_free(im);
|
||||||
}
|
}
|
||||||
|
|||||||
39
image.c
39
image.c
@@ -302,3 +302,42 @@ image_size_in_cells(u_int w, u_int h, u_int xpixel, u_int ypixel, u_int *sx,
|
|||||||
*sx = w / xpixel + (w % xpixel != 0);
|
*sx = w / xpixel + (w % xpixel != 0);
|
||||||
*sy = h / ypixel + (h % ypixel != 0);
|
*sy = h / ypixel + (h % ypixel != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find area covered by a rectangle of cells in pixels. */
|
||||||
|
void
|
||||||
|
image_get_pixel_area(struct image *im, u_int x, u_int y, u_int w, u_int h,
|
||||||
|
u_int *px, u_int *py, u_int *pw, u_int *ph)
|
||||||
|
{
|
||||||
|
u_int left, top, right, bottom;
|
||||||
|
|
||||||
|
*px = *py = *pw = *ph = 0;
|
||||||
|
|
||||||
|
if (im == NULL || x >= im->sx || y >= im->sy || w == 0 || h == 0)
|
||||||
|
return;
|
||||||
|
if (w > im->sx - x)
|
||||||
|
w = im->sx - x;
|
||||||
|
if (h > im->sy - y)
|
||||||
|
h = im->sy - y;
|
||||||
|
|
||||||
|
left = (uint64_t)x * im->canvas_width / im->sx;
|
||||||
|
top = (uint64_t)y * im->canvas_height / im->sy;
|
||||||
|
right = ((uint64_t)(x + w) * im->canvas_width + im->sx - 1) / im->sx;
|
||||||
|
bottom = ((uint64_t)(y + h) * im->canvas_height + im->sy - 1) / im->sy;
|
||||||
|
|
||||||
|
if (left >= im->width || top >= im->height)
|
||||||
|
*px = *py = 0;
|
||||||
|
else {
|
||||||
|
if (right <= left)
|
||||||
|
right = left + 1;
|
||||||
|
if (bottom <= top)
|
||||||
|
bottom = top + 1;
|
||||||
|
if (right > im->width)
|
||||||
|
right = im->width;
|
||||||
|
if (bottom > im->height)
|
||||||
|
bottom = im->height;
|
||||||
|
*px = left;
|
||||||
|
*py = top;
|
||||||
|
*pw = right - left;
|
||||||
|
*ph = bottom - top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ void image_get_size_in_cells(struct image *, u_int *, u_int *);
|
|||||||
const u_char *image_get_pixels(struct image *, size_t *, size_t *);
|
const u_char *image_get_pixels(struct image *, size_t *, size_t *);
|
||||||
void image_size_in_cells(u_int, u_int, u_int, u_int, u_int *,
|
void image_size_in_cells(u_int, u_int, u_int, u_int, u_int *,
|
||||||
u_int *);
|
u_int *);
|
||||||
|
void image_get_pixel_area(struct image *, u_int, u_int, u_int,
|
||||||
|
u_int, u_int *, u_int *, u_int *, u_int *);
|
||||||
|
|
||||||
/* image-grid.c */
|
/* image-grid.c */
|
||||||
void image_grid_add(struct grid *, struct image *, u_int, u_int,
|
void image_grid_add(struct grid *, struct image *, u_int, u_int,
|
||||||
@@ -92,6 +94,7 @@ void image_redraw_all(struct screen_write_ctx *);
|
|||||||
void image_redraw_scroll(struct screen_write_ctx *);
|
void image_redraw_scroll(struct screen_write_ctx *);
|
||||||
void image_damage_screen(struct screen_write_ctx *, u_int, u_int,
|
void image_damage_screen(struct screen_write_ctx *, u_int, u_int,
|
||||||
u_int, u_int);
|
u_int, u_int);
|
||||||
|
void image_write(struct screen_write_ctx *, struct image *, u_int);
|
||||||
|
|
||||||
/* image-sixel.c */
|
/* image-sixel.c */
|
||||||
#define SIXEL_COLOUR_REGISTERS 1024
|
#define SIXEL_COLOUR_REGISTERS 1024
|
||||||
|
|||||||
Reference in New Issue
Block a user