mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
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:
parent
827c2f2013
commit
af46077775
5
NEWS.md
5
NEWS.md
@ -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_`.
|
||||||
|
8
USAGE.md
8
USAGE.md
@ -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);
|
||||||
|
@ -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);**
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user