diff --git a/src/lib/internal.h b/src/lib/internal.h index a6a9f8809..bd41287d9 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -469,7 +469,7 @@ typedef struct tinfo { int (*pixel_rebuild)(sprixel* s, int y, int x, uint8_t* auxvec); int (*pixel_remove)(int id, FILE* out); // kitty only, issue actual delete command int (*pixel_init)(int fd); // called when support is detected - int (*pixel_draw)(const struct notcurses* n, const struct ncpile* p, sprixel* s, FILE* out); + int (*pixel_draw)(const struct ncpile* p, sprixel* s, FILE* out); int (*pixel_shutdown)(int fd); // called during context shutdown bool bitmap_supported; // do we support bitmaps (post pixel_query_done)? bool sprixel_cursor_hack; // do sprixels reset the cursor? (mlterm) @@ -949,8 +949,8 @@ int kitty_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec); void sprixel_free(sprixel* s); void sprixel_hide(sprixel* s); -int kitty_draw(const notcurses* n, const ncpile *p, sprixel* s, FILE* out); -int sixel_draw(const notcurses* n, const ncpile *p, sprixel* s, FILE* out); +int kitty_draw(const ncpile *p, sprixel* s, FILE* out); +int sixel_draw(const ncpile *p, sprixel* s, FILE* out); // dimy and dimx are cell geometry, not pixel. sprixel* sprixel_alloc(ncplane* n, int dimy, int dimx, int placey, int placex); sprixel* sprixel_recycle(ncplane* n); @@ -990,7 +990,7 @@ sprite_destroy(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s){ static inline int sprite_draw(const notcurses* n, const ncpile* p, sprixel* s, FILE* out){ //sprixel_debug(stderr, s); - return n->tcache.pixel_draw(n, p, s, out); + return n->tcache.pixel_draw(p, s, out); } static inline int diff --git a/src/lib/kitty.c b/src/lib/kitty.c index 53fda7aba..d4b954c27 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -571,8 +571,6 @@ int kitty_remove(int id, FILE* out){ // removes the kitty bitmap graphic identified by s->id, and damages those // cells which weren't SPRIXCEL_OPAQUE int kitty_destroy(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s){ - (void)p; - (void)nc; if(kitty_remove(s->id, out)){ return -1; } @@ -601,8 +599,7 @@ int kitty_destroy(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s){ return 0; } -int kitty_draw(const notcurses* nc, const ncpile* p, sprixel* s, FILE* out){ - (void)nc; +int kitty_draw(const ncpile* p, sprixel* s, FILE* out){ (void)p; int ret = 0; if(fwrite(s->glyph, s->glyphlen, 1, out) != 1){ diff --git a/src/lib/sixel.c b/src/lib/sixel.c index 427351352..c6a9b996e 100644 --- a/src/lib/sixel.c +++ b/src/lib/sixel.c @@ -532,6 +532,45 @@ write_sixel(FILE* fp, int leny, int lenx, const sixeltable* stab, int* parse_sta return 0; } +// once per render cycle (if needed), make the actual payload match the TAM. we +// don't do these one at a time due to the complex (expensive) process involved +// in regenerating a sixel (we can't easily do it in-place). anything newly +// ANNIHILATED (state is ANNIHILATED, but no auxvec present) is dropped from +// the payload, and an auxvec is generated. anything newly restored (state is +// OPAQUE_SIXEL or MIXED_SIXEL, but an auxvec is present) is restored to the +// payload, and the auxvec is freed. none of this takes effect until the sixel +// is redrawn, and annihilated sprixcells still require a glyph to be emitted. +static inline int +sixel_reblit(sprixel* s, tament* tam){ + char* buf = NULL; + size_t size = 0; + FILE* fp = open_memstream(&buf, &size); + if(fp == NULL){ + return -1; + } + if(fwrite(s->glyph, s->parse_start, 1, fp) != (size_t)s->parse_start){ + fclose(fp); + free(buf); + return -1; + } + // FIXME need to get cursor_hack in here for shitty mlterm! + (void)tam; // FIXME needs to update with tam! or hit with tam at wipe time! + if(write_sixel_payload(fp, s->pixx, s->smap, NULL) < 0){ + fclose(fp); + free(buf); + return -1; + } + if(fclose(fp) == EOF){ + free(buf); + return -1; + } + free(s->glyph); + // FIXME update P2 if necessary + s->glyph = buf; + s->glyphlen = size; + return 0; +} + // Sixel blitter. Sixels are stacks 6 pixels high, and 1 pixel wide. RGB colors // are programmed as a set of registers, which are then referenced by the // stacks. There is also a RLE component, handled in rasterization. @@ -620,16 +659,19 @@ int sixel_blit(ncplane* n, int linesize, const void* data, return -1; } refine_color_table(data, linesize, bargs->begy, bargs->begx, leny, lenx, &stable); + // takes ownership of sixelmap on success int r = sixel_blit_inner(leny, lenx, &stable, rows, cols, bargs, tam); - // FIXME give stable.map to sprixel after trimming it + if(r < 0){ + sixelmap_free(stable.map); + } free(stable.deets); return r; } int sixel_destroy(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s){ //fprintf(stderr, "%d] %d %p\n", s->id, s->invalidated, s->n); - (void)out; (void)nc; + (void)out; int starty = s->movedfromy; int startx = s->movedfromx; for(int yy = starty ; yy < starty + s->dimy && yy < p->dimy ; ++yy){ @@ -643,29 +685,11 @@ int sixel_destroy(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s){ return 0; } -// once per render cycle (if needed), make the actual payload match the TAM. we -// don't do these one at a time due to the complex (expensive) process involved -// in regenerating a sixel (we can't easily do it in-place). anything newly -// ANNIHILATED (state is ANNIHILATED, but no auxvec present) is dropped from -// the payload, and an auxvec is generated. anything newly restored (state is -// OPAQUE_SIXEL or MIXED_SIXEL, but an auxvec is present) is restored to the -// payload, and the auxvec is freed. none of this takes effect until the sixel -// is redrawn, and annihilated sprixcells still require a glyph to be emitted. -static int -sixel_update(const notcurses* n, sprixel* s){ - blitterargs bargs = { }; // FIXME need prep this - // FIXME need a sixel_blit_inner() that reuses the header - /*if(sixel_blit_inner(s->pixy, s->pixx, s->dimy, s->dimx, &bargs, s->n->tam)){ - return -1; - }*/ - return 0; -} - -int sixel_draw(const notcurses* n, const ncpile* p, sprixel* s, FILE* out){ +int sixel_draw(const ncpile* p, sprixel* s, FILE* out){ // if we've wiped or rebuilt any cells, effect those changes now, or else // we'll get flicker when we move to the new location. if(s->wipes_outstanding){ - if(sixel_update(n, s)){ + if(sixel_reblit(s, s->n->tam)){ return -1; } s->wipes_outstanding = false;