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

dankamongmen/linuxfbdumb
nick black 3 years ago
parent 0ffa587a68
commit 14a50cfa3f
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -13,6 +13,8 @@ rearrangements of Notcurses.
the number of columns consumed, and makes available the number of bytes
used by the EGC.
* `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)
* Marked all capability functions `__attribute__ ((pure))`. If you were

@ -2940,6 +2940,19 @@ ncchannels_fchannel(uint64_t channels){
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.
static inline unsigned
ncchannels_fg_rgb(uint64_t channels){

@ -83,6 +83,8 @@ notcurses_channels - operations on notcurses channels
**uint64_t ncchannels_set_bg_default(uint64_t* ***channels***);**
**uint64_t ncchannels_reverse(uint64_t ***channels***);**
# 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
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
**notcurses(3)**,

@ -118,6 +118,10 @@ API int notcurses_ucs32_to_utf8(const char32_t* ucs32, unsigned ucs32count,
#define NCALPHA_BLEND 0x10000000ull
#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
#define CELL_BGDEFAULT_MASK 0x0000000040000000ull
// 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);
}
// 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.
static inline uint64_t
ncchannels_set_bchannel(uint64_t* channels, uint32_t channel){

@ -38,10 +38,6 @@ extern "C" {
struct sixelmap;
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
// blitter stacking rather than the standard trichannel solver.
#define CELL_BLITTERSTACK_MASK CELL_NOBACKGROUND_MASK

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

@ -170,3 +170,28 @@ TEST_CASE("ChannelBlendDefaultRight") {
CHECK(0x20 == b);
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));
}

Loading…
Cancel
Save