subtle ncplane bugfixes

ncplane_dup(): properly set target plane attributes/channels
ncplane_move_below_unsafe(): speedup, at most one traversal
ncplane_rgba(): accept null glyph
ncvisual_from_plane(): dup the plane, own it in ncvisual
normal: spin the visual
This commit is contained in:
nick black 2020-05-11 12:32:45 -04:00
parent 084bb721fa
commit 0f5333f103
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
5 changed files with 58 additions and 20 deletions

View File

@ -3,6 +3,13 @@ rearrangements of Notcurses.
* 1.4.2 (not yet released) * 1.4.2 (not yet released)
* Added `notcurses_canutf8()`, to verify use of UTF-8 encoding. * Added `notcurses_canutf8()`, to verify use of UTF-8 encoding.
* Fixed bug in `ncvisual_from_plane()` when invoked on the standard plane.
* `ncvisual_from_plane()` now accepts the same four geometric parameters
as other plane selectors. To reproduce the old behavior, for `ncv`, call
it as `ncvisual_from_plane(ncv, 0, 0, -1, -1)`.
* `ncvisual_from_plane()`, `ncplane_move_below_unsafe()`, `ncplane_dup()`,
and `ncplane_move_above_unsafe()` now accept `const` arguments where they
did not before.
* 1.4.1 (2020-05-11) * 1.4.1 (2020-05-11)
* No user-visible changes (fixed two unit tests). * No user-visible changes (fixed two unit tests).

View File

@ -990,7 +990,7 @@ API struct ncplane* ncplane_reparent(struct ncplane* n, struct ncplane* newparen
// Duplicate an existing ncplane. The new plane will have the same geometry, // Duplicate an existing ncplane. The new plane will have the same geometry,
// will duplicate all content, and will start with the same rendering state. // will duplicate all content, and will start with the same rendering state.
// The new plane will be immediately above the old one on the z axis. // The new plane will be immediately above the old one on the z axis.
API struct ncplane* ncplane_dup(struct ncplane* n, void* opaque); API struct ncplane* ncplane_dup(const struct ncplane* n, void* opaque);
// provided a coordinate relative to the origin of 'src', map it to the same // provided a coordinate relative to the origin of 'src', map it to the same
// absolute coordinate relative to thte origin of 'dst'. either or both of 'y' // absolute coordinate relative to thte origin of 'dst'. either or both of 'y'
@ -1126,7 +1126,7 @@ API int ncplane_move_bottom(struct ncplane* n);
// Splice ncplane 'n' out of the z-buffer, and reinsert it above 'above'. // Splice ncplane 'n' out of the z-buffer, and reinsert it above 'above'.
API int ncplane_move_above_unsafe(struct ncplane* RESTRICT n, API int ncplane_move_above_unsafe(struct ncplane* RESTRICT n,
struct ncplane* RESTRICT above); const struct ncplane* RESTRICT above);
static inline int static inline int
ncplane_move_above(struct ncplane* n, struct ncplane* above){ ncplane_move_above(struct ncplane* n, struct ncplane* above){
@ -1138,7 +1138,7 @@ ncplane_move_above(struct ncplane* n, struct ncplane* above){
// Splice ncplane 'n' out of the z-buffer, and reinsert it below 'below'. // Splice ncplane 'n' out of the z-buffer, and reinsert it below 'below'.
API int ncplane_move_below_unsafe(struct ncplane* RESTRICT n, API int ncplane_move_below_unsafe(struct ncplane* RESTRICT n,
struct ncplane* RESTRICT below); const struct ncplane* RESTRICT below);
static inline int static inline int
ncplane_move_below(struct ncplane* n, struct ncplane* below){ ncplane_move_below(struct ncplane* n, struct ncplane* below){
@ -2802,7 +2802,8 @@ API int ncplane_qrcode(struct ncplane* n, int maxversion, const void* data, size
// in a NULL being returned. This function exists so that planes can be // in a NULL being returned. This function exists so that planes can be
// subjected to ncvisual transformations. If possible, it's usually better // subjected to ncvisual transformations. If possible, it's usually better
// to create the ncvisual from memory using ncvisual_from_rgba(). // to create the ncvisual from memory using ncvisual_from_rgba().
API struct ncvisual* ncvisual_from_plane(struct ncplane* n); API struct ncvisual* ncvisual_from_plane(const struct ncplane* n,
int begy, int begx, int leny, int lenx);
#define NCREADER_OPTION_HORSCROLL 0x0001 #define NCREADER_OPTION_HORSCROLL 0x0001
#define NCREADER_OPTION_VERSCROLL 0x0002 #define NCREADER_OPTION_VERSCROLL 0x0002

View File

@ -36,6 +36,7 @@ offset(uint32_t* rgba, int y, int x, int dx){
int normal_demo(struct notcurses* nc){ int normal_demo(struct notcurses* nc){
int dy, dx; int dy, dx;
struct ncplane* n = notcurses_stddim_yx(nc, &dy, &dx); struct ncplane* n = notcurses_stddim_yx(nc, &dy, &dx);
ncplane_erase(n);
dy *= VSCALE; // double-block trick means both 2x resolution and even linecount yay dy *= VSCALE; // double-block trick means both 2x resolution and even linecount yay
uint32_t* rgba = malloc(sizeof(*rgba) * dy * dx); uint32_t* rgba = malloc(sizeof(*rgba) * dy * dx);
if(!rgba){ if(!rgba){
@ -66,5 +67,20 @@ int normal_demo(struct notcurses* nc){
DEMO_RENDER(nc); DEMO_RENDER(nc);
} }
free(rgba); free(rgba);
struct ncvisual* ncv = ncvisual_from_plane(n, 0, 0, -1, -1);
if(!ncv){
return -1;
}
// FIXME use smaller rotations once supported
for(int i = 1 ; i < 4 ; ++i){
if(ncvisual_rotate(ncv, M_PI / 2)){
return -1;
}
if(ncvisual_render(ncv, 0, 0, -1, -1) <= 0){
return -1;
}
DEMO_RENDER(nc);
}
ncvisual_destroy(ncv);
return 0; return 0;
} }

View File

@ -367,7 +367,7 @@ inline int ncplane_cursor_move_yx(ncplane* n, int y, int x){
return 0; return 0;
} }
ncplane* ncplane_dup(ncplane* n, void* opaque){ ncplane* ncplane_dup(const ncplane* n, void* opaque){
int dimy = n->leny; int dimy = n->leny;
int dimx = n->lenx; int dimx = n->lenx;
int aty = n->absy; int aty = n->absy;
@ -383,8 +383,8 @@ ncplane* ncplane_dup(ncplane* n, void* opaque){
return NULL; return NULL;
}else{ }else{
ncplane_cursor_move_yx(newn, y, x); ncplane_cursor_move_yx(newn, y, x);
n->attrword = attr; newn->attrword = attr;
n->channels = chan; newn->channels = chan;
ncplane_move_above_unsafe(newn, n); ncplane_move_above_unsafe(newn, n);
memmove(newn->fb, n->fb, sizeof(*n->fb) * dimx * dimy); memmove(newn->fb, n->fb, sizeof(*n->fb) * dimx * dimy);
} }
@ -499,7 +499,7 @@ int ncplane_resize(ncplane* n, int keepy, int keepx, int keepleny,
// find the pointer on the z-index referencing the specified plane. writing to // find the pointer on the z-index referencing the specified plane. writing to
// this pointer will remove the plane (and everything below it) from the stack. // this pointer will remove the plane (and everything below it) from the stack.
static ncplane** static ncplane**
find_above_ncplane(ncplane* n){ find_above_ncplane(const ncplane* n){
notcurses* nc = n->nc; notcurses* nc = n->nc;
ncplane** above = &nc->top; ncplane** above = &nc->top;
while(*above){ while(*above){
@ -1189,7 +1189,7 @@ const char* cell_extended_gcluster(const ncplane* n, const cell* c){
} }
// 'n' ends up above 'above' // 'n' ends up above 'above'
int ncplane_move_above_unsafe(ncplane* restrict n, ncplane* restrict above){ int ncplane_move_above_unsafe(ncplane* restrict n, const ncplane* restrict above){
if(n->z == above){ if(n->z == above){
return 0; return 0;
} }
@ -1201,24 +1201,37 @@ int ncplane_move_above_unsafe(ncplane* restrict n, ncplane* restrict above){
if(aa == NULL){ if(aa == NULL){
return -1; return -1;
} }
ncplane* deconst_above = *aa;
*an = n->z; // splice n out *an = n->z; // splice n out
n->z = above; // attach above below n n->z = deconst_above; // attach above below n
*aa = n; // spline n in above *aa = n; // spline n in above
return 0; return 0;
} }
// 'n' ends up below 'below' // 'n' ends up below 'below'
int ncplane_move_below_unsafe(ncplane* restrict n, ncplane* restrict below){ int ncplane_move_below_unsafe(ncplane* restrict n, const ncplane* restrict below){
if(below->z == n){ if(below->z == n){
return 0; return 0;
} }
ncplane** an = find_above_ncplane(n); ncplane* deconst_below = NULL;
ncplane** an = &n->nc->top;
// go down, looking for n and below. if we find below, mark it. if we
// find n, break from the loop.
while(*an){
if(*an == below){
deconst_below = *an;
}else if(*an == n){
*an = n->z; // splice n out
}
}
if(an == NULL){ if(an == NULL){
return -1; return -1;
} }
*an = n->z; // splice n out while(deconst_below != below){
n->z = below->z; // reattach subbelow list to n deconst_below = deconst_below->z;
below->z = n; // splice n in below }
n->z = deconst_below->z; // reattach subbelow list to n
deconst_below->z = n; // splice n in below
return 0; return 0;
} }
@ -2054,7 +2067,7 @@ uint32_t* ncplane_rgba(const ncplane* nc, int begy, int begx, int leny, int lenx
// FIXME how do we deal with transparency? // FIXME how do we deal with transparency?
uint32_t frgba = (fr << 24u) + (fg << 16u) + (fb << 8u) + 0xff; uint32_t frgba = (fr << 24u) + (fg << 16u) + (fb << 8u) + 0xff;
uint32_t brgba = (br << 24u) + (bg << 16u) + (bb << 8u) + 0xff; uint32_t brgba = (br << 24u) + (bg << 16u) + (bb << 8u) + 0xff;
if(strcmp(c, " ") == 0){ if((strcmp(c, " ") == 0) || (strcmp(c, "") == 0)){
*top = *bot = brgba; *top = *bot = brgba;
}else if(strcmp(c, "") == 0){ }else if(strcmp(c, "") == 0){
*top = frgba; *top = frgba;

View File

@ -105,8 +105,9 @@ auto ncvisual_create(float timescale) -> ncvisual* {
return ret; return ret;
} }
auto ncvisual_from_plane(ncplane* n) -> ncvisual* { auto ncvisual_from_plane(const ncplane* n, int begy, int begx, int leny, int lenx)
uint32_t* rgba = ncplane_rgba(n, 0, 0, -1, -1); -> ncvisual* {
uint32_t* rgba = ncplane_rgba(n, begx, begy, leny, lenx);
if(rgba == nullptr){ if(rgba == nullptr){
return nullptr; return nullptr;
} }
@ -118,8 +119,8 @@ auto ncvisual_from_plane(ncplane* n) -> ncvisual* {
return nullptr; return nullptr;
} }
ncplane_destroy(ncv->ncp); ncplane_destroy(ncv->ncp);
ncv->ncp = n; ncv->ncp = ncplane_dup(n, nullptr);
ncv->ncobj = nullptr; ncv->ncobj = n->nc;
return ncv; return ncv;
} }