sixel: limit image size to the one specified in the raster attrs

If a sixel has set an explicit width/height, in its raster attributes,
do *not* allow the image to extend beyond this.

Before this patch, we dynamically resized images if the sixel encoder
emitted sixel data beyond the previously set width/height.

Now, we ignore writes outside the configured size.
This commit is contained in:
Daniel Eklöf 2024-03-04 16:33:58 +01:00
parent f17b989650
commit f7bdc4c5b4
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 18 additions and 1 deletions

View file

@ -107,6 +107,9 @@
determining whether a key combination produces text or not. determining whether a key combination produces text or not.
* CSI-t queries now report pixel values **unscaled**, instead of * CSI-t queries now report pixel values **unscaled**, instead of
**scaled** ([#1643][1643]). **scaled** ([#1643][1643]).
* Sixel "level 2" images (raster attributes set) are no longer
extended beyond the width/height specified in the raster attributes
([#chafa-192][chafa-192]).
[1526]: https://codeberg.org/dnkl/foot/issues/1526 [1526]: https://codeberg.org/dnkl/foot/issues/1526
[1528]: https://codeberg.org/dnkl/foot/issues/1528 [1528]: https://codeberg.org/dnkl/foot/issues/1528
@ -114,6 +117,7 @@
[kitty-6913]: https://github.com/kovidgoyal/kitty/issues/6913 [kitty-6913]: https://github.com/kovidgoyal/kitty/issues/6913
[1584]: https://codeberg.org/dnkl/foot/issues/1584 [1584]: https://codeberg.org/dnkl/foot/issues/1584
[1643]: https://codeberg.org/dnkl/foot/issues/1643 [1643]: https://codeberg.org/dnkl/foot/issues/1643
[chafa-192]: https://github.com/hpjansson/chafa/issues/192
### Deprecated ### Deprecated

13
sixel.c
View file

@ -82,6 +82,7 @@ sixel_init(struct terminal *term, int p1, int p2, int p3)
term->sixel.color_idx = 0; term->sixel.color_idx = 0;
term->sixel.pan = pan; term->sixel.pan = pan;
term->sixel.pad = pad; term->sixel.pad = pad;
term->sixel.size_locked = false;
term->sixel.param = 0; term->sixel.param = 0;
term->sixel.param_idx = 0; term->sixel.param_idx = 0;
memset(term->sixel.params, 0, sizeof(term->sixel.params)); memset(term->sixel.params, 0, sizeof(term->sixel.params));
@ -90,6 +91,7 @@ sixel_init(struct terminal *term, int p1, int p2, int p3)
term->sixel.image.p = NULL; term->sixel.image.p = NULL;
term->sixel.image.width = 0; term->sixel.image.width = 0;
term->sixel.image.height = 0; term->sixel.image.height = 0;
term->sixel.image.alloc_height = 0;
if (term->sixel.use_private_palette) { if (term->sixel.use_private_palette) {
xassert(term->sixel.private_palette == NULL); xassert(term->sixel.private_palette == NULL);
@ -1299,6 +1301,7 @@ sixel_unhook(struct terminal *term)
term->sixel.image.p = NULL; term->sixel.image.p = NULL;
term->sixel.image.width = 0; term->sixel.image.width = 0;
term->sixel.image.height = 0; term->sixel.image.height = 0;
term->sixel.image.alloc_height = 0;
term->sixel.pos = (struct coord){0, 0}; term->sixel.pos = (struct coord){0, 0};
free(term->sixel.private_palette); free(term->sixel.private_palette);
@ -1314,6 +1317,9 @@ sixel_unhook(struct terminal *term)
static void static void
resize_horizontally(struct terminal *term, int new_width) resize_horizontally(struct terminal *term, int new_width)
{ {
if (likely(term->sixel.size_locked))
return;
if (unlikely(new_width > term->sixel.max_width)) { if (unlikely(new_width > term->sixel.max_width)) {
LOG_WARN("maximum image dimensions exceeded, truncating"); LOG_WARN("maximum image dimensions exceeded, truncating");
new_width = term->sixel.max_width; new_width = term->sixel.max_width;
@ -1375,6 +1381,9 @@ resize_vertically(struct terminal *term, int new_height)
term->sixel.image.width, term->sixel.image.height, term->sixel.image.width, term->sixel.image.height,
term->sixel.image.width, new_height); term->sixel.image.width, new_height);
if (likely(term->sixel.size_locked))
return false;
if (unlikely(new_height > term->sixel.max_height)) { if (unlikely(new_height > term->sixel.max_height)) {
LOG_WARN("maximum image dimensions reached"); LOG_WARN("maximum image dimensions reached");
return false; return false;
@ -1493,6 +1502,7 @@ resize(struct terminal *term, int new_width, int new_height)
term->sixel.image.width = new_width; term->sixel.image.width = new_width;
term->sixel.image.height = new_height; term->sixel.image.height = new_height;
term->sixel.image.p = &term->sixel.image.data[term->sixel.pos.row * new_width + term->sixel.pos.col]; term->sixel.image.p = &term->sixel.image.data[term->sixel.pos.row * new_width + term->sixel.pos.col];
term->sixel.image.alloc_height = alloc_new_height;
return true; return true;
} }
@ -1663,7 +1673,7 @@ decsixel_generic(struct terminal *term, uint8_t c)
term->sixel.pos.col = 0; term->sixel.pos.col = 0;
term->sixel.image.p = &term->sixel.image.data[term->sixel.pos.row * term->sixel.image.width]; term->sixel.image.p = &term->sixel.image.data[term->sixel.pos.row * term->sixel.image.width];
if (term->sixel.pos.row >= term->sixel.image.height) { if (unlikely(term->sixel.pos.row >= term->sixel.image.alloc_height)) {
if (!resize_vertically(term, term->sixel.pos.row + 6 * term->sixel.pan)) if (!resize_vertically(term, term->sixel.pos.row + 6 * term->sixel.pan))
term->sixel.pos.col = term->sixel.max_width + 1 * term->sixel.pad; term->sixel.pos.col = term->sixel.max_width + 1 * term->sixel.pad;
} }
@ -1737,6 +1747,7 @@ decgra(struct terminal *term, uint8_t c)
ph <= term->sixel.max_height && pv <= term->sixel.max_width) ph <= term->sixel.max_height && pv <= term->sixel.max_width)
{ {
resize(term, ph, pv); resize(term, ph, pv);
term->sixel.size_locked = true;
} }
term->sixel.state = SIXEL_DECSIXEL; term->sixel.state = SIXEL_DECSIXEL;

View file

@ -677,6 +677,7 @@ struct terminal {
uint32_t *p; /* Pointer into data, for current position */ uint32_t *p; /* Pointer into data, for current position */
int width; /* Image width, in pixels */ int width; /* Image width, in pixels */
int height; /* Image height, in pixels */ int height; /* Image height, in pixels */
int alloc_height; /* Image height, in pixels, aligned to 6-pixel boundary */
} image; } image;
/* /*
@ -687,6 +688,7 @@ struct terminal {
*/ */
int pan; int pan;
int pad; int pad;
bool size_locked;
bool scrolling:1; /* Private mode 80 */ bool scrolling:1; /* Private mode 80 */
bool use_private_palette:1; /* Private mode 1070 */ bool use_private_palette:1; /* Private mode 1070 */