[sixel] create sixelmap for rematerialization #1440

pull/1610/head
nick black 3 years ago committed by Nick Black
parent eb5c9185e5
commit 262550c5ea

@ -32,6 +32,7 @@ extern "C" {
#define ALLOC __attribute__((malloc)) __attribute__((warn_unused_result))
struct esctrie;
struct sixelmap;
struct ncvisual_details;
// Does this glyph completely obscure the background? If so, there's no need
@ -163,7 +164,7 @@ typedef struct tament {
typedef struct sprixel {
char* glyph; // glyph; can be quite large
int glyphlen; // length of the glyph in bytes
uint32_t id; // embedded into glusters field of nccell, 24 bits
uint32_t id; // embedded into gcluster field of nccell, 24 bits
// both the plane and visual can die before the sprixel does. they are
// responsible in such a case for NULLing out this link themselves.
struct ncplane* n; // associated ncplane
@ -176,10 +177,13 @@ typedef struct sprixel {
int cellpxy, cellpxx; // cell-pixel geometry at time of creation
// each tacache entry is one of 0 (standard opaque cell), 1 (cell with
// some transparency), 2 (annihilated, excised)
int parse_start; // where to start parsing for cell wipes
int movedfromy; // for SPRIXEL_MOVED, the starting absolute position,
int movedfromx; // so that we can damage old cells when redrawn
bool wipes_outstanding; // do we need execute wipes on move?
// only used for kitty-based sprixels
int parse_start; // where to start parsing for cell wipes
// only used for sixel-based sprixels
struct sixelmap* smap; // copy of palette indices + transparency bits
bool wipes_outstanding; // do we need rebuild the sixel next render?
} sprixel;
// A plane is memory for some rectilinear virtual window, plus current cursor
@ -966,6 +970,7 @@ sprixel* sprixel_by_id(const ncpile* n, uint32_t id);
void sprixel_invalidate(sprixel* s, int y, int x);
void sprixel_movefrom(sprixel* s, int y, int x);
void sprixel_debug(FILE* out, const sprixel* s);
void free_sixelmap(struct sixelmap *s);
// create an auxiliary vector suitable for a sprixcell, and zero it out
uint8_t* sprixel_auxiliary_vector(const sprixel* s);

@ -10,6 +10,51 @@ typedef enum {
SIXEL_P2_TRANS = 1,
} sixel_p2_e;
// we keep a copy of the visual data, reduced to a color index and a
// transparency bit per pixel. we keep the two arrays separate so the
// transparency bits don't absolutely destroy cache efficiency for the
// data array. this allows us to rebuild wiped sprixcells by simply
// rerunning the sprixel generation process following palette quantization,
// which is much, much easier than rebuilding inline, and can be done at
// the same time as wiping, and batches them both, and is probably just as
// fast (slow) as the complex in-place rebuild would be. there is, of course,
// a memory cost of about 1.125MB for a 1024x1024 sixel, but at least we
// needn't muck with auxvectors.
typedef struct sixelmap {
uint8_t* pixels; // 1 byte per pixel, index into color table
uint8_t* transmap; // 1 bit per pixel, 1 == transparent, 0 == opaque
} sixelmap;
// whip up an all-zero sixelmap for the specified number of pixels
static sixelmap*
create_sixelmap(int pixels){
sixelmap* ret = malloc(sizeof(*ret));
if(ret){
size_t pixsize = sizeof(*ret->pixels) * pixels;
ret->pixels = malloc(pixsize);
if(ret->pixels){
size_t transsize = (pixels + 7) / 8;
ret->transmap = malloc(transsize);
if(ret->transmap){
memset(ret->transmap, 0, transsize);
memset(ret->pixels, 0, pixsize);
return ret;
}
free(ret->pixels);
}
free(ret);
}
return NULL;
}
void free_sixelmap(sixelmap *s){
if(s){
free(s->transmap);
free(s->pixels);
free(s);
}
}
// the P2 parameter on a sixel specifies how unspecified pixels are drawn.
// if P2 is 1, unspecified pixels are transparent. otherwise, they're drawn
// as something else. some terminals (e.g. foot) can draw more quickly if
@ -49,6 +94,7 @@ typedef struct cdetails {
// second pass: construct data for extracted colors over the sixels
typedef struct sixeltable {
sixelmap* map; // copy of palette indices / transparency bits
// FIXME keep these internal to palette extraction; finalize there
int colors;
cdetails* deets; // |colorregs| cdetails structures
@ -469,6 +515,7 @@ int sixel_blit(ncplane* n, int linesize, const void* data,
colorregs = 256;
}
sixeltable stable = {
.map = create_sixelmap(sixelcount * 6),
.data = malloc(colorregs * sixelcount),
.deets = malloc(colorregs * sizeof(cdetails)),
.table = malloc(colorregs * CENTSIZE),
@ -477,7 +524,9 @@ int sixel_blit(ncplane* n, int linesize, const void* data,
.colors = 0,
.p2 = SIXEL_P2_ALLOPAQUE,
};
if(stable.data == NULL || stable.deets == NULL || stable.table == NULL){
if(stable.data == NULL || stable.deets == NULL || stable.table == NULL
|| stable.map == NULL){
free_sixelmap(stable.map);
free(stable.table);
free(stable.deets);
free(stable.data);

@ -40,6 +40,7 @@ void sprixel_free(sprixel* s){
if(s->n){
s->n->sprite = NULL;
}
free_sixelmap(s->smap);
free(s->glyph);
free(s);
}
@ -131,7 +132,6 @@ sprixel* sprixel_alloc(ncplane* n, int dimy, int dimx, int placey, int placex){
ret->y = placey;
ret->x = placex;
ret->id = ++sprixelid_nonce;
ret->wipes_outstanding = false;
//fprintf(stderr, "LOOKING AT %p (p->n = %p)\n", ret, ret->n);
if(ncplane_pile(ret->n)){
ncpile* np = ncplane_pile(ret->n);

Loading…
Cancel
Save