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 * Added `notcurses_debug_caps()` to dump terminal properties, both those
reported and those inferred, to a `FILE*`. reported and those inferred, to a `FILE*`.
* Added `NCOPTION_NO_CLEAR_BITMAPS` option for `notcurses_init()`. * 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 * Added `NCVISUAL_OPTION_HORALIGNED` and `NCVISUAL_OPTION_VERALIGNED` flags
for `ncvisual_render()`. for `ncvisual_render()`.
* Added `NCPLANE_OPTION_VERALIGNED` flag for `ncplane_create()`. * Added `NCPLANE_OPTION_VERALIGNED` flag for `ncplane_create()`.

View File

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

View File

@ -33,7 +33,7 @@
</div> </div>
<hr> <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> <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/> <a href="notcurses.3.html">notcurses(3)</a>—a blingful TUI library<br/>
<h3>Executables (section 1)</h3> <h3>Executables (section 1)</h3>
<a href="ncls.1.html">ncls</a>—list files, displaying multimedia along with them<br/> <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 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 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, API void ncplane_center_abs(const struct ncplane* n, int* RESTRICT y,
int* RESTRICT x); int* RESTRICT x);
// Return the offset into 'availcols' at which 'cols' ought be output given the // Return the offset into 'availu' at which 'u' ought be output given the
// requirements of 'align'. Return -INT_MAX if unaligned or in case of invalid // requirements of 'align'. Return -INT_MAX on invalid 'align'. Undefined
// 'align'. Undefined behavior on negative 'cols'. // behavior on negative 'availu' or 'u'.
static inline int static inline int
notcurses_align(int availcols, ncalign_e align, int cols){ notcurses_align(int availu, ncalign_e align, int u){
if(cols < 0){ if(align == NCALIGN_LEFT || align == NCALIGN_TOP){
return -INT_MAX;
}
if(align == NCALIGN_LEFT){
return 0;
}
if(cols > availcols){
return 0; return 0;
} }
if(align == NCALIGN_CENTER){ if(align == NCALIGN_CENTER){
return (availcols - cols) / 2; return (availu - u) / 2;
} }
if(align == NCALIGN_RIGHT){ if(align == NCALIGN_RIGHT || align == NCALIGN_BOTTOM){
return availcols - cols; 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 // 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 // according to 'align' within ncplane 'n'. Return -INT_MAX on invalid
// or in case of invalid 'align'. Undefined behavior on negative 'c'. // '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 static inline int
ncplane_align(const struct ncplane* n, ncalign_e align, int c){ 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). // 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, ncplane_putwstr_aligned(struct ncplane* n, int y, ncalign_e align,
const wchar_t* gclustarr){ const wchar_t* gclustarr){
int width = wcswidth(gclustarr, INT_MAX); int width = wcswidth(gclustarr, INT_MAX);
int xpos = ncplane_align(n, align, width); int xpos = ncplane_halign(n, align, width);
if(xpos < 0){ if(xpos < 0){
return -1; return -1;
} }

View File

@ -3417,7 +3417,7 @@ mojiplane(struct ncplane* title, int y, int rows, const char* summary){
ncplane_destroy(n); ncplane_destroy(n);
return NULL; 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){ if(ncplane_putstr_yx(n, rows - 1, x, summary) < 0){
ncplane_destroy(n); ncplane_destroy(n);
return NULL; return NULL;

View File

@ -376,7 +376,7 @@ reader_demo(struct notcurses* nc){
struct ncplane* std = notcurses_stddim_yx(nc, &dimy, &dimx); struct ncplane* std = notcurses_stddim_yx(nc, &dimy, &dimx);
const int READER_COLS = 64; const int READER_COLS = 64;
const int READER_ROWS = 8; 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 ncselector* selector = NULL;
struct ncmultiselector* mselector = NULL; struct ncmultiselector* mselector = NULL;
struct ncplane_options nopts = { struct ncplane_options nopts = {

View File

@ -334,14 +334,14 @@ ncplane* ncplane_new_internal(notcurses* nc, ncplane* n,
p->boundto = p; p->boundto = p;
}else{ // bound to preexisting pile }else{ // bound to preexisting pile
if(nopts->flags & NCPLANE_OPTION_HORALIGNED){ 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; p->halign = nopts->x;
}else{ }else{
p->absx = nopts->x; p->absx = nopts->x;
} }
p->absx += n->absx; p->absx += n->absx;
if(nopts->flags & NCPLANE_OPTION_VERALIGNED){ 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; p->valign = nopts->y;
}else{ }else{
p->absy = nopts->y; p->absy = nopts->y;
@ -2176,11 +2176,11 @@ int ncplane_resize_realign(ncplane* n){
} }
int xpos = ncplane_x(n); int xpos = ncplane_x(n);
if(n->halign != NCALIGN_UNALIGNED){ 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); int ypos = ncplane_y(n);
if(n->valign != NCALIGN_UNALIGNED){ 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); return ncplane_move_yx(n, ypos, xpos);
} }

View File

@ -78,7 +78,7 @@ ncselector_draw(ncselector* n){
int yoff = 0; int yoff = 0;
if(n->title){ if(n->title){
size_t riserwidth = n->titlecols + 4; 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_cursor_move_yx(n->ncp, 0, 0);
ncplane_hline(n->ncp, &transchar, offx); ncplane_hline(n->ncp, &transchar, offx);
ncplane_cursor_move_yx(n->ncp, 0, offx); ncplane_cursor_move_yx(n->ncp, 0, offx);
@ -92,7 +92,7 @@ ncselector_draw(ncselector* n){
int bodywidth = ncselector_body_width(n); int bodywidth = ncselector_body_width(n);
int dimy, dimx; int dimy, dimx;
ncplane_dim_yx(n->ncp, &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){ if(xoff){
for(int y = yoff + 1 ; y < dimy ; ++y){ for(int y = yoff + 1 ; y < dimy ; ++y){
ncplane_cursor_move_yx(n->ncp, y, 0); ncplane_cursor_move_yx(n->ncp, y, 0);
@ -572,7 +572,7 @@ ncmultiselector_draw(ncmultiselector* n){
int yoff = 0; int yoff = 0;
if(n->title){ if(n->title){
size_t riserwidth = n->titlecols + 4; 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_cursor_move_yx(n->ncp, 0, 0);
ncplane_hline(n->ncp, &transchar, offx); ncplane_hline(n->ncp, &transchar, offx);
ncplane_rounded_box_sized(n->ncp, 0, n->boxchannels, 3, riserwidth, 0); 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 bodywidth = ncmultiselector_body_width(n);
int dimy, dimx; int dimy, dimx;
ncplane_dim_yx(n->ncp, &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){ if(xoff){
for(int y = yoff + 1 ; y < dimy ; ++y){ for(int y = yoff + 1 ; y < dimy ; ++y){
ncplane_cursor_move_yx(n->ncp, y, 0); 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; 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, ncplane* ncvisual_render_cells(notcurses* nc, ncvisual* ncv, const struct blitset* bset,
int placey, int placex, int begy, int begx, int placey, int placex, int begy, int begx,
int leny, int lenx, ncplane* n, ncscale_e scaling, 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 } // else stretch
} }
if(flags & NCVISUAL_OPTION_HORALIGNED){ 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){ 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); 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]); ncv = std::make_unique<Visual>(argv[i]);
struct ncvisual_options vopts{}; struct ncvisual_options vopts{};
int r; int r;
vopts.flags |= NCVISUAL_OPTION_HORALIGNED/* | NCVISUAL_OPTION_VERALIGNED*/; vopts.flags |= NCVISUAL_OPTION_HORALIGNED | NCVISUAL_OPTION_VERALIGNED;
vopts.y = NCALIGN_CENTER; vopts.y = NCALIGN_CENTER;
vopts.x = NCALIGN_CENTER; vopts.x = NCALIGN_CENTER;
vopts.n = n; vopts.n = n;