diff --git a/CHANGELOG.md b/CHANGELOG.md index 04571604..af92841d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,6 +107,9 @@ determining whether a key combination produces text or not. * CSI-t queries now report pixel values **unscaled**, instead of **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 [1528]: https://codeberg.org/dnkl/foot/issues/1528 @@ -114,6 +117,7 @@ [kitty-6913]: https://github.com/kovidgoyal/kitty/issues/6913 [1584]: https://codeberg.org/dnkl/foot/issues/1584 [1643]: https://codeberg.org/dnkl/foot/issues/1643 +[chafa-192]: https://github.com/hpjansson/chafa/issues/192 ### Deprecated diff --git a/sixel.c b/sixel.c index 0cb089ed..ec65085a 100644 --- a/sixel.c +++ b/sixel.c @@ -82,6 +82,7 @@ sixel_init(struct terminal *term, int p1, int p2, int p3) term->sixel.color_idx = 0; term->sixel.pan = pan; term->sixel.pad = pad; + term->sixel.size_locked = false; term->sixel.param = 0; term->sixel.param_idx = 0; 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.width = 0; term->sixel.image.height = 0; + term->sixel.image.alloc_height = 0; if (term->sixel.use_private_palette) { xassert(term->sixel.private_palette == NULL); @@ -1299,6 +1301,7 @@ sixel_unhook(struct terminal *term) term->sixel.image.p = NULL; term->sixel.image.width = 0; term->sixel.image.height = 0; + term->sixel.image.alloc_height = 0; term->sixel.pos = (struct coord){0, 0}; free(term->sixel.private_palette); @@ -1314,6 +1317,9 @@ sixel_unhook(struct terminal *term) static void resize_horizontally(struct terminal *term, int new_width) { + if (likely(term->sixel.size_locked)) + return; + if (unlikely(new_width > term->sixel.max_width)) { LOG_WARN("maximum image dimensions exceeded, truncating"); 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, new_height); + if (likely(term->sixel.size_locked)) + return false; + if (unlikely(new_height > term->sixel.max_height)) { LOG_WARN("maximum image dimensions reached"); 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.height = new_height; 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; } @@ -1663,7 +1673,7 @@ decsixel_generic(struct terminal *term, uint8_t c) term->sixel.pos.col = 0; 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)) 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) { resize(term, ph, pv); + term->sixel.size_locked = true; } term->sixel.state = SIXEL_DECSIXEL; diff --git a/terminal.h b/terminal.h index eeff8af0..09872000 100644 --- a/terminal.h +++ b/terminal.h @@ -677,6 +677,7 @@ struct terminal { uint32_t *p; /* Pointer into data, for current position */ int width; /* Image width, in pixels */ int height; /* Image height, in pixels */ + int alloc_height; /* Image height, in pixels, aligned to 6-pixel boundary */ } image; /* @@ -687,6 +688,7 @@ struct terminal { */ int pan; int pad; + bool size_locked; bool scrolling:1; /* Private mode 80 */ bool use_private_palette:1; /* Private mode 1070 */