mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-18 03:25:55 +00:00
[sixel] create sixelmap for rematerialization #1440
This commit is contained in:
parent
eb5c9185e5
commit
262550c5ea
@ -32,6 +32,7 @@ extern "C" {
|
|||||||
#define ALLOC __attribute__((malloc)) __attribute__((warn_unused_result))
|
#define ALLOC __attribute__((malloc)) __attribute__((warn_unused_result))
|
||||||
|
|
||||||
struct esctrie;
|
struct esctrie;
|
||||||
|
struct sixelmap;
|
||||||
struct ncvisual_details;
|
struct ncvisual_details;
|
||||||
|
|
||||||
// Does this glyph completely obscure the background? If so, there's no need
|
// Does this glyph completely obscure the background? If so, there's no need
|
||||||
@ -163,7 +164,7 @@ typedef struct tament {
|
|||||||
typedef struct sprixel {
|
typedef struct sprixel {
|
||||||
char* glyph; // glyph; can be quite large
|
char* glyph; // glyph; can be quite large
|
||||||
int glyphlen; // length of the glyph in bytes
|
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
|
// both the plane and visual can die before the sprixel does. they are
|
||||||
// responsible in such a case for NULLing out this link themselves.
|
// responsible in such a case for NULLing out this link themselves.
|
||||||
struct ncplane* n; // associated ncplane
|
struct ncplane* n; // associated ncplane
|
||||||
@ -176,10 +177,13 @@ typedef struct sprixel {
|
|||||||
int cellpxy, cellpxx; // cell-pixel geometry at time of creation
|
int cellpxy, cellpxx; // cell-pixel geometry at time of creation
|
||||||
// each tacache entry is one of 0 (standard opaque cell), 1 (cell with
|
// each tacache entry is one of 0 (standard opaque cell), 1 (cell with
|
||||||
// some transparency), 2 (annihilated, excised)
|
// 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 movedfromy; // for SPRIXEL_MOVED, the starting absolute position,
|
||||||
int movedfromx; // so that we can damage old cells when redrawn
|
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;
|
} sprixel;
|
||||||
|
|
||||||
// A plane is memory for some rectilinear virtual window, plus current cursor
|
// 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_invalidate(sprixel* s, int y, int x);
|
||||||
void sprixel_movefrom(sprixel* s, int y, int x);
|
void sprixel_movefrom(sprixel* s, int y, int x);
|
||||||
void sprixel_debug(FILE* out, const sprixel* s);
|
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
|
// create an auxiliary vector suitable for a sprixcell, and zero it out
|
||||||
uint8_t* sprixel_auxiliary_vector(const sprixel* s);
|
uint8_t* sprixel_auxiliary_vector(const sprixel* s);
|
||||||
|
@ -10,6 +10,51 @@ typedef enum {
|
|||||||
SIXEL_P2_TRANS = 1,
|
SIXEL_P2_TRANS = 1,
|
||||||
} sixel_p2_e;
|
} 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.
|
// the P2 parameter on a sixel specifies how unspecified pixels are drawn.
|
||||||
// if P2 is 1, unspecified pixels are transparent. otherwise, they're 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
|
// 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
|
// second pass: construct data for extracted colors over the sixels
|
||||||
typedef struct sixeltable {
|
typedef struct sixeltable {
|
||||||
|
sixelmap* map; // copy of palette indices / transparency bits
|
||||||
// FIXME keep these internal to palette extraction; finalize there
|
// FIXME keep these internal to palette extraction; finalize there
|
||||||
int colors;
|
int colors;
|
||||||
cdetails* deets; // |colorregs| cdetails structures
|
cdetails* deets; // |colorregs| cdetails structures
|
||||||
@ -469,6 +515,7 @@ int sixel_blit(ncplane* n, int linesize, const void* data,
|
|||||||
colorregs = 256;
|
colorregs = 256;
|
||||||
}
|
}
|
||||||
sixeltable stable = {
|
sixeltable stable = {
|
||||||
|
.map = create_sixelmap(sixelcount * 6),
|
||||||
.data = malloc(colorregs * sixelcount),
|
.data = malloc(colorregs * sixelcount),
|
||||||
.deets = malloc(colorregs * sizeof(cdetails)),
|
.deets = malloc(colorregs * sizeof(cdetails)),
|
||||||
.table = malloc(colorregs * CENTSIZE),
|
.table = malloc(colorregs * CENTSIZE),
|
||||||
@ -477,7 +524,9 @@ int sixel_blit(ncplane* n, int linesize, const void* data,
|
|||||||
.colors = 0,
|
.colors = 0,
|
||||||
.p2 = SIXEL_P2_ALLOPAQUE,
|
.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.table);
|
||||||
free(stable.deets);
|
free(stable.deets);
|
||||||
free(stable.data);
|
free(stable.data);
|
||||||
|
@ -40,6 +40,7 @@ void sprixel_free(sprixel* s){
|
|||||||
if(s->n){
|
if(s->n){
|
||||||
s->n->sprite = NULL;
|
s->n->sprite = NULL;
|
||||||
}
|
}
|
||||||
|
free_sixelmap(s->smap);
|
||||||
free(s->glyph);
|
free(s->glyph);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
@ -131,7 +132,6 @@ sprixel* sprixel_alloc(ncplane* n, int dimy, int dimx, int placey, int placex){
|
|||||||
ret->y = placey;
|
ret->y = placey;
|
||||||
ret->x = placex;
|
ret->x = placex;
|
||||||
ret->id = ++sprixelid_nonce;
|
ret->id = ++sprixelid_nonce;
|
||||||
ret->wipes_outstanding = false;
|
|
||||||
//fprintf(stderr, "LOOKING AT %p (p->n = %p)\n", ret, ret->n);
|
//fprintf(stderr, "LOOKING AT %p (p->n = %p)\n", ret, ret->n);
|
||||||
if(ncplane_pile(ret->n)){
|
if(ncplane_pile(ret->n)){
|
||||||
ncpile* np = ncplane_pile(ret->n);
|
ncpile* np = ncplane_pile(ret->n);
|
||||||
|
Loading…
Reference in New Issue
Block a user