From 25b09b909ca39cee6432ffd10e179336dbc178e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 22 Feb 2020 21:03:24 +0100 Subject: [PATCH] sixel: application configurable image max width/height --- csi.c | 10 +++++--- sixel.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++--- sixel.h | 5 ++++ terminal.h | 4 ++- 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/csi.c b/csi.c index d5c06905..38d017f5 100644 --- a/csi.c +++ b/csi.c @@ -1243,11 +1243,13 @@ csi_dispatch(struct terminal *term, uint8_t final) break; case 2: + switch (operation) { + case 1: sixel_geometry_report_current(term); break; + case 2: sixel_geometry_reset(term); break; + case 3: sixel_geometry_set(term, vt_param_get(term, 2, 0), vt_param_get(term, 3, 0)); break; + case 4: sixel_geometry_report_max(term); + } break; - - case 3: - break; - } break; } diff --git a/sixel.c b/sixel.c index 2536f467..01c6987b 100644 --- a/sixel.c +++ b/sixel.c @@ -94,6 +94,22 @@ sixel_unhook(struct terminal *term) render_refresh(term); } +static unsigned +max_width(const struct terminal *term) +{ + return term->sixel.max_width == 0 + ? term->cols * term->cell_width + : term->sixel.max_width; +} + +static unsigned +max_height(const struct terminal *term) +{ + return term->sixel.max_height == 0 + ? term->rows * term->cell_height + : term->sixel.max_height; +} + static bool resize(struct terminal *term, int new_width, int new_height) { @@ -156,8 +172,14 @@ sixel_add(struct terminal *term, uint32_t color, uint8_t sixel) { //LOG_DBG("adding sixel %02hhx using color 0x%06x", sixel, color); + if (term->sixel.pos.col >= max_width(term) || + term->sixel.pos.row * 6 + 5 >= max_height(term)) + { + return; + } + if (term->sixel.pos.col >= term->sixel.image.width || - term->sixel.pos.row * 6 >= term->sixel.image.height) + term->sixel.pos.row * 6 + 5 >= term->sixel.image.height) { resize(term, max(term->sixel.max_col, term->sixel.pos.col + 1), @@ -174,7 +196,6 @@ sixel_add(struct terminal *term, uint32_t color, uint8_t sixel) } assert(sixel == 0); - term->sixel.pos.col++; } @@ -260,8 +281,11 @@ decgra(struct terminal *term, uint8_t c) LOG_DBG("pan=%u, pad=%u (aspect ratio = %u), size=%ux%u", pan, pad, pan / pad, ph, pv); - if (ph >= term->sixel.image.height && pv >= term->sixel.image.width) + if (ph >= term->sixel.image.height && pv >= term->sixel.image.width && + ph <= max_height(term) && pv <= max_width(term)) + { resize(term, ph, pv); + } term->sixel.state = SIXEL_DECSIXEL; sixel_put(term, c); @@ -365,6 +389,7 @@ sixel_colors_report_current(struct terminal *term) char reply[24]; snprintf(reply, sizeof(reply), "\033[?1;0;%uS", term->sixel.palette_size); term_to_slave(term, reply, strlen(reply)); + LOG_DBG("query response for current color count: %u", term->sixel.palette_size); } void @@ -388,4 +413,48 @@ sixel_colors_report_max(struct terminal *term) char reply[24]; snprintf(reply, sizeof(reply), "\033[?1;0;%uS", SIXEL_MAX_COLORS); term_to_slave(term, reply, strlen(reply)); + LOG_DBG("query response for max color count: %u", SIXEL_MAX_COLORS); +} + +void +sixel_geometry_report_current(struct terminal *term) +{ + char reply[64]; + snprintf(reply, sizeof(reply), "\033[?2;0;%u;%uS", + max_width(term), max_height(term)); + term_to_slave(term, reply, strlen(reply)); + + LOG_DBG("query response for current sixel geometry: %ux%u", + max_width(term), max_height(term)); +} + +void +sixel_geometry_reset(struct terminal *term) +{ + term->sixel.max_width = 0; + term->sixel.max_height = 0; + LOG_DBG("sixel geometry reset to %ux%u", max_width(term), max_height(term)); +} + +void +sixel_geometry_set(struct terminal *term, unsigned width, unsigned height) +{ + term->sixel.max_width = width; + term->sixel.max_height = height; + LOG_DBG("sixel geometry set to %ux%u", + term->sixel.max_width, term->sixel.max_height); +} + +void +sixel_geometry_report_max(struct terminal *term) +{ + unsigned max_width = term->cols * term->cell_width; + unsigned max_height = term->rows * term->cell_height; + + char reply[64]; + snprintf(reply, sizeof(reply), "\033[?2;0;%u;%uS", max_width, max_height); + term_to_slave(term, reply, strlen(reply)); + + LOG_DBG("query response for max sixel geometry: %ux%u", + max_width, max_height); } diff --git a/sixel.h b/sixel.h index 8e6d2949..dbce21c5 100644 --- a/sixel.h +++ b/sixel.h @@ -14,3 +14,8 @@ void sixel_colors_report_current(struct terminal *term); void sixel_colors_reset(struct terminal *term); void sixel_colors_set(struct terminal *term, unsigned count); void sixel_colors_report_max(struct terminal *term); + +void sixel_geometry_report_current(struct terminal *term); +void sixel_geometry_reset(struct terminal *term); +void sixel_geometry_set(struct terminal *term, unsigned width, unsigned height); +void sixel_geometry_report_max(struct terminal *term); diff --git a/terminal.h b/terminal.h index e0738057..5e491d29 100644 --- a/terminal.h +++ b/terminal.h @@ -378,7 +378,9 @@ struct terminal { unsigned param_idx; /* Parameters seen */ /* Application configurable */ - unsigned palette_size; + unsigned palette_size; /* Number of colors in palette */ + unsigned max_width; /* Maximum image width, in pixels */ + unsigned max_height; /* Maximum image height, in pixels */ } sixel; tll(struct sixel) sixel_images;