[core] introduce ncvisual_geom(), replacing ncvisual_blitter_geom() #1684

pull/2320/head
nick black 3 years ago committed by nick black
parent c906d2cf8a
commit a0b34f7062

@ -12,6 +12,12 @@ rearrangements of Notcurses.
deprecated functionality, ABI3 ought require small changes, if any. deprecated functionality, ABI3 ought require small changes, if any.
* 2.4.9 (not yet released) * 2.4.9 (not yet released)
* `ncvisual_geom()` has been introduced, using the `ncvgeom` struct
introduced for direct mode. This allows complete statement of geometry
for an `ncvisual`. It replaces `ncvisual_blitter_geom()`, which has been
deprecated, and will be removed in ABI3. It furthermore exposes some of
the information previously available only from `ncplane_pixelgeom()`,
though that function continues to be supported.
* On transition between `ncplane`s (on terminals implementing complex wide * On transition between `ncplane`s (on terminals implementing complex wide
glyphs), Notcurses now always issues an `hpa` sequence to force horizontal glyphs), Notcurses now always issues an `hpa` sequence to force horizontal
positioning. This fixes a number of longstanding bugs in e.g. the positioning. This fixes a number of longstanding bugs in e.g. the

@ -3299,17 +3299,38 @@ Various transformations can be applied to an `ncvisual`, regardless of how
it was built up: it was built up:
```c ```c
// Get the size and ratio of ncvisual pixels to output cells along the y // describes all geometries of an ncvisual: those which are inherent, and those
// and x axes. The input size (in pixels) will be written to 'y' and 'x'. // dependent upon a given rendering regime. pixy and pixx are the true internal
// The scaling will be written to 'scaley' and 'scalex'. With these: // pixel geometry, taken directly from the load (and updated by
// rows = (y / scaley) + !!(y % scaley) or (y + scaley - 1) / scaley // ncvisual_resize()). cdimy/cdimx are the cell-pixel geometry *at the time
// cols = (x / scalex) + !!(x % scalex) or (x + scalex - 1) / scalex // of this call* (it can change with a font change, in which case all values
// Returns non-zero for an invalid 'vopts'. The blitter that will be used // other than pixy/pixx are invalidated). rpixy/rpixx are the pixel geometry as
// is returned in '*blitter'. // handed to the blitter, following any scaling. scaley/scalex are the number
// These results are invalidated upon a terminal resize. // of input pixels drawn to a single cell; when using NCBLIT_PIXEL, they are
int ncvisual_blitter_geom(const struct notcurses* nc, const struct ncvisual* n, // equivalent to cdimy/cdimx. rcelly/rcellx are the cell geometry as written by
const struct ncvisual_options* vopts, int* y, int* x, // the blitter, following any padding (there is padding whenever rpix{y, x} is
int* scaley, int* scalex, ncblitter_e* blitter); // not evenly divided by scale{y, x}, and also sometimes for Sixel).
// maxpixely/maxpixelx are defined only when NCBLIT_PIXEL is used, and specify
// the largest bitmap that the terminal is willing to accept. blitter is the
// blitter which will be used, a function of the requested blitter and the
// blitters actually supported by this environment. if no ncvisual was
// supplied, only cdimy/cdimx are filled in.
typedef struct ncvgeom {
int pixy, pixx; // true pixel geometry of ncvisual data
int cdimy, cdimx; // terminal cell geometry when this was calculated
int rpixy, rpixx; // rendered pixel geometry (per visual_options)
int rcelly, rcellx; // rendered cell geometry (per visual_options)
int scaley, scalex; // pixels per filled cell (scale == c for bitmaps)
int maxpixely, maxpixelx; // only defined for NCBLIT_PIXEL
ncblitter_e blitter;// blitter that will be used
} ncvgeom;
// all-purpose ncvisual geometry solver. one or both of 'nc' and 'n' must be
// non-NULL. if 'nc' is NULL, only pixy/pixx will be filled in, with the true
// pixel geometry of 'n'. if 'n' is NULL, only cdimy/cdimx, blitter, and (if
// applicable) maxpixely/maxpixelx are filled in.
int ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n,
const struct ncvisual_options* vopts, ncvgeom* geom);
// Scale the visual to 'rows' X 'columns' pixels, using the best scheme // Scale the visual to 'rows' X 'columns' pixels, using the best scheme
// available. This is a lossy transformation, unless the size is unchanged. // available. This is a lossy transformation, unless the size is unchanged.

@ -51,6 +51,16 @@ struct ncvisual_options {
}; };
typedef int (*streamcb)(struct notcurses*, struct ncvisual*, void*); typedef int (*streamcb)(struct notcurses*, struct ncvisual*, void*);
typedef struct ncvgeom {
int pixy, pixx; // true pixel geometry of ncvisual data
int cdimy, cdimx; // terminal cell geometry when this was calculated
int rpixy, rpixx; // rendered pixel geometry (per visual_options)
int rcelly, rcellx; // rendered cell geometry (per visual_options)
int scaley, scalex; // pixels per filled cell (scale == c for bitmaps)
int maxpixely, maxpixelx; // only defined for NCBLIT_PIXEL
ncblitter_e blitter;// blitter that will be used
} ncvgeom;
``` ```
**struct ncvisual* ncvisual_from_file(const char* ***file***);** **struct ncvisual* ncvisual_from_file(const char* ***file***);**
@ -67,7 +77,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***);** **struct ncvisual* ncvisual_from_plane(struct ncplane* ***n***, ncblitter_e ***blit***, int ***begy***, int ***begx***, int ***leny***, int ***lenx***);**
**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***);** **int ncvisual_geom(const struct notcurses* ***nc***, const struct ncvisual* ***n***, const struct ncvisual_options* ***vopts***, ncvgeom* ***geom***);**
**void ncvisual_destroy(struct ncvisual* ***ncv***);** **void ncvisual_destroy(struct ncvisual* ***ncv***);**
@ -177,9 +187,14 @@ geometry of same. ***flags*** is a bitfield over:
as a transparent color. as a transparent color.
* **NCVISUAL_OPTION_CHILDPLANE**: Make a new plane, as a child of ***n***. * **NCVISUAL_OPTION_CHILDPLANE**: Make a new plane, as a child of ***n***.
**ncvisual_blitter_geom** allows the caller to determine any or all of the **ncvisual_geom** allows the caller to determine any or all of the visual's
visual's pixel geometry, the blitter to be used, and that blitter's scaling pixel geometry, the blitter to be used, and that blitter's scaling in both
in both dimensions. Any but the first argument may be **NULL**. dimensions. Any but the final argument may be **NULL**, though at least one
of ***nc*** and ***n*** must be non-**NULL**. If ***nc*** is **NULL**,
only properties intrinsic to the visual are returned (i.e. its original
pixel geometry). If ***n*** is **NULL**, only properties independent of the
visual are returned (i.e. cell-pixel geometry and maximum bitmap geometry).
If both are supplied, all fields of the **ncvgeom** structure are filled in.
**ncplane_qrcode** draws an ISO/IEC 18004:2015 QR Code for the **len** bytes of **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 **data** using **NCBLIT_2x1** (this is the only blitter that will work with QR
@ -317,7 +332,8 @@ 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 **opts->n**. Otherwise, a plane will be created, perfectly sized for the
visual and the specified blitter. visual and the specified blitter.
**ncvisual_blitter_geom** returns non-zero if the specified blitter is invalid. **ncvisual_geom** returns non-zero if the specified configuration is invalid,
or if both ***nc*** and ***n*** are **NULL**.
**ncvisual_media_defblitter** returns the blitter selected by **NCBLIT_DEFAULT** **ncvisual_media_defblitter** returns the blitter selected by **NCBLIT_DEFAULT**
in the specified configuration. If UTF8 is not enabled, this will always be in the specified configuration. If UTF8 is not enabled, this will always be
@ -358,7 +374,7 @@ When using non-interpolative blitting together with scaling, unless your goal
includes minimizing the total area required, lower-resolution blitters will includes minimizing the total area required, lower-resolution blitters will
generally look just as good as higher resolution blitters, and be faster. generally look just as good as higher resolution blitters, and be faster.
The results of **ncvisual_blitter_geom** are invalidated by a terminal resize. The results of **ncvisual_geom** are invalidated by a terminal resize.
# BUGS # BUGS

@ -96,9 +96,9 @@ namespace ncpp
return error_guard<int> (ncvisual_polyfill_yx (visual, y, x, rgba), -1); return error_guard<int> (ncvisual_polyfill_yx (visual, y, x, rgba), -1);
} }
bool geom (const struct ncvisual_options *vopts, int *y, int *x, int *toy, int *tox, ncblitter_e* blitter) const NOEXCEPT_MAYBE bool geom (const struct ncvisual_options *vopts, ncvgeom* geom) const NOEXCEPT_MAYBE
{ {
return error_guard (ncvisual_blitter_geom (get_notcurses (), visual, vopts, y, x, toy, tox, blitter), -1); return error_guard (ncvisual_geom (get_notcurses (), visual, vopts, geom), -1);
} }
bool at (int y, int x, uint32_t* pixel) const bool at (int y, int x, uint32_t* pixel) const

@ -2895,13 +2895,14 @@ struct ncvisual_options {
// maxpixely/maxpixelx are defined only when NCBLIT_PIXEL is used, and specify // maxpixely/maxpixelx are defined only when NCBLIT_PIXEL is used, and specify
// the largest bitmap that the terminal is willing to accept. blitter is the // the largest bitmap that the terminal is willing to accept. blitter is the
// blitter which will be used, a function of the requested blitter and the // blitter which will be used, a function of the requested blitter and the
// blitters actually supported by this environment. // blitters actually supported by this environment. if no ncvisual was
// supplied, only cdimy/cdimx are filled in.
typedef struct ncvgeom { typedef struct ncvgeom {
int pixy, pixx; // true pixel geometry of ncvisual data int pixy, pixx; // true pixel geometry of ncvisual data
int cdimy, cdimx; // terminal cell geometry when this was calculated int cdimy, cdimx; // terminal cell geometry when this was calculated
int rpixy, rpixx; // rendered pixel geometry int rpixy, rpixx; // rendered pixel geometry (per visual_options)
int rcelly, rcellx; // rendered cell geometry int rcelly, rcellx; // rendered cell geometry (per visual_options)
int scaley, scalex; // pixels per filled cell int scaley, scalex; // pixels per filled cell (scale == c for bitmaps)
int maxpixely, maxpixelx; // only defined for NCBLIT_PIXEL int maxpixely, maxpixelx; // only defined for NCBLIT_PIXEL
ncblitter_e blitter;// blitter that will be used ncblitter_e blitter;// blitter that will be used
} ncvgeom; } ncvgeom;
@ -2916,7 +2917,15 @@ typedef struct ncvgeom {
API int ncvisual_blitter_geom(const struct notcurses* nc, const struct ncvisual* n, API int ncvisual_blitter_geom(const struct notcurses* nc, const struct ncvisual* n,
const struct ncvisual_options* vopts, int* y, int* x, const struct ncvisual_options* vopts, int* y, int* x,
int* scaley, int* scalex, ncblitter_e* blitter) int* scaley, int* scalex, ncblitter_e* blitter)
__attribute__ ((nonnull (1))); __attribute__ ((nonnull (1))) __attribute__ ((deprecated));
// all-purpose ncvisual geometry solver. one or both of 'nc' and 'n' must be
// non-NULL. if 'nc' is NULL, only pixy/pixx will be filled in, with the true
// pixel geometry of 'n'. if 'n' is NULL, only cdimy/cdimx, blitter, and (if
// applicable) maxpixely/maxpixelx are filled in.
API int ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n,
const struct ncvisual_options* vopts, ncvgeom* geom)
__attribute__ ((nonnull (4)));
// Destroy an ncvisual. Rendered elements will not be disrupted, but the visual // Destroy an ncvisual. Rendered elements will not be disrupted, but the visual
// can be neither decoded nor rendered any further. // can be neither decoded nor rendered any further.

@ -36,8 +36,6 @@ zoom_map(struct notcurses* nc, const char* map, int* ret){
if(ncv == NULL){ if(ncv == NULL){
return NULL; return NULL;
} }
// 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, // 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. // but *do* explicitly supply NCBLIT_2x2 since we're not scaling.
struct ncvisual_options vopts = { struct ncvisual_options vopts = {
@ -45,11 +43,16 @@ zoom_map(struct notcurses* nc, const char* map, int* ret){
.blitter = NCBLIT_2x2, .blitter = NCBLIT_2x2,
.flags = NCVISUAL_OPTION_NOINTERPOLATE, .flags = NCVISUAL_OPTION_NOINTERPOLATE,
}; };
if(ncvisual_blitter_geom(nc, ncv, &vopts, &vheight, &vwidth, ncvgeom geom;
&yscale, &xscale, NULL)){ if(ncvisual_geom(nc, ncv, &vopts, &geom)){
ncvisual_destroy(ncv); ncvisual_destroy(ncv);
return NULL; return NULL;
} }
// true height and width of visual, and blitter scaling parameters
int vheight = geom.pixy;
int vwidth = geom.pixx;
int yscale = geom.scaley;
int xscale = geom.scalex;
//fprintf(stderr, "VHEIGHT: %d VWIDTH: %d scale: %d/%d\n", vheight, vwidth, yscale, xscale); //fprintf(stderr, "VHEIGHT: %d VWIDTH: %d scale: %d/%d\n", vheight, vwidth, yscale, xscale);
// we start at the lower left corner of the outzoomed map // we start at the lower left corner of the outzoomed map
int placey, placex; // dimensions of true display int placey, placex; // dimensions of true display

@ -78,20 +78,11 @@ orcashow(struct notcurses* nc, int dimy, int dimx){
.blitter = NCBLIT_PIXEL, .blitter = NCBLIT_PIXEL,
.scaling = NCSCALE_STRETCH, .scaling = NCSCALE_STRETCH,
}; };
int cellpxy, cellpxx; ncvgeom geom;
ncplane_pixelgeom(notcurses_stdplane_const(nc), NULL, NULL, ncvisual_geom(nc, ncv, &vopts, &geom);
&cellpxy, &cellpxx, NULL, NULL);
int odimy, odimx, scaley, scalex;
ncvisual_blitter_geom(nc, ncv, &vopts, &odimy, &odimx, &scaley, &scalex, NULL);
// even if we can't do pixel output, we want her the same size as if weu
// *could* do pixel output. if we have no idea as to the geom, use scale.
if(cellpxy == 0){
cellpxy = scaley;
cellpxx = scalex;
}
struct ncplane_options nopts = { struct ncplane_options nopts = {
.rows = (odimy / cellpxy) + !!(odimy % cellpxy), .rows = geom.rcelly,
.cols = (odimx / cellpxx) + !!(odimx % cellpxx), .cols = geom.rcellx,
.name = "orca", .name = "orca",
}; };
if(nopts.cols > dimx - 1){ if(nopts.cols > dimx - 1){

@ -36,18 +36,18 @@ visualize(struct notcurses* nc, struct ncvisual* ncv){
| NCVISUAL_OPTION_VERALIGNED | NCVISUAL_OPTION_VERALIGNED
| NCVISUAL_OPTION_CHILDPLANE, | NCVISUAL_OPTION_CHILDPLANE,
}; };
int scalex, scaley, truey, truex;
vopts.x = NCALIGN_CENTER; vopts.x = NCALIGN_CENTER;
vopts.y = NCALIGN_CENTER; vopts.y = NCALIGN_CENTER;
ncplane_erase(stdn); // to clear out old text ncplane_erase(stdn); // to clear out old text
struct ncplane* n = NULL; struct ncplane* n = NULL;
if(ncvisual_blitter_geom(nc, ncv, &vopts, &truey, &truex, &scaley, &scalex, NULL) == 0){ ncvgeom geom;
if(ncvisual_geom(nc, ncv, &vopts, &geom) == 0){
if( (n = ncvisual_blit(nc, ncv, &vopts)) ){ if( (n = ncvisual_blit(nc, ncv, &vopts)) ){
ncplane_move_below(n, stdn); ncplane_move_below(n, stdn);
ncplane_printf_aligned(stdn, ncplane_dim_y(stdn) / 2 - 1, NCALIGN_CENTER, ncplane_printf_aligned(stdn, ncplane_dim_y(stdn) / 2 - 1, NCALIGN_CENTER,
"%03dx%03d", truex, truey); "%03dx%03d", geom.pixx, geom.pixy);
ncplane_printf_aligned(stdn, ncplane_dim_y(stdn) / 2 + 1, NCALIGN_CENTER, ncplane_printf_aligned(stdn, ncplane_dim_y(stdn) / 2 + 1, NCALIGN_CENTER,
"%d:%d pixels -> cell", scalex, scaley); "%d:%d pixels -> cell", geom.scalex, geom.scaley);
} }
} }
//fprintf(stderr, "X: %d truex: %d scalex: %d\n", vopts.x, truex, scalex); //fprintf(stderr, "X: %d truex: %d scalex: %d\n", vopts.x, truex, scalex);

@ -219,10 +219,10 @@ int luigi_demo(struct notcurses* nc){
ncplane_move_top(lastseen); ncplane_move_top(lastseen);
} }
ncplane_move_yx(lastseen, yoff, i); ncplane_move_yx(lastseen, yoff, i);
int dimy, scaley; ncvgeom geom;
ncvisual_blitter_geom(nc, wmncv, NULL, &dimy, NULL, &scaley, NULL, NULL); ncvisual_geom(nc, wmncv, NULL, &geom);
dimy /= scaley; geom.pixy /= geom.scaley;
ncplane_move_yx(wmplane, rows * 4 / 5 - dimy + 1 + (i % 2), i - 60); ncplane_move_yx(wmplane, rows * 4 / 5 - geom.pixy + 1 + (i % 2), i - 60);
DEMO_RENDER(nc); DEMO_RENDER(nc);
demo_nanosleep(nc, &stepdelay); demo_nanosleep(nc, &stepdelay);
} }

@ -167,10 +167,10 @@ int normal_demo(struct notcurses* nc){
struct ncvisual_options vopts = { struct ncvisual_options vopts = {
.n = nstd, .n = nstd,
}; };
int yscale, xscale; ncvgeom geom;
ncvisual_blitter_geom(nc, NULL, &vopts, NULL, NULL, &yscale, &xscale, NULL); ncvisual_geom(nc, NULL, &vopts, &geom);
dy *= yscale; dy *= geom.scaley;
dx *= xscale; dx *= geom.scalex;
uint32_t* rgba = malloc(sizeof(*rgba) * dy * dx); uint32_t* rgba = malloc(sizeof(*rgba) * dy * dx);
if(!rgba){ if(!rgba){
goto err; goto err;
@ -179,10 +179,10 @@ int normal_demo(struct notcurses* nc){
rgba[off] = 0xff000000; rgba[off] = 0xff000000;
} }
int y; int y;
if(dy / yscale % 2){ if(dy / geom.scaley % 2){
y = dy / yscale + 1; y = dy / geom.scaley + 1;
for(int x = 0 ; x < dx ; ++x){ for(int x = 0 ; x < dx ; ++x){
if(mcell(offset(rgba, y, x, dx), y, x, dy / yscale, dx)){ if(mcell(offset(rgba, y, x, dx), y, x, dy / geom.scaley, dx)){
goto err; goto err;
} }
} }

@ -237,7 +237,8 @@ int yield_demo(struct notcurses* nc){
ncplane_set_fg_rgb8(label, 0xff, 0xff, 0xff); ncplane_set_fg_rgb8(label, 0xff, 0xff, 0xff);
ncplane_set_styles(label, NCSTYLE_BOLD); ncplane_set_styles(label, NCSTYLE_BOLD);
ncplane_printf_aligned(label, 0, NCALIGN_CENTER, "Yield: %03.1f%%", 0.0); ncplane_printf_aligned(label, 0, NCALIGN_CENTER, "Yield: %03.1f%%", 0.0);
if(ncvisual_blitter_geom(nc, v1, &m1.vopts, &maxy, &maxx, NULL, NULL, NULL)){ ncvgeom geom;
if(ncvisual_geom(nc, v1, &m1.vopts, &geom)){
ncplane_destroy(label); ncplane_destroy(label);
ncvisual_destroy(v1); ncvisual_destroy(v1);
ncvisual_destroy(v2); ncvisual_destroy(v2);
@ -253,7 +254,7 @@ int yield_demo(struct notcurses* nc){
ncplane_destroy(m1.vopts.n); ncplane_destroy(m1.vopts.n);
return -1; return -1;
} }
total = maxx * maxy; total = geom.pixy * geom.pixx;
DEMO_RENDER(nc); DEMO_RENDER(nc);

@ -132,7 +132,6 @@ ncvisual_origin(const struct ncvisual_options* vopts, int* restrict begy, int* r
// FIXME we ought also do the output calculations here (how many rows x cols, // 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 // given the input plane vopts->n and scaling vopts->scaling)--but do not
// perform any actual scaling, nor create any planes! // perform any actual scaling, nor create any planes!
// takes tcache distinctly; nc is used only for logging, and can be NULL
int ncvisual_blitset_geom(const notcurses* nc, const tinfo* tcache, int ncvisual_blitset_geom(const notcurses* nc, const tinfo* tcache,
const ncvisual* n, const struct ncvisual_options* vopts, const ncvisual* n, const struct ncvisual_options* vopts,
int* y, int* x, int* scaley, int* scalex, int* y, int* x, int* scaley, int* scalex,
@ -287,6 +286,16 @@ int ncvisual_blitter_geom(const notcurses* nc, const ncvisual* n,
return ret; return ret;
} }
int ncvisual_geom(const notcurses* nc, const ncvisual* n,
const struct ncvisual_options* vopts, ncvgeom* geom){
if(nc == NULL && n == NULL){
logerror("got NULL for both sources\n");
return -1;
}
// FIXME
return 0;
}
void* rgb_loose_to_rgba(const void* data, int rows, int* rowstride, int cols, int alpha){ void* rgb_loose_to_rgba(const void* data, int rows, int* rowstride, int cols, int alpha){
if(*rowstride % 4){ // must be a multiple of 4 bytes if(*rowstride % 4){ // must be a multiple of 4 bytes
return NULL; return NULL;

@ -498,9 +498,11 @@ int ffmpeg_stream(notcurses* nc, ncvisual* ncv, float timescale,
ncplane_erase(activevopts.n); // new frame could be partially transparent ncplane_erase(activevopts.n); // new frame could be partially transparent
} }
// decay the blitter explicitly, so that the callback knows the blitter it // decay the blitter explicitly, so that the callback knows the blitter it
// was actually rendered with // was actually rendered with. basically just need rgba_blitter(), but
ncvisual_blitter_geom(nc, ncv, &activevopts, NULL, NULL, NULL, NULL, // that's not exported.
&activevopts.blitter); ncvgeom geom;
ncvisual_geom(nc, ncv, &activevopts, &geom);
activevopts.blitter = geom.blitter;
if((newn = ncvisual_blit(nc, ncv, &activevopts)) == NULL){ if((newn = ncvisual_blit(nc, ncv, &activevopts)) == NULL){
if(activevopts.n != vopts->n){ if(activevopts.n != vopts->n){
ncplane_destroy(activevopts.n); ncplane_destroy(activevopts.n);

@ -41,7 +41,6 @@ int main(int argc, char** argv){
if(!ncv){ if(!ncv){
goto err; goto err;
} }
int scaley, scalex;
vopts.n = n; vopts.n = n;
if((ncvisual_blit(nc, ncv, &vopts)) == NULL){ if((ncvisual_blit(nc, ncv, &vopts)) == NULL){
goto err; goto err;
@ -52,8 +51,9 @@ int main(int argc, char** argv){
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
ncplane_erase(n); ncplane_erase(n);
ncvisual_blitter_geom(nc, ncv, &vopts, NULL, NULL, &scaley, &scalex, NULL); ncvgeom geom;
if(ncvisual_resize(ncv, dimy * scaley, dimx * scalex)){ ncvisual_geom(nc, ncv, &vopts, &geom);
if(ncvisual_resize(ncv, dimy * geom.scaley, dimx * geom.scalex)){
goto err; goto err;
} }
if(ncvisual_blit(nc, ncv, &vopts) == NULL){ if(ncvisual_blit(nc, ncv, &vopts) == NULL){

@ -92,14 +92,18 @@ TEST_CASE("Media") {
ncplane_dim_yx(ncp_, &dimy, &dimx); ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_from_file(find_data("changes.jpg").get()); auto ncv = ncvisual_from_file(find_data("changes.jpg").get());
REQUIRE(ncv); REQUIRE(ncv);
int odimy, odimx, ndimy, ndimx;
struct ncvisual_options opts{}; struct ncvisual_options opts{};
opts.n = ncp_; opts.n = ncp_;
CHECK(0 == ncvisual_blitter_geom(nc_, ncv, &opts, &odimy, &odimx, nullptr, nullptr, nullptr)); ncvgeom geom{};
CHECK(0 == ncvisual_geom(nc_, ncv, &opts, &geom));
int odimy = geom.pixy;
int odimx = geom.pixx;
CHECK(ncvisual_blit(nc_, ncv, &opts)); CHECK(ncvisual_blit(nc_, ncv, &opts));
CHECK(0 == notcurses_render(nc_)); CHECK(0 == notcurses_render(nc_));
CHECK(0 == ncvisual_resize_noninterpolative(ncv, ncv->pixy * 2, ncv->pixx * 2)); CHECK(0 == ncvisual_resize_noninterpolative(ncv, ncv->pixy * 2, ncv->pixx * 2));
CHECK(0 == ncvisual_blitter_geom(nc_, ncv, &opts, &ndimy, &ndimx, nullptr, nullptr, nullptr)); CHECK(0 == ncvisual_geom(nc_, ncv, &opts, &geom));
int ndimy = geom.pixy;
int ndimx = geom.pixx;
CHECK(ndimy == odimy * 2); CHECK(ndimy == odimy * 2);
CHECK(ndimx == odimx * 2); CHECK(ndimx == odimx * 2);
CHECK(ncvisual_blit(nc_, ncv, &opts)); CHECK(ncvisual_blit(nc_, ncv, &opts));

Loading…
Cancel
Save