add ncchannels_reverse, use it in ncmenu, add unit test #1878

This commit is contained in:
nick black 2021-07-07 09:36:31 -04:00
parent 0ffa587a68
commit 14a50cfa3f
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
7 changed files with 65 additions and 7 deletions

View File

@ -13,6 +13,8 @@ rearrangements of Notcurses.
the number of columns consumed, and makes available the number of bytes the number of columns consumed, and makes available the number of bytes
used by the EGC. used by the EGC.
* `ncmenu`s can now be used with any plane, not just the standard plane. * `ncmenu`s can now be used with any plane, not just the standard plane.
* Added `ncchannels_reverse()`, which reverses the color aspects of the
two channels, while keeping other elements constant.
* 2.3.8 (2021-07-04) * 2.3.8 (2021-07-04)
* Marked all capability functions `__attribute__ ((pure))`. If you were * Marked all capability functions `__attribute__ ((pure))`. If you were

View File

@ -2940,6 +2940,19 @@ ncchannels_fchannel(uint64_t channels){
return ncchannels_bchannel(channels >> 32u); return ncchannels_bchannel(channels >> 32u);
} }
// Returns the channels with the color information swapped, but not
// alpha, nor other housekeeping bits.
static inline uint64_t
ncchannels_reverse(uint64_t channels){
const uint64_t raw = ((uint64_t)ncchannels_bchannel(channels) << 32u) +
ncchannels_fchannel(channels);
const uint64_t statemask = (CELL_NOBACKGROUND_MASK | CELL_FG_ALPHA_MASK |
CELL_BG_ALPHA_MASK | (CELL_NOBACKGROUND_MASK >> 32u));
uint64_t ret = raw & ~statemask;
ret |= channels & statemask;
return ret;
}
// Extract 24 bits of foreground RGB from 'channels', shifted to LSBs. // Extract 24 bits of foreground RGB from 'channels', shifted to LSBs.
static inline unsigned static inline unsigned
ncchannels_fg_rgb(uint64_t channels){ ncchannels_fg_rgb(uint64_t channels){

View File

@ -83,6 +83,8 @@ notcurses_channels - operations on notcurses channels
**uint64_t ncchannels_set_bg_default(uint64_t* ***channels***);** **uint64_t ncchannels_set_bg_default(uint64_t* ***channels***);**
**uint64_t ncchannels_reverse(uint64_t ***channels***);**
# DESCRIPTION # DESCRIPTION
@ -93,6 +95,10 @@ always due to invalid inputs. Functions returning `bool` are predicates, and
return the requested value. Functions returning `unsigned` forms return the return the requested value. Functions returning `unsigned` forms return the
input, modified as requested. input, modified as requested.
**ncchannels_reverse** inverts the color components of the two channels,
while holding all other elements constant. It's the Notcurses approximation
to reverse video.
# SEE ALSO # SEE ALSO
**notcurses(3)**, **notcurses(3)**,

View File

@ -118,6 +118,10 @@ API int notcurses_ucs32_to_utf8(const char32_t* ucs32, unsigned ucs32count,
#define NCALPHA_BLEND 0x10000000ull #define NCALPHA_BLEND 0x10000000ull
#define NCALPHA_OPAQUE 0x00000000ull #define NCALPHA_OPAQUE 0x00000000ull
// Does this glyph completely obscure the background? If so, there's no need
// to emit a background when rasterizing, a small optimization. These are
// also used to track regions into which we must not cellblit.
#define CELL_NOBACKGROUND_MASK 0x8700000000000000ull
// if this bit is set, we are *not* using the default background color // if this bit is set, we are *not* using the default background color
#define CELL_BGDEFAULT_MASK 0x0000000040000000ull #define CELL_BGDEFAULT_MASK 0x0000000040000000ull
// if this bit is set, we are *not* using the default foreground color // if this bit is set, we are *not* using the default foreground color
@ -297,6 +301,19 @@ ncchannels_fchannel(uint64_t channels){
return ncchannels_bchannel(channels >> 32u); return ncchannels_bchannel(channels >> 32u);
} }
// Returns the channels with the color information swapped, but not
// alpha, nor other housekeeping bits.
static inline uint64_t
ncchannels_reverse(uint64_t channels){
const uint64_t raw = ((uint64_t)ncchannels_bchannel(channels) << 32u) +
ncchannels_fchannel(channels);
const uint64_t statemask = (CELL_NOBACKGROUND_MASK | CELL_FG_ALPHA_MASK |
CELL_BG_ALPHA_MASK | (CELL_NOBACKGROUND_MASK >> 32u));
uint64_t ret = raw & ~statemask;
ret |= channels & statemask;
return ret;
}
// Set the 32-bit background channel of a channel pair. // Set the 32-bit background channel of a channel pair.
static inline uint64_t static inline uint64_t
ncchannels_set_bchannel(uint64_t* channels, uint32_t channel){ ncchannels_set_bchannel(uint64_t* channels, uint32_t channel){

View File

@ -38,10 +38,6 @@ extern "C" {
struct sixelmap; struct sixelmap;
struct ncvisual_details; struct ncvisual_details;
// Does this glyph completely obscure the background? If so, there's no need
// to emit a background when rasterizing, a small optimization.
#define CELL_NOBACKGROUND_MASK 0x8700000000000000ull
// Was this glyph drawn as part of an ncvisual? If so, we need to honor // Was this glyph drawn as part of an ncvisual? If so, we need to honor
// blitter stacking rather than the standard trichannel solver. // blitter stacking rather than the standard trichannel solver.
#define CELL_BLITTERSTACK_MASK CELL_NOBACKGROUND_MASK #define CELL_BLITTERSTACK_MASK CELL_NOBACKGROUND_MASK

View File

@ -452,10 +452,9 @@ int ncmenu_unroll(ncmenu* n, int sectionidx){
ncplane_set_channels(n->ncp, n->disablechannels); ncplane_set_channels(n->ncp, n->disablechannels);
} }
if(i == sec->itemselected){ if(i == sec->itemselected){
ncplane_set_styles(n->ncp, NCSTYLE_REVERSE); ncplane_set_channels(n->ncp, ncchannels_reverse(ncplane_channels(n->ncp)));
}else{
ncplane_set_styles(n->ncp, 0);
} }
ncplane_set_styles(n->ncp, 0);
int cols = ncplane_putstr_yx(n->ncp, ypos, xpos + 1, sec->items[i].desc); int cols = ncplane_putstr_yx(n->ncp, ypos, xpos + 1, sec->items[i].desc);
if(cols < 0){ if(cols < 0){
return -1; return -1;

View File

@ -170,3 +170,28 @@ TEST_CASE("ChannelBlendDefaultRight") {
CHECK(0x20 == b); CHECK(0x20 == b);
CHECK(2 == blends); CHECK(2 == blends);
} }
// test that colors are inverted, but nothing else
TEST_CASE("ChannelsReverse") {
uint64_t channels = 0;
uint64_t rev = ncchannels_reverse(channels);
CHECK(0 == rev);
ncchannels_set_fg_palindex(&channels, 8);
rev = ncchannels_reverse(channels);
CHECK(8 == ncchannels_bg_palindex(rev));
CHECK(0 == ncchannels_fg_palindex(rev));
ncchannels_set_fg_palindex(&rev, 63);
rev = ncchannels_reverse(rev);
CHECK(8 == ncchannels_fg_palindex(rev));
CHECK(63 == ncchannels_bg_palindex(rev));
ncchannels_set_fg_default(&rev);
ncchannels_set_bg_alpha(&rev, NCALPHA_TRANSPARENT);
rev = ncchannels_reverse(rev);
CHECK(63 == ncchannels_fg_palindex(rev));
CHECK(ncchannels_bg_default_p(rev));
CHECK(NCALPHA_TRANSPARENT == ncchannels_bg_alpha(rev));
ncchannels_set_fg_rgb(&rev, 0x2288cc);
rev = ncchannels_reverse(rev);
CHECK(0x2288cc == ncchannels_bg_rgb(rev));
CHECK(ncchannels_fg_default_p(rev));
}