mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 09:09:03 -04:00
ncplane_as_rgba(), returns pixel geometry along with bitmap #1508
This commit is contained in:
parent
4996bebad0
commit
05082fc277
5
NEWS.md
5
NEWS.md
@ -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.
|
||||
|
||||
|
8
USAGE.md
8
USAGE.md
@ -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,
|
||||
|
@ -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**).
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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){
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user