mirror of
https://github.com/tmux/tmux.git
synced 2026-08-28 09:31:34 +00:00
Redraw SIXEL images before or after text depending on which was placed first in the cell.
This commit is contained in:
@@ -50,6 +50,7 @@ struct sixel_image {
|
||||
u_int *colours;
|
||||
u_int ncolours;
|
||||
u_int used_colours;
|
||||
u_int p1;
|
||||
u_int p2;
|
||||
|
||||
u_int dx;
|
||||
@@ -356,7 +357,8 @@ sixel_parse_repeat(struct sixel_image *si, const char *cp, const char *end)
|
||||
|
||||
/* Parse SIXEL data into an indexed image. */
|
||||
struct sixel_image *
|
||||
sixel_parse(const char *buf, size_t len, u_int p2, u_int xpixel, u_int ypixel)
|
||||
sixel_parse(const char *buf, size_t len, u_int p1, u_int p2, u_int xpixel,
|
||||
u_int ypixel)
|
||||
{
|
||||
struct sixel_image *si;
|
||||
const char *cp = buf, *end = buf + len;
|
||||
@@ -370,6 +372,7 @@ sixel_parse(const char *buf, size_t len, u_int p2, u_int xpixel, u_int ypixel)
|
||||
si = xcalloc (1, sizeof *si);
|
||||
si->xpixel = xpixel;
|
||||
si->ypixel = ypixel;
|
||||
si->p1 = p1;
|
||||
si->p2 = p2;
|
||||
|
||||
while (cp != end) {
|
||||
@@ -609,18 +612,13 @@ sixel_scale(struct sixel_image *si, u_int xpixel, u_int ypixel, u_int ox,
|
||||
new = xcalloc (1, sizeof *si);
|
||||
new->xpixel = xpixel;
|
||||
new->ypixel = ypixel;
|
||||
new->p1 = si->p1;
|
||||
new->p2 = si->p2;
|
||||
|
||||
new->set_ra = si->set_ra;
|
||||
/* subtract offset */
|
||||
new->ra_x = si->ra_x > pox ? si->ra_x - pox : 0;
|
||||
new->ra_y = si->ra_y > poy ? si->ra_y - poy : 0;
|
||||
/* clamp to size */
|
||||
new->ra_x = new->ra_x < psx ? new->ra_x : psx;
|
||||
new->ra_y = new->ra_y < psy ? new->ra_y : psy;
|
||||
/* resize */
|
||||
new->ra_x = new->ra_x * xpixel / si->xpixel;
|
||||
new->ra_y = new->ra_y * ypixel / si->ypixel;
|
||||
/* The raster attributes describe the scaled output rectangle. */
|
||||
new->ra_x = tsx;
|
||||
new->ra_y = tsy;
|
||||
|
||||
new->used_colours = si->used_colours;
|
||||
for (y = 0; y < tsy; y++) {
|
||||
@@ -753,7 +751,7 @@ sixel_print(struct sixel_image *si, struct sixel_image *map, size_t *size)
|
||||
len = 8192;
|
||||
buf = xmalloc(len);
|
||||
|
||||
tmplen = xsnprintf(tmp, sizeof tmp, "\033P9;%uq", si->p2);
|
||||
tmplen = xsnprintf(tmp, sizeof tmp, "\033P%u;%uq", si->p1, si->p2);
|
||||
sixel_print_add(&buf, &len, &used, tmp, tmplen);
|
||||
|
||||
if (si->set_ra) {
|
||||
@@ -1133,6 +1131,7 @@ sixel_from_image(struct image *im, u_int ox, u_int oy, u_int cells_x,
|
||||
si = xcalloc(1, sizeof *si);
|
||||
si->xpixel = xpixel;
|
||||
si->ypixel = ypixel;
|
||||
si->p1 = 9;
|
||||
si->p2 = 1;
|
||||
si->set_ra = 1;
|
||||
si->ra_x = sx;
|
||||
@@ -1417,7 +1416,8 @@ sixel_draw_rect(struct tty *tty, const struct image_rect *rectangle,
|
||||
tty_cursor(tty, destination_x, destination_y);
|
||||
tty->flags |= TTY_NOBLOCK;
|
||||
tty_putn(tty, data, size, 0);
|
||||
tty_invalidate(tty);
|
||||
/* SIXEL moves the cursor, but does not change terminal attributes. */
|
||||
tty->cx = tty->cy = UINT_MAX;
|
||||
free(data);
|
||||
}
|
||||
|
||||
|
||||
33
image.c
33
image.c
@@ -570,6 +570,11 @@ image_get_draw_cell(struct tty *tty, const struct grid_cell *gc,
|
||||
GRID_FLAG_SELECTED);
|
||||
return (1);
|
||||
}
|
||||
if (gc->flags & GRID_FLAG_IMAGE_DAMAGED) {
|
||||
memcpy(out, gc, sizeof *out);
|
||||
out->flags &= ~(GRID_FLAG_IMAGE|GRID_FLAG_IMAGE_DAMAGED);
|
||||
return (0);
|
||||
}
|
||||
image_get_fallback_cell(tty, im, gc->image_x, gc->image_y, gc, out,
|
||||
style_ctx);
|
||||
return (0);
|
||||
@@ -787,10 +792,11 @@ image_redraw_scroll(struct screen_write_ctx *ctx, __unused u_int lines)
|
||||
image_redraw_all(ctx);
|
||||
}
|
||||
|
||||
/* Draw the graphical image marker runs in one visible scene span. */
|
||||
/* Draw a span's graphical image markers before or after its text. */
|
||||
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, const struct tty_style_ctx *style_ctx)
|
||||
u_int nx, u_int atx, u_int aty, int before,
|
||||
const struct tty_style_ctx *style_ctx)
|
||||
{
|
||||
const struct image_backend *backend;
|
||||
struct image_rect rectangle;
|
||||
@@ -802,6 +808,8 @@ image_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py,
|
||||
backend = tty->image_backend;
|
||||
if (~backend->flags & IMAGE_BACKEND_GRAPHICAL)
|
||||
return;
|
||||
if (before && (~backend->flags & IMAGE_BACKEND_TEMPORAL))
|
||||
return;
|
||||
|
||||
for (i = 0; i < nx; i += run) {
|
||||
grid_view_get_cell(s->grid, px + i, py, &gc);
|
||||
@@ -809,10 +817,12 @@ image_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py,
|
||||
run = 1;
|
||||
continue;
|
||||
}
|
||||
if ((backend->flags & IMAGE_BACKEND_TEMPORAL) &&
|
||||
(gc.flags & GRID_FLAG_IMAGE_DAMAGED)) {
|
||||
run = 1;
|
||||
continue;
|
||||
if (backend->flags & IMAGE_BACKEND_TEMPORAL) {
|
||||
if ((before && (~gc.flags & GRID_FLAG_IMAGE_DAMAGED)) ||
|
||||
(!before && (gc.flags & GRID_FLAG_IMAGE_DAMAGED))) {
|
||||
run = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
im = image_find(gc.image_id);
|
||||
if (im == NULL) {
|
||||
@@ -821,10 +831,13 @@ image_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py,
|
||||
}
|
||||
for (run = 1; i + run < nx; run++) {
|
||||
grid_view_get_cell(s->grid, px + i + run, py, &next);
|
||||
if (~next.flags & GRID_FLAG_IMAGE ||
|
||||
((backend->flags & IMAGE_BACKEND_TEMPORAL) &&
|
||||
(next.flags & GRID_FLAG_IMAGE_DAMAGED)) ||
|
||||
next.image_id != gc.image_id ||
|
||||
if (~next.flags & GRID_FLAG_IMAGE)
|
||||
break;
|
||||
if ((backend->flags & IMAGE_BACKEND_TEMPORAL) &&
|
||||
((before && (~next.flags & GRID_FLAG_IMAGE_DAMAGED)) ||
|
||||
(!before && (next.flags & GRID_FLAG_IMAGE_DAMAGED))))
|
||||
break;
|
||||
if (next.image_id != gc.image_id ||
|
||||
next.image_y != gc.image_y ||
|
||||
next.image_x != gc.image_x + run)
|
||||
break;
|
||||
|
||||
7
input.c
7
input.c
@@ -2638,7 +2638,7 @@ input_dcs_dispatch(struct input_ctx *ictx)
|
||||
#ifdef ENABLE_IMAGES
|
||||
struct window *w;
|
||||
struct sixel_image *si;
|
||||
int p2;
|
||||
int p1, p2;
|
||||
#endif
|
||||
|
||||
if (wp == NULL)
|
||||
@@ -2656,10 +2656,13 @@ input_dcs_dispatch(struct input_ctx *ictx)
|
||||
w = wp->window;
|
||||
if (input_split(ictx) != 0)
|
||||
return (0);
|
||||
p1 = input_get(ictx, 0, 0, 0);
|
||||
if (p1 == -1)
|
||||
p1 = 0;
|
||||
p2 = input_get(ictx, 1, 0, 0);
|
||||
if (p2 == -1)
|
||||
p2 = 0;
|
||||
si = sixel_parse(buf, len, p2, w->xpixel, w->ypixel);
|
||||
si = sixel_parse(buf, len, p1, p2, w->xpixel, w->ypixel);
|
||||
if (si != NULL)
|
||||
screen_write_sixelimage(sctx, si, ictx->cell.cell.bg);
|
||||
}
|
||||
|
||||
6
resize.c
6
resize.c
@@ -386,10 +386,12 @@ recalculate_size(struct window *w, int now)
|
||||
* got a resize scheduled, then use the new size; otherwise the old.
|
||||
*/
|
||||
if (w->flags & WINDOW_RESIZE) {
|
||||
if (!now && changed && w->new_sx == sx && w->new_sy == sy)
|
||||
if (!now && changed && w->new_sx == sx && w->new_sy == sy &&
|
||||
w->new_xpixel == xpixel && w->new_ypixel == ypixel)
|
||||
changed = 0;
|
||||
} else {
|
||||
if (!now && changed && w->sx == sx && w->sy == sy)
|
||||
if (!now && changed && w->sx == sx && w->sy == sy &&
|
||||
w->xpixel == xpixel && w->ypixel == ypixel)
|
||||
changed = 0;
|
||||
}
|
||||
|
||||
|
||||
117
screen-redraw.c
117
screen-redraw.c
@@ -99,6 +99,12 @@ enum redraw_span_type {
|
||||
#define REDRAW_ALL 0x7fffffff
|
||||
#define REDRAW_IS_ALL(flags) ((flags) == REDRAW_ALL)
|
||||
|
||||
enum redraw_image_phase {
|
||||
REDRAW_IMAGES_BEFORE,
|
||||
REDRAW_TEXT,
|
||||
REDRAW_IMAGES_AFTER
|
||||
};
|
||||
|
||||
/* UTF-8 isolate characters. */
|
||||
#define REDRAW_START_ISOLATE "\342\201\246"
|
||||
#define REDRAW_END_ISOLATE "\342\201\251"
|
||||
@@ -1237,7 +1243,8 @@ redraw_get_scene(struct client *c)
|
||||
/* Draw a pane span. */
|
||||
static void
|
||||
redraw_draw_pane_span(struct redraw_draw_ctx *dctx,
|
||||
struct redraw_span *span, u_int x, u_int y, u_int n)
|
||||
struct redraw_span *span, u_int x, u_int y, u_int n,
|
||||
enum redraw_image_phase phase)
|
||||
{
|
||||
struct redraw_scene *scene = dctx->scene;
|
||||
struct client *c = scene->c;
|
||||
@@ -1255,10 +1262,14 @@ redraw_draw_pane_span(struct redraw_draw_ctx *dctx,
|
||||
|
||||
px = span->data.p.px + (x - span->x);
|
||||
py = span->data.p.py;
|
||||
tty_draw_line(tty, s, px, py, n, x, y, &style_ctx);
|
||||
#ifdef ENABLE_IMAGES
|
||||
image_draw_line(tty, s, px, py, n, x, y, &style_ctx);
|
||||
if (phase != REDRAW_TEXT)
|
||||
image_draw_line(tty, s, px, py, n, x, y,
|
||||
phase == REDRAW_IMAGES_BEFORE, &style_ctx);
|
||||
else
|
||||
#endif
|
||||
if (phase == REDRAW_TEXT)
|
||||
tty_draw_line(tty, s, px, py, n, x, y, &style_ctx);
|
||||
}
|
||||
|
||||
/* Get default border style for spans without a pane. */
|
||||
@@ -1518,7 +1529,7 @@ redraw_draw_menu_span(struct redraw_draw_ctx *dctx,
|
||||
*/
|
||||
static void
|
||||
redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span,
|
||||
u_int y, u_int clip_x, u_int clip_n)
|
||||
u_int y, u_int clip_x, u_int clip_n, enum redraw_image_phase phase)
|
||||
{
|
||||
struct redraw_scene *scene = dctx->scene;
|
||||
struct redraw_span_data *data = &span->data;
|
||||
@@ -1539,10 +1550,12 @@ redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span,
|
||||
continue;
|
||||
x = rr->px;
|
||||
n = rr->nx;
|
||||
if (phase != REDRAW_TEXT && type != REDRAW_SPAN_PANE)
|
||||
continue;
|
||||
|
||||
switch (span->data.type) {
|
||||
case REDRAW_SPAN_PANE:
|
||||
redraw_draw_pane_span(dctx, span, x, y, n);
|
||||
redraw_draw_pane_span(dctx, span, x, y, n, phase);
|
||||
break;
|
||||
case REDRAW_SPAN_BORDER:
|
||||
case REDRAW_SPAN_EMPTY:
|
||||
@@ -1607,27 +1620,29 @@ redraw_draw_pane_lines(struct redraw_draw_ctx *dctx, struct window_pane *wp,
|
||||
}
|
||||
#endif
|
||||
|
||||
for (y = top; y < bottom; y++) {
|
||||
line = &scene->lines[y];
|
||||
if (dctx->flags & REDRAW_STATUS_TOP)
|
||||
cy = dctx->status_lines + y;
|
||||
else
|
||||
cy = y;
|
||||
if (flags & REDRAW_PANE) {
|
||||
spans = &line->spans[REDRAW_SPAN_PANE];
|
||||
TAILQ_FOREACH(span, spans, entry) {
|
||||
if (span->data.p.wp == wp) {
|
||||
redraw_draw_span(dctx, span, cy,
|
||||
span->x, span->width);
|
||||
for (enum redraw_image_phase phase = REDRAW_IMAGES_BEFORE;
|
||||
phase <= REDRAW_IMAGES_AFTER; phase++) {
|
||||
for (y = top; y < bottom; y++) {
|
||||
line = &scene->lines[y];
|
||||
if (dctx->flags & REDRAW_STATUS_TOP)
|
||||
cy = dctx->status_lines + y;
|
||||
else
|
||||
cy = y;
|
||||
if (flags & REDRAW_PANE) {
|
||||
spans = &line->spans[REDRAW_SPAN_PANE];
|
||||
TAILQ_FOREACH(span, spans, entry) {
|
||||
if (span->data.p.wp == wp)
|
||||
redraw_draw_span(dctx, span, cy, span->x,
|
||||
span->width, phase);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flags & REDRAW_PANE_SCROLLBAR) {
|
||||
spans = &line->spans[REDRAW_SPAN_SCROLLBAR];
|
||||
TAILQ_FOREACH(span, spans, entry) {
|
||||
if (span->data.sb.wp == wp) {
|
||||
redraw_draw_span(dctx, span, cy,
|
||||
span->x, span->width);
|
||||
if (phase == REDRAW_TEXT &&
|
||||
(flags & REDRAW_PANE_SCROLLBAR)) {
|
||||
spans = &line->spans[REDRAW_SPAN_SCROLLBAR];
|
||||
TAILQ_FOREACH(span, spans, entry) {
|
||||
if (span->data.sb.wp == wp)
|
||||
redraw_draw_span(dctx, span, cy, span->x,
|
||||
span->width, phase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1644,13 +1659,17 @@ redraw_draw_lines(struct redraw_draw_ctx *dctx, int flags)
|
||||
struct redraw_span *span;
|
||||
u_int y, cy, type;
|
||||
|
||||
for (y = 0; y < scene->sy; y++) {
|
||||
line = &scene->lines[y];
|
||||
if (dctx->flags & REDRAW_STATUS_TOP)
|
||||
cy = dctx->status_lines + y;
|
||||
else
|
||||
cy = y;
|
||||
for (type = 0; type < REDRAW_SPAN_TYPES; type++) {
|
||||
for (enum redraw_image_phase phase = REDRAW_IMAGES_BEFORE;
|
||||
phase <= REDRAW_IMAGES_AFTER; phase++) {
|
||||
for (y = 0; y < scene->sy; y++) {
|
||||
line = &scene->lines[y];
|
||||
if (dctx->flags & REDRAW_STATUS_TOP)
|
||||
cy = dctx->status_lines + y;
|
||||
else
|
||||
cy = y;
|
||||
for (type = 0; type < REDRAW_SPAN_TYPES; type++) {
|
||||
if (phase != REDRAW_TEXT && type != REDRAW_SPAN_PANE)
|
||||
continue;
|
||||
if (!REDRAW_IS_ALL(flags)) {
|
||||
switch (type) {
|
||||
case REDRAW_SPAN_PANE:
|
||||
@@ -1686,9 +1705,9 @@ redraw_draw_lines(struct redraw_draw_ctx *dctx, int flags)
|
||||
}
|
||||
}
|
||||
spans = &line->spans[type];
|
||||
TAILQ_FOREACH(span, spans, entry) {
|
||||
redraw_draw_span(dctx, span, cy, span->x,
|
||||
span->width);
|
||||
TAILQ_FOREACH(span, spans, entry)
|
||||
redraw_draw_span(dctx, span, cy, span->x, span->width,
|
||||
phase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1709,10 +1728,9 @@ redraw_draw_menu_lines(struct redraw_draw_ctx *dctx)
|
||||
cy = dctx->status_lines + y;
|
||||
else
|
||||
cy = y;
|
||||
TAILQ_FOREACH(span, &line->spans[REDRAW_SPAN_MENU], entry) {
|
||||
redraw_draw_span(dctx, span, cy, span->x,
|
||||
span->width);
|
||||
}
|
||||
TAILQ_FOREACH(span, &line->spans[REDRAW_SPAN_MENU], entry)
|
||||
redraw_draw_span(dctx, span, cy, span->x, span->width,
|
||||
REDRAW_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2191,13 +2209,17 @@ redraw_draw_damage_rect(struct redraw_draw_ctx *dctx, u_int x, u_int y,
|
||||
if (sx == 0 || sy == 0)
|
||||
return;
|
||||
|
||||
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++) {
|
||||
for (enum redraw_image_phase phase = REDRAW_IMAGES_BEFORE;
|
||||
phase <= REDRAW_IMAGES_AFTER; phase++) {
|
||||
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 (phase != REDRAW_TEXT && type != REDRAW_SPAN_PANE)
|
||||
continue;
|
||||
spans = &line->spans[type];
|
||||
TAILQ_FOREACH(span, spans, entry) {
|
||||
clip_x = (span->x > x) ? span->x : x;
|
||||
@@ -2212,14 +2234,15 @@ redraw_draw_damage_rect(struct redraw_draw_ctx *dctx, u_int x, u_int y,
|
||||
redraw_damage_grow_span_clip(span, &clip_x,
|
||||
&clip_end);
|
||||
redraw_draw_span(dctx, span, cy, clip_x,
|
||||
clip_end - clip_x);
|
||||
if (type == REDRAW_SPAN_PANE) {
|
||||
clip_end - clip_x, phase);
|
||||
if (phase == REDRAW_TEXT && type == REDRAW_SPAN_PANE) {
|
||||
redraw_damage_draw_pane_prompt(dctx,
|
||||
span, cy, clip_x,
|
||||
clip_end - clip_x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
5
tmux.h
5
tmux.h
@@ -4279,7 +4279,7 @@ void image_tty_update(struct tty *);
|
||||
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 *);
|
||||
u_int, u_int, u_int, int, const struct tty_style_ctx *);
|
||||
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 *);
|
||||
@@ -4312,7 +4312,8 @@ void sixel_draw_rect(struct tty *,
|
||||
const struct image_rect *, 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);
|
||||
struct sixel_image *sixel_parse(const char *, size_t, u_int, u_int, u_int,
|
||||
u_int);
|
||||
void sixel_free(struct sixel_image *);
|
||||
void sixel_log(struct sixel_image *);
|
||||
void sixel_size_in_cells(struct sixel_image *, u_int *, u_int *);
|
||||
|
||||
@@ -729,6 +729,7 @@ tty_keys_winsz(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||
char_y = (ypixel && tty->sy) ? ypixel / tty->sy : 0;
|
||||
tty_set_size(tty, tty->sx, tty->sy, char_x, char_y);
|
||||
tty_invalidate(tty);
|
||||
recalculate_sizes();
|
||||
|
||||
tty->flags &= ~TTY_WINSIZEQUERY;
|
||||
*size = end + 1;
|
||||
|
||||
Reference in New Issue
Block a user