|
|
|
@ -126,137 +126,48 @@ ncvisual_origin(const struct ncvisual_options* vopts, int* restrict begy, int* r
|
|
|
|
|
*begx = vopts ? vopts->begx : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 'leny' and 'lenx' get the number of pixels to actually be rendered, 'y' and
|
|
|
|
|
// 'x' get the original size of the visual in pixels, and 'scaley' and 'scalex'
|
|
|
|
|
// get the number of pixels per cell with the selected 'blitter'. this is the
|
|
|
|
|
// first part of real geometry calculation.
|
|
|
|
|
static int
|
|
|
|
|
ncvisual_blitset_geom(const notcurses* nc, const tinfo* tcache,
|
|
|
|
|
const ncvisual* n, const struct ncvisual_options* vopts,
|
|
|
|
|
int* y, int* x, int* scaley, int* scalex,
|
|
|
|
|
int* leny, int* lenx, const struct blitset** blitter){
|
|
|
|
|
int fakeleny, fakelenx;
|
|
|
|
|
if(leny == NULL){
|
|
|
|
|
leny = &fakeleny;
|
|
|
|
|
}
|
|
|
|
|
if(lenx == NULL){
|
|
|
|
|
lenx = &fakelenx;
|
|
|
|
|
}
|
|
|
|
|
if(vopts && vopts->flags >= (NCVISUAL_OPTION_NOINTERPOLATE << 1u)){
|
|
|
|
|
logwarn("Warning: unknown ncvisual options %016" PRIx64 "\n", vopts->flags);
|
|
|
|
|
}
|
|
|
|
|
if(vopts && (vopts->flags & NCVISUAL_OPTION_CHILDPLANE) && !vopts->n){
|
|
|
|
|
logerror("Requested child plane with NULL n\n");
|
|
|
|
|
|
|
|
|
|
int ncvisual_blitter_geom(const notcurses* nc, const ncvisual* n,
|
|
|
|
|
const struct ncvisual_options* vopts,
|
|
|
|
|
int* y, int* x, int* scaley, int* scalex,
|
|
|
|
|
ncblitter_e* blitter){
|
|
|
|
|
ncvgeom geom;
|
|
|
|
|
const struct blitset* bset;
|
|
|
|
|
if(ncvisual_geom_inner(&nc->tcache, n, vopts, &geom, &bset)){
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
int begy, begx;
|
|
|
|
|
ncvisual_origin(vopts, &begy, &begx);
|
|
|
|
|
*lenx = vopts ? vopts->lenx : 0;
|
|
|
|
|
*leny = vopts ? vopts->leny : 0;
|
|
|
|
|
//fprintf(stderr, "blit %dx%d+%dx%d %p\n", begy, begx, *leny, *lenx, ncv->data);
|
|
|
|
|
if(begy < 0 || begx < 0 || *lenx <= -1 || *leny <= -1){
|
|
|
|
|
logerror("Invalid geometry for visual %d %d %d %d\n", begy, begx, *leny, *lenx);
|
|
|
|
|
return -1;
|
|
|
|
|
if(y){
|
|
|
|
|
*y = geom.pixy;
|
|
|
|
|
}
|
|
|
|
|
if(n){
|
|
|
|
|
//fprintf(stderr, "OUR DATA: %p rows/cols: %d/%d\n", n->data, n->pixy, n->pixx);
|
|
|
|
|
if(n->data == NULL){
|
|
|
|
|
logerror("No data in visual\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
//fprintf(stderr, "blit %d/%d to %dx%d+%dx%d scaling: %d\n", n->pixy, n->pixx, begy, begx, *leny, *lenx, vopts ? vopts->scaling : 0);
|
|
|
|
|
if(begx >= n->pixx || begy >= n->pixy){
|
|
|
|
|
logerror("Visual too large %d > %d or %d > %d\n", begy, n->pixy, begx, n->pixx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(*lenx == 0){ // 0 means "to the end"; use all available source material
|
|
|
|
|
*lenx = n->pixx - begx;
|
|
|
|
|
}
|
|
|
|
|
if(*leny == 0){
|
|
|
|
|
*leny = n->pixy - begy;
|
|
|
|
|
}
|
|
|
|
|
//fprintf(stderr, "blit %d/%d to %dx%d+%dx%d scaling: %d flags: 0x%016lx\n", n->pixy, n->pixx, begy, begx, *leny, *lenx, vopts ? vopts->scaling : 0, vopts ? vopts->flags : 0);
|
|
|
|
|
if(*lenx <= 0 || *leny <= 0){ // no need to draw zero-size object, exit
|
|
|
|
|
logerror("Zero-size object %d %d\n", *leny, *lenx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(begx + *lenx > n->pixx || begy + *leny > n->pixy){
|
|
|
|
|
logerror("Geometry too large %d > %d or %d > %d\n", begy + *leny, n->pixy, begx + *lenx, n->pixx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(x){
|
|
|
|
|
*x = geom.pixx;
|
|
|
|
|
}
|
|
|
|
|
const struct blitset* bset = rgba_blitter(tcache, vopts);
|
|
|
|
|
if(!bset){
|
|
|
|
|
logerror("Couldn't get a blitter for %d\n", vopts ? vopts->blitter : NCBLIT_DEFAULT);
|
|
|
|
|
return -1;
|
|
|
|
|
if(scaley){
|
|
|
|
|
*scaley = geom.scaley;
|
|
|
|
|
}
|
|
|
|
|
if(blitter){
|
|
|
|
|
*blitter = bset;
|
|
|
|
|
if(scalex){
|
|
|
|
|
*scalex = geom.scalex;
|
|
|
|
|
}
|
|
|
|
|
// FIXME several unsafe uses of NULL nc within here!
|
|
|
|
|
if(vopts){
|
|
|
|
|
if(bset->geom == NCBLIT_PIXEL){
|
|
|
|
|
if(vopts->n){
|
|
|
|
|
if(vopts->n == notcurses_stdplane_const(nc)){
|
|
|
|
|
if(!(vopts->flags & NCVISUAL_OPTION_CHILDPLANE)){
|
|
|
|
|
logerror("Won't blit bitmaps to the standard plane\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(vopts->y && !(vopts->flags & (NCVISUAL_OPTION_VERALIGNED | NCVISUAL_OPTION_CHILDPLANE))){
|
|
|
|
|
logerror("Non-origin y placement %d for sprixel\n", vopts->y);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(vopts->x && !(vopts->flags & (NCVISUAL_OPTION_HORALIGNED | NCVISUAL_OPTION_CHILDPLANE))){
|
|
|
|
|
logerror("Non-origin x placement %d for sprixel\n", vopts->x);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
// FIXME clamp to sprixel limits
|
|
|
|
|
if(vopts->scaling == NCSCALE_NONE || vopts->scaling == NCSCALE_NONE_HIRES){
|
|
|
|
|
if(vopts->pxoffy >= nc->tcache.cellpixy){
|
|
|
|
|
logerror("pixel y-offset %d too tall for cell %d\n", vopts->pxoffy, nc->tcache.cellpixy);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
int rows = ((*leny + nc->tcache.cellpixy - 1) / nc->tcache.cellpixy)
|
|
|
|
|
+ !!vopts->pxoffy;
|
|
|
|
|
if(rows > ncplane_dim_y(vopts->n)){
|
|
|
|
|
logerror("sprixel too tall %d for plane %d\n",
|
|
|
|
|
*leny + vopts->pxoffy, ncplane_dim_y(vopts->n) * nc->tcache.cellpixy);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(vopts->pxoffx >= nc->tcache.cellpixx){
|
|
|
|
|
logerror("pixel x-offset %d too wide for cell %d\n", vopts->pxoffx, nc->tcache.cellpixx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
int cols = ((*lenx + nc->tcache.cellpixx - 1) / nc->tcache.cellpixx)
|
|
|
|
|
+ !!vopts->pxoffx;
|
|
|
|
|
if(cols > ncplane_dim_x(vopts->n)){
|
|
|
|
|
logerror("sprixel too wide %d for plane %d\n",
|
|
|
|
|
*lenx + vopts->pxoffx, ncplane_dim_x(vopts->n) * nc->tcache.cellpixx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}else{
|
|
|
|
|
if(vopts->pxoffx || vopts->pxoffy){
|
|
|
|
|
logerror("pixel offsets cannot be used with cell blitting\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(blitter){
|
|
|
|
|
*blitter = bset->geom;
|
|
|
|
|
}
|
|
|
|
|
if(n){
|
|
|
|
|
if(y){
|
|
|
|
|
*y = n->pixy;
|
|
|
|
|
}
|
|
|
|
|
if(x){
|
|
|
|
|
*x = n->pixx;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
|
|
|
|
const struct ncvisual_options* vopts, ncvgeom* geom,
|
|
|
|
|
const struct blitset** bset){
|
|
|
|
|
if(ti == NULL && n == NULL){
|
|
|
|
|
logerror("got NULL for both sources\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(scaley){
|
|
|
|
|
*scaley = encoding_y_scale(tcache, bset);
|
|
|
|
|
// check basic vopts preconditions
|
|
|
|
|
if(vopts && vopts->flags >= (NCVISUAL_OPTION_NOINTERPOLATE << 1u)){
|
|
|
|
|
logwarn("Warning: unknown ncvisual options %016" PRIx64 "\n", vopts->flags);
|
|
|
|
|
}
|
|
|
|
|
if(scalex){
|
|
|
|
|
*scalex = encoding_x_scale(tcache, bset);
|
|
|
|
|
if(vopts && (vopts->flags & NCVISUAL_OPTION_CHILDPLANE) && !vopts->n){
|
|
|
|
|
logerror("Requested child plane with NULL n\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(vopts && vopts->flags & NCVISUAL_OPTION_HORALIGNED){
|
|
|
|
|
if(vopts->x < NCALIGN_UNALIGNED || vopts->x > NCALIGN_RIGHT){
|
|
|
|
@ -270,29 +181,6 @@ ncvisual_blitset_geom(const notcurses* nc, const tinfo* tcache,
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ncvisual_blitter_geom(const notcurses* nc, const ncvisual* n,
|
|
|
|
|
const struct ncvisual_options* vopts,
|
|
|
|
|
int* y, int* x, int* scaley, int* scalex,
|
|
|
|
|
ncblitter_e* blitter){
|
|
|
|
|
const struct blitset* bset;
|
|
|
|
|
int ret = ncvisual_blitset_geom(nc, &nc->tcache, n, vopts, y, x,
|
|
|
|
|
scaley, scalex, NULL, NULL, &bset);
|
|
|
|
|
if(ret == 0 && blitter){
|
|
|
|
|
*blitter = bset->geom;
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
|
|
|
|
const struct ncvisual_options* vopts, ncvgeom* geom,
|
|
|
|
|
const struct blitset** bset){
|
|
|
|
|
if(ti == NULL && n == NULL){
|
|
|
|
|
logerror("got NULL for both sources\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
// when nc is NULL, we only report properties intrinsic to the ncvisual,
|
|
|
|
|
// i.e. only its original pixel geometry.
|
|
|
|
|
if(ti == NULL){
|
|
|
|
@ -311,12 +199,9 @@ int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
|
|
|
|
if((geom->blitter = (*bset)->geom) == NCBLIT_PIXEL){
|
|
|
|
|
geom->maxpixely = ti->sixel_maxy_pristine;
|
|
|
|
|
geom->maxpixelx = ti->sixel_maxx;
|
|
|
|
|
geom->scaley = ti->cellpixy;
|
|
|
|
|
geom->scalex = ti->cellpixx;
|
|
|
|
|
}else{
|
|
|
|
|
geom->scaley = (*bset)->height;
|
|
|
|
|
geom->scalex = (*bset)->width;
|
|
|
|
|
}
|
|
|
|
|
geom->scaley = encoding_y_scale(ti, *bset);
|
|
|
|
|
geom->scalex = encoding_x_scale(ti, *bset);
|
|
|
|
|
// when n is NULL, we only report properties unrelated to the ncvisual,
|
|
|
|
|
// i.e. the cell-pixel geometry, max bitmap geometry, blitter, and scaling.
|
|
|
|
|
if(n == NULL){
|
|
|
|
@ -353,6 +238,59 @@ int ncvisual_geom_inner(const tinfo* ti, const ncvisual* n,
|
|
|
|
|
logerror("geometry too large %d > %d or %d > %d\n", geom->begy + geom->leny, n->pixy, geom->begx + geom->lenx, n->pixx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
// FIXME several unsafe uses of NULL nc within here!
|
|
|
|
|
if(vopts){
|
|
|
|
|
if(bset->geom == NCBLIT_PIXEL){
|
|
|
|
|
if(vopts->n){
|
|
|
|
|
if(vopts->n == notcurses_stdplane_const(nc)){
|
|
|
|
|
if(!(vopts->flags & NCVISUAL_OPTION_CHILDPLANE)){
|
|
|
|
|
logerror("Won't blit bitmaps to the standard plane\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(vopts->y && !(vopts->flags & (NCVISUAL_OPTION_VERALIGNED | NCVISUAL_OPTION_CHILDPLANE))){
|
|
|
|
|
logerror("Non-origin y placement %d for sprixel\n", vopts->y);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(vopts->x && !(vopts->flags & (NCVISUAL_OPTION_HORALIGNED | NCVISUAL_OPTION_CHILDPLANE))){
|
|
|
|
|
logerror("Non-origin x placement %d for sprixel\n", vopts->x);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
// FIXME clamp to sprixel limits
|
|
|
|
|
if(vopts->scaling == NCSCALE_NONE || vopts->scaling == NCSCALE_NONE_HIRES){
|
|
|
|
|
if(vopts->pxoffy >= nc->tcache.cellpixy){
|
|
|
|
|
logerror("pixel y-offset %d too tall for cell %d\n", vopts->pxoffy, nc->tcache.cellpixy);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
int rows = ((*leny + nc->tcache.cellpixy - 1) / nc->tcache.cellpixy)
|
|
|
|
|
+ !!vopts->pxoffy;
|
|
|
|
|
if(rows > ncplane_dim_y(vopts->n)){
|
|
|
|
|
logerror("sprixel too tall %d for plane %d\n",
|
|
|
|
|
*leny + vopts->pxoffy, ncplane_dim_y(vopts->n) * nc->tcache.cellpixy);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(vopts->pxoffx >= nc->tcache.cellpixx){
|
|
|
|
|
logerror("pixel x-offset %d too wide for cell %d\n", vopts->pxoffx, nc->tcache.cellpixx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
int cols = ((*lenx + nc->tcache.cellpixx - 1) / nc->tcache.cellpixx)
|
|
|
|
|
+ !!vopts->pxoffx;
|
|
|
|
|
if(cols > ncplane_dim_x(vopts->n)){
|
|
|
|
|
logerror("sprixel too wide %d for plane %d\n",
|
|
|
|
|
*lenx + vopts->pxoffx, ncplane_dim_x(vopts->n) * nc->tcache.cellpixx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}else{
|
|
|
|
|
if(vopts->pxoffx || vopts->pxoffy){
|
|
|
|
|
logerror("pixel offsets cannot be used with cell blitting\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|