Update sixdraw.
This commit is contained in:
parent
bc83491c2a
commit
96d17772f9
|
@ -56,6 +56,8 @@
|
|||
|
||||
#define SIXEL_SEQ_HEAD CTLSEQS_DCS "0;1q\"1;1;"
|
||||
|
||||
static char sixel_seq[2048] = SIXEL_SEQ_HEAD;
|
||||
|
||||
struct sixdraw_ctx {
|
||||
struct termios termios;
|
||||
union ctlseqs_value result[64];
|
||||
|
@ -70,9 +72,13 @@ struct sixdraw_ctx {
|
|||
int in_fd;
|
||||
int out_fd;
|
||||
int timeout;
|
||||
unsigned rows;
|
||||
unsigned canvas_width;
|
||||
unsigned canvas_height;
|
||||
unsigned ch_width;
|
||||
unsigned ch_height;
|
||||
unsigned line_color;
|
||||
unsigned sixel_init_size;
|
||||
};
|
||||
|
||||
static inline void
|
||||
|
@ -128,8 +134,11 @@ get_winsize(struct sixdraw_ctx *ctx)
|
|||
print_error(ctx, "failed to get terminal window size (in pixels)");
|
||||
return false;
|
||||
}
|
||||
ctx->rows = ws.ws_row;
|
||||
ctx->ch_width = ws.ws_xpixel / ws.ws_col;
|
||||
ctx->ch_height = ws.ws_ypixel / ws.ws_row;
|
||||
ctx->canvas_width = ws.ws_xpixel - ctx->ch_width;
|
||||
ctx->canvas_height = ws.ws_ypixel - ctx->ch_height * 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -153,51 +162,32 @@ decrqm(struct sixdraw_ctx *ctx, unsigned mode, char const *name)
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
get_sixel_color(unsigned rgb888, unsigned *red, unsigned *green, unsigned *blue)
|
||||
{
|
||||
*red = ((rgb888 >> 16) & 0xFF) * 100 / 0xFF;
|
||||
*green = ((rgb888 >> 8) & 0xFF) * 100 / 0xFF;
|
||||
*blue = ((rgb888 >> 0) & 0xFF) * 100 / 0xFF;
|
||||
}
|
||||
|
||||
static inline char *
|
||||
get_sixel_buffer()
|
||||
{
|
||||
static char sixel_seq_buffer[2048] = SIXEL_SEQ_HEAD;
|
||||
return sixel_seq_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
print_sixel_dot(struct sixdraw_ctx *ctx, unsigned x, unsigned y)
|
||||
{
|
||||
char *sixel_seq = get_sixel_buffer();
|
||||
size_t seq_len = sizeof(SIXEL_SEQ_HEAD) - 1;
|
||||
seq_len += sprintf(sixel_seq + seq_len, "%d;%d", ctx->ch_width, ctx->ch_height);
|
||||
|
||||
// Select color.
|
||||
unsigned red, green, blue;
|
||||
get_sixel_color(ctx->line_color, &red, &green, &blue);
|
||||
seq_len += sprintf(sixel_seq + seq_len, "#0;2;%d;%d;%d#0", red, green, blue);
|
||||
if (x >= ctx->canvas_width || y >= ctx->canvas_height) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Move cursor.
|
||||
unsigned row = y / ctx->ch_height + 1;
|
||||
unsigned col = x / ctx->ch_width + 1;
|
||||
dprintf(ctx->out_fd, CTLSEQS_CUP("%d", "%d"), row, col);
|
||||
|
||||
// Draw dot.
|
||||
// Build sixel sequence.
|
||||
row = y % ctx->ch_height;
|
||||
col = x % ctx->ch_width;
|
||||
seq_len += sprintf(sixel_seq + seq_len, "%.*s", row / 6, "------------------------");
|
||||
seq_len += sprintf(sixel_seq + seq_len, "!%u?%c" CTLSEQS_ST, col, (1 << row % 6) + 0x3F);
|
||||
unsigned seq_size = ctx->sixel_init_size;
|
||||
seq_size += sprintf(sixel_seq + seq_size, "%.*s!%u?%c" CTLSEQS_ST,
|
||||
row / 6, "------------------------", col, (1 << row % 6) + 0x3F);
|
||||
|
||||
// Output sixel sequence.
|
||||
do {
|
||||
ssize_t nbytes = write(ctx->out_fd, sixel_seq, seq_len);
|
||||
if (nbytes > 0) {
|
||||
seq_len -= nbytes;
|
||||
for (ssize_t nbytes; seq_size > 0; seq_size -= nbytes) {
|
||||
nbytes = write(ctx->out_fd, sixel_seq, seq_size);
|
||||
if (nbytes < 0) {
|
||||
break;
|
||||
}
|
||||
} while (seq_len > 0);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -364,17 +354,27 @@ prepare(struct sixdraw_ctx *ctx)
|
|||
dprintf(ctx->out_fd, CTLSEQS_DECSET("%d"), SGR_MOUSE_PIXELMODE);
|
||||
}
|
||||
|
||||
// Build the immutable part of sixel sequence.
|
||||
ctx->sixel_init_size = sizeof(SIXEL_SEQ_HEAD) - 1;
|
||||
ctx->sixel_init_size += sprintf(sixel_seq + ctx->sixel_init_size, "%u;%u#0;2;%d;%d;%d#0",
|
||||
ctx->ch_width, ctx->ch_height, ((ctx->line_color >> 16) & 0xFF) * 100 / 0xFF,
|
||||
((ctx->line_color >> 8) & 0xFF) * 100 / 0xFF, ((ctx->line_color >> 0) & 0xFF) * 100 / 0xFF);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
draw(struct sixdraw_ctx *ctx)
|
||||
{
|
||||
dprintf(ctx->out_fd, CTLSEQS_CUP("%d", "1") "Canvas size: %ux%u. Line color: #%06X.",
|
||||
ctx->rows - 1, ctx->canvas_width, ctx->canvas_height, ctx->line_color);
|
||||
dprintf(ctx->out_fd, CTLSEQS_CUP("%d", "1") "Usage: Draw with mouse. Press Ctrl+C to exit.", ctx->rows);
|
||||
|
||||
union ctlseqs_value *result = ctx->result;
|
||||
while (true) {
|
||||
switch (ctlseqs_read(ctx->reader, ctx->matcher, -1)) {
|
||||
case 2: // CTLSEQS_RESP_SGR_MOUSE
|
||||
print_sixel_dot(ctx, result[1].num, result[2].num);
|
||||
print_sixel_dot(ctx, result[1].num - 1, result[2].num - 1);
|
||||
break;
|
||||
case CTLSEQS_NOSEQ:
|
||||
// Press Ctrl+C to exit.
|
||||
|
|
Loading…
Reference in New Issue