mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-02 09:40:15 +00:00
[pixel] pass celldimy through blitterargs #1401
This commit is contained in:
parent
b2ef9a074b
commit
645b61e9dc
@ -586,10 +586,6 @@ typedef struct nccell {
|
||||
// are single-byte ASCII-derived values. The XXXXXX is interpreted as a 24-bit
|
||||
// index into the egcpool. These pools may thus be up to 16MB.
|
||||
//
|
||||
// A pixel graphic (a "sprixel") is indicated by the value 0x02XXXXXX. This
|
||||
// is safe for the same reasons as a spilled EGC. The remaining 24 bits are
|
||||
// an identifier for the sprixel cache, shared across the notcurses context.
|
||||
//
|
||||
// The cost of this scheme is that the character 0x01 (SOH) cannot be encoded
|
||||
// in a nccell, which is absolutely fine because what 70s horseshit is SOH?
|
||||
// It must not be allowed through the API, or havoc will result.
|
||||
|
@ -519,6 +519,7 @@ ncdirectv* ncdirect_render_frame(ncdirect* n, const char* file,
|
||||
blitterargs bargs = {
|
||||
.pixel = {
|
||||
.celldimx = n->tcache.cellpixx,
|
||||
.celldimy = n->tcache.cellpixy,
|
||||
.colorregs = n->tcache.color_registers,
|
||||
},
|
||||
};
|
||||
|
@ -256,16 +256,10 @@ cell_extended_p(const nccell* c){
|
||||
return (htole(c->gcluster) & htole(0xff000000ul)) == htole(0x01000000ul);
|
||||
}
|
||||
|
||||
// Is the cell a sprixel?
|
||||
static inline bool
|
||||
cell_pixels_p(const nccell* c){
|
||||
return (htole(c->gcluster) & htole(0xff000000ul)) == htole(0x02000000ul);
|
||||
}
|
||||
|
||||
// Is the cell simple (a UTF8-encoded EGC of four bytes or fewer)?
|
||||
static inline bool
|
||||
cell_simple_p(const nccell* c){
|
||||
return !cell_pixels_p(c) && !cell_extended_p(c);
|
||||
return !cell_extended_p(c);
|
||||
}
|
||||
|
||||
// only applies to complex cells, do not use on simple cells
|
||||
|
@ -401,6 +401,7 @@ typedef union {
|
||||
unsigned blendcolors; // for cells
|
||||
struct {
|
||||
int celldimx; // horizontal pixels per cell
|
||||
int celldimy; // vertical pixels per cell
|
||||
int colorregs; // number of color registers
|
||||
} pixel; // for pixels
|
||||
} blitterargs;
|
||||
@ -1068,6 +1069,17 @@ egc_rtl(const char* egc, int* bytes){
|
||||
return s;
|
||||
}
|
||||
|
||||
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
|
||||
return 0;
|
||||
}
|
||||
|
||||
// lowest level of cell+pool setup. if the EGC changes the output to RTL, it
|
||||
// must be suffixed with a LTR-forcing character by now. The four bits of
|
||||
// CELL_BLITTERSTACK_MASK ought already be initialized. If gcluster is four
|
||||
|
@ -118,9 +118,10 @@ write_kitty_data(FILE* fp, int linesize, int leny, int lenx, const uint32_t* dat
|
||||
|
||||
// Kitty graphics blitter. Kitty can take in up to 4KiB at a time of (optionally
|
||||
// deflate-compressed) 24bit RGB.
|
||||
int kitty_blit_inner(ncplane* nc, int placey, int placex, int linesize,
|
||||
int leny, int lenx, unsigned cellpixx, const void* data){
|
||||
unsigned width = lenx / cellpixx + !!(lenx % cellpixx);
|
||||
int kitty_blit_inner(ncplane* nc, int linesize, int leny, int lenx,
|
||||
const void* data, const blitterargs* bargs){
|
||||
int rows = leny / bargs->pixel.celldimx + !!(leny % bargs->pixel.celldimx);
|
||||
int cols = lenx / bargs->pixel.celldimx + !!(lenx % bargs->pixel.celldimx);
|
||||
char* buf = NULL;
|
||||
size_t size = 0;
|
||||
FILE* fp = open_memstream(&buf, &size);
|
||||
@ -132,8 +133,7 @@ int kitty_blit_inner(ncplane* nc, int placey, int placex, int linesize,
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
nccell* c = ncplane_cell_ref_yx(nc, placey, placex);
|
||||
if(pool_blit_direct(&nc->pool, c, buf, size, width) < 0){
|
||||
if(plane_blit_sixel(nc, buf, size, rows, cols) < 0){
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
@ -147,9 +147,10 @@ int kitty_blit(ncplane* nc, int placey, int placex, int linesize,
|
||||
int leny, int lenx, const blitterargs* bargs){
|
||||
(void)begy;
|
||||
(void)begx;
|
||||
(void)placey;
|
||||
(void)placex;
|
||||
//fprintf(stderr, "s=%d,v=%d\n", lenx, leny);
|
||||
int r = kitty_blit_inner(nc, placey, placex, linesize, leny, lenx,
|
||||
bargs->pixel.celldimx, data);
|
||||
int r = kitty_blit_inner(nc, linesize, leny, lenx, data, bargs);
|
||||
if(r < 0){
|
||||
return -1;
|
||||
}
|
||||
|
116
src/lib/render.c
116
src/lib/render.c
@ -960,76 +960,72 @@ notcurses_rasterize_inner(notcurses* nc, const ncpile* p, FILE* out){
|
||||
if(goto_location(nc, out, y, x, &nc->rstate.hardcursorpos)){
|
||||
return -1;
|
||||
}
|
||||
if(!cell_pixels_p(srccell)){
|
||||
// set the style. this can change the color back to the default; if it
|
||||
// does, we need update our elision possibilities.
|
||||
if(term_setstyles(out, nc, srccell)){
|
||||
// set the style. this can change the color back to the default; if it
|
||||
// does, we need update our elision possibilities.
|
||||
if(term_setstyles(out, nc, srccell)){
|
||||
return -1;
|
||||
}
|
||||
// if our cell has a default foreground *or* background, we can elide
|
||||
// the default set iff one of:
|
||||
// * we are a partial glyph, and the previous was default on both, or
|
||||
// * we are a no-foreground glyph, and the previous was default background, or
|
||||
// * we are a no-background glyph, and the previous was default foreground
|
||||
bool nobackground = cell_nobackground_p(srccell);
|
||||
if((cell_fg_default_p(srccell)) || (!nobackground && cell_bg_default_p(srccell))){
|
||||
if(raster_defaults(nc, cell_fg_default_p(srccell),
|
||||
!nobackground && cell_bg_default_p(srccell), out)){
|
||||
return -1;
|
||||
}
|
||||
// if our cell has a default foreground *or* background, we can elide
|
||||
// the default set iff one of:
|
||||
// * we are a partial glyph, and the previous was default on both, or
|
||||
// * we are a no-foreground glyph, and the previous was default background, or
|
||||
// * we are a no-background glyph, and the previous was default foreground
|
||||
bool nobackground = cell_nobackground_p(srccell);
|
||||
if((cell_fg_default_p(srccell)) || (!nobackground && cell_bg_default_p(srccell))){
|
||||
if(raster_defaults(nc, cell_fg_default_p(srccell),
|
||||
!nobackground && cell_bg_default_p(srccell), out)){
|
||||
}
|
||||
// if our cell has a non-default foreground, we can elide the
|
||||
// non-default foreground set iff either:
|
||||
// * the previous was non-default, and matches what we have now, or
|
||||
// * we are a no-foreground glyph (iswspace() is true)
|
||||
if(cell_fg_palindex_p(srccell)){ // palette-indexed foreground
|
||||
if(emit_fg_palindex(nc, out, srccell)){
|
||||
return -1;
|
||||
}
|
||||
}else if(!cell_fg_default_p(srccell)){ // rgb foreground
|
||||
cell_fg_rgb8(srccell, &r, &g, &b);
|
||||
if(nc->rstate.fgelidable && nc->rstate.lastr == r && nc->rstate.lastg == g && nc->rstate.lastb == b){
|
||||
++nc->stats.fgelisions;
|
||||
}else{
|
||||
if(term_fg_rgb8(nc->tcache.RGBflag, nc->tcache.setaf, nc->tcache.colors, out, r, g, b)){
|
||||
return -1;
|
||||
}
|
||||
++nc->stats.fgemissions;
|
||||
nc->rstate.fgelidable = true;
|
||||
}
|
||||
// if our cell has a non-default foreground, we can elide the
|
||||
// non-default foreground set iff either:
|
||||
// * the previous was non-default, and matches what we have now, or
|
||||
// * we are a no-foreground glyph (iswspace() is true)
|
||||
if(cell_fg_palindex_p(srccell)){ // palette-indexed foreground
|
||||
if(emit_fg_palindex(nc, out, srccell)){
|
||||
return -1;
|
||||
}
|
||||
}else if(!cell_fg_default_p(srccell)){ // rgb foreground
|
||||
cell_fg_rgb8(srccell, &r, &g, &b);
|
||||
if(nc->rstate.fgelidable && nc->rstate.lastr == r && nc->rstate.lastg == g && nc->rstate.lastb == b){
|
||||
++nc->stats.fgelisions;
|
||||
}else{
|
||||
if(term_fg_rgb8(nc->tcache.RGBflag, nc->tcache.setaf, nc->tcache.colors, out, r, g, b)){
|
||||
return -1;
|
||||
}
|
||||
++nc->stats.fgemissions;
|
||||
nc->rstate.fgelidable = true;
|
||||
}
|
||||
nc->rstate.lastr = r; nc->rstate.lastg = g; nc->rstate.lastb = b;
|
||||
nc->rstate.fgdefelidable = false;
|
||||
nc->rstate.fgpalelidable = false;
|
||||
nc->rstate.lastr = r; nc->rstate.lastg = g; nc->rstate.lastb = b;
|
||||
nc->rstate.fgdefelidable = false;
|
||||
nc->rstate.fgpalelidable = false;
|
||||
}
|
||||
// if our cell has a non-default background, we can elide the
|
||||
// non-default background set iff either:
|
||||
// * we do not use the background, because the cell is all-foreground,
|
||||
// * the previous was non-default, and matches what we have now, or
|
||||
if(nobackground){
|
||||
++nc->stats.bgelisions;
|
||||
}else if(cell_bg_palindex_p(srccell)){ // palette-indexed background
|
||||
if(emit_bg_palindex(nc, out, srccell)){
|
||||
return -1;
|
||||
}
|
||||
// if our cell has a non-default background, we can elide the
|
||||
// non-default background set iff either:
|
||||
// * we do not use the background, because the cell is all-foreground,
|
||||
// * the previous was non-default, and matches what we have now, or
|
||||
if(nobackground){
|
||||
}else if(!cell_bg_default_p(srccell)){ // rgb background
|
||||
cell_bg_rgb8(srccell, &br, &bg, &bb);
|
||||
if(nc->rstate.bgelidable && nc->rstate.lastbr == br && nc->rstate.lastbg == bg && nc->rstate.lastbb == bb){
|
||||
++nc->stats.bgelisions;
|
||||
}else if(cell_bg_palindex_p(srccell)){ // palette-indexed background
|
||||
if(emit_bg_palindex(nc, out, srccell)){
|
||||
}else{
|
||||
if(term_bg_rgb8(nc->tcache.RGBflag, nc->tcache.setab,
|
||||
nc->tcache.colors, out, br, bg, bb,
|
||||
nc->tcache.bg_collides_default)){
|
||||
return -1;
|
||||
}
|
||||
}else if(!cell_bg_default_p(srccell)){ // rgb background
|
||||
cell_bg_rgb8(srccell, &br, &bg, &bb);
|
||||
if(nc->rstate.bgelidable && nc->rstate.lastbr == br && nc->rstate.lastbg == bg && nc->rstate.lastbb == bb){
|
||||
++nc->stats.bgelisions;
|
||||
}else{
|
||||
if(term_bg_rgb8(nc->tcache.RGBflag, nc->tcache.setab,
|
||||
nc->tcache.colors, out, br, bg, bb,
|
||||
nc->tcache.bg_collides_default)){
|
||||
return -1;
|
||||
}
|
||||
++nc->stats.bgemissions;
|
||||
nc->rstate.bgelidable = true;
|
||||
}
|
||||
nc->rstate.lastbr = br; nc->rstate.lastbg = bg; nc->rstate.lastbb = bb;
|
||||
nc->rstate.bgdefelidable = false;
|
||||
nc->rstate.bgpalelidable = false;
|
||||
++nc->stats.bgemissions;
|
||||
nc->rstate.bgelidable = true;
|
||||
}
|
||||
}else{
|
||||
nc->rstate.hardcursorpos = true;
|
||||
nc->rstate.lastbr = br; nc->rstate.lastbg = bg; nc->rstate.lastbb = bb;
|
||||
nc->rstate.bgdefelidable = false;
|
||||
nc->rstate.bgpalelidable = false;
|
||||
}
|
||||
//fprintf(stderr, "RAST %08x [%s] to %d/%d cols: %u %016lx\n", srccell->gcluster, pool_extended_gcluster(&nc->pool, srccell), y, x, srccell->width, srccell->channels);
|
||||
if(term_putc(out, &nc->pool, srccell)){
|
||||
|
@ -243,8 +243,8 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab){
|
||||
// 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 placey, int placex, int lenx,
|
||||
sixeltable* stab, unsigned cellpixx){
|
||||
int sixel_blit_inner(ncplane* nc, int leny, int lenx, sixeltable* stab,
|
||||
const blitterargs* bargs){
|
||||
char* buf = NULL;
|
||||
size_t size = 0;
|
||||
FILE* fp = open_memstream(&buf, &size);
|
||||
@ -256,9 +256,9 @@ int sixel_blit_inner(ncplane* nc, int placey, int placex, int lenx,
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
nccell* c = ncplane_cell_ref_yx(nc, placey, placex);
|
||||
unsigned width = lenx / cellpixx + !!(lenx % cellpixx);
|
||||
if(pool_blit_direct(&nc->pool, c, buf, size, width) < 0){
|
||||
unsigned cols = lenx / bargs->pixel.celldimx + !!(lenx % bargs->pixel.celldimx);
|
||||
unsigned rows = leny / bargs->pixel.celldimy + !!(leny % bargs->pixel.celldimx);
|
||||
if(plane_blit_sixel(nc, buf, size, rows, cols) < 0){
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
@ -269,6 +269,8 @@ int sixel_blit_inner(ncplane* nc, int placey, int placex, int lenx,
|
||||
int sixel_blit(ncplane* nc, int placey, int placex, int linesize,
|
||||
const void* data, int begy, int begx,
|
||||
int leny, int lenx, const blitterargs* bargs){
|
||||
(void)placey;
|
||||
(void)placex;
|
||||
int sixelcount = (lenx - begx) * ((leny - begy + 5) / 6);
|
||||
sixeltable stable = {
|
||||
.data = malloc(MAXCOLORS * sixelcount),
|
||||
@ -292,7 +294,7 @@ int sixel_blit(ncplane* nc, int placey, int placex, int linesize,
|
||||
free(stable.deets);
|
||||
return -1;
|
||||
}
|
||||
int r = sixel_blit_inner(nc, placey, placex, lenx, &stable, bargs->pixel.celldimx);
|
||||
int r = sixel_blit_inner(nc, leny, lenx, &stable, bargs);
|
||||
free(stable.data);
|
||||
free(stable.deets);
|
||||
free(stable.table);
|
||||
|
@ -528,6 +528,7 @@ auto ncvisual_render_pixels(tinfo* tcache, ncvisual* ncv, const blitset* bset,
|
||||
//fprintf(stderr, "pblit: %dx%d <- %dx%d of %d/%d stride %u @%dx%d %p %u\n", disprows, dispcols, begy, begx, ncv->rows, ncv->cols, ncv->rowstride, placey, placex, ncv->data, ncplane_notcurses(stdn)->tcache.cellpixx);
|
||||
blitterargs bargs;
|
||||
bargs.pixel.celldimx = ncplane_notcurses(stdn)->tcache.cellpixx;
|
||||
bargs.pixel.celldimy = ncplane_notcurses(stdn)->tcache.cellpixy;
|
||||
bargs.pixel.colorregs = ncplane_notcurses(stdn)->tcache.color_registers;
|
||||
if(ncvisual_blit(ncv, disprows, dispcols, n, bset,
|
||||
placey, placex, begy, begx, disprows, dispcols, &bargs)){
|
||||
|
Loading…
Reference in New Issue
Block a user