mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-08 01:10:23 +00:00
[sprixels] use cell-pixel geometry from ncpile #1687
This commit is contained in:
parent
b26bc27072
commit
0dbb469a27
@ -1778,6 +1778,7 @@ API int ncplane_scrollup(struct ncplane* n, int r)
|
||||
// Scroll |n| up until |child| is no longer hidden beneath it. Returns an
|
||||
// error if |child| is not a child of |n|, or |n| is not scrolling, or |child|
|
||||
// is fixed. Returns the number of scrolling events otherwise (might be 0).
|
||||
// If the child plane is not fixed, it will likely scroll as well.
|
||||
API int ncplane_scrollup_child(struct ncplane* n, const struct ncplane* child)
|
||||
__attribute__ ((nonnull (1, 2)));
|
||||
|
||||
|
@ -38,13 +38,13 @@ int init_banner(const notcurses* nc, fbuf* f){
|
||||
free(osver);
|
||||
term_fg_palindex(nc, f, nc->tcache.caps.colors <= 256 ?
|
||||
14 % nc->tcache.caps.colors : 0x2080e0);
|
||||
if(nc->tcache.cellpixy && nc->tcache.cellpixx){
|
||||
if(nc->tcache.cellpxy && nc->tcache.cellpxx){
|
||||
fbuf_printf(f, "%s%d rows (%dpx) %d cols (%dpx) %dx%d ",
|
||||
clreol,
|
||||
nc->stdplane->leny, nc->tcache.cellpixy,
|
||||
nc->stdplane->lenx, nc->tcache.cellpixx,
|
||||
nc->stdplane->leny * nc->tcache.cellpixy,
|
||||
nc->stdplane->lenx * nc->tcache.cellpixx);
|
||||
nc->stdplane->leny, nc->tcache.cellpxy,
|
||||
nc->stdplane->lenx, nc->tcache.cellpxx,
|
||||
nc->stdplane->leny * nc->tcache.cellpxy,
|
||||
nc->stdplane->lenx * nc->tcache.cellpxx);
|
||||
}else{
|
||||
fbuf_printf(f, "%d rows %d cols ",
|
||||
nc->stdplane->leny, nc->stdplane->lenx);
|
||||
|
@ -9,7 +9,7 @@ extern "C" {
|
||||
static inline int
|
||||
encoding_y_scale(const tinfo* tcache, const struct blitset* bset) {
|
||||
if(bset->geom == NCBLIT_PIXEL){
|
||||
return tcache->cellpixy;
|
||||
return tcache->cellpxy;
|
||||
}
|
||||
return bset->height;
|
||||
}
|
||||
@ -18,7 +18,7 @@ encoding_y_scale(const tinfo* tcache, const struct blitset* bset) {
|
||||
static inline int
|
||||
encoding_x_scale(const tinfo* tcache, const struct blitset* bset) {
|
||||
if(bset->geom == NCBLIT_PIXEL){
|
||||
return tcache->cellpixx;
|
||||
return tcache->cellpxx;
|
||||
}
|
||||
return bset->width;
|
||||
}
|
||||
|
@ -654,8 +654,8 @@ ncdirect_render_visual(ncdirect* n, ncvisual* ncv,
|
||||
disprows = dimy * encoding_y_scale(&n->tcache, bset) - 1;
|
||||
outy = disprows;
|
||||
}else{
|
||||
dispcols = dimx * n->tcache.cellpixx;
|
||||
disprows = dimy * n->tcache.cellpixy;
|
||||
dispcols = dimx * n->tcache.cellpxx;
|
||||
disprows = dimy * n->tcache.cellpxy;
|
||||
clamp_to_sixelmax(&n->tcache, &disprows, &dispcols, &outy, vopts->scaling);
|
||||
}
|
||||
if(vopts->scaling == NCSCALE_SCALE || vopts->scaling == NCSCALE_SCALE_HIRES){
|
||||
@ -675,7 +675,7 @@ ncdirect_render_visual(ncdirect* n, ncvisual* ncv,
|
||||
}
|
||||
}
|
||||
if(bset->geom == NCBLIT_PIXEL){
|
||||
while((outy + n->tcache.cellpixy - 1) / n->tcache.cellpixy > dimy){
|
||||
while((outy + n->tcache.cellpxy - 1) / n->tcache.cellpxy > dimy){
|
||||
outy -= n->tcache.sprixel_scale_height;
|
||||
disprows = outy;
|
||||
}
|
||||
@ -693,8 +693,8 @@ ncdirect_render_visual(ncdirect* n, ncvisual* ncv,
|
||||
.flags = 0,
|
||||
};
|
||||
if(bset->geom == NCBLIT_PIXEL){
|
||||
nopts.rows = outy / n->tcache.cellpixy + !!(outy % n->tcache.cellpixy);
|
||||
nopts.cols = dispcols / n->tcache.cellpixx + !!(dispcols % n->tcache.cellpixx);
|
||||
nopts.rows = outy / n->tcache.cellpxy + !!(outy % n->tcache.cellpxy);
|
||||
nopts.cols = dispcols / n->tcache.cellpxx + !!(dispcols % n->tcache.cellpxx);
|
||||
}
|
||||
if(ymax && nopts.rows > ymax){
|
||||
nopts.rows = ymax;
|
||||
@ -717,7 +717,9 @@ ncdirect_render_visual(ncdirect* n, ncvisual* ncv,
|
||||
}
|
||||
if(bset->geom == NCBLIT_PIXEL){
|
||||
bargs.u.pixel.colorregs = n->tcache.color_registers;
|
||||
if((bargs.u.pixel.spx = sprixel_alloc(&n->tcache, ncdv, nopts.rows, nopts.cols)) == NULL){
|
||||
bargs.u.pixel.cellpxy = n->tcache.cellpxy;
|
||||
bargs.u.pixel.cellpxx = n->tcache.cellpxx;
|
||||
if((bargs.u.pixel.spx = sprixel_alloc(ncdv, nopts.rows, nopts.cols)) == NULL){
|
||||
free_plane(ncdv);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -288,17 +288,37 @@ struct crender {
|
||||
} s;
|
||||
};
|
||||
|
||||
// a pile is a collection of planes which will be rendered together. piles are
|
||||
// completely distinct with regards to thread-safety; one can always operate
|
||||
// concurrently on distinct piles (save rasterizing, of course). material from
|
||||
// other piles will be blown away whenever a pile is rasterized. no ordering
|
||||
// is meaningful between planes. when a new one is added, or one is destroyed,
|
||||
// the pilelock (in struct notcurses) is taken. a pile is destroyed whenever
|
||||
// its last plane is destroyed or reparented away. a pile contains a totally-
|
||||
// ordered list of piles (ordered on the z axis) and a directed acyclic forest
|
||||
// of bound planes, with each root plane rooting a DAG.
|
||||
//
|
||||
// the geometries are updated each time the pile is rendered. until a pile is
|
||||
// rendered, its geometries might be out-of-date with regards to the terminal
|
||||
// description in tcache. when it is rendered again, the geometries will be
|
||||
// updated, sprixels will have their TAMs rebuilt (if necessary), and each
|
||||
// root plane will have its resize callback invoked (possibly invoking its
|
||||
// bound planes' resize callbacks in turn).
|
||||
//
|
||||
// at context start, there is one pile (the standard pile), containing one
|
||||
// plane (the standard plane). each ncplane holds a pointer to its pile.
|
||||
typedef struct ncpile {
|
||||
ncplane* top; // topmost plane, never NULL
|
||||
ncplane* bottom; // bottommost plane, never NULL
|
||||
ncplane* roots; // head of root plane list
|
||||
struct crender* crender; // array (rows * cols crender objects)
|
||||
struct notcurses* nc; // notcurses context
|
||||
struct ncpile *prev, *next; // circular list
|
||||
struct ncpile *prev, *next; // circular list pointers
|
||||
size_t crenderlen; // size of crender vector
|
||||
unsigned dimy, dimx; // rows and cols at time of last render
|
||||
unsigned dimy, dimx; // rows and cols at last render/creation
|
||||
unsigned cellpxx, cellpxy; // cell-pixel geometry at last render/creation
|
||||
int scrolls; // how many real lines need be scrolled at raster
|
||||
sprixel* sprixelcache; // list of sprixels
|
||||
sprixel* sprixelcache; // sorted list of sprixels, assembled during paint
|
||||
} ncpile;
|
||||
|
||||
// the standard pile can be reached through ->stdplane.
|
||||
@ -359,6 +379,8 @@ typedef struct blitterargs {
|
||||
sprixel* spx; // sprixel object
|
||||
int pxoffy; // pixel y-offset within origin cell
|
||||
int pxoffx; // pixel x-offset within origin cell
|
||||
int cellpxy; // targeted cell-pixel geometry. this ought come from the
|
||||
int cellpxx; // target ncpile, or tcache in Direct Mode
|
||||
} pixel; // for pixels
|
||||
} u;
|
||||
} blitterargs;
|
||||
@ -664,7 +686,7 @@ void sprixel_free(sprixel* s);
|
||||
void sprixel_hide(sprixel* s);
|
||||
|
||||
// dimy and dimx are cell geometry, not pixel.
|
||||
sprixel* sprixel_alloc(const tinfo* ti, ncplane* n, int dimy, int dimx);
|
||||
sprixel* sprixel_alloc(ncplane* n, int dimy, int dimx);
|
||||
sprixel* sprixel_recycle(ncplane* n);
|
||||
int sprite_init(const tinfo* t, int fd);
|
||||
int sprite_clear_all(const tinfo* t, fbuf* f);
|
||||
@ -1748,7 +1770,7 @@ typedef struct ncvisual_implementation {
|
||||
int (*visual_decode_loop)(struct ncvisual* nc);
|
||||
int (*visual_stream)(notcurses* nc, struct ncvisual* ncv, float timescale,
|
||||
ncstreamcb streamer, const struct ncvisual_options* vopts, void* curry);
|
||||
struct ncplane* (*visual_subtitle)(struct ncplane* parent, const struct ncvisual* ncv);
|
||||
ncplane* (*visual_subtitle)(ncplane* parent, const struct ncvisual* ncv);
|
||||
int rowalign; // rowstride base, can be 0 for no padding
|
||||
// do a persistent resize, changing the ncv itself
|
||||
int (*visual_resize)(struct ncvisual* ncv, unsigned rows, unsigned cols);
|
||||
|
@ -233,8 +233,8 @@ init_sprixel_animation(sprixel* s){
|
||||
// auxiliary vector back into the actual data. we then free the auxvector.
|
||||
int kitty_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
const int totalpixels = s->pixy * s->pixx;
|
||||
const int xpixels = s->cellpxx;
|
||||
const int ypixels = s->cellpxy;
|
||||
const int xpixels = ncplane_pile(s->n)->cellpxx;
|
||||
const int ypixels = ncplane_pile(s->n)->cellpxy;
|
||||
int targx = xpixels;
|
||||
if((xcell + 1) * xpixels > s->pixx){
|
||||
targx = s->pixx - xcell * xpixels;
|
||||
@ -308,8 +308,8 @@ int kitty_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
// wiping)?
|
||||
static inline unsigned
|
||||
kitty_anim_auxvec_blitsource_p(const sprixel* s, const uint8_t* auxvec){
|
||||
const size_t offset = s->cellpxy * s->cellpxx * 4;
|
||||
if(auxvec[offset]){
|
||||
size_t off = ncplane_pile(s->n)->cellpxy * ncplane_pile(s->n)->cellpxx * 4;
|
||||
if(auxvec[off]){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -354,8 +354,8 @@ kitty_anim_auxvec(int dimy, int dimx, int posy, int posx,
|
||||
return a;
|
||||
}
|
||||
|
||||
uint8_t* kitty_trans_auxvec(const tinfo* ti){
|
||||
const size_t slen = ti->cellpixy * ti->cellpixx;
|
||||
uint8_t* kitty_trans_auxvec(const ncpile* p){
|
||||
const size_t slen = p->cellpxy * p->cellpxx;
|
||||
uint8_t* a = malloc(slen);
|
||||
if(a){
|
||||
memset(a, 0, slen);
|
||||
@ -367,13 +367,14 @@ uint8_t* kitty_trans_auxvec(const tinfo* ti){
|
||||
// by the wipe proper, and when blitting a new frame with annihilations.
|
||||
static int
|
||||
kitty_blit_wipe_selfref(sprixel* s, fbuf* f, int ycell, int xcell){
|
||||
const int cellpxx = ncplane_pile(s->n)->cellpxx;
|
||||
const int cellpxy = ncplane_pile(s->n)->cellpxy;
|
||||
if(fbuf_printf(f, "\x1b_Ga=f,x=%d,y=%d,s=%d,v=%d,i=%d,X=1,r=2,c=1,q=2;",
|
||||
xcell * s->cellpxx, ycell * s->cellpxy,
|
||||
s->cellpxx, s->cellpxy, s->id) < 0){
|
||||
xcell * cellpxx, ycell * cellpxy, cellpxx, cellpxy, s->id) < 0){
|
||||
return -1;
|
||||
}
|
||||
// FIXME ought be smaller around the fringes!
|
||||
int totalp = s->cellpxy * s->cellpxx;
|
||||
int totalp = cellpxy * cellpxx;
|
||||
// FIXME preserve so long as cellpixel geom stays constant?
|
||||
#define TRINULLALPHA "AAAAAAAAAAAAAAAA"
|
||||
for(int p = 0 ; p + 3 <= totalp ; p += 3){
|
||||
@ -416,7 +417,7 @@ int kitty_wipe_animation(sprixel* s, int ycell, int xcell){
|
||||
}
|
||||
int tamidx = ycell * s->dimx + xcell;
|
||||
uint8_t* auxvec = s->n->tam[tamidx].auxvector;
|
||||
auxvec[s->cellpxx * s->cellpxy * 4] = 0;
|
||||
auxvec[ncplane_pile(s->n)->cellpxx * ncplane_pile(s->n)->cellpxy * 4] = 0;
|
||||
s->invalidated = SPRIXEL_INVALIDATED;
|
||||
return 1;
|
||||
}
|
||||
@ -444,14 +445,14 @@ sprixel* kitty_recycle(ncplane* n){
|
||||
int dimy = hides->dimy;
|
||||
int dimx = hides->dimx;
|
||||
sprixel_hide(hides);
|
||||
return sprixel_alloc(&ncplane_notcurses_const(n)->tcache, n, dimy, dimx);
|
||||
return sprixel_alloc(n, dimy, dimx);
|
||||
}
|
||||
|
||||
// for pre-animation kitty (NCPIXEL_KITTY_STATIC), we need a byte per pixel,
|
||||
// in which we stash the alpha.
|
||||
static inline uint8_t*
|
||||
kitty_auxiliary_vector(const sprixel* s){
|
||||
int pixels = s->cellpxy * s->cellpxx;
|
||||
int pixels = ncplane_pile(s->n)->cellpxy * ncplane_pile(s->n)->cellpxx;
|
||||
uint8_t* ret = malloc(sizeof(*ret) * pixels);
|
||||
if(ret){
|
||||
memset(ret, 0, sizeof(*ret) * pixels);
|
||||
@ -466,8 +467,8 @@ int kitty_wipe(sprixel* s, int ycell, int xcell){
|
||||
return -1;
|
||||
}
|
||||
const int totalpixels = s->pixy * s->pixx;
|
||||
const int xpixels = s->cellpxx;
|
||||
const int ypixels = s->cellpxy;
|
||||
const int xpixels = ncplane_pile(s->n)->cellpxx;
|
||||
const int ypixels = ncplane_pile(s->n)->cellpxy;
|
||||
// if the cell is on the right or bottom borders, it might only be partially
|
||||
// filled by actual graphic data, and we need to cap our target area.
|
||||
int targx = xpixels;
|
||||
@ -515,7 +516,7 @@ int kitty_wipe(sprixel* s, int ycell, int xcell){
|
||||
//fprintf(stderr, "POSTCHOMP: [%.16s]\n", c + tripbytes);
|
||||
assert(chomped >= 0);
|
||||
auxvecidx += chomped;
|
||||
assert(auxvecidx <= s->cellpxy * s->cellpxx);
|
||||
assert(auxvecidx <= ypixels * xpixels);
|
||||
thisrow -= chomped;
|
||||
//fprintf(stderr, "POSTCHIMP CHOMP: %d pixoffset: %d next: %d tripbytes: %d tripskip: %d thisrow: %d\n", chomped, pixoffset, nextpixel, tripbytes, tripskip, thisrow);
|
||||
if(thisrow == 0){
|
||||
@ -746,8 +747,10 @@ write_kitty_data(fbuf* f, int linesize, int leny, int lenx, int cols,
|
||||
unsigned bufidx = 0; // an index; the actual offset is bufidx * 4
|
||||
bool translucent = bargs->flags & NCVISUAL_OPTION_BLEND;
|
||||
sprixel* s = bargs->u.pixel.spx;
|
||||
const int cdimy = s->cellpxy;
|
||||
const int cdimx = s->cellpxx;
|
||||
const int cdimy = bargs->u.pixel.cellpxy;
|
||||
const int cdimx = bargs->u.pixel.cellpxx;
|
||||
assert(0 != cdimy);
|
||||
assert(0 != cdimx);
|
||||
const uint32_t transcolor = bargs->transcolor;
|
||||
int total = leny * lenx; // total number of pixels (4 * total == bytecount)
|
||||
// number of 4KiB chunks we'll need
|
||||
@ -847,7 +850,7 @@ write_kitty_data(fbuf* f, int linesize, int leny, int lenx, int cols,
|
||||
}else if(level == NCPIXEL_KITTY_SELFREF){
|
||||
selfref_annihilated = true;
|
||||
}else{
|
||||
((uint8_t*)tam[tyx].auxvector)[s->cellpxx * s->cellpxy * 4] = 1;
|
||||
((uint8_t*)tam[tyx].auxvector)[cdimx * cdimy * 4] = 1;
|
||||
wipe[e] = 1;
|
||||
}
|
||||
if(rgba_trans_p(source[e], transcolor)){
|
||||
@ -938,14 +941,16 @@ int kitty_rebuild_selfref(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
return -1;
|
||||
}
|
||||
fbuf* f = &s->glyph;
|
||||
const int ystart = ycell * s->cellpxy;
|
||||
const int xstart = xcell * s->cellpxx;
|
||||
const int xlen = xstart + s->cellpxx > s->pixx ? s->pixx - xstart : s->cellpxx;
|
||||
const int ylen = ystart + s->cellpxy > s->pixy ? s->pixy - ystart : s->cellpxy;
|
||||
const int cellpxy = ncplane_pile(s->n)->cellpxy;
|
||||
const int cellpxx = ncplane_pile(s->n)->cellpxx;
|
||||
const int ystart = ycell * cellpxy;
|
||||
const int xstart = xcell * cellpxx;
|
||||
const int xlen = xstart + cellpxx > s->pixx ? s->pixx - xstart : cellpxx;
|
||||
const int ylen = ystart + cellpxy > s->pixy ? s->pixy - ystart : cellpxy;
|
||||
logdebug("rematerializing %u at %d/%d (%dx%d)\n", s->id, ycell, xcell, ylen, xlen);
|
||||
fbuf_printf(f, "\e_Ga=c,x=%d,y=%d,X=%d,Y=%d,w=%d,h=%d,i=%d,r=1,c=2,q=2;\x1b\\",
|
||||
xcell * s->cellpxx, ycell * s->cellpxy,
|
||||
xcell * s->cellpxx, ycell * s->cellpxy,
|
||||
xcell * cellpxx, ycell * cellpxy,
|
||||
xcell * cellpxx, ycell * cellpxy,
|
||||
xlen, ylen, s->id);
|
||||
const int tyx = xcell + ycell * s->dimx;
|
||||
memcpy(&s->n->tam[tyx].state, auxvec, sizeof(s->n->tam[tyx].state));
|
||||
@ -959,10 +964,12 @@ int kitty_rebuild_animation(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
return -1;
|
||||
}
|
||||
fbuf* f = &s->glyph;
|
||||
const int ystart = ycell * s->cellpxy;
|
||||
const int xstart = xcell * s->cellpxx;
|
||||
const int xlen = xstart + s->cellpxx > s->pixx ? s->pixx - xstart : s->cellpxx;
|
||||
const int ylen = ystart + s->cellpxy > s->pixy ? s->pixy - ystart : s->cellpxy;
|
||||
const int cellpxy = ncplane_pile(s->n)->cellpxy;
|
||||
const int cellpxx = ncplane_pile(s->n)->cellpxx;
|
||||
const int ystart = ycell * cellpxy;
|
||||
const int xstart = xcell * cellpxx;
|
||||
const int xlen = xstart + cellpxx > s->pixx ? s->pixx - xstart : cellpxx;
|
||||
const int ylen = ystart + cellpxy > s->pixy ? s->pixy - ystart : cellpxy;
|
||||
const int linesize = xlen * 4;
|
||||
const int total = xlen * ylen;
|
||||
const int tyx = xcell + ycell * s->dimx;
|
||||
@ -973,13 +980,13 @@ int kitty_rebuild_animation(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
int targetout = 0; // number of pixels expected out after this chunk
|
||||
//fprintf(stderr, "total: %d chunks = %d, s=%d,v=%d\n", total, chunks, lenx, leny);
|
||||
// FIXME this ought be factored out and shared with write_kitty_data()
|
||||
logdebug("placing %d/%d at %d/%d\n", ylen, xlen, ycell * s->cellpxy, xcell * s->cellpxx);
|
||||
logdebug("placing %d/%d at %d/%d\n", ylen, xlen, ycell * cellpxy, xcell * cellpxx);
|
||||
while(chunks--){
|
||||
if(totalout == 0){
|
||||
const int c = kitty_anim_auxvec_blitsource_p(s, auxvec) ? 2 : 1;
|
||||
const int r = kitty_anim_auxvec_blitsource_p(s, auxvec) ? 1 : 2;
|
||||
if(fbuf_printf(f, "\e_Ga=f,x=%d,y=%d,s=%d,v=%d,i=%d,X=1,c=%d,r=%d,%s;",
|
||||
xcell * s->cellpxx, ycell * s->cellpxy, xlen, ylen,
|
||||
xcell * cellpxx, ycell * cellpxy, xlen, ylen,
|
||||
s->id, c, r, chunks ? "m=1" : "q=2") < 0){
|
||||
return -1;
|
||||
}
|
||||
@ -1023,13 +1030,13 @@ int kitty_rebuild_animation(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
//fprintf(stderr, "Tyx: %d y: %d (%d) * %d x: %d (%d) state %d %p\n", tyx, y, y / cdimy, cols, x, x / cdimx, tam[tyx].state, tam[tyx].auxvector);
|
||||
wipe[e] = 0;
|
||||
if(rgba_trans_p(source[e], 0)){
|
||||
if(x % s->cellpxx == 0 && y % s->cellpxy == 0){
|
||||
if(x % cellpxx == 0 && y % cellpxy == 0){
|
||||
s->n->tam[tyx].state = SPRIXCELL_TRANSPARENT;
|
||||
}else if(s->n->tam[tyx].state == SPRIXCELL_OPAQUE_KITTY){
|
||||
s->n->tam[tyx].state = SPRIXCELL_MIXED_KITTY;
|
||||
}
|
||||
}else{
|
||||
if(x % s->cellpxx == 0 && y % s->cellpxy == 0){
|
||||
if(x % cellpxx == 0 && y % cellpxy == 0){
|
||||
s->n->tam[tyx].state = SPRIXCELL_OPAQUE_KITTY;
|
||||
}else if(s->n->tam[tyx].state == SPRIXCELL_TRANSPARENT){
|
||||
s->n->tam[tyx].state = SPRIXCELL_MIXED_KITTY;
|
||||
|
@ -1,11 +1,11 @@
|
||||
#include "linux.h"
|
||||
#include "internal.h"
|
||||
|
||||
// auxvecs for framebuffer are 1B each for s->cellpxx * s->cellpxy elements,
|
||||
// auxvecs for framebuffer are 1B each for cellpxx * cellpxy elements,
|
||||
// and store the original alpha value.
|
||||
static inline uint8_t*
|
||||
fbcon_auxiliary_vector(const sprixel* s){
|
||||
int pixels = s->cellpxy * s->cellpxx;
|
||||
int pixels = ncplane_pile(s->n)->cellpxy * ncplane_pile(s->n)->cellpxx;
|
||||
uint8_t* ret = malloc(sizeof(*ret) * pixels);
|
||||
if(ret){
|
||||
memset(ret, 0, sizeof(*ret) * pixels);
|
||||
@ -18,19 +18,21 @@ int fbcon_wipe(sprixel* s, int ycell, int xcell){
|
||||
if(auxvec == NULL){
|
||||
return -1;
|
||||
}
|
||||
const int cellpxy = ncplane_pile(s->n)->cellpxy;
|
||||
const int cellpxx = ncplane_pile(s->n)->cellpxx;
|
||||
char* glyph = s->glyph.buf;
|
||||
for(int y = 0 ; y < s->cellpxy ; ++y){
|
||||
if(ycell * s->cellpxy + y >= s->pixy){
|
||||
for(int y = 0 ; y < cellpxy ; ++y){
|
||||
if(ycell * cellpxy + y >= s->pixy){
|
||||
break;
|
||||
}
|
||||
// number of pixels total above our pixel row
|
||||
const size_t yoff = s->pixx * (ycell * s->cellpxy + y);
|
||||
for(int x = 0 ; x < s->cellpxx ; ++x){
|
||||
if(xcell * s->cellpxx + x >= s->pixx){
|
||||
const size_t yoff = s->pixx * (ycell * cellpxy + y);
|
||||
for(int x = 0 ; x < cellpxx ; ++x){
|
||||
if(xcell * cellpxx + x >= s->pixx){
|
||||
break;
|
||||
}
|
||||
size_t offset = (yoff + xcell * s->cellpxx + x) * 4;
|
||||
const int vyx = (y % s->cellpxy) * s->cellpxx + x;
|
||||
size_t offset = (yoff + xcell * cellpxx + x) * 4;
|
||||
const int vyx = (y % cellpxy) * cellpxx + x;
|
||||
auxvec[vyx] = glyph[offset + 3];
|
||||
glyph[offset + 3] = 0;
|
||||
}
|
||||
@ -43,8 +45,8 @@ int fbcon_blit(struct ncplane* n, int linesize, const void* data,
|
||||
int leny, int lenx, const struct blitterargs* bargs){
|
||||
uint32_t transcolor = bargs->transcolor;
|
||||
sprixel* s = bargs->u.pixel.spx;
|
||||
int cdimx = s->cellpxx;
|
||||
int cdimy = s->cellpxy;
|
||||
int cdimx = bargs->u.pixel.cellpxx;
|
||||
int cdimy = bargs->u.pixel.cellpxy;
|
||||
// FIXME this will need be a copy of the tinfo's fbuf map
|
||||
size_t flen = leny * lenx * 4;
|
||||
if(fbuf_reserve(&s->glyph, flen)){
|
||||
@ -124,18 +126,20 @@ int fbcon_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
if(auxvec == NULL){
|
||||
return -1;
|
||||
}
|
||||
const int cellpxy = ncplane_pile(s->n)->cellpxy;
|
||||
const int cellpxx = ncplane_pile(s->n)->cellpxx;
|
||||
sprixcell_e state = SPRIXCELL_TRANSPARENT;
|
||||
for(int y = 0 ; y < s->cellpxy ; ++y){
|
||||
if(ycell * s->cellpxy + y >= s->pixy){
|
||||
for(int y = 0 ; y < cellpxy ; ++y){
|
||||
if(ycell * cellpxy + y >= s->pixy){
|
||||
break;
|
||||
}
|
||||
const size_t yoff = s->pixx * (ycell * s->cellpxy + y);
|
||||
for(int x = 0 ; x < s->cellpxx ; ++x){
|
||||
if(xcell * s->cellpxx + x >= s->pixx){
|
||||
const size_t yoff = s->pixx * (ycell * cellpxy + y);
|
||||
for(int x = 0 ; x < cellpxx ; ++x){
|
||||
if(xcell * cellpxx + x >= s->pixx){
|
||||
break;
|
||||
}
|
||||
size_t offset = (yoff + xcell * s->cellpxx + x) * 4;
|
||||
const int vyx = (y % s->cellpxy) * s->cellpxx + x;
|
||||
size_t offset = (yoff + xcell * cellpxx + x) * 4;
|
||||
const int vyx = (y % cellpxy) * cellpxx + x;
|
||||
if(x == 0 && y == 0){
|
||||
if(auxvec[vyx] == 0){
|
||||
state = SPRIXCELL_TRANSPARENT;
|
||||
@ -160,9 +164,11 @@ int fbcon_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
int fbcon_draw(const tinfo* ti, sprixel* s, int y, int x){
|
||||
logdebug("id %" PRIu32 " dest %d/%d\n", s->id, y, x);
|
||||
int wrote = 0;
|
||||
for(unsigned l = 0 ; l < (unsigned)s->pixy && l + y * ti->cellpixy < ti->pixy ; ++l){
|
||||
const int cellpxy = ncplane_pile(s->n)->cellpxy;
|
||||
const int cellpxx = ncplane_pile(s->n)->cellpxx;
|
||||
for(unsigned l = 0 ; l < (unsigned)s->pixy && l + y * cellpxy < ti->pixy ; ++l){
|
||||
// FIXME pixel size isn't necessarily 4B, line isn't necessarily psize*pixx
|
||||
size_t offset = ((l + y * ti->cellpixy) * ti->pixx + x * ti->cellpixx) * 4;
|
||||
size_t offset = ((l + y * cellpxy) * ti->pixx + x * cellpxx) * 4;
|
||||
uint8_t* tl = ti->linux_fbuffer + offset;
|
||||
const char* src = (char*)s->glyph.buf + (l * s->pixx * 4);
|
||||
for(unsigned c = 0 ; c < (unsigned)s->pixx && c < ti->pixx ; ++c){
|
||||
@ -186,13 +192,15 @@ int fbcon_draw(const tinfo* ti, sprixel* s, int y, int x){
|
||||
// they're written in order. if we're scrolling all rows, we're clearing the
|
||||
// entire space; we always clear something (we might not always move anything).
|
||||
void fbcon_scroll(const struct ncpile* p, tinfo* ti, int rows){
|
||||
if(ti->cellpixy < 1){
|
||||
const int cellpxy = p->cellpxy;
|
||||
const int cellpxx = p->cellpxx;
|
||||
if(cellpxy < 1){
|
||||
return;
|
||||
}
|
||||
logdebug("scrolling %d\n", rows);
|
||||
const int rowbytes = ti->cellpixx * p->dimx * 4;
|
||||
const int totalrows = ti->cellpixy * p->dimy;
|
||||
int srows = rows * ti->cellpixy; // number of pixel rows being scrolled
|
||||
const int rowbytes = cellpxx * p->dimx * 4;
|
||||
const int totalrows = cellpxy * p->dimy;
|
||||
int srows = rows * cellpxy; // number of pixel rows being scrolled
|
||||
if(srows > totalrows){
|
||||
srows = totalrows;
|
||||
}
|
||||
|
@ -261,8 +261,8 @@ int update_term_dimensions(unsigned* rows, unsigned* cols, tinfo* tcache,
|
||||
if(cols){
|
||||
*cols = tcache->default_cols;
|
||||
}
|
||||
tcache->cellpixy = 0;
|
||||
tcache->cellpixx = 0;
|
||||
tcache->cellpxy = 0;
|
||||
tcache->cellpxx = 0;
|
||||
return 0;
|
||||
}
|
||||
unsigned rowsafe, colsafe;
|
||||
@ -296,18 +296,18 @@ int update_term_dimensions(unsigned* rows, unsigned* cols, tinfo* tcache,
|
||||
tcache->pixx = ws.ws_xpixel;
|
||||
}
|
||||
// update even if we didn't get values just now, because we need set
|
||||
// cellpix{y,x} up from an initial CSI14n, which set only pix{y,x}.
|
||||
// cellpx{y,x} up from an initial CSI14n, which set only pix{y,x}.
|
||||
unsigned cpixy = ws.ws_row ? tcache->pixy / ws.ws_row : 0;
|
||||
unsigned cpixx = ws.ws_col ? tcache->pixx / ws.ws_col : 0;
|
||||
if(tcache->cellpixy != cpixy){
|
||||
tcache->cellpixy = cpixy;
|
||||
if(tcache->cellpxy != cpixy){
|
||||
tcache->cellpxy = cpixy;
|
||||
*pgeo_changed = 1;
|
||||
}
|
||||
if(tcache->cellpixx != cpixx){
|
||||
tcache->cellpixx = cpixx;
|
||||
if(tcache->cellpxx != cpixx){
|
||||
tcache->cellpxx = cpixx;
|
||||
*pgeo_changed = 1;
|
||||
}
|
||||
if(tcache->cellpixy == 0 || tcache->cellpixx == 0){
|
||||
if(tcache->cellpxy == 0 || tcache->cellpxx == 0){
|
||||
tcache->pixel_draw = NULL; // disable support
|
||||
}
|
||||
}
|
||||
@ -363,7 +363,7 @@ int update_term_dimensions(unsigned* rows, unsigned* cols, tinfo* tcache,
|
||||
if(margin_b){
|
||||
++sixelrows;
|
||||
}
|
||||
tcache->sixel_maxy = sixelrows * tcache->cellpixy;
|
||||
tcache->sixel_maxy = sixelrows * tcache->cellpxy;
|
||||
if(tcache->sixel_maxy > tcache->sixel_maxy_pristine){
|
||||
tcache->sixel_maxy = tcache->sixel_maxy_pristine;
|
||||
}
|
||||
@ -451,8 +451,10 @@ make_ncpile(notcurses* nc, ncplane* n){
|
||||
}
|
||||
n->above = NULL;
|
||||
n->below = NULL;
|
||||
ret->dimy = 0;
|
||||
ret->dimx = 0;
|
||||
ret->dimy = nc->tcache.dimy;
|
||||
ret->dimx = nc->tcache.dimx;
|
||||
ret->cellpxy = nc->tcache.cellpxy;
|
||||
ret->cellpxx = nc->tcache.cellpxx;
|
||||
ret->crender = NULL;
|
||||
ret->crenderlen = 0;
|
||||
ret->sprixelcache = NULL;
|
||||
@ -3102,28 +3104,29 @@ void ncplane_pixel_geom(const ncplane* n,
|
||||
unsigned* RESTRICT pxy, unsigned* RESTRICT pxx,
|
||||
unsigned* RESTRICT celldimy, unsigned* RESTRICT celldimx,
|
||||
unsigned* RESTRICT maxbmapy, unsigned* RESTRICT maxbmapx){
|
||||
notcurses* nc = ncplane_notcurses(n);
|
||||
const notcurses* nc = ncplane_notcurses_const(n);
|
||||
const ncpile* p = ncplane_pile_const(n);
|
||||
if(celldimy){
|
||||
*celldimy = nc->tcache.cellpixy;
|
||||
*celldimy = p->cellpxy;
|
||||
}
|
||||
if(celldimx){
|
||||
*celldimx = nc->tcache.cellpixx;
|
||||
*celldimx = p->cellpxx;
|
||||
}
|
||||
if(pxy){
|
||||
*pxy = nc->tcache.cellpixy * ncplane_dim_y(n);
|
||||
*pxy = p->cellpxy * ncplane_dim_y(n);
|
||||
}
|
||||
if(pxx){
|
||||
*pxx = nc->tcache.cellpixx * ncplane_dim_x(n);
|
||||
*pxx = p->cellpxx * ncplane_dim_x(n);
|
||||
}
|
||||
if(notcurses_check_pixel_support(nc) > 0){
|
||||
if(maxbmapy){
|
||||
*maxbmapy = nc->tcache.cellpixy * ncplane_dim_y(n);
|
||||
*maxbmapy = p->cellpxy * ncplane_dim_y(n);
|
||||
if(*maxbmapy > nc->tcache.sixel_maxy && nc->tcache.sixel_maxy){
|
||||
*maxbmapy = nc->tcache.sixel_maxy;
|
||||
}
|
||||
}
|
||||
if(maxbmapx){
|
||||
*maxbmapx = nc->tcache.cellpixx * ncplane_dim_x(n);
|
||||
*maxbmapx = p->cellpxx * ncplane_dim_x(n);
|
||||
if(*maxbmapx > nc->tcache.sixel_maxx && nc->tcache.sixel_maxx){
|
||||
*maxbmapx = nc->tcache.sixel_maxx;
|
||||
}
|
||||
|
@ -59,11 +59,11 @@ create_pixelp(ncplot *p, ncplane* n){
|
||||
// we have some color gradient across the life of the plot (almost; it gets
|
||||
// recalculated if the cell-pixel geometry changes and we're using
|
||||
// NCBLIT_PIXEL). if we're using cell blitting, we only get one channel pair
|
||||
// per row, no matter what height we have. with pixels, we get cellpixy * rows.
|
||||
// per row, no matter what height we have. with pixels, we get cellpxy * rows.
|
||||
static int
|
||||
calculate_gradient_vector(ncplot* p, unsigned pixelp){
|
||||
const int dimy = ncplane_dim_y(p->ncp);
|
||||
const unsigned states = dimy * (pixelp ? ncplane_notcurses(p->ncp)->tcache.cellpixy : 1);
|
||||
const unsigned states = dimy * (pixelp ? ncplane_pile(p->ncp)->cellpxy : 1);
|
||||
if(states == p->chancount){ // no need to recalculate
|
||||
return 0;
|
||||
}
|
||||
@ -93,13 +93,13 @@ int redraw_pixelplot_##T(nc##X##plot* ncp){ \
|
||||
if(calculate_gradient_vector(&ncp->plot, 1)){ \
|
||||
return -1; \
|
||||
} \
|
||||
const int scale = ncplane_notcurses_const(ncp->plot.ncp)->tcache.cellpixx; \
|
||||
const int scale = ncplane_pile_const(ncp->plot.ncp)->cellpxx; \
|
||||
ncplane_erase(ncp->plot.ncp); \
|
||||
unsigned dimy, dimx; \
|
||||
ncplane_dim_yx(ncp->plot.ncp, &dimy, &dimx); \
|
||||
const unsigned scaleddim = dimx * scale; \
|
||||
/* each transition is worth this much change in value */ \
|
||||
const size_t states = ncplane_notcurses_const(ncp->plot.ncp)->tcache.cellpixy; \
|
||||
const size_t states = ncplane_pile_const(ncp->plot.ncp)->cellpxy; \
|
||||
/* FIXME can we not rid ourselves of this meddlesome double? either way, the \
|
||||
interval is one row's range (for linear plots), or the base \
|
||||
(base^slots == maxy-miny) of the range (for exponential plots). */ \
|
||||
@ -480,8 +480,8 @@ create_##T(nc##X##plot* ncpp, ncplane* n, const ncplot_options* opts, const T mi
|
||||
ncpp->plot.rangex = opts->rangex; \
|
||||
/* if we're sizing the plot based off the plane dimensions, scale it by the \
|
||||
plot geometry's width for all calculations */ \
|
||||
const unsigned scaleddim = dimx * (bset->geom == NCBLIT_PIXEL ? ncplane_notcurses(n)->tcache.cellpixx : bset->width); \
|
||||
const unsigned scaledprefixlen = NCPREFIXCOLUMNS * (bset->geom == NCBLIT_PIXEL ? ncplane_notcurses(n)->tcache.cellpixx : bset->width); \
|
||||
const unsigned scaleddim = dimx * (bset->geom == NCBLIT_PIXEL ? ncplane_pile_const(n)->cellpxx : bset->width); \
|
||||
const unsigned scaledprefixlen = NCPREFIXCOLUMNS * (bset->geom == NCBLIT_PIXEL ? ncplane_pile_const(n)->cellpxx : bset->width); \
|
||||
if((ncpp->plot.slotcount = ncpp->plot.rangex) == 0){ \
|
||||
ncpp->plot.slotcount = scaleddim; \
|
||||
} \
|
||||
|
@ -27,7 +27,7 @@ sixelcount(int dimy, int dimx){
|
||||
// bytes, saving 7/8 of the space FIXME).
|
||||
static inline uint8_t*
|
||||
sixel_auxiliary_vector(const sprixel* s){
|
||||
int pixels = s->cellpxy * s->cellpxx;
|
||||
int pixels = ncplane_pile(s->n)->cellpxy * ncplane_pile(s->n)->cellpxx;
|
||||
uint8_t* ret = malloc(sizeof(*ret) * pixels * 2);
|
||||
if(ret){
|
||||
memset(ret, 0, sizeof(*ret) * pixels);
|
||||
@ -229,15 +229,17 @@ int sixel_wipe(sprixel* s, int ycell, int xcell){
|
||||
if(auxvec == NULL){
|
||||
return -1;
|
||||
}
|
||||
memset(auxvec + s->cellpxx * s->cellpxy, 0xff, s->cellpxx * s->cellpxy);
|
||||
const int cellpxy = ncplane_pile(s->n)->cellpxy;
|
||||
const int cellpxx = ncplane_pile(s->n)->cellpxx;
|
||||
memset(auxvec + cellpxx * cellpxy, 0xff, cellpxx * cellpxy);
|
||||
sixelmap* smap = s->smap;
|
||||
const int startx = xcell * s->cellpxx;
|
||||
const int starty = ycell * s->cellpxy;
|
||||
int endx = ((xcell + 1) * s->cellpxx) - 1;
|
||||
const int startx = xcell * cellpxx;
|
||||
const int starty = ycell * cellpxy;
|
||||
int endx = ((xcell + 1) * cellpxx) - 1;
|
||||
if(endx >= s->pixx){
|
||||
endx = s->pixx - 1;
|
||||
}
|
||||
int endy = ((ycell + 1) * s->cellpxy) - 1;
|
||||
int endy = ((ycell + 1) * cellpxy) - 1;
|
||||
if(endy >= s->pixy){
|
||||
endy = s->pixy - 1;
|
||||
}
|
||||
@ -248,7 +250,7 @@ int sixel_wipe(sprixel* s, int ycell, int xcell){
|
||||
int w = 0;
|
||||
for(int c = 0 ; c < smap->colors ; ++c){
|
||||
w |= wipe_color(smap, c, startband, endband, startx, endx, starty, endy,
|
||||
s->pixx, s->cellpxy, s->cellpxx, auxvec);
|
||||
s->pixx, cellpxy, cellpxx, auxvec);
|
||||
}
|
||||
if(w){
|
||||
s->wipes_outstanding = true;
|
||||
@ -429,8 +431,8 @@ extract_color_table(const uint32_t* data, int linesize, int cols,
|
||||
const int begx = bargs->begx;
|
||||
const int begy = bargs->begy;
|
||||
sprixel* s = bargs->u.pixel.spx;
|
||||
const int cdimy = s->cellpxy;
|
||||
const int cdimx = s->cellpxx;
|
||||
const int cdimy = ncplane_pile(s->n)->cellpxy;
|
||||
const int cdimx = ncplane_pile(s->n)->cellpxx;
|
||||
unsigned char mask = 0xc0;
|
||||
int pos = 0; // pixel position
|
||||
unsigned char* rmatrix = bargs->u.pixel.spx->needs_refresh;
|
||||
@ -876,11 +878,14 @@ sixel_reblit(sprixel* s){
|
||||
// scaled geometry in pixels. We calculate output geometry herein, and supply
|
||||
// transparent filler input for any missing rows.
|
||||
static inline int
|
||||
sixel_blit_inner(int leny, int lenx, sixeltable* stab, sprixel* s, tament* tam){
|
||||
sixel_blit_inner(int leny, int lenx, sixeltable* stab, const blitterargs* bargs, tament* tam){
|
||||
fbuf f;
|
||||
if(fbuf_init(&f)){
|
||||
return -1;
|
||||
}
|
||||
sprixel* s = bargs->u.pixel.spx;
|
||||
const int cellpxy = bargs->u.pixel.cellpxy;
|
||||
const int cellpxx = bargs->u.pixel.cellpxx;
|
||||
int parse_start = 0;
|
||||
int outy = leny;
|
||||
if(leny % 6){
|
||||
@ -892,7 +897,7 @@ sixel_blit_inner(int leny, int lenx, sixeltable* stab, sprixel* s, tament* tam){
|
||||
fbuf_free(&f);
|
||||
return -1;
|
||||
}
|
||||
scrub_tam_boundaries(tam, outy, lenx, s->cellpxy, s->cellpxx);
|
||||
scrub_tam_boundaries(tam, outy, lenx, cellpxy, cellpxx);
|
||||
// take ownership of buf on success
|
||||
if(plane_blit_sixel(s, &f, outy, lenx, parse_start, tam, SPRIXEL_INVALIDATED) < 0){
|
||||
fbuf_free(&f);
|
||||
@ -945,7 +950,7 @@ int sixel_blit(ncplane* n, int linesize, const void* data, int leny, int lenx,
|
||||
}
|
||||
refine_color_table(data, linesize, bargs->begy, bargs->begx, leny, lenx, &stable);
|
||||
// takes ownership of sixelmap on success
|
||||
int r = sixel_blit_inner(leny, lenx, &stable, bargs->u.pixel.spx, n->tam);
|
||||
int r = sixel_blit_inner(leny, lenx, &stable, bargs, n->tam);
|
||||
if(r < 0){
|
||||
sixelmap_free(stable.map);
|
||||
}
|
||||
@ -1063,13 +1068,15 @@ int sixel_init_inverted(int fd){
|
||||
int sixel_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
s->wipes_outstanding = true;
|
||||
sixelmap* smap = s->smap;
|
||||
const int startx = xcell * s->cellpxx;
|
||||
const int starty = ycell * s->cellpxy;
|
||||
int endx = ((xcell + 1) * s->cellpxx) - 1;
|
||||
const int cellpxx = ncplane_pile(s->n)->cellpxx;
|
||||
const int cellpxy = ncplane_pile(s->n)->cellpxy;
|
||||
const int startx = xcell * cellpxx;
|
||||
const int starty = ycell * cellpxy;
|
||||
int endx = ((xcell + 1) * cellpxx) - 1;
|
||||
if(endx > s->pixx){
|
||||
endx = s->pixx;
|
||||
}
|
||||
int endy = ((ycell + 1) * s->cellpxy) - 1;
|
||||
int endy = ((ycell + 1) * cellpxy) - 1;
|
||||
if(endy > s->pixy){
|
||||
endy = s->pixy;
|
||||
}
|
||||
@ -1077,8 +1084,8 @@ int sixel_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
//fprintf(stderr, "%d/%d start: %d/%d end: %d/%d bands: %d-%d\n", ycell, xcell, starty, startx, endy, endx, starty / 6, endy / 6);
|
||||
for(int x = startx ; x <= endx ; ++x){
|
||||
for(int y = starty ; y <= endy ; ++y){
|
||||
int auxvecidx = (y - starty) * s->cellpxx + (x - startx);
|
||||
int trans = auxvec[s->cellpxx * s->cellpxy + auxvecidx];
|
||||
int auxvecidx = (y - starty) * cellpxx + (x - startx);
|
||||
int trans = auxvec[cellpxx * cellpxy + auxvecidx];
|
||||
if(!trans){
|
||||
int color = auxvec[auxvecidx];
|
||||
int didx = ctable_to_dtable(smap->table + color * CENTSIZE);
|
||||
@ -1094,7 +1101,7 @@ int sixel_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){
|
||||
}
|
||||
}
|
||||
sprixcell_e newstate;
|
||||
if(transparent == s->cellpxx * s->cellpxy){
|
||||
if(transparent == cellpxx * cellpxy){
|
||||
newstate = SPRIXCELL_TRANSPARENT;
|
||||
}else if(transparent){
|
||||
newstate = SPRIXCELL_MIXED_SIXEL;
|
||||
@ -1111,8 +1118,8 @@ int sixel_shutdown(fbuf* f){
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t* sixel_trans_auxvec(const tinfo* ti){
|
||||
const size_t slen = 2 * ti->cellpixy * ti->cellpixx;
|
||||
uint8_t* sixel_trans_auxvec(const ncpile* p){
|
||||
const size_t slen = 2 * p->cellpxy * p->cellpxx;
|
||||
uint8_t* a = malloc(slen);
|
||||
if(a){
|
||||
memset(a, 0, slen);
|
||||
|
@ -56,7 +56,7 @@ sprixel* sprixel_recycle(ncplane* n){
|
||||
int dimy = hides->dimy;
|
||||
int dimx = hides->dimx;
|
||||
sprixel_hide(hides);
|
||||
return sprixel_alloc(&nc->tcache, n, dimy, dimx);
|
||||
return sprixel_alloc(n, dimy, dimx);
|
||||
}
|
||||
sixelmap_free(n->sprite->smap);
|
||||
n->sprite->smap = NULL;
|
||||
@ -114,7 +114,7 @@ void sprixel_invalidate(sprixel* s, int y, int x){
|
||||
}
|
||||
}
|
||||
|
||||
sprixel* sprixel_alloc(const tinfo* ti, ncplane* n, int dimy, int dimx){
|
||||
sprixel* sprixel_alloc(ncplane* n, int dimy, int dimx){
|
||||
sprixel* ret = malloc(sizeof(sprixel));
|
||||
if(ret == NULL){
|
||||
return NULL;
|
||||
@ -134,8 +134,6 @@ sprixel* sprixel_alloc(const tinfo* ti, ncplane* n, int dimy, int dimx){
|
||||
sprixelid_nonce = 1;
|
||||
}
|
||||
//fprintf(stderr, "LOOKING AT %p (p->n = %p)\n", ret, ret->n);
|
||||
ret->cellpxy = ti->cellpixy;
|
||||
ret->cellpxx = ti->cellpixx;
|
||||
if(ncplane_pile(ret->n)){ // rendered mode
|
||||
ncpile* np = ncplane_pile(ret->n);
|
||||
if( (ret->next = np->sprixelcache) ){
|
||||
@ -156,6 +154,7 @@ sprixel* sprixel_alloc(const tinfo* ti, ncplane* n, int dimy, int dimx){
|
||||
int sprixel_load(sprixel* spx, fbuf* f, unsigned pixy, unsigned pixx,
|
||||
int parse_start, sprixel_e state){
|
||||
assert(spx->n);
|
||||
/*
|
||||
if(spx->cellpxy > 0){ // don't explode on ncdirect case
|
||||
if((pixy + spx->cellpxy - 1) / spx->cellpxy > spx->dimy){
|
||||
logerror("bad pixy %d (cellpxy %d dimy %d)\n", pixy, spx->cellpxy, spx->dimy);
|
||||
@ -166,6 +165,7 @@ int sprixel_load(sprixel* spx, fbuf* f, unsigned pixy, unsigned pixx,
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if(&spx->glyph != f){
|
||||
fbuf_free(&spx->glyph);
|
||||
memcpy(&spx->glyph, f, sizeof(*f));
|
||||
@ -187,7 +187,7 @@ int sprite_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell){
|
||||
// be entirely 0s coming from pixel_trans_auxvec().
|
||||
if(s->n->tam[idx].auxvector == NULL){
|
||||
if(nc->tcache.pixel_trans_auxvec){
|
||||
s->n->tam[idx].auxvector = nc->tcache.pixel_trans_auxvec(&nc->tcache);
|
||||
s->n->tam[idx].auxvector = nc->tcache.pixel_trans_auxvec(ncplane_pile(s->n));
|
||||
if(s->n->tam[idx].auxvector == NULL){
|
||||
return -1;
|
||||
}
|
||||
|
@ -143,7 +143,6 @@ typedef struct sprixel {
|
||||
struct sprixel* prev;
|
||||
unsigned dimy, dimx; // cell geometry
|
||||
int pixy, pixx; // pixel geometry (might be smaller than cell geo)
|
||||
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 movedfromy; // for SPRIXEL_MOVED, the starting absolute position,
|
||||
@ -196,8 +195,8 @@ int kitty_remove(int id, fbuf* f);
|
||||
int kitty_clear_all(fbuf* f);
|
||||
int sixel_init(int fd);
|
||||
int sixel_init_inverted(int fd);
|
||||
uint8_t* sixel_trans_auxvec(const struct tinfo* ti);
|
||||
uint8_t* kitty_trans_auxvec(const struct tinfo* ti);
|
||||
uint8_t* sixel_trans_auxvec(const struct ncpile* p);
|
||||
uint8_t* kitty_trans_auxvec(const struct ncpile* p);
|
||||
int kitty_commit(fbuf* f, sprixel* s, unsigned noscroll);
|
||||
int sixel_blit(struct ncplane* nc, int linesize, const void* data,
|
||||
int leny, int lenx, const struct blitterargs* bargs);
|
||||
|
@ -1078,8 +1078,8 @@ int interrogate_terminfo(tinfo* ti, FILE* out, unsigned utf8,
|
||||
ti->pixx = iresp->pixx;
|
||||
}
|
||||
if(ti->default_rows && ti->default_cols){
|
||||
ti->cellpixy = ti->pixy / ti->default_rows;
|
||||
ti->cellpixx = ti->pixx / ti->default_cols;
|
||||
ti->cellpxy = ti->pixy / ti->default_rows;
|
||||
ti->cellpxx = ti->pixx / ti->default_cols;
|
||||
}
|
||||
if(iresp->got_bg){
|
||||
// reset the 0xfe000000 we loaded during initialization. if we're
|
||||
|
@ -110,8 +110,8 @@ typedef struct tinfo {
|
||||
unsigned pixx; // total pixel geometry, width
|
||||
// we use the cell's size in pixels for pixel blitting. this information can
|
||||
// be acquired on all terminals with pixel support.
|
||||
unsigned cellpixy; // cell pixel height, might be 0
|
||||
unsigned cellpixx; // cell pixel width, might be 0
|
||||
unsigned cellpxy; // cell pixel height, might be 0
|
||||
unsigned cellpxx; // cell pixel width, might be 0
|
||||
unsigned dimy, dimx; // most recent cell geometry
|
||||
|
||||
unsigned supported_styles; // bitmask over NCSTYLE_* driven via sgr/ncv
|
||||
@ -149,7 +149,7 @@ typedef struct tinfo {
|
||||
int (*pixel_commit)(fbuf* f, struct sprixel* s, unsigned noscroll);
|
||||
// scroll all graphics up. only used with fbcon.
|
||||
void (*pixel_scroll)(const struct ncpile* p, struct tinfo*, int rows);
|
||||
uint8_t* (*pixel_trans_auxvec)(const struct tinfo* ti); // create tranparent auxvec
|
||||
uint8_t* (*pixel_trans_auxvec)(const struct ncpile* p); // create tranparent auxvec
|
||||
// sprixel parameters. there are several different sprixel protocols, of
|
||||
// which we support sixel and kitty. the kitty protocol is used based
|
||||
// on TERM heuristics. otherwise, we attempt to detect sixel support, and
|
||||
|
@ -141,22 +141,27 @@ ncvisual_origin(const struct ncvisual_options* vopts, unsigned* restrict begy,
|
||||
// included within |disppixx| nor |disppixy|, but count towards |outx| and
|
||||
// |outy|. these last two are furthermore clamped to sixel maxima, and |outy|
|
||||
// accounts for sixels being a multiple of six pixels tall.
|
||||
//
|
||||
// cellpxy/cellpxx and dimy/dimx ought describe the cell-pixel and cell
|
||||
// geometry of the target pile or, in Direct Mode, the tcache.
|
||||
static void
|
||||
shape_sprixel_plane(const tinfo* ti, ncplane* parent, const ncvisual* ncv,
|
||||
shape_sprixel_plane(const tinfo* ti, unsigned cellpxy, unsigned cellpxx,
|
||||
unsigned dimy, unsigned dimx,
|
||||
ncplane* parent, const ncvisual* ncv,
|
||||
ncscale_e scaling, unsigned* disppixy, unsigned* disppixx,
|
||||
uint64_t flags, unsigned* outy, unsigned* outx,
|
||||
int* placey, int* placex, int pxoffy, int pxoffx){
|
||||
if(scaling != NCSCALE_NONE && scaling != NCSCALE_NONE_HIRES){
|
||||
// disppixy/disppix are treated initially as cells
|
||||
if(parent == NULL){
|
||||
*disppixy = ti->dimy;
|
||||
*disppixx = ti->dimx;
|
||||
*disppixy = dimy;
|
||||
*disppixx = dimx;
|
||||
}else{
|
||||
ncplane_dim_yx(parent, disppixy, disppixx);
|
||||
}
|
||||
// FIXME why do we clamp only vertical, not horizontal, here?
|
||||
if(*placey + *disppixy >= ti->dimy){
|
||||
*disppixy = ti->dimy - *placey;
|
||||
if(*placey + *disppixy >= dimy){
|
||||
*disppixy = dimy - *placey;
|
||||
}
|
||||
if(!(flags & NCVISUAL_OPTION_VERALIGNED)){
|
||||
*disppixy -= *placey;
|
||||
@ -164,8 +169,8 @@ shape_sprixel_plane(const tinfo* ti, ncplane* parent, const ncvisual* ncv,
|
||||
if(!(flags & NCVISUAL_OPTION_HORALIGNED)){
|
||||
*disppixx -= *placex;
|
||||
}
|
||||
*disppixx *= ti->cellpixx;
|
||||
*disppixy *= ti->cellpixy;
|
||||
*disppixx *= cellpxx;
|
||||
*disppixy *= cellpxy;
|
||||
*disppixx += pxoffx;
|
||||
*disppixy += pxoffy;
|
||||
*outx = *disppixx;
|
||||
@ -187,10 +192,16 @@ shape_sprixel_plane(const tinfo* ti, ncplane* parent, const ncvisual* ncv,
|
||||
*disppixx -= pxoffx;
|
||||
}
|
||||
|
||||
// in addition to the geom fields, we pass out:
|
||||
// in addition to the fields in 'geom', we pass out:
|
||||
// * 'disppixx'/'disppixy': scaled output size in pixels
|
||||
// * 'outy'/'outx': true output size in pixels (ie post-sixel clamping)
|
||||
// * 'placey'/'placex': offset at which to draw
|
||||
// * 'bset': blitter that will be used
|
||||
// we take in:
|
||||
// * 'p': target pile (for cell-pixel and cell geometry)
|
||||
// * 'ti': used if p is NULL (direct mode only!)
|
||||
// * 'n': input ncvisual
|
||||
// * 'vopts': requested ncvisual_options
|
||||
int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
||||
const struct ncvisual_options* vopts, ncvgeom* geom,
|
||||
const struct blitset** bset,
|
||||
@ -230,7 +241,7 @@ int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
||||
geom->pixy = n->pixy;
|
||||
geom->pixx = n->pixx;
|
||||
}
|
||||
// when nc is NULL, we only report properties intrinsic to the ncvisual,
|
||||
// when ti is NULL, we only report properties intrinsic to the ncvisual,
|
||||
// i.e. only its original pixel geometry.
|
||||
if(ti == NULL){
|
||||
return 0;
|
||||
@ -241,8 +252,9 @@ int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
||||
logerror("couldn't get a blitter for %d\n", vopts ? vopts->blitter : NCBLIT_DEFAULT);
|
||||
return -1;
|
||||
}
|
||||
geom->cdimy = ti->cellpixy;
|
||||
geom->cdimx = ti->cellpixx;
|
||||
const ncpile* p = vopts->n ? ncplane_pile_const(vopts->n) : NULL;
|
||||
geom->cdimy = p ? p->cellpxy : ti->cellpxy;
|
||||
geom->cdimx = p ? p->cellpxx : ti->cellpxx;
|
||||
if((geom->blitter = (*bset)->geom) == NCBLIT_PIXEL){
|
||||
geom->maxpixely = ti->sixel_maxy;
|
||||
geom->maxpixelx = ti->sixel_maxx;
|
||||
@ -301,41 +313,44 @@ int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
||||
logerror("non-origin x placement %d for sprixel\n", vopts->x);
|
||||
return -1;
|
||||
}
|
||||
if(vopts->pxoffy >= ti->cellpixy){
|
||||
logerror("pixel y-offset %d too tall for cell %d\n", vopts->pxoffy, ti->cellpixy);
|
||||
if(vopts->pxoffy >= geom->cdimy){
|
||||
logerror("pixel y-offset %d too tall for cell %d\n", vopts->pxoffy, geom->cdimy);
|
||||
return -1;
|
||||
}
|
||||
if(vopts->pxoffx >= ti->cellpixx){
|
||||
logerror("pixel x-offset %d too wide for cell %d\n", vopts->pxoffx, ti->cellpixx);
|
||||
if(vopts->pxoffx >= geom->cdimx){
|
||||
logerror("pixel x-offset %d too wide for cell %d\n", vopts->pxoffx, geom->cdimx);
|
||||
return -1;
|
||||
}
|
||||
if(scaling == NCSCALE_NONE || scaling == NCSCALE_NONE_HIRES){
|
||||
// FIXME clamp to sprixel limits
|
||||
unsigned rows = ((geom->leny + ti->cellpixy - 1) / ti->cellpixy) + !!vopts->pxoffy;
|
||||
unsigned rows = ((geom->leny + geom->cdimy - 1) / geom->cdimy) + !!vopts->pxoffy;
|
||||
if(rows > ncplane_dim_y(vopts->n)){
|
||||
logerror("sprixel too tall %d for plane %d\n", geom->leny + vopts->pxoffy,
|
||||
ncplane_dim_y(vopts->n) * ti->cellpixy);
|
||||
ncplane_dim_y(vopts->n) * geom->cdimy);
|
||||
return -1;
|
||||
}
|
||||
unsigned cols = ((geom->lenx + ti->cellpixx - 1) / ti->cellpixx) + !!vopts->pxoffx;
|
||||
unsigned cols = ((geom->lenx + geom->cdimx - 1) / geom->cdimx) + !!vopts->pxoffx;
|
||||
if(cols > ncplane_dim_x(vopts->n)){
|
||||
logerror("sprixel too wide %d for plane %d\n", geom->lenx + vopts->pxoffx,
|
||||
ncplane_dim_x(vopts->n) * ti->cellpixx);
|
||||
ncplane_dim_x(vopts->n) * geom->cdimx);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(vopts->n == NULL || (vopts->flags & NCVISUAL_OPTION_CHILDPLANE)){
|
||||
// we'll need to create the plane
|
||||
shape_sprixel_plane(ti, vopts->n, n, scaling, disppixy, disppixx,
|
||||
const int dimy = p ? p->dimy : ti->dimy;
|
||||
const int dimx = p ? p->dimx : ti->dimx;
|
||||
shape_sprixel_plane(ti, geom->cdimy, geom->cdimx, dimy, dimx,
|
||||
vopts->n, n, scaling, disppixy, disppixx,
|
||||
vopts->flags, outy, outx, placey, placex,
|
||||
vopts->pxoffy, vopts->pxoffx);
|
||||
}else{
|
||||
if(scaling != NCSCALE_NONE && scaling != NCSCALE_NONE_HIRES){
|
||||
ncplane_dim_yx(vopts->n, disppixy, disppixx);
|
||||
*disppixx *= ti->cellpixx;
|
||||
*disppixx *= geom->cdimx;
|
||||
*disppixx += vopts->pxoffx;
|
||||
*disppixy *= ti->cellpixy;
|
||||
*disppixy *= geom->cdimy;
|
||||
*disppixy += vopts->pxoffy;
|
||||
clamp_to_sixelmax(ti, disppixy, disppixx, outy, scaling);
|
||||
int absplacex = 0, absplacey = 0;
|
||||
@ -345,8 +360,8 @@ int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
||||
if(!(vopts->flags & NCVISUAL_OPTION_VERALIGNED)){
|
||||
absplacey = *placey;
|
||||
}
|
||||
*disppixx -= absplacex * ti->cellpixx;
|
||||
*disppixy -= absplacey * ti->cellpixy;
|
||||
*disppixx -= absplacex * geom->cdimx;
|
||||
*disppixy -= absplacey * geom->cdimy;
|
||||
}else{
|
||||
*disppixx = geom->lenx + vopts->pxoffx;
|
||||
*disppixy = geom->leny + vopts->pxoffy;
|
||||
@ -358,7 +373,7 @@ int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
||||
}
|
||||
clamp_to_sixelmax(ti, disppixy, disppixx, outy, scaling);
|
||||
// FIXME use a closed form
|
||||
while((*outy + ti->cellpixy - 1) / ti->cellpixy > (unsigned)ncplane_dim_y(vopts->n)){
|
||||
while((*outy + geom->cdimy - 1) / geom->cdimy > ncplane_dim_y(vopts->n)){
|
||||
*outy -= ti->sprixel_scale_height;
|
||||
*disppixy = *outy;
|
||||
}
|
||||
@ -366,11 +381,11 @@ int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
||||
*disppixx -= vopts->pxoffx;
|
||||
*disppixy -= vopts->pxoffy;
|
||||
}
|
||||
logdebug("pblit: %dx%d ← %dx%d of %d/%d stride %u @%dx%d %p %u\n", *disppixy, *disppixx, geom->begy, geom->begx, n->pixy, n->pixx, n->rowstride, *placey, *placex, n->data, ti->cellpixx);
|
||||
logdebug("pblit: %dx%d ← %dx%d of %d/%d stride %u @%dx%d %p %u\n", *disppixy, *disppixx, geom->begy, geom->begx, n->pixy, n->pixx, n->rowstride, *placey, *placex, n->data, geom->cdimx);
|
||||
geom->rpixy = *disppixy;
|
||||
geom->rpixx = *disppixx;
|
||||
geom->rcellx = *outx / ti->cellpixx + !!(*outx % ti->cellpixx);
|
||||
geom->rcelly = *outy / ti->cellpixy + !!(*outy % ti->cellpixy);
|
||||
geom->rcellx = *outx / geom->cdimx + !!(*outx % geom->cdimx);
|
||||
geom->rcelly = *outy / geom->cdimy + !!(*outy % geom->cdimy);
|
||||
}else{ // cellblit
|
||||
if(vopts->pxoffx || vopts->pxoffy){
|
||||
logerror("pixel offsets cannot be used with cell blitting\n");
|
||||
@ -1009,8 +1024,11 @@ ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blits
|
||||
bargs.u.pixel.colorregs = ti->color_registers;
|
||||
bargs.u.pixel.pxoffy = pxoffy;
|
||||
bargs.u.pixel.pxoffx = pxoffx;
|
||||
bargs.u.pixel.cellpxy = geom->cdimy;
|
||||
bargs.u.pixel.cellpxx = geom->cdimx;
|
||||
const ncpile* p = ncplane_pile_const(n);
|
||||
if(n->sprite == NULL){
|
||||
if((n->sprite = sprixel_alloc(&nc->tcache, n, geom->rcelly, geom->rcellx)) == NULL){
|
||||
if((n->sprite = sprixel_alloc(n, geom->rcelly, geom->rcellx)) == NULL){
|
||||
return NULL;
|
||||
}
|
||||
if((n->tam = create_tam(geom->rcelly, geom->rcellx)) == NULL){
|
||||
@ -1036,9 +1054,9 @@ ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blits
|
||||
// zeroed out, thus neither of these will have any effect.
|
||||
if(flags & NCVISUAL_OPTION_HORALIGNED){
|
||||
if(placex == NCALIGN_CENTER){
|
||||
placex = (ncplane_dim_x(ncplane_parent_const(n)) * ti->cellpixx - geom->rpixx) / 2 / ti->cellpixx;
|
||||
placex = (ncplane_dim_x(ncplane_parent_const(n)) * p->cellpxx - geom->rpixx) / 2 / p->cellpxx;
|
||||
}else if(placex == NCALIGN_RIGHT){
|
||||
placex = (ncplane_dim_x(ncplane_parent_const(n)) * ti->cellpixx - geom->rpixx) / ti->cellpixx;
|
||||
placex = (ncplane_dim_x(ncplane_parent_const(n)) * p->cellpxx - geom->rpixx) / p->cellpxx;
|
||||
}
|
||||
if(placex < 0){
|
||||
return NULL;
|
||||
@ -1046,9 +1064,9 @@ ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blits
|
||||
}
|
||||
if(flags & NCVISUAL_OPTION_VERALIGNED){
|
||||
if(placey == NCALIGN_CENTER){
|
||||
placey = (ncplane_dim_y(ncplane_parent_const(n)) * ti->cellpixy - geom->rpixy) / 2 / ti->cellpixy;
|
||||
placey = (ncplane_dim_y(ncplane_parent_const(n)) * p->cellpxy - geom->rpixy) / 2 / p->cellpxy;
|
||||
}else if(placey == NCALIGN_BOTTOM){
|
||||
placey = (ncplane_dim_y(ncplane_parent_const(n)) * ti->cellpixy - geom->rpixy) / ti->cellpixy;
|
||||
placey = (ncplane_dim_y(ncplane_parent_const(n)) * p->cellpxy - geom->rpixy) / p->cellpxy;
|
||||
}
|
||||
if(placey < 0){
|
||||
return NULL;
|
||||
|
@ -173,7 +173,9 @@ struct ncplane* ffmpeg_subtitle(ncplane* parent, const ncvisual* ncv){
|
||||
continue;
|
||||
}
|
||||
struct notcurses* nc = ncplane_notcurses(parent);
|
||||
if(nc->tcache.cellpixy <= 0 || nc->tcache.cellpixx <= 0){
|
||||
const unsigned cellpxy = ncplane_pile_const(parent)->cellpxy;
|
||||
const unsigned cellpxx = ncplane_pile_const(parent)->cellpxx;
|
||||
if(cellpxy <= 0 || cellpxx <= 0){
|
||||
continue;
|
||||
}
|
||||
struct ncvisual* v = ncvisual_from_palidx(rect->data[0], rect->h,
|
||||
@ -182,10 +184,10 @@ struct ncplane* ffmpeg_subtitle(ncplane* parent, const ncvisual* ncv){
|
||||
if(v == NULL){
|
||||
return NULL;
|
||||
}
|
||||
int rows = (rect->h + nc->tcache.cellpixy - 1) / nc->tcache.cellpixy;
|
||||
int rows = (rect->h + cellpxx - 1) / cellpxy;
|
||||
struct ncplane_options nopts = {
|
||||
.rows = rows,
|
||||
.cols = (rect->w + nc->tcache.cellpixx - 1) / nc->tcache.cellpixx,
|
||||
.cols = (rect->w + cellpxx - 1) / cellpxx,
|
||||
.y = ncplane_dim_y(parent) - rows - 1,
|
||||
.name = "t1st",
|
||||
};
|
||||
|
@ -14,8 +14,8 @@ TEST_CASE("Bitmaps") {
|
||||
}
|
||||
|
||||
SUBCASE("SprixelTermValues") {
|
||||
CHECK(0 < nc_->tcache.cellpixy);
|
||||
CHECK(0 < nc_->tcache.cellpixx);
|
||||
CHECK(0 < nc_->tcache.cellpxy);
|
||||
CHECK(0 < nc_->tcache.cellpxx);
|
||||
if(!nc_->tcache.pixel_draw_late){
|
||||
CHECK(nc_->tcache.pixel_draw);
|
||||
}
|
||||
@ -66,8 +66,8 @@ TEST_CASE("Bitmaps") {
|
||||
|
||||
// a sprixel requires a plane large enough to hold it
|
||||
SUBCASE("SprixelTooTall") {
|
||||
auto y = nc_->tcache.cellpixy + 6;
|
||||
auto x = nc_->tcache.cellpixx;
|
||||
auto y = nc_->tcache.cellpxy + 6;
|
||||
auto x = nc_->tcache.cellpxx;
|
||||
std::vector<uint32_t> v(x * y, htole(0xe61c28ff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -89,8 +89,8 @@ TEST_CASE("Bitmaps") {
|
||||
}
|
||||
|
||||
SUBCASE("SprixelTooWide") {
|
||||
auto y = nc_->tcache.cellpixy;
|
||||
auto x = nc_->tcache.cellpixx + 1;
|
||||
auto y = nc_->tcache.cellpxy;
|
||||
auto x = nc_->tcache.cellpxx + 1;
|
||||
std::vector<uint32_t> v(x * y, htole(0xe61c28ff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -114,8 +114,8 @@ TEST_CASE("Bitmaps") {
|
||||
|
||||
// should not be able to emit glyphs to a sprixelated plane
|
||||
SUBCASE("SprixelNoGlyphs") {
|
||||
auto y = nc_->tcache.cellpixy;
|
||||
auto x = nc_->tcache.cellpixx;
|
||||
auto y = nc_->tcache.cellpxy;
|
||||
auto x = nc_->tcache.cellpxx;
|
||||
std::vector<uint32_t> v(x * y, htole(0xe61c28ff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -139,8 +139,8 @@ TEST_CASE("Bitmaps") {
|
||||
}
|
||||
|
||||
SUBCASE("BitmapStack") {
|
||||
auto y = nc_->tcache.cellpixy * 10;
|
||||
auto x = nc_->tcache.cellpixx * 10;
|
||||
auto y = nc_->tcache.cellpxy * 10;
|
||||
auto x = nc_->tcache.cellpxx * 10;
|
||||
std::vector<uint32_t> v(x * y, htole(0xe61c28ff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -152,8 +152,8 @@ TEST_CASE("Bitmaps") {
|
||||
REQUIRE(nullptr != botn);
|
||||
// should just have a red plane
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
y = nc_->tcache.cellpixy * 5;
|
||||
x = nc_->tcache.cellpixx * 5;
|
||||
y = nc_->tcache.cellpxy * 5;
|
||||
x = nc_->tcache.cellpxx * 5;
|
||||
std::vector<uint32_t> v2(x * y, htole(0x8142f1ff));
|
||||
auto ncv2 = ncvisual_from_rgba(v2.data(), y, sizeof(decltype(v2)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv2);
|
||||
@ -198,8 +198,8 @@ TEST_CASE("Bitmaps") {
|
||||
|
||||
SUBCASE("BitmapStretch") {
|
||||
// first, assemble a visual equivalent to 1 cell
|
||||
auto y = nc_->tcache.cellpixy;
|
||||
auto x = nc_->tcache.cellpixx;
|
||||
auto y = nc_->tcache.cellpxy;
|
||||
auto x = nc_->tcache.cellpxx;
|
||||
std::vector<uint32_t> v(x * y, htole(0xffffffff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -211,8 +211,8 @@ TEST_CASE("Bitmaps") {
|
||||
REQUIRE(nullptr != n);
|
||||
auto s = n->sprite;
|
||||
REQUIRE(nullptr != s);
|
||||
CHECK(nc_->tcache.cellpixy == ncv->pixy);
|
||||
CHECK(nc_->tcache.cellpixx == ncv->pixx);
|
||||
CHECK(nc_->tcache.cellpxy == ncv->pixy);
|
||||
CHECK(nc_->tcache.cellpxx == ncv->pixx);
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
struct ncplane_options nopts = {
|
||||
.y = 1,
|
||||
@ -232,8 +232,8 @@ TEST_CASE("Bitmaps") {
|
||||
CHECK(vopts.n == ncvisual_blit(nc_, ncv, &vopts));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
CHECK(0 == ncvisual_resize_noninterpolative(ncv, ncv->pixy * 4, ncv->pixx * 4));
|
||||
CHECK(4 * nc_->tcache.cellpixy == ncv->pixy);
|
||||
CHECK(4 * nc_->tcache.cellpixx == ncv->pixx);
|
||||
CHECK(4 * nc_->tcache.cellpxy == ncv->pixy);
|
||||
CHECK(4 * nc_->tcache.cellpxx == ncv->pixx);
|
||||
vopts.y = 1;
|
||||
vopts.x = 6;
|
||||
vopts.n = n_;
|
||||
@ -242,7 +242,7 @@ TEST_CASE("Bitmaps") {
|
||||
auto infn = ncvisual_blit(nc_, ncv, &vopts);
|
||||
REQUIRE(infn);
|
||||
if(nc_->tcache.sprixel_scale_height == 6){
|
||||
if(4 * nc_->tcache.cellpixy % 6){
|
||||
if(4 * nc_->tcache.cellpxy % 6){
|
||||
CHECK(5 == ncplane_dim_y(infn));
|
||||
}else{
|
||||
CHECK(4 == ncplane_dim_y(infn));
|
||||
@ -259,8 +259,8 @@ TEST_CASE("Bitmaps") {
|
||||
vopts.x = 11;
|
||||
auto resizen = ncvisual_blit(nc_, ncv, &vopts);
|
||||
REQUIRE(resizen);
|
||||
CHECK((8 + nc_->tcache.cellpixy - 1) / nc_->tcache.cellpixy == ncplane_dim_y(resizen));
|
||||
CHECK((8 + nc_->tcache.cellpixx - 1) / nc_->tcache.cellpixx == ncplane_dim_x(resizen));
|
||||
CHECK((8 + nc_->tcache.cellpxy - 1) / nc_->tcache.cellpxy == ncplane_dim_y(resizen));
|
||||
CHECK((8 + nc_->tcache.cellpxx - 1) / nc_->tcache.cellpxx == ncplane_dim_x(resizen));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
CHECK(0 == ncplane_destroy(bigp));
|
||||
CHECK(0 == ncplane_destroy(resizen));
|
||||
@ -274,8 +274,8 @@ TEST_CASE("Bitmaps") {
|
||||
// resulting geometries for (rough) equality
|
||||
SUBCASE("InflateVsScale") {
|
||||
// first, assemble a visual equivalent to 1 cell
|
||||
auto y = nc_->tcache.cellpixy;
|
||||
auto x = nc_->tcache.cellpixx;
|
||||
auto y = nc_->tcache.cellpxy;
|
||||
auto x = nc_->tcache.cellpxx;
|
||||
std::vector<uint32_t> v(x * y, htole(0xff7799dd));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -355,8 +355,8 @@ TEST_CASE("Bitmaps") {
|
||||
.transcolor = 0,
|
||||
.pxoffy = 0, .pxoffx = 0,
|
||||
};
|
||||
auto y = nc_->tcache.cellpixy * 6;
|
||||
auto x = nc_->tcache.cellpixx;
|
||||
auto y = nc_->tcache.cellpxy * 6;
|
||||
auto x = nc_->tcache.cellpxx;
|
||||
std::vector<uint32_t> v(x * y, htole(0xffffffff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -399,8 +399,8 @@ TEST_CASE("Bitmaps") {
|
||||
.transcolor = 0,
|
||||
.pxoffy = 0, .pxoffx = 0,
|
||||
};
|
||||
auto y = nc_->tcache.cellpixy * 6;
|
||||
auto x = nc_->tcache.cellpixx;
|
||||
auto y = nc_->tcache.cellpxy * 6;
|
||||
auto x = nc_->tcache.cellpxx;
|
||||
std::vector<uint32_t> v(x * y, htole(0xffffffff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -417,8 +417,8 @@ TEST_CASE("Bitmaps") {
|
||||
|
||||
SUBCASE("PixelCellWipe") {
|
||||
// first, assemble a visual equivalent to 4 cells
|
||||
auto y = 2 * nc_->tcache.cellpixy;
|
||||
auto x = 2 * nc_->tcache.cellpixx;
|
||||
auto y = 2 * nc_->tcache.cellpxy;
|
||||
auto x = 2 * nc_->tcache.cellpxx;
|
||||
std::vector<uint32_t> v(x * y, htole(0xffffffff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -446,8 +446,8 @@ TEST_CASE("Bitmaps") {
|
||||
|
||||
SUBCASE("PixelCellWipePolychromatic") {
|
||||
// first, assemble a visual equivalent to 4 cells
|
||||
auto y = 2 * nc_->tcache.cellpixy;
|
||||
auto x = 2 * nc_->tcache.cellpixx;
|
||||
auto y = 2 * nc_->tcache.cellpxy;
|
||||
auto x = 2 * nc_->tcache.cellpxx;
|
||||
std::vector<uint32_t> v(x * y, htole(0xffffffff));
|
||||
for(auto& e : v){
|
||||
e -= htole(rand() % 0x1000000);
|
||||
@ -478,8 +478,8 @@ TEST_CASE("Bitmaps") {
|
||||
|
||||
SUBCASE("PixelBigCellWipePolychromatic") {
|
||||
// first, assemble a visual equivalent to 100 cells
|
||||
auto y = 10 * nc_->tcache.cellpixy;
|
||||
auto x = 10 * nc_->tcache.cellpixx;
|
||||
auto y = 10 * nc_->tcache.cellpxy;
|
||||
auto x = 10 * nc_->tcache.cellpxx;
|
||||
std::vector<uint32_t> v(x * y, htole(0xffffffff));
|
||||
for(auto& e : v){
|
||||
e -= htole(rand() % 0x1000000);
|
||||
@ -513,14 +513,14 @@ TEST_CASE("Bitmaps") {
|
||||
// first, assemble a visual equivalent to 54 cells
|
||||
auto dimy = 6;
|
||||
auto dimx = 9;
|
||||
auto y = dimy * nc_->tcache.cellpixy;
|
||||
auto x = dimx * nc_->tcache.cellpixx;
|
||||
auto y = dimy * nc_->tcache.cellpxy;
|
||||
auto x = dimx * nc_->tcache.cellpxx;
|
||||
std::vector<uint32_t> v(x * y, htole(0xffffffff));
|
||||
// every other cell, set some pixels transparent
|
||||
for(int i = 0 ; i < dimy * dimx ; ++i){
|
||||
if(i % 2){
|
||||
int py = (i / dimx) * nc_->tcache.cellpixy;
|
||||
int px = (i % dimx) * nc_->tcache.cellpixx;
|
||||
int py = (i / dimx) * nc_->tcache.cellpxy;
|
||||
int px = (i % dimx) * nc_->tcache.cellpxx;
|
||||
ncpixel_set_a(&v[py * x + px], 0);
|
||||
}
|
||||
}
|
||||
@ -540,8 +540,8 @@ TEST_CASE("Bitmaps") {
|
||||
CHECK(s->dimx == dimx);
|
||||
const auto tam = n->tam;
|
||||
for(unsigned i = 0 ; i < s->dimy * s->dimx ; ++i){
|
||||
int py = (i / dimx) * nc_->tcache.cellpixy;
|
||||
int px = (i % dimx) * nc_->tcache.cellpixx;
|
||||
int py = (i / dimx) * nc_->tcache.cellpxy;
|
||||
int px = (i % dimx) * nc_->tcache.cellpxx;
|
||||
// cells with a transparent pixel ought be SPRIXCELL_MIXED;
|
||||
// cells without one ought be SPRIXCELL_OPAQUE.
|
||||
sprixcell_e state = tam[(i / dimx) + (i % dimx)].state;
|
||||
@ -613,8 +613,8 @@ TEST_CASE("Bitmaps") {
|
||||
|
||||
SUBCASE("BitmapMoveOffscreenLeft") {
|
||||
// first, assemble a visual equivalent to 2x2 cells
|
||||
auto y = nc_->tcache.cellpixy * 2;
|
||||
auto x = nc_->tcache.cellpixx * 2;
|
||||
auto y = nc_->tcache.cellpxy * 2;
|
||||
auto x = nc_->tcache.cellpxx * 2;
|
||||
std::vector<uint32_t> v(x * y * 4, htole(0xffccccff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -634,8 +634,8 @@ TEST_CASE("Bitmaps") {
|
||||
|
||||
SUBCASE("BitmapMoveOffscreenRight") {
|
||||
// first, assemble a visual equivalent to 2x2 cells
|
||||
auto y = nc_->tcache.cellpixy * 2;
|
||||
auto x = nc_->tcache.cellpixx * 2;
|
||||
auto y = nc_->tcache.cellpxy * 2;
|
||||
auto x = nc_->tcache.cellpxx * 2;
|
||||
std::vector<uint32_t> v(x * y * 4, htole(0xffccccff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -656,8 +656,8 @@ TEST_CASE("Bitmaps") {
|
||||
|
||||
SUBCASE("BitmapMoveOffscreenDown") {
|
||||
// first, assemble a visual equivalent to 2x2 cells
|
||||
auto y = nc_->tcache.cellpixy * 2;
|
||||
auto x = nc_->tcache.cellpixx * 2;
|
||||
auto y = nc_->tcache.cellpxy * 2;
|
||||
auto x = nc_->tcache.cellpxx * 2;
|
||||
std::vector<uint32_t> v(x * y * 4, htole(0xffccccff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -677,8 +677,8 @@ TEST_CASE("Bitmaps") {
|
||||
|
||||
SUBCASE("BitmapMoveOffscreenUp") {
|
||||
// first, assemble a visual equivalent to 2x2 cells
|
||||
auto y = nc_->tcache.cellpixy * 2;
|
||||
auto x = nc_->tcache.cellpixx * 2;
|
||||
auto y = nc_->tcache.cellpxy * 2;
|
||||
auto x = nc_->tcache.cellpxx * 2;
|
||||
std::vector<uint32_t> v(x * y * 4, htole(0xffccccff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -700,8 +700,8 @@ TEST_CASE("Bitmaps") {
|
||||
// smoothly move a bitmap diagonally across the screen
|
||||
SUBCASE("BitmapSmoothMove") {
|
||||
// first, assemble a visual equivalent to 2x2 cells
|
||||
auto y = nc_->tcache.cellpixy * 2;
|
||||
auto x = nc_->tcache.cellpixx * 2;
|
||||
auto y = nc_->tcache.cellpxy * 2;
|
||||
auto x = nc_->tcache.cellpxx * 2;
|
||||
std::vector<uint32_t> v(x * y * 4, htole(0xffccccff));
|
||||
auto ncv = ncvisual_from_rgba(v.data(), y, sizeof(decltype(v)::value_type) * x, x);
|
||||
REQUIRE(nullptr != ncv);
|
||||
@ -711,15 +711,15 @@ TEST_CASE("Bitmaps") {
|
||||
vopts.flags = NCVISUAL_OPTION_NODEGRADE | NCVISUAL_OPTION_CHILDPLANE;
|
||||
auto n = ncvisual_blit(nc_, ncv, &vopts);
|
||||
REQUIRE(nullptr != n);
|
||||
auto xpx = (ncplane_dim_x(n_) - 2) * nc_->tcache.cellpixx;
|
||||
auto ypx = (ncplane_dim_y(n_) - 2) * nc_->tcache.cellpixy;
|
||||
auto xpx = (ncplane_dim_x(n_) - 2) * nc_->tcache.cellpxx;
|
||||
auto ypx = (ncplane_dim_y(n_) - 2) * nc_->tcache.cellpxy;
|
||||
double xyrat = (double)ypx / xpx;
|
||||
for(unsigned xat = 0 ; xat < xpx ; ++xat){
|
||||
vopts.x = xat / nc_->tcache.cellpixx;
|
||||
vopts.pxoffx = xat % nc_->tcache.cellpixx;
|
||||
vopts.x = xat / nc_->tcache.cellpxx;
|
||||
vopts.pxoffx = xat % nc_->tcache.cellpxx;
|
||||
int yat = xat * xyrat;
|
||||
vopts.y = yat / nc_->tcache.cellpixy;
|
||||
vopts.pxoffy = yat % nc_->tcache.cellpixy;
|
||||
vopts.y = yat / nc_->tcache.cellpxy;
|
||||
vopts.pxoffy = yat % nc_->tcache.cellpxy;
|
||||
CHECK(0 == ncplane_destroy(n));
|
||||
n = ncvisual_blit(nc_, ncv, &vopts);
|
||||
REQUIRE(nullptr != n);
|
||||
|
@ -7,8 +7,8 @@
|
||||
void default_visual_extrinsics(const notcurses* nc, const ncvgeom& g) {
|
||||
CHECK(0 == g.pixy);
|
||||
CHECK(0 == g.pixx);
|
||||
CHECK(nc->tcache.cellpixy == g.cdimy);
|
||||
CHECK(nc->tcache.cellpixx == g.cdimx);
|
||||
CHECK(nc->tcache.cellpxy == g.cdimy);
|
||||
CHECK(nc->tcache.cellpxx == g.cdimx);
|
||||
CHECK(1 <= g.scaley);
|
||||
CHECK(1 <= g.scalex);
|
||||
CHECK(0 == g.rpixy);
|
||||
@ -91,8 +91,8 @@ TEST_CASE("Visual") {
|
||||
CHECK(0 == ncvisual_geom(nc_, nullptr, &vopts, &g));
|
||||
CHECK(0 == g.pixy);
|
||||
CHECK(0 == g.pixx);
|
||||
CHECK(nc_->tcache.cellpixy == g.cdimy);
|
||||
CHECK(nc_->tcache.cellpixx == g.cdimx);
|
||||
CHECK(nc_->tcache.cellpxy == g.cdimy);
|
||||
CHECK(nc_->tcache.cellpxx == g.cdimx);
|
||||
if(notcurses_canpixel(nc_)){
|
||||
CHECK(g.cdimy == g.scaley);
|
||||
CHECK(g.cdimx == g.scalex);
|
||||
|
Loading…
Reference in New Issue
Block a user