[sprixels] kill glyph copy on sprixel load

pull/1480/head
nick black 3 years ago committed by Nick Black
parent 4ee0582321
commit 69c8e25894

@ -56,6 +56,7 @@ typedef enum {
SPRIXCELL_NORMAL, // no transparent pixels in this cell
SPRIXCELL_CONTAINS_TRANS, // this cell has transparent pixels
SPRIXCELL_ANNIHILATED, // this cell has been wiped
SPRIXCELL_UNHIDDEN, // this cell needs be unwiped
} sprixcell_e;
// there is a context-wide set of displayed pixel glyphs ("sprixels"); i.e.
@ -761,8 +762,9 @@ plane_debug(const ncplane* n, bool details){
void sprixel_free(sprixel* s);
void sprixel_invalidate(sprixel* s);
void sprixel_hide(sprixel* s);
// dimy and dimx are cell geometry, not pixel
// takes ownership of g on success
sprixel* sprixel_update(sprixel* s, char* g, int bytes);
// dimy and dimx are cell geometry, not pixel. takes ownership of s on success.
sprixel* sprixel_create(ncplane* n, char* s, int bytes, int placey, int placex,
int sprixelid, int dimy, int dimx, int pixy, int pixx,
int parse_start, sprixcell_e* tacache);
@ -1180,7 +1182,11 @@ plane_blit_sixel(ncplane* n, char* s, int bytes, int placey, int placex,
for(int y = placey ; y < placey + leny && y < ncplane_dim_y(n) ; ++y){
for(int x = placex ; x < placex + lenx && x < ncplane_dim_x(n) ; ++x){
nccell* c = ncplane_cell_ref_yx(n, y, x);
memcpy(&c->gcluster, &gcluster, sizeof(gcluster));
if(x == placex){
memcpy(&c->gcluster, &gcluster, sizeof(gcluster));
}else{
c->gcluster = 0;
}
c->width = lenx;
}
}

@ -296,6 +296,7 @@ int kitty_blit(ncplane* nc, int linesize, const void* data,
return -1;
}
int parse_start = 0;
// closes fp on success
sprixcell_e* tacache = write_kitty_data(fp, rows, cols, linesize, leny, lenx, data,
bargs->u.pixel.sprixelid, &parse_start);
if(tacache == NULL){

@ -485,7 +485,7 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab, int* parse_start, sprixce
// are programmed as a set of registers, which are then referenced by the
// stacks. There is also a RLE component, handled in rasterization.
// A pixel block is indicated by setting cell_pixels_p().
int sixel_blit_inner(ncplane* nc, int leny, int lenx, sixeltable* stab,
int sixel_blit_inner(ncplane* n, int leny, int lenx, sixeltable* stab,
const blitterargs* bargs){
char* buf = NULL;
size_t size = 0;
@ -494,31 +494,55 @@ int sixel_blit_inner(ncplane* nc, int leny, int lenx, sixeltable* stab,
return -1;
}
int parse_start = 0;
unsigned cols = lenx / bargs->u.pixel.celldimx + !!(lenx % bargs->u.pixel.celldimx);
unsigned rows = leny / bargs->u.pixel.celldimy + !!(leny % bargs->u.pixel.celldimy);
sprixcell_e* tacache = malloc(sizeof(*tacache) * rows * cols);
memset(tacache, 0, sizeof(*tacache) * rows * cols);
if(tacache == NULL){
free(buf);
return -1;
int cols = lenx / bargs->u.pixel.celldimx + !!(lenx % bargs->u.pixel.celldimx);
int rows = leny / bargs->u.pixel.celldimy + !!(leny % bargs->u.pixel.celldimy);
sprixcell_e* tacache = NULL;
bool reuse = false;
// if we have a sprixel attached to this plane, see if we can reuse it
// (we need the same dimensions) and thus immediately apply its T-A table.
if(n->sprite){
sprixel* s = n->sprite;
if(s->dimy == rows && s->dimx == cols){
tacache = s->tacache;
reuse = true;
}
}
if(!reuse){
tacache = malloc(sizeof(*tacache) * rows * cols);
if(tacache == NULL){
fclose(fp);
free(buf);
return -1;
}
memset(tacache, 0, sizeof(*tacache) * rows * cols);
}
// calls fclose() on success
if(write_sixel_data(fp, lenx, stab, &parse_start, tacache)){
free(tacache);
if(!reuse){
free(tacache);
}
fclose(fp);
free(buf);
return -1;
}
// takes ownership of |buf| on success
if(plane_blit_sixel(nc, buf, size, bargs->placey, bargs->placex,
rows, cols, bargs->u.pixel.sprixelid, leny, lenx,
parse_start, tacache) < 0){
free(tacache);
free(buf);
return -1;
// both paths take ownership of buf on success
if(reuse){
sprixel_update(n->sprite, buf, size);
}else{
if(plane_blit_sixel(n, buf, size, bargs->placey, bargs->placex,
rows, cols, bargs->u.pixel.sprixelid, leny, lenx,
parse_start, tacache) < 0){
if(!reuse){
free(tacache);
}
free(buf);
return -1;
}
}
return 1;
}
int sixel_blit(ncplane* nc, int linesize, const void* data,
int sixel_blit(ncplane* n, int linesize, const void* data,
int leny, int lenx, const blitterargs* bargs){
int sixelcount = (lenx - bargs->begx) * ((leny - bargs->begy + 5) / 6);
int colorregs = bargs->u.pixel.colorregs;
@ -552,7 +576,7 @@ int sixel_blit(ncplane* nc, int linesize, const void* data,
return -1;
}
refine_color_table(data, linesize, bargs->begy, bargs->begx, leny, lenx, &stable);
int r = sixel_blit_inner(nc, leny, lenx, &stable, bargs);
int r = sixel_blit_inner(n, leny, lenx, &stable, bargs);
free(stable.data);
free(stable.deets);
free(stable.table);

@ -30,14 +30,16 @@ sprixel* sprixel_by_id(notcurses* nc, uint32_t id){
}
// s ought already have been scrubbed according to the T-A matrix
sprixel* sprixel_update(sprixel* s, const char* g, int bytes){
sprixel* sprixel_update(sprixel* s, char* g, int bytes){
free(s->glyph);
s->glyph = g;
s->glyphlen = bytes;
s->invalidated = SPRIXEL_INVALIDATED;
return s;
}
// y and x are the cell geometry, not the pixel geometry
// 'y' and 'x' are the cell geometry, not the pixel geometry. takes
// ownership of 's' on success.
sprixel* sprixel_create(ncplane* n, char* s, int bytes, int placey, int placex,
int sprixelid, int dimy, int dimx, int pixy, int pixx,
int parse_start, sprixcell_e* tacache){

Loading…
Cancel
Save