add nplane_polyfill_yx() #340

pull/345/head
nick black 4 years ago committed by Nick Black
parent ce3e5d112e
commit 124004c87c

@ -1129,6 +1129,15 @@ ncplane_double_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels,
}
```
Similarly, areas can be filled with a cell.
```c
// The specified coordinate must not currently have a glyph, or it is an error.
// Otherwise, that coordinate, and all cardinally-connected glyphless cells,
// will have 'c' written to them.
int ncplane_polyfill_yx(struct ncplane* n, int y, int x, const cell* c);
```
My 14 year-old self would never forgive me if we didn't have sweet palette fades.
```c

@ -8,6 +8,7 @@ libnotcurses.so.1 libnotcurses1 #MINVER#
ncblit_rgba@Base 1.1.8
ncdirect_bg@Base 1.1.8
ncdirect_bg_rgb8@Base 1.1.8
ncdirect_clear@Base 1.1.9
ncdirect_fg@Base 1.1.8
ncdirect_fg_rgb8@Base 1.1.8
ncdirect_stop@Base 1.1.8

@ -57,6 +57,8 @@ ncplane_box_sized(struct ncplane* n, const cell* ul, const cell* ur,
**static inline int ncplane_double_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels, int ylen, int xlen, unsigned ctlword);**
**int ncplane_polyfill_yx(struct ncplane* n, int y, int x, const cell* c);**
# DESCRIPTION

@ -940,6 +940,12 @@ ncplane_perimeter(struct ncplane* n, const cell* ul, const cell* ur,
return ncplane_box_sized(n, ul, ur, ll, lr, hline, vline, dimy, dimx, ctlword);
}
// Starting at the specified coordinate, if it has no glyph, 'c' is copied into
// it. We do the same to all cardinally-connected glyphless cells, filling in
// everything behind a boundary. Returns the number of cells polyfilled. An
// invalid initial y, x is an error.
API int ncplane_polyfill_yx(struct ncplane* n, int y, int x, const cell* c);
// 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
// with this ncplane is invalidated, and must not be used after the call,

@ -9,7 +9,6 @@ setup(
version="1.1.8",
packages=['notcurses'],
package_dir={'': 'src'},
py_modules=['notcurses'],
author="Nick Black",
author_email="nickblack@linux.com",
description="Blingful TUI construction library (python bindings)",

@ -352,6 +352,7 @@ struct nctablet* ncreel_prev(struct ncreel* pr);
int ncreel_destroy(struct ncreel* pr);
void* nctablet_userptr(struct nctablet* t);
struct ncplane* nctablet_ncplane(struct nctablet* t);
int ncplane_polyfill_yx(struct ncplane* n, int y, int x, const cell* c);
""")
if __name__ == "__main__":

@ -191,14 +191,21 @@ int ncplane_at_cursor(ncplane* n, cell* c){
return cell_duplicate(n, c, &n->fb[nfbcellidx(n, n->y, n->x)]);
}
int ncplane_at_yx(ncplane* n, int y, int x, cell* c){
static inline int
ncplane_at_yx_locked(ncplane* n, int y, int x, cell* c){
int ret = -1;
pthread_mutex_lock(&n->nc->lock);
if(y < n->leny && x < n->lenx){
if(y >= 0 && x >= 0){
ret = cell_duplicate(n, c, &n->fb[nfbcellidx(n, y, x)]);
}
}
return ret;
}
int ncplane_at_yx(ncplane* n, int y, int x, cell* c){
int ret = -1;
pthread_mutex_lock(&n->nc->lock);
ret = ncplane_at_yx_locked(n, y, x, c);
pthread_mutex_unlock(&n->nc->lock);
return ret;
}
@ -1934,3 +1941,58 @@ void ncplane_greyscale(ncplane *n){
}
ncplane_unlock(n);
}
// if this is not polyfillable cell, we return 0. if it is, we attempt to fill
// it, then recurse out. return -1 on error, or number of cells filled on
// success. so a return of 0 means there's no work to be done here, and N means
// we did some work here, filling everything we could reach. out-of-plane is 0.
static int
ncplane_polyfill_locked(ncplane* n, int y, int x, const cell* c){
fprintf(stderr, "%d %d\n", y, x);
if(y >= n->leny || x >= n->lenx){
return 0; // not fillable
}
if(y < 0 || x < 0){
return 0; // not fillable
}
fprintf(stderr, "%d %d\n", y, x);
cell* cur = &n->fb[nfbcellidx(n, y, x)];
if(cur->gcluster){
return 0; // glyph, not polyfillable
}
fprintf(stderr, "%c\n", c->gcluster);
if(cell_duplicate(n, cur, c) < 0){
return -1;
}
int r, ret = 1;
if((r = ncplane_polyfill_locked(n, y - 1, x, c)) < 0){
return -1;
}
ret += r;
if((r = ncplane_polyfill_locked(n, y + 1, x, c)) < 0){
return -1;
}
ret += r;
if((r = ncplane_polyfill_locked(n, y, x - 1, c)) < 0){
return -1;
}
ret += r;
if((r = ncplane_polyfill_locked(n, y, x + 1, c)) < 0){
return -1;
}
ret += r;
return ret;
}
// at the initial step only, invalid y, x is an error, so explicitly check.
int ncplane_polyfill_yx(ncplane* n, int y, int x, const cell* c){
int ret = -1;
ncplane_lock(n);
if(y < n->leny && x < n->lenx){
if(y >= 0 && x >= 0){
ret = ncplane_polyfill_locked(n, y, x, c);
}
}
ncplane_unlock(n);
return ret;
}

@ -52,7 +52,6 @@ TEST_CASE("Fade") {
}
}
SUBCASE("FadeOut") {
CHECK(0 == notcurses_render(nc_));
struct timespec ts;

@ -0,0 +1,59 @@
#include <array>
#include <cstdlib>
#include <notcurses.h>
#include "internal.h"
#include "main.h"
TEST_CASE("Fills") {
if(getenv("TERM") == nullptr){
return;
}
notcurses_options nopts{};
nopts.inhibit_alternate_screen = true;
nopts.suppress_banner = true;
FILE* outfp_ = fopen("/dev/tty", "wb");
REQUIRE(outfp_);
struct notcurses* nc_ = notcurses_init(&nopts, outfp_);
REQUIRE(nc_);
struct ncplane* n_ = notcurses_stdplane(nc_);
REQUIRE(n_);
// trying to polyfill an invalid cell ought be an error
SUBCASE("PolyfillOffplane") {
int dimx, dimy;
ncplane_dim_yx(n_, &dimy, &dimx);
cell c = CELL_SIMPLE_INITIALIZER('+');
CHECK(0 > ncplane_polyfill_yx(n_, dimy, 0, &c));
CHECK(0 > ncplane_polyfill_yx(n_, 0, dimx, &c));
CHECK(0 > ncplane_polyfill_yx(n_, 0, -1, &c));
CHECK(0 > ncplane_polyfill_yx(n_, -1, 0, &c));
}
SUBCASE("PolyfillEmptyPlane") {
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 == notcurses_render(nc_));
CHECK(0 == ncplane_destroy(pfn));
}
SUBCASE("PolyfillWalledPlane") {
cell c = CELL_SIMPLE_INITIALIZER('+');
struct ncplane* pfn = ncplane_new(nc_, 4, 4, 0, 0, nullptr);
REQUIRE(nullptr != pfn);
CHECK(0 < ncplane_putc_yx(pfn, 0, 1, &c));
CHECK(0 < ncplane_putc_yx(pfn, 1, 1, &c));
CHECK(0 < ncplane_putc_yx(pfn, 1, 0, &c));
// Trying to fill the origin ought fill exactly one cell
CHECK(1 == ncplane_polyfill_yx(pfn, 0, 0, &c));
// Beyond the origin, we ought fill 12
CHECK(12 == ncplane_polyfill_yx(pfn, 2, 2, &c));
CHECK(0 == notcurses_render(nc_));
CHECK(0 == ncplane_destroy(pfn));
}
CHECK(0 == notcurses_stop(nc_));
CHECK(0 == fclose(outfp_));
}

@ -9,7 +9,6 @@ setup(
version="${PROJECT_VERSION}",
packages=['notcurses'],
package_dir={ '': '${CMAKE_CURRENT_BINARY_DIR}/python/src' },
py_modules=['notcurses'],
author="Nick Black",
author_email="nickblack@linux.com",
description="Blingful TUI construction library (python bindings)",

Loading…
Cancel
Save