implement sixel_reblit() #1440

pull/1610/head
nick black 3 years ago committed by Nick Black
parent fe719a6c39
commit a34714ca68

@ -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

@ -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){

@ -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;

Loading…
Cancel
Save