sixel: improve handling of images when reflowing the grids

Update the sixels' 'row' attribute when re-flowing a grid, to ensure
it is rendered at the correct place.

This should work in most cases, but will break when the cell size has
changed (e.g. font size increase/decrease, or a DPI change).

This patch also moves the sixel image list from the terminal struct
into the grid struct. The sixels are per-grid after all.
This commit is contained in:
Daniel Eklöf 2020-03-13 18:44:23 +01:00
parent 62a5805d4b
commit d482bf0a30
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
7 changed files with 69 additions and 42 deletions

35
grid.c
View file

@ -6,6 +6,7 @@
#define LOG_MODULE "grid"
#define LOG_ENABLE_DBG 0
#include "log.h"
#include "sixel.h"
#define max(x, y) ((x) > (y) ? (x) : (y))
@ -76,6 +77,8 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
* at the output that is *oldest* */
int offset = grid->offset + old_screen_rows;
tll(struct sixel) new_sixels = tll_init();
/*
* Walk the old grid
*/
@ -86,6 +89,28 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
if (old_row == NULL)
continue;
/*
* Update 'row' in all sixels that *begin* at current row
*
* Since we might end up pushing the sixel down, we can't
* simply update the row inline - we'd then end up pushing the
* sixel down again, when we reach the next 'old'
* row. Instead, copy the sixel (with 'row' updated), to a
* temporary list and remove the original sixel.
*
* After we've reflowed the grid we'll move the sixels back to
* the "real" sixel list.
*/
tll_foreach(grid->sixel_images, it) {
if (it->item.pos.row == ((offset + r) & (old_rows - 1))) {
struct sixel six = it->item;
six.pos.row = new_row_idx;
tll_push_back(new_sixels, six);
tll_remove(grid->sixel_images, it);
}
}
/*
* Keep track of empty cells. If the old line ends with a
* string of empty cells, we don't need to, nor do we want to,
@ -191,5 +216,15 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
grid->num_rows = new_rows;
grid->num_cols = new_cols;
/* Destroy any non-moved sixels */
tll_foreach(grid->sixel_images, it)
sixel_destroy(&it->item);
tll_free(grid->sixel_images);
/* Move updated sixels back */
tll_foreach(new_sixels, it)
tll_push_back(grid->sixel_images, it->item);
tll_free(new_sixels);
return new_row_idx;
}