ncvisual_geom: take degradation into account #697

In order to properly determine the scaling of an ncvisual to
be rendered, ncvisual_geom() needs know the blitting method.
For this reason, it took an ncblitter_e argument. It also,
however, needs handle degradation, which means knowing whether
NCVISUAL_OPTIONS_NODEGRADE is in use. It thus really wants the
struct ncvisual_options. Pass and accept it. Closes #697, and
fixes the "yield" demo in ASCII mode (#696).
This commit is contained in:
nick black 2020-06-09 05:00:08 -04:00
parent 827c2f2013
commit af46077775
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
7 changed files with 73 additions and 54 deletions

View File

@ -1,6 +1,11 @@
This document attempts to list user-visible changes and any major internal This document attempts to list user-visible changes and any major internal
rearrangements of Notcurses. rearrangements of Notcurses.
* 1.5.1 (not yet released)
* `ncvisual_geom()`'s `ncblitter_e` argument has been replaced with a
`const struct ncvisual_options*`, so that `NCVISUAL_OPTIONS_NODEGRADE`
can be taken into account (the latter contains a `blitter_e` field).
* 1.5.0 (2020-07-08) * 1.5.0 (2020-07-08)
* The various `bool`s of `struct notcurses_options` have been folded into * The various `bool`s of `struct notcurses_options` have been folded into
that `struct`'s `flags` field. Each `bool` has its own `NCOPTION_`. that `struct`'s `flags` field. Each `bool` has its own `NCOPTION_`.

View File

@ -2544,6 +2544,14 @@ 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
// ('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'.
int ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n,
const struct ncvisual_options* vopts,
int* y, int* x, int* toy, int* tox);
// Rotate the visual 'rads' radians. Only M_PI/2 and -M_PI/2 are // Rotate the visual 'rads' radians. Only M_PI/2 and -M_PI/2 are
// supported at the moment, but this will change FIXME. // supported at the moment, but this will change FIXME.
nc_err_e ncvisual_rotate(struct ncvisual* n, double rads); nc_err_e ncvisual_rotate(struct ncvisual* n, double rads);

View File

@ -58,17 +58,17 @@ 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_geom(const struct notcurses* nc, const struct ncvisual* n, ncblitter_e blitter, int* y, int* x, int* toy, int* tox);** **int ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n, const struct ncvisual_options* vopts, int* y, int* x, int* toy, int* tox);**
**void ncvisual_destroy(struct ncvisual* ncv);** **void ncvisual_destroy(struct ncvisual* ncv);**
**nc_err_e ncvisual_decode(struct ncvisual* nc);** **nc_err_e ncvisual_decode(struct ncvisual* nc);**
**struct ncplane* ncvisual_render(struct notcurses* nc, struct ncvisual* ncv, const struct visual_options* vopts);** **struct ncplane* ncvisual_render(struct notcurses* nc, struct ncvisual* ncv, const struct ncvisual_options* vopts);**
**int ncvisual_simple_streamer(struct ncplane* n, struct ncvisual* ncv, const struct timespec* disptime, void* curry);** **int ncvisual_simple_streamer(struct ncplane* n, struct ncvisual* ncv, const struct timespec* disptime, void* curry);**
**int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, nc_err_e* err, float timescale, streamcb streamer, const struct visual_options* vopts, void* curry);** **int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, nc_err_e* err, float timescale, streamcb streamer, const struct ncvisual_options* vopts, void* curry);**
**int ncvisual_rotate(struct ncvisual* n, double rads);** **int ncvisual_rotate(struct ncvisual* n, double rads);**

View File

@ -2229,46 +2229,6 @@ API struct ncvisual* ncvisual_from_plane(const struct ncplane* n,
int begy, int begx, int begy, int begx,
int leny, int lenx); int leny, int lenx);
// Create an RGBA flat array from the selected region of the ncplane 'nc'.
// Start at the plane's 'begy'x'begx' coordinate (which must lie on the
// plane), continuing for 'leny'x'lenx' cells. Either or both of 'leny' and
// 'lenx' can be specified as -1 to go through the boundary of the plane.
// Only glyphs from the specified blitset may be present.
API uint32_t* ncplane_rgba(const struct ncplane* nc, ncblitter_e blit,
int begy, int begx, int leny, int lenx);
// 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'.
API int ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n,
ncblitter_e blitter, int* y, int* x, int* toy, int* tox);
// Destroy an ncvisual. Rendered elements will not be disrupted, but the visual
// can be neither decoded nor rendered any further.
API void ncvisual_destroy(struct ncvisual* ncv);
// extract the next frame from an ncvisual. returns NCERR_EOF on end of file,
// and NCERR_SUCCESS on success, otherwise some other NCERR.
API nc_err_e ncvisual_decode(struct ncvisual* nc);
// Rotate the visual 'rads' radians. Only M_PI/2 and -M_PI/2 are
// supported at the moment, but this will change FIXME.
API nc_err_e ncvisual_rotate(struct ncvisual* n, double rads);
// Resize the visual so that it is 'rows' X 'columns'. This is a lossy
// transformation, unless the size is unchanged.
API nc_err_e ncvisual_resize(struct ncvisual* n, int rows, int cols);
// Polyfill at the specified location within the ncvisual 'n', using 'rgba'.
API int ncvisual_polyfill_yx(struct ncvisual* n, int y, int x, uint32_t rgba);
// Get the specified pixel from the specified ncvisual.
API int ncvisual_at_yx(const struct ncvisual* n, int y, int x, uint32_t* pixel);
// Set the specified pixel in the specified ncvisual.
API int ncvisual_set_yx(const struct ncvisual* n, int y, int x, uint32_t pixel);
#define NCVISUAL_OPTION_NODEGRADE 0x0001 // fail rather than degrading #define NCVISUAL_OPTION_NODEGRADE 0x0001 // fail rather than degrading
#define NCVISUAL_OPTION_BLEND 0x0002 // use CELL_ALPHA_BLEND with visual #define NCVISUAL_OPTION_BLEND 0x0002 // use CELL_ALPHA_BLEND with visual
@ -2297,6 +2257,47 @@ struct ncvisual_options {
uint64_t flags; // bitmask over NCVISUAL_OPTION_* uint64_t flags; // bitmask over NCVISUAL_OPTION_*
}; };
// Create an RGBA flat array from the selected region of the ncplane 'nc'.
// Start at the plane's 'begy'x'begx' coordinate (which must lie on the
// plane), continuing for 'leny'x'lenx' cells. Either or both of 'leny' and
// 'lenx' can be specified as -1 to go through the boundary of the plane.
// Only glyphs from the specified blitset may be present.
API uint32_t* ncplane_rgba(const struct ncplane* nc, ncblitter_e blit,
int begy, int begx, int leny, int lenx);
// 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'.
API int ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n,
const struct ncvisual_options* vopts,
int* y, int* x, int* toy, int* tox);
// Destroy an ncvisual. Rendered elements will not be disrupted, but the visual
// can be neither decoded nor rendered any further.
API void ncvisual_destroy(struct ncvisual* ncv);
// extract the next frame from an ncvisual. returns NCERR_EOF on end of file,
// and NCERR_SUCCESS on success, otherwise some other NCERR.
API nc_err_e ncvisual_decode(struct ncvisual* nc);
// Rotate the visual 'rads' radians. Only M_PI/2 and -M_PI/2 are
// supported at the moment, but this will change FIXME.
API nc_err_e ncvisual_rotate(struct ncvisual* n, double rads);
// Resize the visual so that it is 'rows' X 'columns'. This is a lossy
// transformation, unless the size is unchanged.
API nc_err_e ncvisual_resize(struct ncvisual* n, int rows, int cols);
// Polyfill at the specified location within the ncvisual 'n', using 'rgba'.
API int ncvisual_polyfill_yx(struct ncvisual* n, int y, int x, uint32_t rgba);
// Get the specified pixel from the specified ncvisual.
API int ncvisual_at_yx(const struct ncvisual* n, int y, int x, uint32_t* pixel);
// Set the specified pixel in the specified ncvisual.
API int ncvisual_set_yx(const struct ncvisual* n, int y, int x, uint32_t pixel);
// Render the decoded frame to the specified ncplane (if one is not provided, // Render the decoded frame to the specified ncplane (if one is not provided,
// one will be created, having the exact size necessary to display the visual. // one will be created, having the exact size necessary to display the visual.
// In this case, 'style' must be NCSTYLE_NONE). A subregion of the visual can // In this case, 'style' must be NCSTYLE_NONE). A subregion of the visual can

View File

@ -38,7 +38,12 @@ zoom_map(struct notcurses* nc, const char* map, int* ret){
} }
int vheight, yscale; int vheight, yscale;
int vwidth, xscale; int vwidth, xscale;
if(ncvisual_geom(nc, ncv, NCBLIT_2x2, &vheight, &vwidth, &yscale, &xscale)){ struct ncvisual_options vopts = {
.y = 1,
.scaling = NCSCALE_STRETCH,
.blitter = NCBLIT_2x2,
};
if(ncvisual_geom(nc, ncv, &vopts, &vheight, &vwidth, &yscale, &xscale)){
ncvisual_destroy(ncv); ncvisual_destroy(ncv);
return NULL; return NULL;
} }
@ -64,12 +69,7 @@ zoom_map(struct notcurses* nc, const char* map, int* ret){
} }
vheight /= yscale; vheight /= yscale;
vwidth /= xscale; vwidth /= xscale;
struct ncvisual_options vopts = { vopts.n = zncp;
.y = 1,
.n = zncp,
.scaling = NCSCALE_STRETCH,
.blitter = NCBLIT_2x2,
};
if(ncvisual_render(nc, ncv, &vopts) == NULL || (*ret = demo_render(nc))){ if(ncvisual_render(nc, ncv, &vopts) == NULL || (*ret = demo_render(nc))){
ncvisual_destroy(ncv); ncvisual_destroy(ncv);
ncplane_destroy(zncp); ncplane_destroy(zncp);

View File

@ -30,7 +30,7 @@ int yield_demo(struct notcurses* nc){
ncplane_erase(std); ncplane_erase(std);
int vy, vx, vscaley, vscalex; int vy, vx, vscaley, vscalex;
ncvisual_geom(nc, wmv, vopts.blitter, &vy, &vx, &vscaley, &vscalex); ncvisual_geom(nc, wmv, &vopts, &vy, &vx, &vscaley, &vscalex);
struct timespec scaled; struct timespec scaled;
const long total = vy * vx; const long total = vy * vx;
const long threshold_painted = total * 4 / 5; const long threshold_painted = total * 4 / 5;

View File

@ -36,12 +36,17 @@ ncvisual_default_blitter(const notcurses* nc) -> ncblitter_e {
return NCBLIT_1x1; return NCBLIT_1x1;
} }
auto ncvisual_geom(const notcurses* nc, const ncvisual* n, ncblitter_e blitter, auto ncvisual_geom(const notcurses* nc, const ncvisual* n,
const struct ncvisual_options* vopts,
int* y, int* x, int* toy, int* tox) -> int { int* y, int* x, int* toy, int* tox) -> int {
if(blitter == NCBLIT_DEFAULT){ ncblitter_e blitter;
if(!vopts || vopts->blitter == NCBLIT_DEFAULT){
blitter = ncvisual_default_blitter(nc); blitter = ncvisual_default_blitter(nc);
}else{
blitter = vopts->blitter;
} }
const struct blitset* bset = lookup_blitset(nc, blitter, false); const bool maydegrade = !(vopts && (vopts->flags & NCVISUAL_OPTION_NODEGRADE));
const struct blitset* bset = lookup_blitset(nc, blitter, maydegrade);
if(!bset){ if(!bset){
return -1; return -1;
} }