sixel: wip: maintain a list of finished, and "active" sixel images

In unhook, add the generated image to a list of finished sixel images,
along with positioning and size information.

When rendering, loop this list of images, and render the images (or
parts of) that are visible.

When scrolling, check if any part of the images cover the re-cycled
lines, and if so, remove the *entire* image from the list.

This means we have the following limitations:

* The renderer always renders the whole (visible area of) the
  image(s). There are times when this isn't necessary - for example,
  when the image is scrolled inside the visible area.
* It would be nice if we could crop the image when parts of it is
  scrolled out.
This commit is contained in:
Daniel Eklöf 2020-02-21 23:40:35 +01:00
parent f81bdfeed5
commit f0fc82f098
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
4 changed files with 122 additions and 38 deletions

44
sixel.c
View file

@ -18,24 +18,9 @@ static size_t count;
void
sixel_init(struct terminal *term)
{
if (term->sixel.pix != NULL) {
pixman_image_unref(term->sixel.pix);
free(term->sixel.image);
term->sixel.pix = NULL;
term->sixel.image = NULL;
}
assert(term->sixel.palette == NULL);
assert(term->sixel.image == NULL);
if (term->sixel.image != NULL) {
if (term->sixel.pix != NULL) {
pixman_image_unref(term->sixel.pix);
term->sixel.pix = NULL;
}
free(term->sixel.image);
}
term->sixel.state = SIXEL_SIXEL;
term->sixel.row = 0;
term->sixel.col = 0;
@ -58,28 +43,39 @@ sixel_unhook(struct terminal *term)
free(term->sixel.palette);
term->sixel.palette = NULL;
if (term->sixel.pix != NULL)
pixman_image_unref(term->sixel.pix);
LOG_DBG("generating %dx%d pixman image", term->sixel.row * 6, term->sixel.max_col);
if (term->sixel.col > 0) {
if (term->sixel.col >= 0) {
if (term->sixel.col > term->sixel.max_col)
term->sixel.max_col = term->sixel.col;
term->sixel.row++;
term->sixel.col = 0;
}
term->sixel.pix = pixman_image_create_bits_no_clear(
struct sixel image = {
.data = term->sixel.image,
.width = term->sixel.max_col,
.height = term->sixel.row * 6,
.pos = (struct coord){term->cursor.point.col, term->grid->offset + term->cursor.point.row},
};
image.pix = pixman_image_create_bits_no_clear(
PIXMAN_a8r8g8b8,
term->sixel.max_col,
term->sixel.row * 6,
image.width, image.height,
term->sixel.image,
IMAGE_WIDTH * sizeof(uint32_t));
size_t lines = max(1, term->sixel.row * 6 / term->cell_height);
tll_push_back(term->sixel_images, image);
term->sixel.image = NULL;
term->sixel.max_col = 0;
term->sixel.col = 0;
term->sixel.row = 0;
const size_t lines = (image.height + term->cell_height - 1) / term->cell_height;
for (size_t i = 0; i < lines; i++)
term_linefeed(term);
term_formfeed(term);
render_refresh(term);
}
@ -101,7 +97,7 @@ sixel_add(struct terminal *term, uint32_t color, uint8_t sixel)
sixel >>= 1;
if (bit) {
size_t idx = (term->sixel.row * 6 + i) * IMAGE_WIDTH + term->sixel.col;
term->sixel.image[idx] = 0x00 << 24 | color;
term->sixel.image[idx] = term->colors.alpha / 256 << 24 | color;
}
}