Update sixdraw.

This commit is contained in:
CismonX 2021-01-11 04:58:39 +08:00
parent bc83491c2a
commit 96d17772f9
Signed by: cismonx
GPG Key ID: 3094873E29A482FB
1 changed files with 32 additions and 32 deletions

View File

@ -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.