mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
Further work on opacity optimizations (#1549)
* [bitmap] on move, clear old OPAQUE cells #1527 * update ncvisual_blitter_geom() documentation #1547 * replace some ncvisual_blitter_geom with NCVISUAL_OPTION_VERALIGNED * [normal] replace ncvisual_blitter_geom with NCVISUAL_OPTION_VERALIGNED * [intro] use ncvisual_blitter_geom() correctly #1547 * ncvisual_blitter_geom: only set *blitter on success
This commit is contained in:
parent
eaee89c99f
commit
8c6cd6a630
15
USAGE.md
15
USAGE.md
@ -3058,14 +3058,15 @@ it was built up:
|
||||
|
||||
```c
|
||||
// Get the size and ratio of ncvisual pixels to output cells along the y
|
||||
// ('toy') and x ('tox') axes. A ncvisual of '*y'X'*x' pixels will require
|
||||
// ('*y' * '*toy')X('*x' * '*tox') cells for full output. Returns non-zero
|
||||
// for an invalid 'blitter' in 'vopts'. Scaling is taken into account. The
|
||||
// blitter that will be used is returned in 'blitter'.
|
||||
// and x axes. The input size (in pixels) will be written to 'y' and 'x'.
|
||||
// The scaling will be written to 'scaley' and 'scalex'. With these:
|
||||
// rows = (y / scaley) + !!(y % scaley)
|
||||
// cols = (x / scalex) + !!(x % scalex)
|
||||
// Returns non-zero for an invalid 'vopts'. The blitter that will be used
|
||||
// is returned in '*blitter'.
|
||||
int ncvisual_blitter_geom(const struct notcurses* nc, const struct ncvisual* n,
|
||||
const struct ncvisual_options* vopts,
|
||||
int* y, int* x, int* toy, int* tox,
|
||||
ncblitter_e* blitter);
|
||||
const struct ncvisual_options* vopts, int* y, int* x,
|
||||
int* scaley, int* scalex, ncblitter_e* blitter);
|
||||
|
||||
// Rotate the visual 'rads' radians. Only M_PI/2 and -M_PI/2 are
|
||||
// supported at the moment, but this will change FIXME.
|
||||
|
@ -58,7 +58,7 @@ typedef int (*streamcb)(struct notcurses*, struct ncvisual*, void*);
|
||||
|
||||
**struct ncvisual* ncvisual_from_plane(struct ncplane* ***n***, ncblitter_e ***blit***, int ***begy***, int ***begx***, int ***leny***, int ***lenx***);**
|
||||
|
||||
**int ncvisual_geom(const struct notcurses* ***nc***, const struct ncvisual* ***n***, const struct ncvisual_options* ***vopts***, int* ***y***, int* ***x***, int* ***toy***, int* ***tox***);**
|
||||
**int ncvisual_blitter_geom(const struct notcurses* ***nc***, const struct ncvisual* ***n***, const struct ncvisual_options* ***vopts***, int* ***y***, int* ***x***, int* ***scaley***, int* ***scalex***, ncblitter_e* ***blitter***);**
|
||||
|
||||
**void ncvisual_destroy(struct ncvisual* ***ncv***);**
|
||||
|
||||
@ -143,6 +143,12 @@ geometry of same. **flags** is a bitfield over:
|
||||
|
||||
* **NCVISUAL_OPTION_NODEGRADE** If the specified blitter is not available, fail rather than degrading.
|
||||
* **NCVISUAL_OPTION_BLEND**: Render with **CELL_ALPHA_BLEND**.
|
||||
* **NCVISUAL_OPTION_HORALIGNED**: Interpret ***x*** as an **ncalign_e**.
|
||||
* **NCVISUAL_OPTION_VERALIGNED**: Interpret ***y*** as an **ncalign_e**.
|
||||
|
||||
**ncvisual_blitter_geom** allows the caller to determine any or all of the
|
||||
visual's pixel geometry, the blitter to be used, and that blitter's scaling
|
||||
in both dimensions. Any but the first argument may be **NULL**.
|
||||
|
||||
**ncplane_qrcode** draws an ISO/IEC 18004:2015 QR Code for the **len** bytes of
|
||||
**data** using **NCBLIT_2x1** (this is the only blitter that will work with QR
|
||||
@ -267,7 +273,7 @@ which the visual was rendered. If **opts->n** is provided, this will be
|
||||
**opts->n**. Otherwise, a plane will be created, perfectly sized for the
|
||||
visual and the specified blitter.
|
||||
|
||||
**ncvisual_geom** returns non-zero if the **blitter** is invalid.
|
||||
**ncvisual_blitter_geom** returns non-zero if the specified blitter is invalid.
|
||||
|
||||
**ncvisual_media_defblitter** returns the blitter selected by **NCBLIT_DEFAULT**
|
||||
in the specified configuration. If UTF8 is not enabled, this will always be
|
||||
|
@ -2696,21 +2696,22 @@ ncplane_rgba(const struct ncplane* n, ncblitter_e blit,
|
||||
}
|
||||
|
||||
// Get the size and ratio of ncvisual pixels to output cells along the y
|
||||
// ('toy') and x ('tox') axes. A ncvisual of '*y'X'*x' pixels will require
|
||||
// ('*y' * '*toy')X('*x' * '*tox') cells for full output. Returns non-zero
|
||||
// for an invalid 'vopts->blitter'. Scaling is taken into consideration.
|
||||
// The blitter that will be used is returned in '*blitter'.
|
||||
// and x axes. The input size (in pixels) will be written to 'y' and 'x'.
|
||||
// The scaling will be written to 'scaley' and 'scalex'. With these:
|
||||
// rows = (y / scaley) + !!(y % scaley)
|
||||
// cols = (x / scalex) + !!(x % scalex)
|
||||
// Returns non-zero for an invalid 'vopts'. The blitter that will be used
|
||||
// is returned in '*blitter'.
|
||||
API int ncvisual_blitter_geom(const struct notcurses* nc, const struct ncvisual* n,
|
||||
const struct ncvisual_options* vopts,
|
||||
int* y, int* x, int* toy, int* tox,
|
||||
ncblitter_e* blitter)
|
||||
const struct ncvisual_options* vopts, int* y, int* x,
|
||||
int* scaley, int* scalex, ncblitter_e* blitter)
|
||||
__attribute__ ((nonnull (1)));
|
||||
|
||||
__attribute__ ((deprecated)) static inline int
|
||||
ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n,
|
||||
const struct ncvisual_options* vopts,
|
||||
int* y, int* x, int* toy, int* tox){
|
||||
return ncvisual_blitter_geom(nc, n, vopts, y, x, toy, tox, NULL);
|
||||
int* y, int* x, int* scaley, int* scalex){
|
||||
return ncvisual_blitter_geom(nc, n, vopts, y, x, scaley, scalex, NULL);
|
||||
}
|
||||
|
||||
// Destroy an ncvisual. Rendered elements will not be disrupted, but the visual
|
||||
|
@ -36,15 +36,16 @@ zoom_map(struct notcurses* nc, const char* map, int* ret){
|
||||
if(ncv == NULL){
|
||||
return NULL;
|
||||
}
|
||||
int vheight, yscale;
|
||||
int vwidth, xscale;
|
||||
// true height and width of visual, and blitter scaling parameters
|
||||
int vheight, yscale, vwidth, xscale;
|
||||
// first we want to get the true size, so don't supply NCSSCALE_STRETCH yet,
|
||||
// but *do* explicitly supply NCBLIT_2x2 since we're not scaling.
|
||||
struct ncvisual_options vopts = {
|
||||
.y = 1,
|
||||
.blitter = NCBLIT_2x2,
|
||||
};
|
||||
if(ncvisual_blitter_geom(nc, ncv, &vopts, &vheight, &vwidth, &yscale, &xscale, NULL)){
|
||||
if(ncvisual_blitter_geom(nc, ncv, &vopts, &vheight, &vwidth,
|
||||
&yscale, &xscale, NULL)){
|
||||
ncvisual_destroy(ncv);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -69,14 +69,16 @@ orcashow(struct notcurses* nc, int dimy, int dimx){
|
||||
.blitter = NCBLIT_PIXEL,
|
||||
.flags = NCVISUAL_OPTION_NODEGRADE,
|
||||
};
|
||||
int odimy, odimx;
|
||||
ncvisual_blitter_geom(nc, ncv, &vopts, NULL, NULL, &odimy, &odimx, NULL);
|
||||
vopts.y = dimy - odimy - 1;
|
||||
vopts.x = dimx - odimx;
|
||||
if(odimx > dimx || odimy > dimy - 1){
|
||||
int odimy, odimx, scaley, scalex;
|
||||
ncvisual_blitter_geom(nc, ncv, &vopts, &odimy, &odimx, &scaley, &scalex, NULL);
|
||||
int rows = (odimy / scaley) + !!(odimy % scaley);
|
||||
int cols = (odimx / scalex) + !!(odimx % scalex);
|
||||
if(cols > dimx || rows > dimy - 1){
|
||||
ncvisual_destroy(ncv);
|
||||
return NULL;
|
||||
}
|
||||
vopts.y = dimy - rows - 1;
|
||||
vopts.x = dimx - cols;
|
||||
struct ncplane* n = ncvisual_render(nc, ncv, &vopts);
|
||||
ncvisual_destroy(ncv);
|
||||
return n;
|
||||
|
@ -110,11 +110,9 @@ rotate_visual(struct notcurses* nc, struct ncplane* n, int dy, int dx){
|
||||
r = -1;
|
||||
break;
|
||||
}
|
||||
int vy, vx, vyscale, vxscale;
|
||||
ncvisual_blitter_geom(nc, ncv, &vopts, &vy, &vx, &vyscale, &vxscale, NULL);
|
||||
vopts.x = NCALIGN_CENTER;
|
||||
vopts.y = (dimy - (vy / vyscale)) / 2;
|
||||
vopts.flags |= NCVISUAL_OPTION_HORALIGNED;
|
||||
vopts.y = NCALIGN_CENTER;
|
||||
vopts.flags |= NCVISUAL_OPTION_HORALIGNED | NCVISUAL_OPTION_VERALIGNED;
|
||||
struct ncplane* newn;
|
||||
if((newn = ncvisual_render(nc, ncv, &vopts)) == NULL){
|
||||
r = -1;
|
||||
|
@ -112,7 +112,7 @@ int xray_demo(struct notcurses* nc){
|
||||
| NCVISUAL_OPTION_ADDALPHA,
|
||||
};
|
||||
float dm = 0;
|
||||
// returns 0 if the selected blitter isn't available
|
||||
// returns non-zero if the selected blitter isn't available
|
||||
if(ncvisual_blitter_geom(nc, ncv, &vopts, NULL, NULL, NULL, NULL, NULL)){
|
||||
vopts.flags &= ~NCVISUAL_OPTION_NODEGRADE;
|
||||
dm = 0.5 * delaymultiplier;
|
||||
|
@ -547,7 +547,7 @@ ncdirect_render_visual(ncdirect* n, ncvisual* ncv, ncblitter_e blitfxn,
|
||||
bargs.u.pixel.colorregs = n->tcache.color_registers;
|
||||
int cols = lenx / bargs.u.pixel.celldimx + !!(lenx % bargs.u.pixel.celldimx);
|
||||
int rows = leny / bargs.u.pixel.celldimy + !!(leny % bargs.u.pixel.celldimy);
|
||||
if((bargs.u.pixel.spx = sprixel_alloc(ncdv, ncv, rows, cols)) == NULL){
|
||||
if((bargs.u.pixel.spx = sprixel_alloc(ncdv, ncv, rows, cols, 0, 0)) == NULL){
|
||||
free_plane(ncdv);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -649,7 +649,8 @@ int ncplane_qrcode(ncplane* n, int* ymax, int* xmax, const void* data, size_t le
|
||||
if(ncvisual_render(ncplane_notcurses(n), ncv, &vopts) == n){
|
||||
ret = square;
|
||||
}
|
||||
ncvisual_blitter_geom(ncplane_notcurses(n), ncv, &vopts, NULL, NULL, &yscale, &xscale, NULL);
|
||||
ncvisual_blitter_geom(ncplane_notcurses(n), ncv, &vopts, NULL, NULL,
|
||||
&yscale, &xscale, NULL);
|
||||
}
|
||||
ncvisual_destroy(ncv);
|
||||
}
|
||||
|
@ -111,7 +111,8 @@ typedef enum {
|
||||
//
|
||||
// when a sprixel is removed from the rendering pile, in Sixel all cells it
|
||||
// covered must be marked damaged, so that they are rendered, obliterating
|
||||
// the bitmap. in Kitty the bitmap can simply be deleted.
|
||||
// the bitmap. in Kitty the bitmap can simply be deleted, except for those
|
||||
// cells which were SPRIXCELL_OPAQUE (they must be damaged).
|
||||
//
|
||||
// when a sprixel is moved, its TAM must be updated. OPAQUE, MIXED, and
|
||||
// TRANSPARENT cells retain their entries. ANNIHILATED cells remain
|
||||
@ -922,7 +923,8 @@ int sprite_draw(const notcurses* n, const ncpile *p, sprixel* s, FILE* out);
|
||||
int kitty_draw(const notcurses* n, const ncpile *p, sprixel* s, FILE* out);
|
||||
int sixel_draw(const notcurses* n, const ncpile *p, sprixel* s, FILE* out);
|
||||
// dimy and dimx are cell geometry, not pixel. takes ownership of s on success.
|
||||
sprixel* sprixel_alloc(ncplane* n, struct ncvisual* ncv, int dimy, int dimx);
|
||||
sprixel* sprixel_alloc(ncplane* n, struct ncvisual* ncv, int dimy, int dimx,
|
||||
int placey, int placex);
|
||||
sprixel* sprixel_recycle(ncplane* n, struct ncvisual* ncv);
|
||||
int sprixel_load(sprixel* spx, char* s, int bytes, int placey, int placex,
|
||||
int pixy, int pixx, int parse_start);
|
||||
@ -945,14 +947,18 @@ static inline bool sprixel_kitty_p(const tinfo* t){
|
||||
}
|
||||
|
||||
// get the TAM entry for these (absolute) coordinates
|
||||
static inline sprixcell_e sprixel_state(sprixel* s, int y, int x){
|
||||
static inline sprixcell_e
|
||||
sprixel_state(sprixel* s, int y, int x){
|
||||
int localy = y - s->n->absy;
|
||||
int localx = x - s->n->absx;
|
||||
assert(localy >= 0);
|
||||
assert(localy < s->dimy);
|
||||
assert(localx >= 0);
|
||||
assert(localx < s->dimx);
|
||||
//fprintf(stderr, "TAM %d at %d/%d (%d/%d)\n", s->n->tacache[localy * s->dimx + localx], localy, localx, y, x);
|
||||
return s->n->tacache[localy * s->dimx + localx];
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
pool_release(egcpool* pool, nccell* c){
|
||||
if(cell_extended_p(c)){
|
||||
|
@ -209,7 +209,7 @@ int sprite_kitty_cell_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell
|
||||
if(thisrow == 0){
|
||||
//fprintf(stderr, "CLEARED ROW, TARGY: %d\n", targy - 1);
|
||||
if(--targy == 0){
|
||||
s->invalidated = SPRIXEL_INVALIDATED;
|
||||
//s->invalidated = SPRIXEL_INVALIDATED;
|
||||
return 0;
|
||||
}
|
||||
thisrow = targx;
|
||||
@ -367,13 +367,27 @@ int kitty_blit(ncplane* n, int linesize, const void* data,
|
||||
return 1;
|
||||
}
|
||||
|
||||
// removes the kitty bitmap graphic identified by s->id
|
||||
// removes the kitty bitmap graphic identified by s->id, and damages those
|
||||
// cells which were SPRIXCEL_OPAQUE
|
||||
int sprite_kitty_annihilate(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s){
|
||||
(void)p;
|
||||
(void)nc;
|
||||
if(fprintf(out, "\e_Ga=d,d=i,i=%d\e\\", s->id) < 0){
|
||||
return 0;
|
||||
}
|
||||
//fprintf(stderr, "MOVED FROM: %d/%d\n", s->movedfromy, s->movedfromx);
|
||||
for(int yy = s->movedfromy ; yy < s->movedfromy + s->dimy && yy < p->dimy ; ++yy){
|
||||
for(int xx = s->movedfromx ; xx < s->movedfromx + s->dimx && xx < p->dimx ; ++xx){
|
||||
struct crender *r = &p->crender[yy * p->dimx + xx];
|
||||
if(s->n){
|
||||
//fprintf(stderr, "CHECKING %d/%d\n", yy - s->movedfromy, xx - s->movedfromx);
|
||||
if(s->n->tacache[(yy - s->movedfromy) * s->dimx + (xx - s->movedfromx)] == SPRIXCELL_OPAQUE){
|
||||
//fprintf(stderr, "DAMAGING %d/%d!\n", yy, xx);
|
||||
r->s.damaged = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -866,7 +866,10 @@ clean_sprixels(notcurses* nc, const ncpile* p, FILE* out){
|
||||
ret = -1;
|
||||
}
|
||||
}else if(s->invalidated == SPRIXEL_MOVED || s->invalidated == SPRIXEL_INVALIDATED){
|
||||
// FIXME clean this up, don't use sprite_draw, don't always move, etc.
|
||||
// FIXME clean this up, don't use sprite_draw, etc.
|
||||
if(s->invalidated == SPRIXEL_MOVED){
|
||||
sprite_destroy(nc, p, out, s);
|
||||
}
|
||||
int y, x;
|
||||
ncplane_yx(s->n, &y, &x);
|
||||
y += s->y;
|
||||
|
@ -527,7 +527,10 @@ int sixel_draw(const notcurses* n, const ncpile* p, sprixel* s, FILE* out){
|
||||
if(s->invalidated == SPRIXEL_MOVED){
|
||||
for(int yy = s->movedfromy ; yy < s->movedfromy + s->dimy ; ++yy){
|
||||
for(int xx = s->movedfromx ; xx < s->movedfromx + s->dimx ; ++xx){
|
||||
p->crender[yy * p->dimx + xx].s.damaged = 1;
|
||||
//fprintf(stderr, "DAMAGING DUE TO MOVE: %d/%d (%d)\n", yy, xx, yy * p->dimx + xx);
|
||||
if(xx < p->dimx && yy < p->dimy){
|
||||
p->crender[yy * p->dimx + xx].s.damaged = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
s->invalidated = SPRIXEL_INVALIDATED;
|
||||
|
@ -24,8 +24,10 @@ sprixel* sprixel_recycle(ncplane* n, ncvisual* ncv){
|
||||
assert(hides);
|
||||
int dimy = hides->dimy;
|
||||
int dimx = hides->dimx;
|
||||
int y = hides->y;
|
||||
int x = hides->x;
|
||||
sprixel_hide(hides);
|
||||
return sprixel_alloc(n, ncv, dimy, dimx);
|
||||
return sprixel_alloc(n, ncv, dimy, dimx, y, x);
|
||||
}
|
||||
return n->sprite;
|
||||
}
|
||||
@ -35,6 +37,7 @@ sprixel* sprixel_recycle(ncplane* n, ncvisual* ncv){
|
||||
void sprixel_movefrom(sprixel* s, int y, int x){
|
||||
if(s->invalidated != SPRIXEL_HIDE){
|
||||
if(s->invalidated != SPRIXEL_MOVED){
|
||||
//fprintf(stderr, "SETTING TO MOVE: %d/%d was: %d\n", y, x, s->invalidated);
|
||||
s->invalidated = SPRIXEL_MOVED;
|
||||
s->movedfromy = y;
|
||||
s->movedfromx = x;
|
||||
@ -83,7 +86,8 @@ sprixel* sprixel_by_id(const notcurses* nc, uint32_t id){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprixel* sprixel_alloc(ncplane* n, ncvisual* ncv, int dimy, int dimx){
|
||||
sprixel* sprixel_alloc(ncplane* n, ncvisual* ncv, int dimy, int dimx,
|
||||
int placey, int placex){
|
||||
sprixel* ret = malloc(sizeof(sprixel));
|
||||
if(ret){
|
||||
memset(ret, 0, sizeof(*ret));
|
||||
@ -91,6 +95,8 @@ sprixel* sprixel_alloc(ncplane* n, ncvisual* ncv, int dimy, int dimx){
|
||||
ret->ncv = ncv;
|
||||
ret->dimy = dimy;
|
||||
ret->dimx = dimx;
|
||||
ret->y = placey;
|
||||
ret->x = placex;
|
||||
ret->id = ++sprixelid_nonce;
|
||||
//fprintf(stderr, "LOOKING AT %p (p->n = %p)\n", ret, ret->n);
|
||||
if(ncplane_pile(ret->n)){
|
||||
|
@ -15,13 +15,17 @@ struct ncplane;
|
||||
struct sprixel;
|
||||
struct ncvisual_details;
|
||||
|
||||
// an ncvisual is essentially just an unpacked RGBA bitmap, created by
|
||||
// reading media from disk, supplying RGBA pixels directly in memory, or
|
||||
// synthesizing pixels from a plane.
|
||||
typedef struct ncvisual {
|
||||
struct ncvisual_details* details;// implementation-specific details
|
||||
uint32_t* data; // (scaled) RGBA image data, rowstride bytes per row
|
||||
int cols, rows;
|
||||
int cols, rows; // pixel geometry, *not* cell geometry
|
||||
// lines are sometimes padded. this many true bytes per row in data.
|
||||
int rowstride;
|
||||
bool owndata; // we own data iff owndata == true
|
||||
// FIXME this cannot live here! it breaks wiping. associate with plane.
|
||||
struct sprixel* spx; // non-NULL if this is NCBLIT_PIXEL
|
||||
} ncvisual;
|
||||
|
||||
|
@ -75,11 +75,24 @@ 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'.
|
||||
// FIXME we ought also do the output calculations here (how many rows x cols,
|
||||
// given the input plane vopts->n and scaling vopts->scaling)--but do not
|
||||
// perform any actual scaling, nor create any planes!
|
||||
static int
|
||||
ncvisual_blitset_geom(const notcurses* nc, const ncvisual* n,
|
||||
const struct ncvisual_options* vopts,
|
||||
int* y, int* x, int* toy, int* tox,
|
||||
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_ADDALPHA << 1u)){
|
||||
logwarn(nc, "Warning: unknown ncvisual options %016jx\n", (uintmax_t)vopts->flags);
|
||||
}
|
||||
@ -140,8 +153,10 @@ ncvisual_blitset_geom(const notcurses* nc, const ncvisual* n,
|
||||
*y = n->rows;
|
||||
*x = n->cols;
|
||||
}else{
|
||||
int rows = vopts->n ? ncplane_dim_y(vopts->n) : ncplane_dim_y(nc->stdplane);
|
||||
int cols = vopts->n ? ncplane_dim_x(vopts->n) : ncplane_dim_x(nc->stdplane);
|
||||
int rows = (vopts && vopts->n) ? ncplane_dim_y(vopts->n) :
|
||||
ncplane_dim_y(nc->stdplane);
|
||||
int cols = (vopts && vopts->n) ? ncplane_dim_x(vopts->n) :
|
||||
ncplane_dim_x(nc->stdplane);
|
||||
*y = rows * encoding_y_scale(&nc->tcache, bset);
|
||||
*x = cols * encoding_x_scale(&nc->tcache, bset);
|
||||
}
|
||||
@ -149,11 +164,11 @@ ncvisual_blitset_geom(const notcurses* nc, const ncvisual* n,
|
||||
scale_visual(n, y, x);
|
||||
}
|
||||
}
|
||||
if(toy){
|
||||
*toy = encoding_y_scale(&nc->tcache, bset);
|
||||
if(scaley){
|
||||
*scaley = encoding_y_scale(&nc->tcache, bset);
|
||||
}
|
||||
if(tox){
|
||||
*tox = encoding_x_scale(&nc->tcache, bset);
|
||||
if(scalex){
|
||||
*scalex = encoding_x_scale(&nc->tcache, bset);
|
||||
}
|
||||
if(vopts && vopts->flags & NCVISUAL_OPTION_HORALIGNED){
|
||||
if(vopts->x < NCALIGN_UNALIGNED || vopts->x > NCALIGN_RIGHT){
|
||||
@ -166,12 +181,12 @@ ncvisual_blitset_geom(const notcurses* nc, const ncvisual* n,
|
||||
|
||||
int ncvisual_blitter_geom(const notcurses* nc, const ncvisual* n,
|
||||
const struct ncvisual_options* vopts,
|
||||
int* y, int* x, int* toy, int* tox,
|
||||
int* y, int* x, int* scaley, int* scalex,
|
||||
ncblitter_e* blitter){
|
||||
const struct blitset* bset;
|
||||
int leny, lenx;
|
||||
int ret = ncvisual_blitset_geom(nc, n, vopts, y, x, toy, tox, &leny, &lenx, &bset);
|
||||
if(blitter){
|
||||
int ret = ncvisual_blitset_geom(nc, n, vopts, y, x, scaley, scalex,
|
||||
NULL, NULL, &bset);
|
||||
if(ret == 0 && blitter){
|
||||
*blitter = bset->geom;
|
||||
}
|
||||
return ret;
|
||||
@ -694,7 +709,7 @@ ncplane* ncvisual_render_pixels(notcurses* nc, ncvisual* ncv, const struct blits
|
||||
if(n->sprite){
|
||||
sprixel_hide(n->sprite);
|
||||
}
|
||||
if((ncv->spx = sprixel_alloc(n, ncv, rows, cols)) == NULL){
|
||||
if((ncv->spx = sprixel_alloc(n, ncv, rows, cols, placey, placex)) == NULL){
|
||||
goto err;
|
||||
}
|
||||
}else{
|
||||
@ -722,8 +737,9 @@ err:
|
||||
|
||||
ncplane* ncvisual_render(notcurses* nc, ncvisual* ncv, const struct ncvisual_options* vopts){
|
||||
const struct blitset* bset;
|
||||
int srcy, srcx, toy, tox, leny, lenx;
|
||||
if(ncvisual_blitset_geom(nc, ncv, vopts, &srcy, &srcx, &toy, &tox, &leny, &lenx, &bset) < 0){
|
||||
int leny, lenx;
|
||||
if(ncvisual_blitset_geom(nc, ncv, vopts, NULL, NULL, NULL, NULL,
|
||||
&leny, &lenx, &bset) < 0){
|
||||
// ncvisual_blitset_geom() emits its own diagnostics, no need for an error here
|
||||
return NULL;
|
||||
}
|
||||
|
@ -402,7 +402,8 @@ int ffmpeg_stream(notcurses* nc, ncvisual* ncv, float timescale,
|
||||
}
|
||||
// decay the blitter explicitly, so that the callback knows the blitter it
|
||||
// was actually rendered with
|
||||
ncvisual_blitter_geom(nc, ncv, &activevopts, NULL, NULL, NULL, NULL, &activevopts.blitter);
|
||||
ncvisual_blitter_geom(nc, ncv, &activevopts, NULL, NULL, NULL, NULL,
|
||||
&activevopts.blitter);
|
||||
if((newn = ncvisual_render(nc, ncv, &activevopts)) == NULL){
|
||||
if(activevopts.n != vopts->n){
|
||||
ncplane_destroy(activevopts.n);
|
||||
|
@ -64,15 +64,14 @@ rotate_grad(struct notcurses* nc){
|
||||
notcurses_render(nc);
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
|
||||
vopts.n = NULL;
|
||||
vopts.x = NCALIGN_CENTER;
|
||||
vopts.y = NCALIGN_CENTER;
|
||||
vopts.flags |= NCVISUAL_OPTION_HORALIGNED | NCVISUAL_OPTION_VERALIGNED;
|
||||
ncplane_erase(n);
|
||||
for(int i = 0 ; i < 4 ; ++i){
|
||||
int vy, vx, scaley, scalex;
|
||||
if(ncvisual_rotate(v, M_PI / 2)){
|
||||
return -1;
|
||||
}
|
||||
ncvisual_blitter_geom(nc, v, &vopts, &vy, &vx, &scaley, &scalex, NULL);
|
||||
vopts.x = (dimx - (vx / scalex)) / 2;
|
||||
vopts.y = (dimy - (vy / scaley)) / 2;
|
||||
struct ncplane* newn = ncvisual_render(nc, v, &vopts);
|
||||
if(newn == NULL){
|
||||
return -1;
|
||||
@ -83,10 +82,6 @@ rotate_grad(struct notcurses* nc){
|
||||
}
|
||||
|
||||
for(int i = 0 ; i < 8 ; ++i){
|
||||
int vy, vx, scaley, scalex;
|
||||
ncvisual_blitter_geom(nc, v, &vopts, &vy, &vx, &scaley, &scalex, NULL);
|
||||
vopts.x = (dimx - (vx / scalex)) / 2;
|
||||
vopts.y = (dimy - (vy / scaley)) / 2;
|
||||
if(ncvisual_rotate(v, M_PI / 4)){
|
||||
return -1;
|
||||
}
|
||||
|
@ -24,14 +24,12 @@ int main(int argc, char** argv){
|
||||
struct ncvisual_options vopts{};
|
||||
bool failed = false;
|
||||
int dimy, dimx;
|
||||
int scaley, scalex;
|
||||
int top = 0;
|
||||
int bot;
|
||||
auto ncv = ncvisual_from_file(file);
|
||||
if(!ncv){
|
||||
goto err;
|
||||
}
|
||||
ncvisual_blitter_geom(nc, ncv, &vopts, nullptr, nullptr, &scaley, &scalex, nullptr);
|
||||
vopts.scaling = NCSCALE_STRETCH;
|
||||
struct ncplane* ntarg;
|
||||
if((ntarg = ncvisual_render(nc, ncv, &vopts)) == nullptr){
|
||||
|
@ -62,6 +62,9 @@ int main(int argc, char** argv){
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
|
||||
|
||||
vopts.n = NULL;
|
||||
vopts.x = NCALIGN_CENTER;
|
||||
vopts.y = NCALIGN_CENTER;
|
||||
vopts.flags |= NCVISUAL_OPTION_HORALIGNED | NCVISUAL_OPTION_VERALIGNED;
|
||||
ncplane_destroy(n);
|
||||
for(double i = 0 ; i < 256 ; ++i){
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
|
||||
@ -69,10 +72,6 @@ int main(int argc, char** argv){
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
int vy, vx;
|
||||
ncvisual_blitter_geom(nc, ncv, &vopts, &vy, &vx, &scaley, &scalex, nullptr);
|
||||
vopts.x = (dimx - (vx / scalex)) / 2;
|
||||
vopts.y = (dimy - (vy / scaley)) / 2;
|
||||
struct ncplane* newn;
|
||||
if((newn = ncvisual_render(nc, ncv, &vopts)) == nullptr){
|
||||
failed = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user