From 96d17772f92a50796df4b4b7be1b25d4a5fa25d9 Mon Sep 17 00:00:00 2001 From: CismonX Date: Mon, 11 Jan 2021 04:58:39 +0800 Subject: [PATCH] Update sixdraw. --- examples/sixdraw.c | 64 +++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/examples/sixdraw.c b/examples/sixdraw.c index d429d1e..663d90e 100644 --- a/examples/sixdraw.c +++ b/examples/sixdraw.c @@ -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.