From 5bdfc0183f17a2e1c3419f5bac01513a11861c1a Mon Sep 17 00:00:00 2001 From: nick black Date: Wed, 6 May 2020 21:40:24 -0400 Subject: [PATCH] ncvisual_from_plane() #559 --- CHANGELOG.md | 5 +++-- USAGE.md | 9 +++++++++ doc/man/man3/notcurses_plane.3.md | 2 ++ include/notcurses/notcurses.h | 7 +++++++ python/src/notcurses/build_notcurses.py | 1 + src/lib/notcurses.c | 26 +++++++++++++++++++++++++ src/lib/visual.cpp | 16 ++++++++++++--- 7 files changed, 61 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8e469803..56dd144ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ This document attempts to list user-visible changes and any major internal rearrangements of Notcurses. -* 1.3.4 (not yet released) +* 1.3.4 (2020-05-06) * `notcurses_lex_margins()` has been added to lex margins expressed in either of two canonical formats. Hopefully this will lead to more programs supporting margins. @@ -13,7 +13,8 @@ rearrangements of Notcurses. radians on `ncvisual` objects. * `ncvisual_from_plane()` has been added to support "promotion" of an `ncplane` to an `ncvisual`. The source plane may contain only spaces, - half blocks, and full blocks. + half blocks, and full blocks. This builds atop the new function + `ncplane_rgba()`, which makes an RGBA flat array from an `ncplane`. * 1.3.3 (2020-04-26) * The `ncdplot` type has been added for plots based on `double`s rather than diff --git a/USAGE.md b/USAGE.md index 89f17a74c..5ba744384 100644 --- a/USAGE.md +++ b/USAGE.md @@ -725,6 +725,13 @@ char* ncplane_at_yx(struct ncplane* n, int y, int x, // invalidated if the associated plane is destroyed. int ncplane_at_yx_cell(struct ncplane* n, int y, int x, cell* c); +// 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. +uint32_t* ncplane_rgba(const struct ncplane* nc, int begy, int begx, + int leny, int lenx); + // Manipulate the opaque user pointer associated with this plane. // ncplane_set_userptr() returns the previous userptr after replacing // it with 'opaque'. the others simply return the userptr. @@ -1196,6 +1203,8 @@ int ncblit_rgba(struct ncplane* nc, int placey, int placex, int linesize, int leny, int lenx); ``` + + ### Plane channels API Helpers are provided to manipulate an `ncplane`'s `channels` member. They are diff --git a/doc/man/man3/notcurses_plane.3.md b/doc/man/man3/notcurses_plane.3.md index b3b807354..7a4d6e0f9 100644 --- a/doc/man/man3/notcurses_plane.3.md +++ b/doc/man/man3/notcurses_plane.3.md @@ -50,6 +50,8 @@ notcurses_plane - operations on ncplanes **int ncplane_at_yx_cell(struct ncplane* n, int y, int x, cell* c);** +**uint32_t* ncplane_rgba(const struct ncplane* nc, int begy, int begx, int leny, int lenx);** + **void* ncplane_set_userptr(struct ncplane* n, void* opaque);** **void* ncplane_userptr(struct ncplane* n);** diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index 163bc3309..f0a02193a 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -1184,6 +1184,13 @@ ncplane_at_yx_cell(struct ncplane* n, int y, int x, cell* c){ return r; } +// 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. +API uint32_t* ncplane_rgba(const struct ncplane* nc, int begy, int begx, + int leny, int lenx); + // Manipulate the opaque user pointer associated with this plane. // ncplane_set_userptr() returns the previous userptr after replacing // it with 'opaque'. the others simply return the userptr. diff --git a/python/src/notcurses/build_notcurses.py b/python/src/notcurses/build_notcurses.py index d690698f0..9024697ec 100644 --- a/python/src/notcurses/build_notcurses.py +++ b/python/src/notcurses/build_notcurses.py @@ -141,6 +141,7 @@ char* ncplane_at_cursor(struct ncplane* n, uint32_t* attrword, uint64_t* channel int ncplane_at_cursor_cell(struct ncplane* n, cell* c); char* ncplane_at_yx(struct ncplane* n, int y, int x, uint32_t* attrword, uint64_t* channels); int ncplane_at_yx_cell(struct ncplane* n, int y, int x, cell* c); +uint32_t* ncplane_rgba(const struct ncplane* nc, int begy, int begx, int leny, int lenx); void* ncplane_set_userptr(struct ncplane* n, void* opaque); void* ncplane_userptr(struct ncplane* n); int ncplane_resize(struct ncplane* n, int keepy, int keepx, int keepleny, diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 2bc5993cc..29c8d98fd 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -1965,3 +1965,29 @@ ncplane* rotate_plane(const ncplane* n){ ncplane* newp = ncplane_new(n->nc, newy, newx, absy, absx, n->userptr); return newp; } + +uint32_t* ncplane_rgba(const ncplane* nc, int begy, int begx, int leny, int lenx){ + if(begy < 0 || begx < 0){ + return NULL; + } + if(begx >= nc->lenx || begy >= nc->leny){ + return NULL; + } + if(lenx == -1){ // -1 means "to the end"; use all space available + lenx = nc->lenx - begx; + } + if(leny == -1){ + leny = nc->leny - begy; + } + if(lenx < 0 || leny < 0){ // no need to draw zero-size object, exit + return NULL; + } + if(begx + lenx > nc->lenx || begy + leny > nc->leny){ + return NULL; + } + uint32_t* ret = malloc(sizeof(*ret) * lenx * leny); + if(ret){ + // FIXME populate via traversal + } + return ret; +} diff --git a/src/lib/visual.cpp b/src/lib/visual.cpp index 79f7ae914..08c3a8d8b 100644 --- a/src/lib/visual.cpp +++ b/src/lib/visual.cpp @@ -94,10 +94,20 @@ ncvisual* ncvisual_create(float timescale){ } struct ncvisual* ncvisual_from_plane(ncplane* n){ + uint32_t* rgba = ncplane_rgba(n, 0, 0, -1, -1); + if(rgba == NULL){ + return NULL; + } int dimy, dimx; ncplane_dim_yx(n, &dimy, &dimx); - struct ncvisual* ncv = ncvisual_create(1); - // FIXME populate via ncplane_at_yx() traversal + struct ncvisual* ncv = ncvisual_from_rgba(n->nc, rgba, n->leny, n->lenx * 4, n->lenx); + if(ncv == NULL){ + free(rgba); + return NULL; + } + ncplane_destroy(ncv->ncp); + ncv->ncp = n; + ncv->ncobj = NULL; return ncv; } @@ -284,7 +294,7 @@ int ncvisual_render(const ncvisual* ncv, int begy, int begx, int leny, int lenx) if(leny == -1){ leny = ncv->dstheight - begy; } - if(lenx == 0 || leny == 0){ // no need to draw zero-size object, exit + if(lenx < 0 || leny < 0){ // no need to draw zero-size object, exit return 0; } if(begx + lenx > ncv->dstwidth || begy + leny > ncv->dstheight){