[pixels] build up the sprixel cache #1401

pull/1418/head
nick black 3 years ago committed by Nick Black
parent b282c2055b
commit 486374a6b0

@ -379,6 +379,12 @@ ncdirect_dump_plane(ncdirect* n, const ncplane* np, int xoff){
const int toty = ncdirect_dim_y(n);
int dimy, dimx;
ncplane_dim_yx(np, &dimy, &dimx);
if(np->sprite){
if(fputs(np->sprite->glyph, n->ttyfp) == EOF){
return -1;
}
return 0;
}
//fprintf(stderr, "rasterizing %dx%d+%d\n", dimy, dimx, xoff);
// save the existing style and colors
const bool fgdefault = ncdirect_fg_default_p(n);

@ -45,6 +45,19 @@ struct ncvisual_details;
// we can't define multipart ncvisual here, because OIIO requires C++ syntax,
// and we can't go throwing C++ syntax into this header. so it goes.
// there is a context-wide set of displayed pixel glyphs ("sprixels"); i.e.
// these are independent of particular piles. there should never be very many
// associated with a context (a dozen or so at max). with the kitty protocol,
// we can register them, and then manipulate them by id. with the sixel
// protocol, we just have to rewrite them.
typedef struct sprixel {
char* glyph; // glyph; can be quite large
int id; // embedded into glusters field of nccell
struct ncplane* n; // associated ncplane, provides location and size
int invalidated;
struct sprixel* next;
} sprixel;
// A plane is memory for some rectilinear virtual window, plus current cursor
// state for that window, and part of a pile. Each pile has a total order along
// its z-axis. Functions update these virtual planes over a series of API
@ -86,6 +99,8 @@ typedef struct ncplane {
struct ncplane* blist; // head of list of bound planes
struct ncplane* boundto;// plane to which we are bound (ourself for roots)
sprixel* sprite; // pointer into the sprixel cache
void* userptr; // slot for the user to stick some opaque pointer
int (*resizecb)(struct ncplane*); // callback after parent is resized
nccell basecell; // cell written anywhere that fb[i].gcluster == 0
@ -342,19 +357,6 @@ typedef struct ncpile {
int dimy, dimx; // rows and cols at time of render
} ncpile;
// there is a context-wide set of displayed pixel glyphs ("sprixels"); i.e.
// these are independent of particular piles. there should never be very many
// associated with a context (a dozen or so at max). with the kitty protocol,
// we can register them, and then manipulate them by id. with the sixel
// protocol, we just have to rewrite them.
typedef struct sprixel {
char* glyph; // glyph; can be quite large
int id; // embedded into glusters field of nccell
ncplane* n; // associated ncplane, provides location and size
int invalidated;
struct sprixel* next;
} sprixel;
// the standard pile can be reached through ->stdplane.
typedef struct notcurses {
ncplane* stdplane; // standard plane, covers screen
@ -387,6 +389,7 @@ typedef struct notcurses {
bool suppress_banner; // from notcurses_options
sprixel* sprixelcache; // list of pixel graphics currently displayed
int sprixelnonce; // next sprixel id FIXME ought be atomic
// desired margins (best-effort only), copied in from notcurses_options
int margin_t, margin_b, margin_r, margin_l;
@ -683,6 +686,7 @@ plane_debug(const ncplane* n, bool details){
}
void sprixel_free(sprixel* s);
sprixel* sprixel_create(ncplane* n, const char* s, int bytes);
static inline void
pool_release(egcpool* pool, nccell* c){
@ -1072,14 +1076,28 @@ egc_rtl(const char* egc, int* bytes){
return s;
}
// a sprixel occupies the entirety of its associated plane. each cell contains
// a reference to the context-wide sprixel cache. this ought be an entirely
// new, purpose-specific plane.
static inline int
plane_blit_sixel(ncplane* n, const char* s, int bytes, int leny, int lenx){
(void)n;
(void)s;
(void)bytes;
(void)leny;
(void)lenx;
// FIXME
sprixel* spx = sprixel_create(n, s, bytes);
if(spx == NULL){
return -1;
}
char gcluster[4];
gcluster[0] = 2;
gcluster[1] = spx->id;
gcluster[2] = 0; // FIXME
gcluster[3] = 0; // FIXME
for(int y = 0 ; y < leny ; ++y){
for(int x = 0 ; x < lenx ; ++x){
nccell* c = ncplane_cell_ref_yx(n, y, x);
memcpy(&c->gcluster, gcluster, sizeof(gcluster));
c->width = lenx;
}
}
n->sprite = spx;
return 0;
}

@ -321,6 +321,7 @@ ncplane* ncplane_new_internal(notcurses* nc, ncplane* n,
p->lenx = nopts->cols;
p->x = p->y = 0;
p->logrow = 0;
p->sprite = NULL;
p->blist = NULL;
p->name = strdup(nopts->name ? nopts->name : "");
p->align = NCALIGN_UNALIGNED;

@ -6,3 +6,22 @@ void sprixel_free(sprixel* s){
free(s);
}
}
sprixel* sprixel_create(ncplane* n, const char* s, int bytes){
sprixel* ret = malloc(sizeof(sprixel));
if(ret){
if((ret->glyph = memdup(s, bytes + 1)) == NULL){
free(ret);
return NULL;
}
ret->invalidated = 1;
ret->n = n;
if(ncplane_pile(n)){
notcurses* nc = ncplane_notcurses(n);
ret->next = nc->sprixelcache;
nc->sprixelcache = ret;
ret->id = nc->sprixelnonce++; // FIXME should be atomic
}
}
return ret;
}

Loading…
Cancel
Save