sixel: re-scale images when the cell dimensions change

Before this patch, when the cell dimensions changed (i.e. when the
font size changes), sixel images were either removed (the new cell
dimensions are smaller than the old), or simply kept at their original
size (new cell dimensions are larger).

With this patch, sixels are instead resized. This means a
sixel *always* occupies the same number of rows and columns,
regardless of how much the font size is changed.

This is done by maintaining two sets of image data and pixman images,
as well as their dimensions. These two sets are the new ‘original’ and
‘scaled’ members of the sixel struct.

The "top-level" pixman image pointer, and the ‘width’ and ‘height’
members either point to the "original", or the "scaled" version.

They are invalidated as soon as the cell dimensions change. They, and
the ‘scaled’ image is updated on-demand (when we need to render a
sixel).

Note that the ‘scaled’ image is always NULL when the current cell
dimensions matches the ones used when emitting the sixel (to save
run-time memory).

Closes #1383
This commit is contained in:
Daniel Eklöf 2023-06-29 14:49:54 +02:00
parent 7a37e6891f
commit 49fb0cf359
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
7 changed files with 295 additions and 112 deletions

View file

@ -763,9 +763,6 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4])
free_custom_glyphs(
&term->custom_glyphs.legacy, GLYPH_LEGACY_COUNT);
const int old_cell_width = term->cell_width;
const int old_cell_height = term->cell_height;
const struct config *conf = term->conf;
const struct fcft_glyph *M = fcft_rasterize_char_utf32(
@ -792,28 +789,7 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4])
LOG_INFO("cell width=%d, height=%d", term->cell_width, term->cell_height);
if (term->cell_width < old_cell_width ||
term->cell_height < old_cell_height)
{
/*
* The cell size has decreased.
*
* This means sixels, which we cannot resize, no longer fit
* into their "allocated" grid space.
*
* To be able to fit them, we would have to change the grid
* content. Inserting empty lines _might_ seem acceptable, but
* we'd also need to insert empty columns, which would break
* existing layout completely.
*
* So we delete them.
*/
sixel_destroy_all(term);
} else if (term->cell_width != old_cell_width ||
term->cell_height != old_cell_height)
{
sixel_cell_size_changed(term);
}
sixel_cell_size_changed(term);
/* Use force, since cell-width/height may have changed */
render_resize_force(term, term->width / term->scale, term->height / term->scale);