add notcurses_drop_planes, use from demo #346

This commit is contained in:
nick black 2020-02-15 18:40:43 -05:00 committed by Nick Black
parent ab9cbf82dc
commit c6520ab84c
9 changed files with 134 additions and 17 deletions

View File

@ -275,6 +275,9 @@ Utility functions operating on the toplevel `notcurses` object include:
// Return the topmost ncplane, of which there is always at least one.
struct ncplane* notcurses_top(struct notcurses* n);
// Destroy any ncplanes other than the stdplane.
void notcurses_drop_planes(struct notcurses* nc);
// Refresh our idea of the terminal's dimensions, reshaping the standard plane
// if necessary. Without a call to this function following a terminal resize
// (as signaled via SIGWINCH), notcurses_render() might not function properly.
@ -1109,9 +1112,14 @@ int ncplane_gradient(struct ncplane* n, const char* egc, uint32_t attrword,
// Draw a gradient with its upper-left corner at the current cursor position,
// having dimensions 'ylen'x'xlen'. See ncplane_gradient for more information.
int ncplane_gradient_sized(struct ncplane* n, const char* egc,
uint32_t attrword, uint64_t ul, uint64_t ur,
uint64_t ll, uint64_t lr, int ylen, int xlen);
static inline int
ncplane_gradient_sized(struct ncplane* n, const char* egc, uint32_t attrword,
uint64_t ul, uint64_t ur, uint64_t ll, uint64_t lr,
int ylen, int xlen){
int y, x;
ncplane_cursor_yx(n, &y, &x);
return ncplane_gradient(n, egc, attrword, ul, ur, ll, lr, y + ylen - 1, x + xlen - 1);
}
```
My 14 year-old self would never forgive me if we didn't have sweet palette fades.
@ -1201,7 +1209,8 @@ static inline unsigned
ncplane_fg_alpha(const struct ncplane* nc){
return channels_fg_alpha(ncplane_channels(nc));
}
/ Extract 2 bits of background alpha from 'struct ncplane', shifted to LSBs.
// Extract 2 bits of background alpha from 'struct ncplane', shifted to LSBs.
static inline unsigned
ncplane_bg_alpha(const struct ncplane* nc){
return channels_bg_alpha(ncplane_channels(nc));

View File

@ -61,7 +61,7 @@ ncplane_box_sized(struct ncplane* n, const cell* ul, const cell* ur,
**int ncplane_gradient(struct ncplane* n, const char* egc, uint32_t attrword, uint64_t ul, uint64_t ur, uint64_t ll, uint64_t lr, int ystop, int xstop);**
**int ncplane_gradient_sized(struct ncplane* n, const char* egc, uint32_t attrword, uint64_t ul, uint64_t ur, uint64_t ll, uint64_t lr, int ylen, int xlen);**
**static inline int ncplane_gradient_sized(struct ncplane* n, const char* egc, uint32_t attrword, uint64_t ul, uint64_t ur, uint64_t ll, uint64_t lr, int ylen, int xlen);**
# DESCRIPTION

View File

@ -116,6 +116,8 @@ notcurses_ncplane - operations on notcurses planes
**int ncblit_rgba(struct ncplane* nc, int placey, int placex, int linesize, const unsigned char* data, int begy, int begx, int leny, int lenx);**
**void notcurses_drop_planes(struct notcurses* nc);**
## DESCRIPTION
Ncplanes are the fundamental drawing object of notcurses. All output functions
@ -132,6 +134,9 @@ anywhere. In addition to its framebuffer--a rectilinear matrix of cells
* its position relative to the visible plane, and
* its z-index.
**notcurses_drop_planes** destroys all ncplanes other than the stdplane. Any
references to such planes are, of course, invalidated.
# RETURN VALUES
**ncplane_new(3)**, **ncplane_aligned(3)**, and **ncplane_dup(3)** all return a
@ -145,7 +150,7 @@ plane is the bottommost plane, NULL is returned. It cannot fail.
Functions returning **int** return 0 on success, and non-zero on error.
All other functions either cannot fail (and return **void**).
All other functions cannot fail (and return **void**).
# NOTES

View File

@ -246,6 +246,9 @@ API int notcurses_render(struct notcurses* nc);
// Return the topmost ncplane, of which there is always at least one.
API struct ncplane* notcurses_top(struct notcurses* n);
// Destroy any ncplanes other than the stdplane.
API void notcurses_drop_planes(struct notcurses* nc);
// All input is currently taken from stdin, though this will likely change. We
// attempt to read a single UTF8-encoded Unicode codepoint, *not* an entire
// Extended Grapheme Cluster. It is also possible that we will read a special
@ -958,9 +961,14 @@ API int ncplane_gradient(struct ncplane* n, const char* egc, uint32_t attrword,
// Draw a gradient with its upper-left corner at the current cursor position,
// having dimensions 'ylen'x'xlen'. See ncplane_gradient for more information.
API int ncplane_gradient_sized(struct ncplane* n, const char* egc,
uint32_t attrword, uint64_t ul, uint64_t ur,
uint64_t ll, uint64_t lr, int ylen, int xlen);
static inline int
ncplane_gradient_sized(struct ncplane* n, const char* egc, uint32_t attrword,
uint64_t ul, uint64_t ur, uint64_t ll, uint64_t lr,
int ylen, int xlen){
int y, x;
ncplane_cursor_yx(n, &y, &x);
return ncplane_gradient(n, egc, attrword, ul, ur, ll, lr, y + ylen - 1, x + xlen - 1);
}
// Erase every cell in the ncplane, resetting all attributes to normal, all
// colors to the default color, and all cells to undrawn. All cells associated

View File

@ -87,6 +87,7 @@ int ncplane_set_base_cell(struct ncplane* ncp, const cell* c);
int ncplane_set_base(struct ncplane* ncp, uint64_t channels, uint32_t attrword, const char* egc);
int ncplane_base(struct ncplane* ncp, cell* c);
struct ncplane* notcurses_top(struct notcurses* n);
void notcurses_drop_planes(struct notcurses* nc);
int notcurses_refresh(struct notcurses* n);
int notcurses_resize(struct notcurses* n, int* y, int* x);
struct ncplane* ncplane_new(struct notcurses* nc, int rows, int cols, int yoff, int xoff, void* opaque);

View File

@ -423,9 +423,6 @@ int main(int argc, char** argv){
if(notcurses_mouse_enable(nc)){
goto err;
}
if(menu_create(nc) == NULL){
goto err;
}
if(input_dispatcher(nc)){
goto err;
}
@ -444,13 +441,17 @@ int main(int argc, char** argv){
do{
restart_demos = false;
interrupted = false;
notcurses_drop_planes(nc);
if(menu_create(nc) == NULL){
goto err;
}
if(ext_demos(nc, spec, ignore_failures) == NULL){
goto err;
}
if(hud_destroy()){ // destroy here since notcurses_drop_planes will kill it
goto err;
}
}while(restart_demos);
if(hud_destroy()){
goto err;
}
if(stop_input()){
goto err;
}

View File

@ -176,8 +176,8 @@ eagles(struct notcurses* nc){
continue;
}
e[i].yoff += random() % (2 + i) - 1;
if(e[i].yoff < 1){
e[i].yoff = 1;
if(e[i].yoff < 0){
e[i].yoff = 0;
}else if(e[i].yoff + height >= truey){
e[i].yoff = truey - height - 1;
}

View File

@ -1003,6 +1003,20 @@ int ncdirect_stop(ncdirect* nc){
return ret;
}
void notcurses_drop_planes(notcurses* nc){
ncplane* p = nc->top;
while(p){
ncplane* tmp = p->z;
if(nc->stdscr == p){
nc->top = p;
p->z = NULL;
}else{
free_plane(p);
}
p = tmp;
}
}
int notcurses_stop(notcurses* nc){
int ret = 0;
if(nc){
@ -1996,3 +2010,60 @@ int ncplane_polyfill_yx(ncplane* n, int y, int x, const cell* c){
ncplane_unlock(n);
return ret;
}
// calculate one of the channels of a gradient at a particular point.
static uint32_t
calc_gradient_channel(uint32_t ul, uint32_t ur, uint32_t ll, uint32_t lr,
int y, int x, int ylen, int xlen){
return 0;
}
// calculate both channels of a gradient at a particular point, storing them
// into `c`->channels. x and y ought be the location within the gradient.
static void
calc_gradient_channels(cell* c, uint64_t ul, uint64_t ur, uint64_t ll,
uint64_t lr, int y, int x, int ylen, int xlen){
cell_set_fchannel(c, calc_gradient_channel(channels_fchannel(ul),
channels_fchannel(ur),
channels_fchannel(ll),
channels_fchannel(lr),
y, x, ylen, xlen));
cell_set_bchannel(c, calc_gradient_channel(channels_fchannel(ul),
channels_fchannel(ur),
channels_fchannel(ll),
channels_fchannel(lr),
y, x, ylen, xlen));
}
int ncplane_gradient(ncplane* n, const char* egc, uint32_t attrword,
uint64_t ul, uint64_t ur, uint64_t ll, uint64_t lr,
int ystop, int xstop){
int yoff, xoff, ymax, xmax;
ncplane_cursor_yx(n, &yoff, &xoff);
// must be at least 1x1, with its upper-left corner at the current cursor
if(ystop < yoff){
return -1;
}
if(xstop < xoff){
return -1;
}
ncplane_dim_yx(n, &ymax, &xmax);
// must be within the ncplane
if(xstop >= xmax || ystop >= ymax){
return -1;
}
const int xlen = xstop - xoff + 1;
const int ylen = ystop - ylen + 1;
for(int y = yoff ; y < ylen ; ++y){
for(int x = xoff ; x < xlen ; ++x){
cell* targc = ncplane_cell_ref_yx(n, y, x);
targc->channels = 0;
targc->attrword = 0;
if(cell_load(n, targc, egc) < 0){
return -1;
}
calc_gradient_channels(&targc, ul, ur, ll, lr, y - yoff, x - xoff, ylen, xlen);
}
}
return 0;
}

View File

@ -29,6 +29,18 @@ TEST_CASE("Fills") {
CHECK(0 > ncplane_polyfill_yx(n_, -1, 0, &c));
}
SUBCASE("PolyfillOnGlyph") {
cell c = CELL_SIMPLE_INITIALIZER('+');
struct ncplane* pfn = ncplane_new(nc_, 4, 4, 0, 0, nullptr);
REQUIRE(nullptr != pfn);
CHECK(16 == ncplane_polyfill_yx(pfn, 0, 0, &c));
CHECK(0 < ncplane_putc_yx(pfn, 0, 0, &c));
// Trying to fill the origin ought fill zero cells
CHECK(0 == ncplane_polyfill_yx(pfn, 0, 0, &c));
CHECK(0 == notcurses_render(nc_));
CHECK(0 == ncplane_destroy(pfn));
}
SUBCASE("PolyfillEmptyPlane") {
cell c = CELL_SIMPLE_INITIALIZER('+');
struct ncplane* pfn = ncplane_new(nc_, 4, 4, 0, 0, nullptr);
@ -53,6 +65,16 @@ TEST_CASE("Fills") {
CHECK(0 == ncplane_destroy(pfn));
}
SUBCASE("GradientMonochromatic") {
struct ncplane* pfn = ncplane_new(nc_, 4, 4, 0, 0, nullptr);
REQUIRE(nullptr != pfn);
uint64_t ul, ur, ll, lr;
ul = ur = ll = lr = 0;
CHECK(0 == ncplane_gradient(pfn, " ", 0, ul, ur, ll, lr, 3, 3));
CHECK(0 == notcurses_render(nc_));
CHECK(0 == ncplane_destroy(pfn));
}
CHECK(0 == notcurses_stop(nc_));
CHECK(0 == fclose(outfp_));