mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-07 08:21:02 -04:00
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.
This commit is contained in:
parent
957e482f45
commit
dec796f525
3 changed files with 20 additions and 6 deletions
|
|
@ -63,7 +63,9 @@
|
||||||
a `;`.
|
a `;`.
|
||||||
* Palette re-use in sixel images. Previously, the palette was reset
|
* Palette re-use in sixel images. Previously, the palette was reset
|
||||||
after each image.
|
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
|
### Security
|
||||||
|
|
||||||
|
|
|
||||||
21
sixel.c
21
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.data = malloc(1 * 6 * sizeof(term->sixel.image.data[0]));
|
||||||
term->sixel.image.width = 1;
|
term->sixel.image.width = 1;
|
||||||
term->sixel.image.height = 6;
|
term->sixel.image.height = 6;
|
||||||
|
term->sixel.image.autosize = true;
|
||||||
|
|
||||||
if (term->sixel.palette == NULL) {
|
if (term->sixel.palette == NULL) {
|
||||||
term->sixel.palette = calloc(
|
term->sixel.palette = calloc(
|
||||||
|
|
@ -212,6 +213,9 @@ max_height(const struct terminal *term)
|
||||||
static bool
|
static bool
|
||||||
resize(struct terminal *term, int new_width, int new_height)
|
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",
|
LOG_DBG("resizing image: %dx%d -> %dx%d",
|
||||||
term->sixel.image.width, term->sixel.image.height,
|
term->sixel.image.width, term->sixel.image.height,
|
||||||
new_width, new_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_width = term->sixel.image.width;
|
||||||
const int old_height = term->sixel.image.height;
|
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_width >= old_width);
|
||||||
assert(new_height >= old_height);
|
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
|
/* Width (and thus stride) is the same, so we can simply
|
||||||
* re-alloc the existing buffer */
|
* 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) {
|
if (new_data == NULL) {
|
||||||
LOG_ERRNO("failed to reallocate sixel image buffer");
|
LOG_ERRNO("failed to reallocate sixel image buffer");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -240,7 +249,7 @@ resize(struct terminal *term, int new_width, int new_height)
|
||||||
} else {
|
} else {
|
||||||
/* Width (and thus stride) change - need to allocate a new buffer */
|
/* Width (and thus stride) change - need to allocate a new buffer */
|
||||||
assert(new_width > old_width);
|
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 */
|
/* Copy old rows, and initialize new columns to background color */
|
||||||
for (int r = 0; r < old_height; r++) {
|
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 ||
|
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(
|
int width = max(
|
||||||
term->sixel.image.width,
|
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.image.height,
|
||||||
(term->sixel.pos.row + 1) * 6);
|
(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) {
|
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 &&
|
if (ph >= term->sixel.image.height && pv >= term->sixel.image.width &&
|
||||||
ph <= max_height(term) && pv <= max_width(term))
|
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;
|
term->sixel.state = SIXEL_DECSIXEL;
|
||||||
|
|
|
||||||
|
|
@ -416,6 +416,7 @@ struct terminal {
|
||||||
uint32_t *data; /* Raw image data, in ARGB */
|
uint32_t *data; /* Raw image data, in ARGB */
|
||||||
int width; /* Image width, in pixels */
|
int width; /* Image width, in pixels */
|
||||||
int height; /* Image height, in pixels */
|
int height; /* Image height, in pixels */
|
||||||
|
bool autosize;
|
||||||
} image;
|
} image;
|
||||||
|
|
||||||
unsigned params[5]; /* Collected parmaeters, for RASTER, COLOR_SPEC */
|
unsigned params[5]; /* Collected parmaeters, for RASTER, COLOR_SPEC */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue