Fix cell blit / plane vertical alignment

Deprecate ncplane_align(), after rewriting it as a passthrough
to new function ncplane_halign(). Add ncplane_valign(). Update
all callers. Closes #1468.
This commit is contained in:
nick black 2021-03-27 01:38:48 -04:00 committed by Nick Black
parent 51ccd60e96
commit 86de98c5d2
11 changed files with 85 additions and 45 deletions

View File

@ -7,6 +7,8 @@ rearrangements of Notcurses.
* Added `notcurses_debug_caps()` to dump terminal properties, both those
reported and those inferred, to a `FILE*`.
* Added `NCOPTION_NO_CLEAR_BITMAPS` option for `notcurses_init()`.
* Added `ncplane_valign()` and `ncplane_halign()`. `ncplane_align()` is now
an alias for `ncplane_halign()`, and deprecated.
* Added `NCVISUAL_OPTION_HORALIGNED` and `NCVISUAL_OPTION_VERALIGNED` flags
for `ncvisual_render()`.
* Added `NCPLANE_OPTION_VERALIGNED` flag for `ncplane_create()`.

View File

@ -492,23 +492,34 @@ typedef enum {
NCALIGN_RIGHT,
} ncalign_e;
// Return the column at which 'c' cols ought start in order to be aligned
// according to 'align' within ncplane 'n'. Returns INT_MAX on invalid 'align'.
// Undefined behavior on negative 'c'.
#define NCALIGN_TOP NCALIGN_LEFT
#define NCALIGN_BOTTOM NCALIGN_RIGHT
// Return the offset into 'availu' at which 'u' ought be output given the
// requirements of 'align'. Return -INT_MAX on invalid 'align'. Undefined
// behavior on negative 'availu' or 'u'.
static inline int
ncplane_align(const struct ncplane* n, ncalign_e align, int c){
if(align == NCALIGN_LEFT){
notcurses_align(int availu, ncalign_e align, int u){
if(align == NCALIGN_LEFT || align == NCALIGN_TOP){
return 0;
}
int cols;
ncplane_dim_yx(n, NULL, &cols);
if(align == NCALIGN_CENTER){
return (cols - c) / 2;
}else if(align == NCALIGN_RIGHT){
return cols - c;
return (availu - u) / 2;
}
return INT_MAX;
if(align == NCALIGN_RIGHT || align == NCALIGN_BOTTOM){
return availu - u;
}
return -INT_MAX; // invalid |align|
}
// Return the column at which 'c' cols ought start in order to be aligned
// according to 'align' within ncplane 'n'. Return -INT_MAX on invalid
// 'align'. Undefined behavior on negative 'c'.
static inline int
ncplane_align(const struct ncplane* n, ncalign_e align, int c){
return notcurses_align(ncplane_dim_x(n), align, c);
}
```
## Input

View File

@ -33,7 +33,7 @@
</div>
<hr>
<iframe align="right" width="560" height="315" src="https://www.youtube.com/embed/cYhZ7myXyyg" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<h2><a href="https://nick-black.com/dankwiki/index.php/Notcurses">notcurses</a> man pages (v2.2.3)</h2>
<h2><a href="https://nick-black.com/dankwiki/index.php/Notcurses">notcurses</a> manual pages (v2.2.3)</h2>
<a href="notcurses.3.html">notcurses(3)</a>—a blingful TUI library<br/>
<h3>Executables (section 1)</h3>
<a href="ncls.1.html">ncls</a>—list files, displaying multimedia along with them<br/>

View File

@ -308,7 +308,17 @@ namespace ncpp
int get_align (NCAlign align, int c) const NOEXCEPT_MAYBE
{
return error_guard<int> (ncplane_align (plane, static_cast<ncalign_e>(align), c), INT_MAX);
return error_guard<int> (ncplane_halign (plane, static_cast<ncalign_e>(align), c), INT_MAX);
}
int get_halign (NCAlign align, int c) const NOEXCEPT_MAYBE
{
return error_guard<int> (ncplane_halign (plane, static_cast<ncalign_e>(align), c), INT_MAX);
}
int get_valign (NCAlign align, int r) const NOEXCEPT_MAYBE
{
return error_guard<int> (ncplane_valign (plane, static_cast<ncalign_e>(align), r), INT_MAX);
}
void get_dim (int *rows, int *cols) const noexcept

View File

@ -1454,35 +1454,46 @@ API void* ncplane_userptr(struct ncplane* n);
API void ncplane_center_abs(const struct ncplane* n, int* RESTRICT y,
int* RESTRICT x);
// Return the offset into 'availcols' at which 'cols' ought be output given the
// requirements of 'align'. Return -INT_MAX if unaligned or in case of invalid
// 'align'. Undefined behavior on negative 'cols'.
// Return the offset into 'availu' at which 'u' ought be output given the
// requirements of 'align'. Return -INT_MAX on invalid 'align'. Undefined
// behavior on negative 'availu' or 'u'.
static inline int
notcurses_align(int availcols, ncalign_e align, int cols){
if(cols < 0){
return -INT_MAX;
}
if(align == NCALIGN_LEFT){
return 0;
}
if(cols > availcols){
notcurses_align(int availu, ncalign_e align, int u){
if(align == NCALIGN_LEFT || align == NCALIGN_TOP){
return 0;
}
if(align == NCALIGN_CENTER){
return (availcols - cols) / 2;
return (availu - u) / 2;
}
if(align == NCALIGN_RIGHT){
return availcols - cols;
if(align == NCALIGN_RIGHT || align == NCALIGN_BOTTOM){
return availu - u;
}
return -INT_MAX;
return -INT_MAX; // invalid |align|
}
// Return the column at which 'c' cols ought start in order to be aligned
// according to 'align' within ncplane 'n'. Return -INT_MAX if unaligned
// or in case of invalid 'align'. Undefined behavior on negative 'c'.
// according to 'align' within ncplane 'n'. Return -INT_MAX on invalid
// 'align'. Undefined behavior on negative 'c'.
static inline int
ncplane_halign(const struct ncplane* n, ncalign_e align, int c){
return notcurses_align(ncplane_dim_x(n), align, c);
}
static inline int
ncplane_align(const struct ncplane* n, ncalign_e align, int c)
__attribute__ ((deprecated));
static inline int
ncplane_align(const struct ncplane* n, ncalign_e align, int c){
return notcurses_align(ncplane_dim_x(n), align, c);
return ncplane_halign(n, align, c);
}
// Return the row at which 'r' rows ought start in order to be aligned
// according to 'align' within ncplane 'n'. Return -INT_MAX on invalid
// 'align'. Undefined behavior on negative 'r'.
static inline int
ncplane_valign(const struct ncplane* n, ncalign_e align, int r){
return notcurses_align(ncplane_dim_y(n), align, r);
}
// Move the cursor to the specified position (the cursor needn't be visible).
@ -1646,7 +1657,7 @@ static inline int
ncplane_putwstr_aligned(struct ncplane* n, int y, ncalign_e align,
const wchar_t* gclustarr){
int width = wcswidth(gclustarr, INT_MAX);
int xpos = ncplane_align(n, align, width);
int xpos = ncplane_halign(n, align, width);
if(xpos < 0){
return -1;
}

View File

@ -3417,7 +3417,7 @@ mojiplane(struct ncplane* title, int y, int rows, const char* summary){
ncplane_destroy(n);
return NULL;
}
const int x = ncplane_align(n, NCALIGN_RIGHT, strlen(summary) + 2);
const int x = ncplane_halign(n, NCALIGN_RIGHT, strlen(summary) + 2);
if(ncplane_putstr_yx(n, rows - 1, x, summary) < 0){
ncplane_destroy(n);
return NULL;

View File

@ -376,7 +376,7 @@ reader_demo(struct notcurses* nc){
struct ncplane* std = notcurses_stddim_yx(nc, &dimy, &dimx);
const int READER_COLS = 64;
const int READER_ROWS = 8;
const int x = ncplane_align(std, NCALIGN_CENTER, READER_COLS);
const int x = ncplane_halign(std, NCALIGN_CENTER, READER_COLS);
struct ncselector* selector = NULL;
struct ncmultiselector* mselector = NULL;
struct ncplane_options nopts = {

View File

@ -334,14 +334,14 @@ ncplane* ncplane_new_internal(notcurses* nc, ncplane* n,
p->boundto = p;
}else{ // bound to preexisting pile
if(nopts->flags & NCPLANE_OPTION_HORALIGNED){
p->absx = ncplane_align(n, nopts->x, nopts->cols);
p->absx = ncplane_halign(n, nopts->x, nopts->cols);
p->halign = nopts->x;
}else{
p->absx = nopts->x;
}
p->absx += n->absx;
if(nopts->flags & NCPLANE_OPTION_VERALIGNED){
p->absy = ncplane_align(n, nopts->y, nopts->rows);
p->absy = ncplane_halign(n, nopts->y, nopts->rows);
p->valign = nopts->y;
}else{
p->absy = nopts->y;
@ -2176,11 +2176,11 @@ int ncplane_resize_realign(ncplane* n){
}
int xpos = ncplane_x(n);
if(n->halign != NCALIGN_UNALIGNED){
xpos = ncplane_align(parent, n->halign, ncplane_dim_x(n));
xpos = ncplane_halign(parent, n->halign, ncplane_dim_x(n));
}
int ypos = ncplane_y(n);
if(n->valign != NCALIGN_UNALIGNED){
ypos = ncplane_align(parent, n->valign, ncplane_dim_y(n));
ypos = ncplane_valign(parent, n->valign, ncplane_dim_y(n));
}
return ncplane_move_yx(n, ypos, xpos);
}

View File

@ -78,7 +78,7 @@ ncselector_draw(ncselector* n){
int yoff = 0;
if(n->title){
size_t riserwidth = n->titlecols + 4;
int offx = ncplane_align(n->ncp, NCALIGN_RIGHT, riserwidth);
int offx = ncplane_halign(n->ncp, NCALIGN_RIGHT, riserwidth);
ncplane_cursor_move_yx(n->ncp, 0, 0);
ncplane_hline(n->ncp, &transchar, offx);
ncplane_cursor_move_yx(n->ncp, 0, offx);
@ -92,7 +92,7 @@ ncselector_draw(ncselector* n){
int bodywidth = ncselector_body_width(n);
int dimy, dimx;
ncplane_dim_yx(n->ncp, &dimy, &dimx);
int xoff = ncplane_align(n->ncp, NCALIGN_RIGHT, bodywidth);
int xoff = ncplane_halign(n->ncp, NCALIGN_RIGHT, bodywidth);
if(xoff){
for(int y = yoff + 1 ; y < dimy ; ++y){
ncplane_cursor_move_yx(n->ncp, y, 0);
@ -572,7 +572,7 @@ ncmultiselector_draw(ncmultiselector* n){
int yoff = 0;
if(n->title){
size_t riserwidth = n->titlecols + 4;
int offx = ncplane_align(n->ncp, NCALIGN_RIGHT, riserwidth);
int offx = ncplane_halign(n->ncp, NCALIGN_RIGHT, riserwidth);
ncplane_cursor_move_yx(n->ncp, 0, 0);
ncplane_hline(n->ncp, &transchar, offx);
ncplane_rounded_box_sized(n->ncp, 0, n->boxchannels, 3, riserwidth, 0);
@ -585,7 +585,7 @@ ncmultiselector_draw(ncmultiselector* n){
int bodywidth = ncmultiselector_body_width(n);
int dimy, dimx;
ncplane_dim_yx(n->ncp, &dimy, &dimx);
int xoff = ncplane_align(n->ncp, NCALIGN_RIGHT, bodywidth);
int xoff = ncplane_halign(n->ncp, NCALIGN_RIGHT, bodywidth);
if(xoff){
for(int y = yoff + 1 ; y < dimy ; ++y){
ncplane_cursor_move_yx(n->ncp, y, 0);

View File

@ -421,6 +421,12 @@ ncvisual* ncvisual_from_bgra(const void* bgra, int rows, int rowstride, int cols
return ncv;
}
// by the end, disprows/dispcols refer to the number of source rows/cols (in
// pixels), which will be mapped to a region of cells scaled by the encodings).
// the blit will begin at placey/placex (in terms of cells). begy/begx define
// the origin of the source region to draw (in pixels). leny/lenx defined the
// geometry of the source region to draw, again in pixels. ncv->rows and
// ncv->cols define the source geometry in pixels.
ncplane* ncvisual_render_cells(notcurses* nc, ncvisual* ncv, const struct blitset* bset,
int placey, int placex, int begy, int begx,
int leny, int lenx, ncplane* n, ncscale_e scaling,
@ -480,10 +486,10 @@ ncplane* ncvisual_render_cells(notcurses* nc, ncvisual* ncv, const struct blitse
} // else stretch
}
if(flags & NCVISUAL_OPTION_HORALIGNED){
placex = ncplane_align(n, placex, dispcols / encoding_x_scale(&nc->tcache, bset));
placex = ncplane_halign(n, placex, dispcols / encoding_x_scale(&nc->tcache, bset));
}
if(flags & NCVISUAL_OPTION_VERALIGNED){
placey = ncplane_align(n, placey, disprows / encoding_y_scale(&nc->tcache, bset));
placey = ncplane_valign(n, placey, disprows / encoding_y_scale(&nc->tcache, bset));
}
}
leny = (leny / (double)ncv->rows) * ((double)disprows);

View File

@ -351,7 +351,7 @@ int rendered_mode_player_inner(NotCurses& nc, int argc, char** argv,
ncv = std::make_unique<Visual>(argv[i]);
struct ncvisual_options vopts{};
int r;
vopts.flags |= NCVISUAL_OPTION_HORALIGNED/* | NCVISUAL_OPTION_VERALIGNED*/;
vopts.flags |= NCVISUAL_OPTION_HORALIGNED | NCVISUAL_OPTION_VERALIGNED;
vopts.y = NCALIGN_CENTER;
vopts.x = NCALIGN_CENTER;
vopts.n = n;