ncplane_as_rgba(), returns pixel geometry along with bitmap #1508

This commit is contained in:
nick black 2021-04-08 04:12:01 -04:00
parent 4996bebad0
commit 05082fc277
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
9 changed files with 64 additions and 17 deletions

View File

@ -1,6 +1,11 @@
This document attempts to list user-visible changes and any major internal
rearrangements of Notcurses.
* 2.2.6 (not yet released)
* `ncplane_rgba()` has been deprecated in favor of the new function
`ncplane_as_rgba()`, which the former now wraps. It will be removed
in ABI3. The new function can report the synthesized pixel geometry.
* 2.2.5 (2021-04-04)
* Bugfix release, no user-visible changes.

View File

@ -1017,9 +1017,11 @@ int ncplane_at_yx_cell(struct ncplane* n, int y, int x, nccell* c);
// 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.
uint32_t* ncplane_rgba(const struct ncplane* nc, ncblitter_e blit,
int begy, int begx, int leny, int lenx);
// Only glyphs from the specified blitset may be present. If 'pxdimy' and/or
// 'pxdimx' are non-NULL, they will be filled in with the pixel geometry.
uint32_t* ncplane_as_rgba(const struct ncplane* n, ncblitter_e blit,
int begy, int begx, int leny, int lenx,
int *pxdimy, int *pxdimx);
// return a nul-terminated, heap copy of the current (UTF-8) contents.
char* ncplane_contents(const struct ncplane* nc, int begy, int begx,

View File

@ -104,7 +104,7 @@ typedef struct ncplane_options {
**int ncplane_at_yx_cell(struct ncplane* ***n***, int ***y***, int ***x***, nccell* ***c***);**
**uint32_t* ncplane_rgba(const struct ncplane* ***nc***, int ***begy***, int ***begx***, int ***leny***, int ***lenx***);**
**uint32_t* ncplane_as_rgba(const struct ncplane* ***nc***, int ***begy***, int ***begx***, int ***leny***, int ***lenx***, int* ***pxdimy***, int* ***pxdimx***);**
**char* ncplane_contents(const struct ncplane* ***nc***, int ***begy***, int ***begx***, int ***leny***, int ***lenx***);**
@ -373,6 +373,9 @@ this result. **ncplane_at_yx_cell** and **ncplane_at_cursor_cell** instead load
these values into an **nccell**, which is invalidated if the associated plane is
destroyed. The caller should release this **nccell** with **cell_release**.
**ncplane_as_rgba** returns a heap-allocated array of **uint32_t** values,
each representing a single RGBA pixel, or **NULL** on failure.
Functions returning **int** return 0 on success, and non-zero on error.
All other functions cannot fail (and return **void**).

View File

@ -805,7 +805,7 @@ namespace ncpp
uint32_t* rgba(ncblitter_e blit, int begy, int begx, int leny, int lenx) const noexcept
{
return ncplane_rgba (plane, blit, begy, begx, leny, lenx);
return ncplane_as_rgba (plane, blit, begy, begx, leny, lenx, nullptr, nullptr);
}
char* content(int begy, int begx, int leny, int lenx) const noexcept

View File

@ -2450,9 +2450,20 @@ struct ncvisual_options {
// 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 ALLOC uint32_t* ncplane_rgba(const struct ncplane* n, ncblitter_e blit,
int begy, int begx, int leny, int lenx);
// Only glyphs from the specified blitset may be present. If 'pxdimy' and/or
// 'pxdimx' are non-NULL, they will be filled in with the pixel geometry.
API ALLOC uint32_t* ncplane_as_rgba(const struct ncplane* n, ncblitter_e blit,
int begy, int begx, int leny, int lenx,
int *pxdimy, int *pxdimx)
__attribute__ ((nonnull (1)));
// Deprecated in favor of ncplane_as_rgba. This will be removed in ABI3.
ALLOC __attribute__ ((deprecated)) __attribute__ ((nonnull (1)))
static inline uint32_t*
ncplane_rgba(const struct ncplane* n, ncblitter_e blit,
int begy, int begx, int leny, int lenx){
return ncplane_as_rgba(n, blit, begy, begx, leny, lenx, NULL, NULL);
}
// 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

View File

@ -2424,12 +2424,16 @@ int ncdirect_inputready_fd(ncdirect* n){
return n->input.ttyinfd;
}
uint32_t* ncplane_rgba(const ncplane* nc, ncblitter_e blit,
int begy, int begx, int leny, int lenx){
uint32_t* ncplane_as_rgba(const ncplane* nc, ncblitter_e blit,
int begy, int begx, int leny, int lenx,
int *pxdimy, int *pxdimx){
const notcurses* ncur = ncplane_notcurses_const(nc);
if(begy < 0 || begx < 0){
logerror(ncur, "Nil offset (%d,%d)\n", begy, begx);
return NULL;
}
if(begx >= nc->lenx || begy >= nc->leny){
logerror(ncur, "Invalid offset (%d,%d)\n", begy, begx);
return NULL;
}
if(lenx == -1){ // -1 means "to the end"; use all space available
@ -2439,13 +2443,27 @@ uint32_t* ncplane_rgba(const ncplane* nc, ncblitter_e blit,
leny = nc->leny - begy;
}
if(lenx < 0 || leny < 0){ // no need to draw zero-size object, exit
logerror(ncur, "Nil geometry (%dx%d)\n", leny, lenx);
return NULL;
}
//fprintf(stderr, "sum: %d/%d avail: %d/%d\n", begy + leny, begx + lenx, nc->leny, nc->lenx);
if(begx + lenx > nc->lenx || begy + leny > nc->leny){
logerror(ncur, "Invalid specs %d + %d > %d or %d + %d > %d\n",
begx, lenx, nc->lenx, begy, leny, nc->leny);
return NULL;
}
if(blit > NCBLIT_2x1){
logerror(ncur, "Blitter %d is not yet supported\n", blit);
return NULL;
}
//fprintf(stderr, "ALLOCATING %zu\n", 4u * lenx * leny * 2);
// FIXME this all assumes NCBLIT_2x1, need blitter-specific scaling
if(pxdimy){
*pxdimy = leny * 2;
}
if(pxdimx){
*pxdimx = lenx;
}
uint32_t* ret = malloc(sizeof(*ret) * lenx * leny * 2);
if(ret){
for(int y = begy, targy = 0 ; y < begy + leny ; ++y, targy += 2){
@ -2466,8 +2484,6 @@ uint32_t* ncplane_rgba(const ncplane* nc, ncblitter_e blit,
// FIXME how do we deal with transparency?
uint32_t frgba = (fr) + (fg << 16u) + (fb << 8u) + 0xff000000;
uint32_t brgba = (br) + (bg << 16u) + (bb << 8u) + 0xff000000;
// FIXME integrate 'blit'
(void)blit;
// FIXME need to be able to pick up quadrants!
if((strcmp(c, " ") == 0) || (strcmp(c, "") == 0)){
*top = *bot = brgba;

View File

@ -698,7 +698,7 @@ ncplane* ncvisual_render(notcurses* nc, ncvisual* ncv, const struct ncvisual_opt
ncvisual* ncvisual_from_plane(const ncplane* n, ncblitter_e blit, int begy, int begx,
int leny, int lenx){
uint32_t* rgba = ncplane_rgba(n, blit, begy, begx, leny, lenx);
uint32_t* rgba = ncplane_as_rgba(n, blit, begy, begx, leny, lenx, NULL, NULL);
//fprintf(stderr, "snarg: %d/%d @ %d/%d (%p)\n", leny, lenx, begy, begx, rgba);
//fprintf(stderr, "RGBA %p\n", rgba);
if(rgba == NULL){

View File

@ -24,7 +24,8 @@ rotate_grad(struct notcurses* nc){
}
notcurses_render(nc);
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
uint32_t* rgba = ncplane_rgba(n, NCBLIT_DEFAULT, 0, 0, dimy, dimx);
uint32_t* rgba = ncplane_as_rgba(n, NCBLIT_DEFAULT, 0, 0,
dimy, dimx, NULL, NULL);
if(rgba == NULL){
return -1;
}
@ -150,7 +151,8 @@ rotate(struct notcurses* nc){
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);;
// we now have 2 rows of 20 cells each, with gradients. load 'em.
uint32_t* rgba = ncplane_rgba(n, NCBLIT_DEFAULT, dimy / 2, 0, 2, XSIZE);
uint32_t* rgba = ncplane_as_rgba(n, NCBLIT_DEFAULT, dimy / 2, 0,
2, XSIZE, NULL, NULL);
if(rgba == NULL){
return -1;
}

View File

@ -173,8 +173,12 @@ TEST_CASE("Rotate") {
ncvisual_options opts{};
auto rendered = ncvisual_render(nc_, ncv, &opts);
REQUIRE(rendered);
uint32_t* rgbaret = ncplane_rgba(rendered, NCBLIT_DEFAULT, 0, 0, -1, -1);
int pxdimy, pxdimx;
uint32_t* rgbaret = ncplane_as_rgba(rendered, NCBLIT_DEFAULT,
0, 0, -1, -1, &pxdimy, &pxdimx);
REQUIRE(rgbaret);
CHECK(pxdimx == width);
CHECK(pxdimy == height);
for(int i = 0 ; i < height * width / 2 ; ++i){
if(rgbaret[i] & CELL_BG_RGB_MASK){
CHECK(htole(rgbaret[i]) == rgba[i]);
@ -226,8 +230,12 @@ TEST_CASE("Rotate") {
ncvisual_options opts{};
auto rendered = ncvisual_render(nc_, ncv, &opts);
REQUIRE(rendered);
uint32_t* rgbaret = ncplane_rgba(rendered, NCBLIT_DEFAULT, 0, 0, -1, -1);
int pxdimy, pxdimx;
uint32_t* rgbaret = ncplane_as_rgba(rendered, NCBLIT_DEFAULT,
0, 0, -1, -1, &pxdimy, &pxdimx);
REQUIRE(rgbaret);
CHECK(pxdimy == height);
CHECK(pxdimx == width);
for(int i = 0 ; i < height * width / 2 ; ++i){
if(rgbaret[i] & CELL_BG_RGB_MASK){
CHECK(htole(rgbaret[i]) == rgba[i]);