sixel: fix sheared image when image crosses scrollback wrap-around

When a sixel image crosses the scrollback wrap-around, it is split up
into (at least) two pieces.

We use cursor->point.col for all pieces’ x-coordinate. This caused the
final image to appear sheared, since we do a carriage-return (after a
number of linefeeds) after each piece - this causes the cursor’s
position to be reset to the left margin.

The solution is simple; remember the cursor’s initial x-coordinate,
and use that to position all image pieces.

Closes #151.
This commit is contained in:
Daniel Eklöf 2020-10-02 20:56:44 +02:00
parent 7a7ba599c3
commit cdcdfe527c
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 14 additions and 1 deletions

View file

@ -48,6 +48,9 @@
* Background opacity when in _reverse video_ mode.
* Crash when writing a sixel image that extends outside the terminal's
right margin (https://codeberg.org/dnkl/foot/issues/151).
* Sixel image at non-zero column positions getting sheared at
seemingly random occasions
(https://codeberg.org/dnkl/foot/issues/151).
### Security

12
sixel.c
View file

@ -448,6 +448,16 @@ sixel_unhook(struct terminal *term)
int pixel_rows_left = term->sixel.image.height;
const int stride = term->sixel.image.width * sizeof(uint32_t);
/*
* Need to 'remember' current cursor column.
*
* If we split up the sixel (to avoid scrollback wrap-around), we
* will emit a carriage-return (after several linefeeds), which
* will reset the cursor column to 0. If we use _that_ column for
* the subsequent image parts, the image will look sheared.
*/
const int start_col = term->grid->cursor.point.col;
/* We do not allow sixels to cross the scrollback wrap-around, as
* this makes intersection calculations much more complicated */
while (pixel_rows_left > 0) {
@ -478,7 +488,7 @@ sixel_unhook(struct terminal *term)
.height = height,
.rows = (height + term->cell_height - 1) / term->cell_height,
.cols = (width + term->cell_width - 1) / term->cell_width,
.pos = (struct coord){cursor->col, cur_row},
.pos = (struct coord){start_col, cur_row},
};
sixel_overwrite_by_rectangle(