From dec796f52564687e9e214adfbc6073ec38b2742a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 11 Jun 2020 18:40:52 +0200 Subject: [PATCH] sixel: if the client has specified a size, do not change that We used to auto-resize images to always be a multiple of 6. This is incorrect. The client may, for example, have specified a size to align the image to a cell boundary, which may not be a multiple of 6. Furthermore, in e.g. Jexer, which splits up an image into stripes, that the next image would "overwrite" the previous one. Since the next image was started on a cell row that the previous image had overflowed into. --- CHANGELOG.md | 4 +++- sixel.c | 21 ++++++++++++++++----- terminal.h | 1 + 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb11f45e..8f9c038d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,7 +63,9 @@ a `;`. * Palette re-use in sixel images. Previously, the palette was reset after each image. - +* Do not auto-resize a sixel image for which the cllent has specified + a size. This fixes an issue where an image would incorrectly + overflow into the cell row beneath. ### Security diff --git a/sixel.c b/sixel.c index 3fd2775c..2186795c 100644 --- a/sixel.c +++ b/sixel.c @@ -41,6 +41,7 @@ sixel_init(struct terminal *term) term->sixel.image.data = malloc(1 * 6 * sizeof(term->sixel.image.data[0])); term->sixel.image.width = 1; term->sixel.image.height = 6; + term->sixel.image.autosize = true; if (term->sixel.palette == NULL) { term->sixel.palette = calloc( @@ -212,6 +213,9 @@ max_height(const struct terminal *term) static bool resize(struct terminal *term, int new_width, int new_height) { + if (!term->sixel.image.autosize) + return false; + LOG_DBG("resizing image: %dx%d -> %dx%d", term->sixel.image.width, term->sixel.image.height, new_width, new_height); @@ -220,6 +224,11 @@ resize(struct terminal *term, int new_width, int new_height) const int old_width = term->sixel.image.width; const int old_height = term->sixel.image.height; + int alloc_new_width = new_width; + int alloc_new_height = (new_height + 6 - 1) / 6 * 6; + assert(alloc_new_height >= new_height); + assert(alloc_new_height - new_height < 6); + assert(new_width >= old_width); assert(new_height >= old_height); @@ -229,7 +238,7 @@ resize(struct terminal *term, int new_width, int new_height) /* Width (and thus stride) is the same, so we can simply * re-alloc the existing buffer */ - new_data = realloc(old_data, new_width * new_height * sizeof(uint32_t)); + new_data = realloc(old_data, alloc_new_width * alloc_new_height * sizeof(uint32_t)); if (new_data == NULL) { LOG_ERRNO("failed to reallocate sixel image buffer"); return false; @@ -240,7 +249,7 @@ resize(struct terminal *term, int new_width, int new_height) } else { /* Width (and thus stride) change - need to allocate a new buffer */ assert(new_width > old_width); - new_data = malloc(new_width * new_height * sizeof(uint32_t)); + new_data = malloc(alloc_new_width * alloc_new_height * sizeof(uint32_t)); /* Copy old rows, and initialize new columns to background color */ for (int r = 0; r < old_height; r++) { @@ -278,7 +287,7 @@ sixel_add(struct terminal *term, uint32_t color, uint8_t sixel) } if (term->sixel.pos.col >= term->sixel.image.width || - term->sixel.pos.row * 6 + 5 >= term->sixel.image.height) + term->sixel.pos.row * 6 + 5 >= (term->sixel.image.height + 6 - 1) / 6 * 6) { int width = max( term->sixel.image.width, @@ -288,7 +297,8 @@ sixel_add(struct terminal *term, uint32_t color, uint8_t sixel) term->sixel.image.height, (term->sixel.pos.row + 1) * 6); - resize(term, width, height); + if (!resize(term, width, height)) + return; } for (int i = 0; i < 6; i++, sixel >>= 1) { @@ -389,7 +399,8 @@ decgra(struct terminal *term, uint8_t c) if (ph >= term->sixel.image.height && pv >= term->sixel.image.width && ph <= max_height(term) && pv <= max_width(term)) { - resize(term, ph, pv); + if (resize(term, ph, pv)) + term->sixel.image.autosize = false; } term->sixel.state = SIXEL_DECSIXEL; diff --git a/terminal.h b/terminal.h index 798307cb..fc98d7cd 100644 --- a/terminal.h +++ b/terminal.h @@ -416,6 +416,7 @@ struct terminal { uint32_t *data; /* Raw image data, in ARGB */ int width; /* Image width, in pixels */ int height; /* Image height, in pixels */ + bool autosize; } image; unsigned params[5]; /* Collected parmaeters, for RASTER, COLOR_SPEC */