mirror of
https://github.com/tmux/tmux.git
synced 2026-10-15 07:44:24 +00:00
SIXEL draw bits.
This commit is contained in:
68
image-grid.c
68
image-grid.c
@@ -88,6 +88,9 @@ struct image_backend {
|
|||||||
const char *name;
|
const char *name;
|
||||||
int flags;
|
int flags;
|
||||||
int (*select)(struct tty *);
|
int (*select)(struct tty *);
|
||||||
|
const struct grid_cell *(*map_cell)(struct tty *, struct grid *, u_int,
|
||||||
|
u_int, const struct grid_cell *, struct grid_cell *,
|
||||||
|
int *);
|
||||||
void (*draw_rect)(struct tty *, struct image_rect *);
|
void (*draw_rect)(struct tty *, struct image_rect *);
|
||||||
void (*start_draw)(struct tty *, u_int, u_int, u_int, u_int);
|
void (*start_draw)(struct tty *, u_int, u_int, u_int, u_int);
|
||||||
void (*flush)(struct tty *);
|
void (*flush)(struct tty *);
|
||||||
@@ -99,6 +102,7 @@ static struct image_backend image_backend_fallback = {
|
|||||||
"fallback",
|
"fallback",
|
||||||
IMAGE_BACKEND_SCROLLS,
|
IMAGE_BACKEND_SCROLLS,
|
||||||
fallback_select,
|
fallback_select,
|
||||||
|
fallback_map_cell,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -108,6 +112,7 @@ static struct image_backend image_backend_sixel = {
|
|||||||
"sixel",
|
"sixel",
|
||||||
IMAGE_BACKEND_GRAPHICAL,
|
IMAGE_BACKEND_GRAPHICAL,
|
||||||
sixel_select,
|
sixel_select,
|
||||||
|
NULL,
|
||||||
sixel_draw_rect,
|
sixel_draw_rect,
|
||||||
sixel_start_draw,
|
sixel_start_draw,
|
||||||
sixel_flush_pending,
|
sixel_flush_pending,
|
||||||
@@ -142,6 +147,69 @@ image_tty_update(struct tty *tty)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Map an image grid cell to text for the selected backend. */
|
||||||
|
const struct grid_cell *
|
||||||
|
image_map_cell(struct tty *tty, struct grid *gd, u_int x, u_int y,
|
||||||
|
const struct grid_cell *gc, struct grid_cell *out, int *empty)
|
||||||
|
{
|
||||||
|
image_tty_update(tty);
|
||||||
|
if (tty->image_backend->map_cell == NULL)
|
||||||
|
return (gc);
|
||||||
|
return (tty->image_backend->map_cell(tty, gd, x, y, gc, out, empty));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw a clipped part of one image span. */
|
||||||
|
static void
|
||||||
|
image_draw_span(struct image_backend *backend, struct tty *tty,
|
||||||
|
struct image_span *span, u_int start, u_int end, u_int px, u_int atx,
|
||||||
|
u_int aty)
|
||||||
|
{
|
||||||
|
struct image_rect rect;
|
||||||
|
|
||||||
|
rect.image = span->placement->image;
|
||||||
|
rect.src_x = span->source_x + start - span->x;
|
||||||
|
rect.src_y = span->source_y;
|
||||||
|
rect.sx = end - start;
|
||||||
|
rect.sy = 1;
|
||||||
|
rect.dst_x = atx + start - px;
|
||||||
|
rect.dst_y = aty;
|
||||||
|
backend->draw_rect(tty, &rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw images in the visible part of one screen line. */
|
||||||
|
void
|
||||||
|
image_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py,
|
||||||
|
u_int nx, u_int atx, u_int aty)
|
||||||
|
{
|
||||||
|
struct image_backend *backend;
|
||||||
|
struct image_line *line;
|
||||||
|
struct image_span *span;
|
||||||
|
u_int start, end, span_end;
|
||||||
|
|
||||||
|
image_tty_update(tty);
|
||||||
|
backend = tty->image_backend;
|
||||||
|
if (backend->draw_rect == NULL)
|
||||||
|
return;
|
||||||
|
if (py >= s->grid->sy)
|
||||||
|
return;
|
||||||
|
line = s->grid->linedata[s->grid->hsize + py].images;
|
||||||
|
if (line == NULL)
|
||||||
|
return;
|
||||||
|
end = px + nx;
|
||||||
|
TAILQ_FOREACH(span, &line->spans, line_entry) {
|
||||||
|
span_end = span->x + span->sx;
|
||||||
|
start = span->x;
|
||||||
|
if (start < px)
|
||||||
|
start = px;
|
||||||
|
if (start >= end || span_end <= px)
|
||||||
|
continue;
|
||||||
|
if (span_end > end)
|
||||||
|
span_end = end;
|
||||||
|
image_draw_span(backend, tty, span, start, span_end, px, atx,
|
||||||
|
aty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Clear old image pixels before redrawing a terminal area. */
|
/* Clear old image pixels before redrawing a terminal area. */
|
||||||
void
|
void
|
||||||
image_redraw_start(struct tty *tty, u_int x, u_int y, u_int w, u_int h)
|
image_redraw_start(struct tty *tty, u_int x, u_int y, u_int w, u_int h)
|
||||||
|
|||||||
@@ -1525,6 +1525,12 @@ redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span,
|
|||||||
case REDRAW_SPAN_PANE:
|
case REDRAW_SPAN_PANE:
|
||||||
if (phase == REDRAW_TEXT)
|
if (phase == REDRAW_TEXT)
|
||||||
redraw_draw_pane_span(dctx, span, span->x, y, width);
|
redraw_draw_pane_span(dctx, span, span->x, y, width);
|
||||||
|
#ifdef ENABLE_IMAGES
|
||||||
|
else {
|
||||||
|
image_draw_line(&dctx->scene->c->tty, data->p.wp->screen,
|
||||||
|
data->p.px, data->p.py, width, span->x, y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case REDRAW_SPAN_BORDER:
|
case REDRAW_SPAN_BORDER:
|
||||||
case REDRAW_SPAN_EMPTY:
|
case REDRAW_SPAN_EMPTY:
|
||||||
@@ -1565,6 +1571,26 @@ redraw_draw_pane_lines(struct redraw_draw_ctx *dctx, struct window_pane *wp,
|
|||||||
if (bottom > (int)scene->sy)
|
if (bottom > (int)scene->sy)
|
||||||
bottom = scene->sy;
|
bottom = scene->sy;
|
||||||
|
|
||||||
|
#ifdef ENABLE_IMAGES
|
||||||
|
/* Erase only pane-owned spans so overlapping panes remain intact. */
|
||||||
|
if (flags & REDRAW_PANE) {
|
||||||
|
for (y = top; y < bottom; y++) {
|
||||||
|
line = &scene->lines[y];
|
||||||
|
if (dctx->flags & REDRAW_STATUS_TOP)
|
||||||
|
cy = dctx->status_lines + y;
|
||||||
|
else
|
||||||
|
cy = y;
|
||||||
|
spans = &line->spans[REDRAW_SPAN_PANE];
|
||||||
|
TAILQ_FOREACH(span, spans, entry) {
|
||||||
|
if (span->data.p.wp == wp) {
|
||||||
|
image_redraw_start(&scene->c->tty,
|
||||||
|
span->x, cy, span->width, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Draw each phase. */
|
/* Draw each phase. */
|
||||||
for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) {
|
for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) {
|
||||||
for (y = top; y < bottom; y++) {
|
for (y = top; y < bottom; y++) {
|
||||||
@@ -1591,6 +1617,9 @@ redraw_draw_pane_lines(struct redraw_draw_ctx *dctx, struct window_pane *wp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_IMAGES
|
||||||
|
image_draw_flush(&scene->c->tty);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1651,6 +1680,9 @@ redraw_draw_lines(struct redraw_draw_ctx *dctx, int flags)
|
|||||||
redraw_draw_span(dctx, span, cy, phase);
|
redraw_draw_span(dctx, span, cy, phase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_IMAGES
|
||||||
|
image_draw_flush(&scene->c->tty);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1906,6 +1938,14 @@ redraw_draw(struct client *c, struct window_pane *wp, int flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tty_sync_start(tty); /* end in server_client_reset_state */
|
tty_sync_start(tty); /* end in server_client_reset_state */
|
||||||
|
#ifdef ENABLE_IMAGES
|
||||||
|
if (wp == NULL && (flags & REDRAW_PANE)) {
|
||||||
|
y = 0;
|
||||||
|
if (dctx.flags & REDRAW_STATUS_TOP)
|
||||||
|
y = dctx.status_lines;
|
||||||
|
image_redraw_start(tty, 0, y, scene->sx, scene->sy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
tty_update_mode(tty, tty->mode & ~CURSOR_MODES, NULL);
|
tty_update_mode(tty, tty->mode & ~CURSOR_MODES, NULL);
|
||||||
|
|
||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
@@ -2084,6 +2124,30 @@ redraw_draw_damage_rectangle(struct redraw_draw_ctx *dctx, u_int x, u_int y,
|
|||||||
if (sx == 0 || sy == 0)
|
if (sx == 0 || sy == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef ENABLE_IMAGES
|
||||||
|
/* Clear old image pixels on all damaged spans. */
|
||||||
|
for (yy = y; yy < y + sy; yy++) {
|
||||||
|
line = &scene->lines[yy];
|
||||||
|
if (dctx->flags & REDRAW_STATUS_TOP)
|
||||||
|
cy = dctx->status_lines + yy;
|
||||||
|
else
|
||||||
|
cy = yy;
|
||||||
|
for (type = 0; type < REDRAW_SPAN_TYPES; type++) {
|
||||||
|
if (type == REDRAW_SPAN_STATUS)
|
||||||
|
continue;
|
||||||
|
spans = &line->spans[type];
|
||||||
|
TAILQ_FOREACH(span, spans, entry) {
|
||||||
|
if (span->x >= x + sx)
|
||||||
|
continue;
|
||||||
|
if (span->x + span->width <= x)
|
||||||
|
continue;
|
||||||
|
image_redraw_start(&scene->c->tty,
|
||||||
|
span->x, cy, span->width, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Draw each phase in the damaged spans. */
|
/* Draw each phase in the damaged spans. */
|
||||||
for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) {
|
for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) {
|
||||||
for (yy = y; yy < y + sy; yy++) {
|
for (yy = y; yy < y + sy; yy++) {
|
||||||
@@ -2108,6 +2172,9 @@ redraw_draw_damage_rectangle(struct redraw_draw_ctx *dctx, u_int x, u_int y,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_IMAGES
|
||||||
|
image_draw_flush(&scene->c->tty);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw prompts and pane status lines last. */
|
/* Draw prompts and pane status lines last. */
|
||||||
|
|||||||
@@ -126,6 +126,10 @@ void image_damage_screen(struct screen_write_ctx *, u_int, u_int,
|
|||||||
void image_write(struct screen_write_ctx *, struct image *, u_int);
|
void image_write(struct screen_write_ctx *, struct image *, u_int);
|
||||||
int image_grid_get_at(struct grid *, u_int, u_int, struct image **,
|
int image_grid_get_at(struct grid *, u_int, u_int, struct image **,
|
||||||
u_int *, u_int *);
|
u_int *, u_int *);
|
||||||
|
const struct grid_cell *image_map_cell(struct tty *, struct grid *, u_int,
|
||||||
|
u_int, const struct grid_cell *, struct grid_cell *, int *);
|
||||||
|
void image_draw_line(struct tty *, struct screen *, u_int, u_int,
|
||||||
|
u_int, u_int, u_int);
|
||||||
void image_redraw_start(struct tty *, u_int, u_int, u_int, u_int);
|
void image_redraw_start(struct tty *, u_int, u_int, u_int, u_int);
|
||||||
void image_draw_flush(struct tty *);
|
void image_draw_flush(struct tty *);
|
||||||
int image_tty_update(struct tty *);
|
int image_tty_update(struct tty *);
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
|
|
||||||
#ifdef ENABLE_IMAGES
|
#ifdef ENABLE_IMAGES
|
||||||
/* Map an image cell if needed. */
|
/* Map an image cell if needed. */
|
||||||
gcp = fallback_map_cell(tty, gd, px + i,
|
gcp = image_map_cell(tty, gd, px + i,
|
||||||
gd->hsize + py, gcp, &gc, &empty);
|
gd->hsize + py, gcp, &gc, &empty);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -278,7 +278,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
|
|
||||||
#ifdef ENABLE_IMAGES
|
#ifdef ENABLE_IMAGES
|
||||||
/* Map an image cell if needed. */
|
/* Map an image cell if needed. */
|
||||||
gcp = fallback_map_cell(tty, gd, px + i,
|
gcp = image_map_cell(tty, gd, px + i,
|
||||||
gd->hsize + py, gcp, &gc, NULL);
|
gd->hsize + py, gcp, &gc, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user