Channels API sanity #119 (#138)

* orthogonalize channel/channels/cells APIs #119
* sync README.md with new ncplane channels api #119
This commit is contained in:
Nick Black 2019-12-14 05:33:34 -05:00 committed by GitHub
parent e3dd36a1a4
commit ff463d464e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1080 additions and 590 deletions

546
README.md
View File

@ -11,6 +11,7 @@ by [nick black](https://nick-black.com/dankwiki/index.php/Hack_on) (<nickblack@l
* [Cells](#cells)
* [Multimedia](#multimedia)
* [Panelreels](#panelreels)
* [Channels](#channels)
* [Perf](#perf)
* [Included tools](#included-tools)
* [Differences from NCURSES](#differences-from-ncurses)
@ -59,23 +60,31 @@ which offers only eight colors and limited glyphs).
Why use this non-standard library?
* A svelter design than that codified in X/Open. All exported identifiers
are prefixed to avoid namespace collisions. Far fewer identifiers are
exported overall. All APIs natively suport UTF-8, and the `cell` API is based
around Unicode's [Extended Grapheme Cluster](https://unicode.org/reports/tr29/) concept.
* Thread safety, and efficient use in parallel programs, has been a design
consideration from the beginning.
* Visual features not directly available via NCURSES, including images,
fonts, video, high-contrast text, and transparent regions. All APIs
natively support 24-bit color, quantized down as necessary for the terminal.
* A svelter design than that codified by X/Open.
* Exported identifiers are prefixed to avoid common namespace collisions.
* The library object exports a minimal set of symbols. Where reasonable,
`static inline` header-only code is used. This facilitates compiler
optimizations, and reduces loader time.
* Thread safety, and use in parallel programs, has been a design consideration
from the beginning.
* All APIs natively suport UTF-8. The `cell` API is based around Unicode's
[Extended Grapheme Cluster](https://unicode.org/reports/tr29/) concept.
* Visual features including images, fonts, video, high-contrast text, sprites,
and transparent regions. All APIs natively support 24-bit color, quantized
down as necessary for the terminal.
* It's Apache2-licensed in its entirety, as opposed to the
[drama in several acts](https://invisible-island.net/ncurses/ncurses-license.html)
that is the NCURSES license (the latter is [summarized](https://invisible-island.net/ncurses/ncurses-license.html#issues_freer)
as "a restatement of MIT-X11").
Much of the above can be had with NCURSES, but they're not what NCURSES was
*designed* for. The most fundamental advantage in my mind, though, is
that notcurses is of the multithreaded era.
On the other hand, if you're targeting industrial or critical applications,
or wish to benefit from the time-tested reliability and portability of Curses,
you should by all means use that fine library.
@ -728,6 +737,81 @@ int ncplane_putwstr_aligned(struct ncplane* n, int y,
const wchar_t* gclustarr, ncalign_e atype);
```
#### Plane channels API
Helpers are provided to manipulate an `ncplane`'s `channels` member. They are
all implemented in terms of the lower-level [Channels API](#channels).
```c
// Get the current channels or attribute word for ncplane 'n'.
API uint64_t ncplane_get_channels(const struct ncplane* n);
API uint32_t ncplane_get_attr(const struct ncplane* n);
// Extract the 32-bit working background channel from an ncplane.
static inline unsigned
ncplane_get_bchannel(const struct ncplane* nc){
return channels_get_bchannel(ncplane_get_channels(nc));
}
// Extract the 32-bit working foreground channel from an ncplane.
static inline unsigned
ncplane_get_fchannel(const struct ncplane* nc){
return channels_get_fchannel(ncplane_get_channels(nc));
}
// Extract 24 bits of working foreground RGB from an ncplane, shifted to LSBs.
static inline unsigned
ncplane_get_fg(const struct ncplane* nc){
return channels_get_fg(ncplane_get_channels(nc));
}
// Extract 24 bits of working background RGB from an ncplane, shifted to LSBs.
static inline unsigned
ncplane_get_bg(const struct ncplane* nc){
return channels_get_bg(ncplane_get_channels(nc));
}
// Extract 2 bits of foreground alpha from 'struct ncplane', shifted to LSBs.
static inline unsigned
ncplane_get_fg_alpha(const struct ncplane* nc){
return channels_get_fg_alpha(ncplane_get_channels(nc));
}
/ Extract 2 bits of background alpha from 'struct ncplane', shifted to LSBs.
static inline unsigned
ncplane_get_bg_alpha(const struct ncplane* nc){
return channels_get_bg_alpha(ncplane_get_channels(nc));
}
// Extract 24 bits of foreground RGB from 'n', split into subcomponents.
static inline unsigned
ncplane_get_fg_rgb(const struct ncplane* n, unsigned* r, unsigned* g, unsigned*
return channels_get_fg_rgb(ncplane_get_channels(n), r, g, b);
}
// Extract 24 bits of background RGB from 'n', split into subcomponents.
static inline unsigned
ncplane_get_bg_rgb(const struct ncplane* n, unsigned* r, unsigned* g, unsigned*
return channels_get_bg_rgb(ncplane_get_channels(n), r, g, b);
}
// Set the current fore/background color using RGB specifications. If the
// terminal does not support directly-specified 3x8b cells (24-bit "Direct
// Color", indicated by the "RGB" terminfo capability), the provided values
// will be interpreted in some lossy fashion. None of r, g, or b may exceed 255.
// "HP-like" terminals require setting foreground and background at the same
// time using "color pairs"; notcurses will manage color pairs transparently.
int ncplane_set_fg_rgb(struct ncplane* n, int r, int g, int b);
int ncplane_set_bg_rgb(struct ncplane* n, int r, int g, int b);
// Same, but with rgb assembled into a channel (i.e. lower 32 bits).
void ncplane_set_fg(struct ncplane* n, uint32_t channel);
void ncplane_set_bg(struct ncplane* n, uint32_t channel);
// use the default color for the foreground/background
void ncplane_set_fg_default(struct ncplane* n);
void ncplane_set_bg_default(struct ncplane* n);
```
### Cells
Unlike the `notcurses` or `ncplane` objects, the definition of `cell` is
@ -759,12 +843,12 @@ typedef struct cell {
uint32_t gcluster; // 1 * 4b -> 4b
// CELL_STYLE_* attributes (16 bits) + 16 reserved bits
uint32_t attrword; // + 4b -> 8b
// (channels & 0x8000000000000000ull): wide character (left or right side)
// (channels & 0x8000000000000000ull): left half of wide character
// (channels & 0x4000000000000000ull): foreground is *not* "default color"
// (channels & 0x3000000000000000ull): foreground alpha (2 bits)
// (channels & 0x0f00000000000000ull): reserved, must be 0
// (channels & 0x00ffffff00000000ull): foreground in 3x8 RGB (rrggbb)
// (channels & 0x0000000080000000ull): reserved, must be 0
// (channels & 0x0000000080000000ull): right half of wide character
// (channels & 0x0000000040000000ull): background is *not* "default color"
// (channels & 0x0000000030000000ull): background alpha (2 bits)
// (channels & 0x000000000f000000ull): reserved, must be 0
@ -869,140 +953,6 @@ cell_styles_off(cell* c, unsigned stylebits){
c->attrword &= ~((stylebits & 0xffff) << 16u);
}
static inline unsigned
cell_rgb_red(uint32_t rgb){
return (rgb & 0xff0000ull) >> 16u;
}
static inline unsigned
cell_rgb_green(uint32_t rgb){
return (rgb & 0xff00ull) >> 8u;
}
static inline unsigned
cell_rgb_blue(uint32_t rgb){
return (rgb & 0xffull);
}
#define CELL_INHERITSTYLE_MASK 0x8000000000000000ull
#define CELL_FGDEFAULT_MASK 0x4000000000000000ull
#define CELL_WIDEASIAN_MASK 0x2000000000000000ull
#define CELL_FG_MASK 0x00ffffff00000000ull
#define CELL_BGDEFAULT_MASK 0x0000000040000000ull
#define CELL_BG_MASK 0x0000000000ffffffull
static inline uint32_t
cell_fg_rgb(uint64_t channel){
return (channel & CELL_FG_MASK) >> 32u;
}
static inline uint32_t
cell_bg_rgb(uint64_t channel){
return (channel & CELL_BG_MASK);
}
static inline void
cell_rgb_get_fg(uint64_t channels, unsigned* r, unsigned* g, unsigned* b){
uint32_t fg = cell_fg_rgb(channels);
*r = cell_rgb_red(fg);
*g = cell_rgb_green(fg);
*b = cell_rgb_blue(fg);
}
static inline void
cell_rgb_get_bg(uint64_t channels, unsigned* r, unsigned* g, unsigned* b){
uint32_t bg = cell_bg_rgb(channels);
*r = cell_rgb_red(bg);
*g = cell_rgb_green(bg);
*b = cell_rgb_blue(bg);
}
// set the r, g, and b channels for either the foreground or background
// component of this 64-bit 'channels' variable. 'shift' is the base number
// of bits to shift r/g/b by; it ought either be 0 (bg) or 32 (fg). each of
// r, g, and b must be in [0, 256), or -1 is returned. 'mask' is the
// appropriate r/g/b mask, and 'nodefbit' is the appropriate nodefault bit.
static inline int
notcurses_channel_prep(uint64_t* channels, uint64_t mask, unsigned shift,
int r, int g, int b, uint64_t nodefbit){
if(r >= 256 || g >= 256 || b >= 256){
return -1;
}
if(r < 0 || g < 0 || b < 0){
return -1;
}
uint64_t rgb = (r & 0xffull) << (shift + 16);
rgb |= (g & 0xffull) << (shift + 8);
rgb |= (b & 0xffull) << shift;
rgb |= nodefbit;
*channels = (*channels & ~(mask | nodefbit)) | rgb;
return 0;
}
static inline int
notcurses_fg_prep(uint64_t* channels, int r, int g, int b){
return notcurses_channel_prep(channels, CELL_FG_MASK, 32, r, g, b, CELL_FGDEFAULT_MASK);
}
static inline int
notcurses_bg_prep(uint64_t* channels, int r, int g, int b){
return notcurses_channel_prep(channels, CELL_BG_MASK, 0, r, g, b, CELL_BGDEFAULT_MASK);
}
static inline void
cell_set_fg(cell* c, unsigned r, unsigned g, unsigned b){
notcurses_fg_prep(&c->channels, r, g, b);
}
static inline void
cell_set_bg(cell* c, unsigned r, unsigned g, unsigned b){
notcurses_bg_prep(&c->channels, r, g, b);
}
static inline void
cell_get_fg(const cell* c, unsigned* r, unsigned* g, unsigned* b){
*r = cell_rgb_red(cell_fg_rgb(c->channels));
*g = cell_rgb_green(cell_fg_rgb(c->channels));
*b = cell_rgb_blue(cell_fg_rgb(c->channels));
}
static inline void
cell_get_bg(const cell* c, unsigned* r, unsigned* g, unsigned* b){
*r = cell_rgb_red(cell_bg_rgb(c->channels));
*g = cell_rgb_green(cell_bg_rgb(c->channels));
*b = cell_rgb_blue(cell_bg_rgb(c->channels));
}
// does the cell passively retain the styling of the previously-rendered cell?
static inline bool
cell_inherits_style(const cell* c){
return (c->channels & CELL_INHERITSTYLE_MASK);
}
// use the default color for the foreground
static inline void
cell_fg_default(cell* c){
c->channels &= ~CELL_FGDEFAULT_MASK;
}
// is the cell using the terminal's default foreground color for its foreground?
static inline bool
cell_fg_default_p(const cell* c){
return !(c->channels & CELL_FGDEFAULT_MASK);
}
// use the default color for the background
static inline void
cell_bg_default(cell* c){
c->channels &= ~CELL_BGDEFAULT_MASK;
}
// is the cell using the terminal's default background color for its background?
static inline bool
cell_bg_default_p(const cell* c){
return !(c->channels & CELL_BGDEFAULT_MASK);
}
// does the cell contain an East Asian Wide codepoint?
static inline bool
cell_double_wide_p(const cell* c){
@ -1070,6 +1020,89 @@ cells_double_box(struct ncplane* n, uint32_t attr, uint64_t channels,
}
```
#### Cell channels API
Helpers are provided to manipulate a `cell`'s `channels` member. They are all
implemented in terms of the lower-level [Channels API](#channels).
```c
// Extract the 32-bit background channel from a cell.
static inline unsigned
cell_get_bchannel(const cell* cl){
return channels_get_bchannel(cl->channels);
}
// Extract the 32-bit foreground channel from a cell.
static inline unsigned
cell_get_fchannel(const cell* cl){
return channels_get_fchannel(cl->channels);
}
// Extract 24 bits of foreground RGB from 'cell', shifted to LSBs.
static inline unsigned
cell_get_fg(const cell* cl){
return channels_get_fg(cl->channels);
}
// Extract 24 bits of background RGB from 'cell', shifted to LSBs.
static inline unsigned
cell_get_bg(const cell* cl){
return channels_get_bg(cl->channels);
}
// Extract 2 bits of foreground alpha from 'cell', shifted to LSBs.
static inline unsigned
cell_get_fg_alpha(const cell* cl){
return channels_get_fg_alpha(cl->channels);
}
// Extract 2 bits of background alpha from 'cell', shifted to LSBs.
static inline unsigned
cell_get_bg_alpha(const cell* cl){
return channels_get_bg_alpha(cl->channels);
}
// Extract 24 bits of foreground RGB from 'cell', split into subcell.
static inline unsigned
cell_get_fg_rgb(const cell* cl, unsigned* r, unsigned* g, unsigned* b){
return channels_get_fg_rgb(cl->channels, r, g, b);
}
// Extract 24 bits of background RGB from 'cell', split into subcell.
static inline unsigned
cell_get_bg_rgb(const cell* cl, unsigned* r, unsigned* g, unsigned* b){
return channels_get_bg_rgb(cl->channels, r, g, b);
}
// Set the r, g, and b cell for the foreground component of this 64-bit
// 'cell' variable, and mark it as not using the default color.
static inline int
cell_set_fg_rgb(cell* cl, int r, int g, int b){
return channels_set_fg_rgb(&cl->channels, r, g, b);
}
// Set the r, g, and b cell for the background component of this 64-bit
// 'cell' variable, and mark it as not using the default color.
static inline int
cell_set_bg_rgb(cell* cl, int r, int g, int b){
return channels_set_bg_rgb(&cl->channels, r, g, b);
}
// Is the foreground using the "default foreground color"?
static inline bool
cell_fg_default_p(const cell* cl){
return channels_fg_default_p(cl->channels);
}
// Is the background using the "default background color"? The "default
// background color" must generally be used to take advantage of
// terminal-effected transparency.
static inline bool
cell_bg_default_p(const cell* cl){
return channels_bg_default_p(cl->channels);
}
```
### Multimedia
Media decoding and scaling is handled by libAV from FFmpeg, resulting in a
@ -1106,6 +1139,224 @@ int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, int* averr);
Panelreels are a complex UI abstraction offered by notcurses, derived from my
similar work in [outcurses](https://github.com/dankamongmen/outcurses#Panelreels).
**FIXME**
### Channels
A channel encodes 24 bits of RGB color, using 8 bits for each component. It
additionally provides 2 bits of alpha channel, a bit for selecting terminal
default colors, and a bit to indicate whether it describes a Wide East Asian
character. The remaining four bits are reserved. Typically two channels are
bound together in a 64-bit unsigned integer (`uint64_t`), with eight bits
currently going unused. There is such a double-channel in every `cell` and
`ncplane` object.
Usually, the higher-level `ncplane` and `cell` functionality ought be used. It
will sometimes be necessary, however, to muck with channels at their lowest
level. The channel API facilitates such muckery. All channel-related `ncplane`
and `cell` functionality is implemented in terms of this API.
```c
// Extract the 8-bit red component from a 32-bit channel.
static inline unsigned
channel_get_r(unsigned channel){
return (channel & 0xff0000u) >> 16u;
}
// Extract the 8-bit green component from a 32-bit channel.
static inline unsigned
channel_get_g(unsigned channel){
return (channel & 0x00ff00u) >> 8u;
}
// Extract the 8-bit blue component from a 32-bit channel.
static inline unsigned
channel_get_b(unsigned channel){
return (channel & 0x0000ffu);
}
// Extract the three 8-bit R/G/B components from a 32-bit channel.
static inline unsigned
channel_get_rgb(unsigned channel, unsigned* r, unsigned* g, unsigned* b){
*r = channel_get_r(channel);
*g = channel_get_g(channel);
*b = channel_get_b(channel);
return channel;
}
// Set the three 8-bit components of a 32-bit channel, and mark it as not using
// the default color. Retain the other bits unchanged.
static inline int
channel_set_rgb(unsigned* channel, int r, int g, int b){
if(r >= 256 || g >= 256 || b >= 256){
return -1;
}
if(r < 0 || g < 0 || b < 0){
return -1;
}
unsigned c = (r << 16u) | (g << 8u) | b;
c |= CELL_BGDEFAULT_MASK;
const uint64_t mask = CELL_BGDEFAULT_MASK | CELL_BG_MASK;
*channel = (*channel & ~mask) | c;
return 0;
}
// Extract the 2-bit alpha component from a 32-bit channel.
static inline unsigned
channel_get_alpha(unsigned channel){
return (channel & CELL_BGALPHA_MASK) >> 28u;
}
// Set the 2-bit alpha component of the 32-bit channel.
static inline int
channel_set_alpha(unsigned* channel, int alpha){
if(alpha < 0 || alpha > 3){
return -1;
}
*channel = (alpha << 28u) | (*channel & ~CELL_BGALPHA_MASK);
return 0;
}
// Is this channel using the "default color" rather than its RGB?
static inline bool
channel_default_p(unsigned channel){
return !(channel & CELL_BGDEFAULT_MASK);
}
// Mark the channel as using its default color.
static inline unsigned
channel_set_default(unsigned* channel){
return *channel &= ~CELL_BGDEFAULT_MASK;
}
// Extract the 32-bit background channel from a channel pair.
static inline unsigned
channels_get_bchannel(uint64_t channels){
return channels & 0xfffffffflu;
}
// Extract the 32-bit foreground channel from a channel pair.
static inline unsigned
channels_get_fchannel(uint64_t channels){
return channels_get_bchannel(channels >> 32u);
}
// Extract 24 bits of foreground RGB from 'channels', shifted to LSBs.
static inline unsigned
channels_get_fg(uint64_t channels){
return channels_get_fchannel(channels) & CELL_BG_MASK;
}
// Extract 24 bits of background RGB from 'channels', shifted to LSBs.
static inline unsigned
channels_get_bg(uint64_t channels){
return channels_get_bchannel(channels) & CELL_BG_MASK;
}
// Extract 2 bits of foreground alpha from 'channels', shifted to LSBs.
static inline unsigned
channels_get_fg_alpha(uint64_t channels){
return channel_get_alpha(channels_get_fchannel(channels));
}
// Extract 2 bits of background alpha from 'channels', shifted to LSBs.
static inline unsigned
channels_get_bg_alpha(uint64_t channels){
return channel_get_alpha(channels_get_bchannel(channels));
}
// Extract 24 bits of foreground RGB from 'channels', split into subchannels.
static inline unsigned
channels_get_fg_rgb(uint64_t channels, unsigned* r, unsigned* g, unsigned* b){
return channel_get_rgb(channels_get_fchannel(channels), r, g, b);
}
// Extract 24 bits of background RGB from 'channels', split into subchannels.
static inline unsigned
channels_get_bg_rgb(uint64_t channels, unsigned* r, unsigned* g, unsigned* b){
return channel_get_rgb(channels_get_bchannel(channels), r, g, b);
}
// Set the r, g, and b channels for the foreground component of this 64-bit
// 'channels' variable, and mark it as not using the default color.
static inline int
channels_set_fg_rgb(uint64_t* channels, int r, int g, int b){
unsigned channel = channels_get_fchannel(*channels);
if(channel_set_rgb(&channel, r, g, b) < 0){
return -1;
}
*channels = ((uint64_t)channel << 32llu) | (*channels & 0xffffffffllu);
return 0;
}
// Set the r, g, and b channels for the background component of this 64-bit
// 'channels' variable, and mark it as not using the default color.
static inline int
channels_set_bg_rgb(uint64_t* channels, int r, int g, int b){
unsigned channel = channels_get_bchannel(*channels);
if(channel_set_rgb(&channel, r, g, b) < 0){
return -1;
}
*channels = (*channels & 0xffffffff00000000llu) | channel;
return 0;
}
// Set the 2-bit alpha component of the foreground channel.
static inline int
channels_set_fg_alpha(uint64_t* channels, int alpha){
unsigned channel = channels_get_fchannel(*channels);
if(channel_set_alpha(&channel, alpha) < 0){
return -1;
}
*channels = ((uint64_t)channel << 32llu) | (*channels & 0xffffffffllu);
return 0;
}
// Set the 2-bit alpha component of the background channel.
static inline int
channels_set_bg_alpha(uint64_t* channels, int alpha){
unsigned channel = channels_get_bchannel(*channels);
if(channel_set_alpha(&channel, alpha) < 0){
return -1;
}
*channels = (*channels & 0xffffffff00000000llu) | channel;
return 0;
}
// Is the foreground using the "default foreground color"?
static inline bool
channels_fg_default_p(uint64_t channels){
return channel_default_p(channels_get_fchannel(channels));
}
// Is the background using the "default background color"? The "default
// background color" must generally be used to take advantage of
// terminal-effected transparency.
static inline bool
channels_bg_default_p(uint64_t channels){
return channel_default_p(channels_get_bchannel(channels));
}
// Mark the foreground channel as using its default color.
static inline uint64_t
channels_set_fg_default(uint64_t* channels){
unsigned channel = channels_get_fchannel(*channels);
channel_set_default(&channel);
*channels = ((uint64_t)channel << 32llu) | (*channels & 0xffffffffllu);
return *channels;
}
// Mark the foreground channel as using its default color.
static inline uint64_t
channels_set_bg_default(uint64_t* channels){
unsigned channel = channels_get_bchannel(*channels);
channel_set_default(&channel);
*channels = (*channels & 0xffffffff00000000llu) | channel;
return *channels;
}
```
### Perf
notcurses tracks statistics across its operation, and a snapshot can be
@ -1271,6 +1522,9 @@ compat_mvwprintw(struct ncplane* nc, int y, int x, const char* fmt, ...){
the BiDi state machine transitions, and thus merrily continues writing
left-to-right. ﷽
* The unit tests assume dimensions of at least 80x25. They might work in a
smaller terminal. They might not. Don't file bugs on it.
## Supplemental material
### Useful links
@ -1285,6 +1539,8 @@ compat_mvwprintw(struct ncplane* nc, int y, int x, const char* fmt, ...){
* [Unicode Standard Annex #29 Text Segmentation](http://www.unicode.org/reports/tr29)
* [Unicode Standard Annex #15 Normalization Forms](https://unicode.org/reports/tr15/)
* [The TTY demystified](http://www.linusakesson.net/programming/tty/)
* [Dark Corners of Unicode](https://eev.ee/blog/2015/09/12/dark-corners-of-unicode/)
* [UTF-8 Decoder Capability and Stress Test](https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt)
### History

View File

@ -78,12 +78,12 @@ typedef struct cell {
uint32_t gcluster; // 1 * 4b -> 4b
// CELL_STYLE_* attributes (16 bits) + 16 reserved bits
uint32_t attrword; // + 4b -> 8b
// (channels & 0x8000000000000000ull): wide character (left or right side)
// (channels & 0x8000000000000000ull): left half of wide character
// (channels & 0x4000000000000000ull): foreground is *not* "default color"
// (channels & 0x3000000000000000ull): foreground alpha (2 bits)
// (channels & 0x0f00000000000000ull): reserved, must be 0
// (channels & 0x00ffffff00000000ull): foreground in 3x8 RGB (rrggbb)
// (channels & 0x0000000080000000ull): reserved, must be 0
// (channels & 0x0000000080000000ull): right half of wide character
// (channels & 0x0000000040000000ull): background is *not* "default color"
// (channels & 0x0000000030000000ull): background alpha (2 bits)
// (channels & 0x000000000f000000ull): reserved, must be 0
@ -380,20 +380,18 @@ ncplane_putc_yx(struct ncplane* n, int y, int x, const cell* c){
return ncplane_putc(n, c);
}
// Replace the cell underneath the cursor with the provided 7-bit char 'c',
// using the specified 'attr' and 'channels' for styling. Advance the cursor by
// 1. On success, returns 1. On failure, returns -1. This works whether the
// underlying char is signed or unsigned.
API int ncplane_putsimple(struct ncplane* n, char c, uint32_t attr, uint64_t channels);
// Replace the cell underneath the cursor with the provided 7-bit char 'c'.
// Advance the cursor by 1. On success, returns 1. On failure, returns -1.
// This works whether the underlying char is signed or unsigned.
API int ncplane_putsimple(struct ncplane* n, char c);
// Call ncplane_simple() after successfully moving to y, x.
static inline int
ncplane_putsimple_yx(struct ncplane* n, int y, int x, char c,
uint32_t attr, uint64_t channels){
ncplane_putsimple_yx(struct ncplane* n, int y, int x, char c){
if(ncplane_cursor_move_yx(n, y, x)){
return -1;
}
return ncplane_putsimple(n, c, attr, channels);
return ncplane_putsimple(n, c);
}
// Replace the cell underneath the cursor with the provided EGC, using the
@ -591,6 +589,344 @@ ncplane_box_sized(struct ncplane* n, const cell* ul, const cell* ur,
// with this ncplane is invalidated, and must not be used after the call.
API void ncplane_erase(struct ncplane* n);
#define CELL_WIDEASIAN_MASK 0x8000000000000000ull
#define CELL_FGDEFAULT_MASK 0x4000000000000000ull
#define CELL_FGALPHA_MASK 0x3000000000000000ull
#define CELL_FG_MASK 0x00ffffff00000000ull
#define CELL_BGDEFAULT_MASK 0x0000000040000000ull
#define CELL_BGALPHA_MASK 0x0000000030000000ull
#define CELL_BG_MASK 0x0000000000ffffffull
// These lowest-level functions manipulate a 64-bit channel encoding directly.
// Users will typically manipulate ncplane and cell channels through those APIs,
// rather than calling these directly.
// Extract the 8-bit red component from a 32-bit channel.
static inline unsigned
channel_get_r(unsigned channel){
return (channel & 0xff0000u) >> 16u;
}
// Extract the 8-bit green component from a 32-bit channel.
static inline unsigned
channel_get_g(unsigned channel){
return (channel & 0x00ff00u) >> 8u;
}
// Extract the 8-bit blue component from a 32-bit channel.
static inline unsigned
channel_get_b(unsigned channel){
return (channel & 0x0000ffu);
}
// Extract the three 8-bit R/G/B components from a 32-bit channel.
static inline unsigned
channel_get_rgb(unsigned channel, unsigned* r, unsigned* g, unsigned* b){
*r = channel_get_r(channel);
*g = channel_get_g(channel);
*b = channel_get_b(channel);
return channel;
}
// Set the three 8-bit components of a 32-bit channel, and mark it as not using
// the default color. Retain the other bits unchanged.
static inline int
channel_set_rgb(unsigned* channel, int r, int g, int b){
if(r >= 256 || g >= 256 || b >= 256){
return -1;
}
if(r < 0 || g < 0 || b < 0){
return -1;
}
unsigned c = (r << 16u) | (g << 8u) | b;
c |= CELL_BGDEFAULT_MASK;
const uint64_t mask = CELL_BGDEFAULT_MASK | CELL_BG_MASK;
*channel = (*channel & ~mask) | c;
return 0;
}
// Extract the 2-bit alpha component from a 32-bit channel.
static inline unsigned
channel_get_alpha(unsigned channel){
return (channel & CELL_BGALPHA_MASK) >> 28u;
}
// Set the 2-bit alpha component of the 32-bit channel.
static inline int
channel_set_alpha(unsigned* channel, int alpha){
if(alpha < 0 || alpha > 3){
return -1;
}
*channel = (alpha << 28u) | (*channel & ~CELL_BGALPHA_MASK);
return 0;
}
// Is this channel using the "default color" rather than its RGB?
static inline bool
channel_default_p(unsigned channel){
return !(channel & CELL_BGDEFAULT_MASK);
}
// Mark the channel as using its default color.
static inline unsigned
channel_set_default(unsigned* channel){
return *channel &= ~CELL_BGDEFAULT_MASK;
}
// Extract the 32-bit background channel from a channel pair.
static inline unsigned
channels_get_bchannel(uint64_t channels){
return channels & 0xfffffffflu;
}
// Extract the 32-bit foreground channel from a channel pair.
static inline unsigned
channels_get_fchannel(uint64_t channels){
return channels_get_bchannel(channels >> 32u);
}
// Extract 24 bits of foreground RGB from 'channels', shifted to LSBs.
static inline unsigned
channels_get_fg(uint64_t channels){
return channels_get_fchannel(channels) & CELL_BG_MASK;
}
// Extract 24 bits of background RGB from 'channels', shifted to LSBs.
static inline unsigned
channels_get_bg(uint64_t channels){
return channels_get_bchannel(channels) & CELL_BG_MASK;
}
// Extract 2 bits of foreground alpha from 'channels', shifted to LSBs.
static inline unsigned
channels_get_fg_alpha(uint64_t channels){
return channel_get_alpha(channels_get_fchannel(channels));
}
// Extract 2 bits of background alpha from 'channels', shifted to LSBs.
static inline unsigned
channels_get_bg_alpha(uint64_t channels){
return channel_get_alpha(channels_get_bchannel(channels));
}
// Extract 24 bits of foreground RGB from 'channels', split into subchannels.
static inline unsigned
channels_get_fg_rgb(uint64_t channels, unsigned* r, unsigned* g, unsigned* b){
return channel_get_rgb(channels_get_fchannel(channels), r, g, b);
}
// Extract 24 bits of background RGB from 'channels', split into subchannels.
static inline unsigned
channels_get_bg_rgb(uint64_t channels, unsigned* r, unsigned* g, unsigned* b){
return channel_get_rgb(channels_get_bchannel(channels), r, g, b);
}
// Set the r, g, and b channels for the foreground component of this 64-bit
// 'channels' variable, and mark it as not using the default color.
static inline int
channels_set_fg_rgb(uint64_t* channels, int r, int g, int b){
unsigned channel = channels_get_fchannel(*channels);
if(channel_set_rgb(&channel, r, g, b) < 0){
return -1;
}
*channels = ((uint64_t)channel << 32llu) | (*channels & 0xffffffffllu);
return 0;
}
// Set the r, g, and b channels for the background component of this 64-bit
// 'channels' variable, and mark it as not using the default color.
static inline int
channels_set_bg_rgb(uint64_t* channels, int r, int g, int b){
unsigned channel = channels_get_bchannel(*channels);
if(channel_set_rgb(&channel, r, g, b) < 0){
return -1;
}
*channels = (*channels & 0xffffffff00000000llu) | channel;
return 0;
}
// Set the 2-bit alpha component of the foreground channel.
static inline int
channels_set_fg_alpha(uint64_t* channels, int alpha){
unsigned channel = channels_get_fchannel(*channels);
if(channel_set_alpha(&channel, alpha) < 0){
return -1;
}
*channels = ((uint64_t)channel << 32llu) | (*channels & 0xffffffffllu);
return 0;
}
// Set the 2-bit alpha component of the background channel.
static inline int
channels_set_bg_alpha(uint64_t* channels, int alpha){
unsigned channel = channels_get_bchannel(*channels);
if(channel_set_alpha(&channel, alpha) < 0){
return -1;
}
*channels = (*channels & 0xffffffff00000000llu) | channel;
return 0;
}
// Is the foreground using the "default foreground color"?
static inline bool
channels_fg_default_p(uint64_t channels){
return channel_default_p(channels_get_fchannel(channels));
}
// Is the background using the "default background color"? The "default
// background color" must generally be used to take advantage of
// terminal-effected transparency.
static inline bool
channels_bg_default_p(uint64_t channels){
return channel_default_p(channels_get_bchannel(channels));
}
// Mark the foreground channel as using its default color.
static inline uint64_t
channels_set_fg_default(uint64_t* channels){
unsigned channel = channels_get_fchannel(*channels);
channel_set_default(&channel);
*channels = ((uint64_t)channel << 32llu) | (*channels & 0xffffffffllu);
return *channels;
}
// Mark the foreground channel as using its default color.
static inline uint64_t
channels_set_bg_default(uint64_t* channels){
unsigned channel = channels_get_bchannel(*channels);
channel_set_default(&channel);
*channels = (*channels & 0xffffffff00000000llu) | channel;
return *channels;
}
// Extract the 32-bit background channel from a cell.
static inline unsigned
cell_get_bchannel(const cell* cl){
return channels_get_bchannel(cl->channels);
}
// Extract the 32-bit foreground channel from a cell.
static inline unsigned
cell_get_fchannel(const cell* cl){
return channels_get_fchannel(cl->channels);
}
// Extract 24 bits of foreground RGB from 'cell', shifted to LSBs.
static inline unsigned
cell_get_fg(const cell* cl){
return channels_get_fg(cl->channels);
}
// Extract 24 bits of background RGB from 'cell', shifted to LSBs.
static inline unsigned
cell_get_bg(const cell* cl){
return channels_get_bg(cl->channels);
}
// Extract 2 bits of foreground alpha from 'cell', shifted to LSBs.
static inline unsigned
cell_get_fg_alpha(const cell* cl){
return channels_get_fg_alpha(cl->channels);
}
// Extract 2 bits of background alpha from 'cell', shifted to LSBs.
static inline unsigned
cell_get_bg_alpha(const cell* cl){
return channels_get_bg_alpha(cl->channels);
}
// Extract 24 bits of foreground RGB from 'cell', split into subcell.
static inline unsigned
cell_get_fg_rgb(const cell* cl, unsigned* r, unsigned* g, unsigned* b){
return channels_get_fg_rgb(cl->channels, r, g, b);
}
// Extract 24 bits of background RGB from 'cell', split into subcell.
static inline unsigned
cell_get_bg_rgb(const cell* cl, unsigned* r, unsigned* g, unsigned* b){
return channels_get_bg_rgb(cl->channels, r, g, b);
}
// Set the r, g, and b cell for the foreground component of this 64-bit
// 'cell' variable, and mark it as not using the default color.
static inline int
cell_set_fg_rgb(cell* cl, int r, int g, int b){
return channels_set_fg_rgb(&cl->channels, r, g, b);
}
// Set the r, g, and b cell for the background component of this 64-bit
// 'cell' variable, and mark it as not using the default color.
static inline int
cell_set_bg_rgb(cell* cl, int r, int g, int b){
return channels_set_bg_rgb(&cl->channels, r, g, b);
}
// Is the foreground using the "default foreground color"?
static inline bool
cell_fg_default_p(const cell* cl){
return channels_fg_default_p(cl->channels);
}
// Is the background using the "default background color"? The "default
// background color" must generally be used to take advantage of
// terminal-effected transparency.
static inline bool
cell_bg_default_p(const cell* cl){
return channels_bg_default_p(cl->channels);
}
// Get the current channels or attribute word for ncplane 'n'.
API uint64_t ncplane_get_channels(const struct ncplane* n);
API uint32_t ncplane_get_attr(const struct ncplane* n);
// Extract the 32-bit working background channel from an ncplane.
static inline unsigned
ncplane_get_bchannel(const struct ncplane* nc){
return channels_get_bchannel(ncplane_get_channels(nc));
}
// Extract the 32-bit working foreground channel from an ncplane.
static inline unsigned
ncplane_get_fchannel(const struct ncplane* nc){
return channels_get_fchannel(ncplane_get_channels(nc));
}
// Extract 24 bits of working foreground RGB from an ncplane, shifted to LSBs.
static inline unsigned
ncplane_get_fg(const struct ncplane* nc){
return channels_get_fg(ncplane_get_channels(nc));
}
// Extract 24 bits of working background RGB from an ncplane, shifted to LSBs.
static inline unsigned
ncplane_get_bg(const struct ncplane* nc){
return channels_get_bg(ncplane_get_channels(nc));
}
// Extract 2 bits of foreground alpha from 'struct ncplane', shifted to LSBs.
static inline unsigned
ncplane_get_fg_alpha(const struct ncplane* nc){
return channels_get_fg_alpha(ncplane_get_channels(nc));
}
// Extract 2 bits of background alpha from 'struct ncplane', shifted to LSBs.
static inline unsigned
ncplane_get_bg_alpha(const struct ncplane* nc){
return channels_get_bg_alpha(ncplane_get_channels(nc));
}
// Extract 24 bits of foreground RGB from 'n', split into subcomponents.
static inline unsigned
ncplane_get_fg_rgb(const struct ncplane* n, unsigned* r, unsigned* g, unsigned* b){
return channels_get_fg_rgb(ncplane_get_channels(n), r, g, b);
}
// Extract 24 bits of background RGB from 'n', split into subcomponents.
static inline unsigned
ncplane_get_bg_rgb(const struct ncplane* n, unsigned* r, unsigned* g, unsigned* b){
return channels_get_bg_rgb(ncplane_get_channels(n), r, g, b);
}
// Set the current fore/background color using RGB specifications. If the
// terminal does not support directly-specified 3x8b cells (24-bit "Direct
// Color", indicated by the "RGB" terminfo capability), the provided values
@ -600,33 +936,13 @@ API void ncplane_erase(struct ncplane* n);
API int ncplane_set_fg_rgb(struct ncplane* n, int r, int g, int b);
API int ncplane_set_bg_rgb(struct ncplane* n, int r, int g, int b);
API uint64_t ncplane_get_channels(const struct ncplane* n);
// Same, but with rgb assembled into a half-channel (i.e. lower 32 bits).
API void ncplane_set_fg(struct ncplane* n, uint32_t halfchannel);
API void ncplane_set_bg(struct ncplane* n, uint32_t halfchannel);
#define CELL_WIDEASIAN_MASK 0x8000000000000000ull
#define CELL_FGDEFAULT_MASK 0x4000000000000000ull
#define CELL_FGALPHA_MASK 0x3000000000000000ull
#define CELL_FG_MASK 0x00ffffff00000000ull
#define CELL_BGDEFAULT_MASK 0x0000000040000000ull
#define CELL_BGALPHA_MASK 0x3000000030000000ull
#define CELL_BG_MASK 0x0000000000ffffffull
static inline uint32_t
ncplane_fg_rgb(uint64_t channel){
return (channel & CELL_FG_MASK) >> 32u;
}
static inline uint32_t
ncplane_bg_rgb(uint64_t channel){
return (channel & CELL_BG_MASK);
}
// Same, but with rgb assembled into a channel (i.e. lower 32 bits).
API void ncplane_set_fg(struct ncplane* n, uint32_t channel);
API void ncplane_set_bg(struct ncplane* n, uint32_t channel);
// use the default color for the foreground/background
API void ncplane_fg_default(struct ncplane* n);
API void ncplane_bg_default(struct ncplane* n);
API void ncplane_set_fg_default(struct ncplane* n);
API void ncplane_set_bg_default(struct ncplane* n);
// Set the specified style bits for the ncplane 'n', whether they're actively
// supported or not.
@ -725,193 +1041,26 @@ cell_styles_off(cell* c, unsigned stylebits){
c->attrword &= ~((stylebits & 0xffff) << CELL_STYLE_SHIFT);
}
static inline unsigned
cell_rgb_red(uint32_t rgb){
return (rgb & 0xff0000ull) >> 16u;
}
static inline unsigned
cell_rgb_green(uint32_t rgb){
return (rgb & 0xff00ull) >> 8u;
}
static inline unsigned
cell_rgb_blue(uint32_t rgb){
return (rgb & 0xffull);
}
static inline uint32_t
cell_fg_rgb(uint64_t channel){
return (channel & CELL_FG_MASK) >> 32u;
}
static inline uint32_t
cell_bg_rgb(uint64_t channel){
return (channel & CELL_BG_MASK);
}
static inline void
cell_rgb_get_fg(uint64_t channels, unsigned* r, unsigned* g, unsigned* b){
uint32_t fg = cell_fg_rgb(channels);
*r = cell_rgb_red(fg);
*g = cell_rgb_green(fg);
*b = cell_rgb_blue(fg);
}
static inline void
cell_rgb_get_bg(uint64_t channels, unsigned* r, unsigned* g, unsigned* b){
uint32_t bg = cell_bg_rgb(channels);
*r = cell_rgb_red(bg);
*g = cell_rgb_green(bg);
*b = cell_rgb_blue(bg);
}
// set the r, g, and b channels for either the foreground or background
// component of this 64-bit 'channels' variable. 'shift' is the base number
// of bits to shift r/g/b by; it ought either be 0 (bg) or 32 (fg). each of
// r, g, and b must be in [0, 256), or -1 is returned. 'mask' is the
// appropriate r/g/b mask, and 'nodefbit' is the appropriate nodefault bit.
static inline int
notcurses_channel_prep(uint64_t* channels, uint64_t mask, unsigned shift,
int r, int g, int b, uint64_t nodefbit){
if(r >= 256 || g >= 256 || b >= 256){
return -1;
}
if(r < 0 || g < 0 || b < 0){
return -1;
}
uint64_t rgb = (r & 0xffull) << (shift + 16);
rgb |= (g & 0xffull) << (shift + 8);
rgb |= (b & 0xffull) << shift;
rgb |= nodefbit;
*channels = (*channels & ~(mask | nodefbit)) | rgb;
return 0;
}
static inline int
notcurses_fg_set_alpha(uint64_t* channels, int alpha){
if(alpha > 3 || alpha < 0){
return -1;
}
*channels = (*channels & ~CELL_FGALPHA_MASK) | ((uint64_t)alpha << 60);
return 0;
}
static inline int
notcurses_bg_set_alpha(uint64_t* channels, int alpha){
if(alpha > 3 || alpha < 0){
return -1;
}
*channels = (*channels & ~CELL_BGALPHA_MASK) | ((uint64_t)alpha << 28);
return 0;
}
static inline int
notcurses_fg_alpha(uint64_t channels){
return (channels & CELL_BGALPHA_MASK) >> 60u;
}
static inline int
notcurses_bg_alpha(uint64_t channels){
return (channels & CELL_BGALPHA_MASK) >> 28u;
}
static inline int
notcurses_fg_prep(uint64_t* channels, int r, int g, int b){
return notcurses_channel_prep(channels, CELL_FG_MASK, 32, r, g, b, CELL_FGDEFAULT_MASK);
}
static inline int
notcurses_bg_prep(uint64_t* channels, int r, int g, int b){
return notcurses_channel_prep(channels, CELL_BG_MASK, 0, r, g, b, CELL_BGDEFAULT_MASK);
}
static inline void
notcurses_fg_default_prep(uint64_t* channels){
*channels &= ~(CELL_FGDEFAULT_MASK);
}
static inline void
notcurses_bg_default_prep(uint64_t* channels){
*channels &= ~(CELL_BGDEFAULT_MASK);
}
static inline void
cell_set_fg(cell* c, unsigned r, unsigned g, unsigned b){
notcurses_fg_prep(&c->channels, r, g, b);
}
static inline void
cell_set_bg(cell* c, unsigned r, unsigned g, unsigned b){
notcurses_bg_prep(&c->channels, r, g, b);
}
static inline void
cell_get_fg(const cell* c, unsigned* r, unsigned* g, unsigned* b){
*r = cell_rgb_red(cell_fg_rgb(c->channels));
*g = cell_rgb_green(cell_fg_rgb(c->channels));
*b = cell_rgb_blue(cell_fg_rgb(c->channels));
}
static inline void
cell_get_bg(const cell* c, unsigned* r, unsigned* g, unsigned* b){
*r = cell_rgb_red(cell_bg_rgb(c->channels));
*g = cell_rgb_green(cell_bg_rgb(c->channels));
*b = cell_rgb_blue(cell_bg_rgb(c->channels));
}
// use the default color for the foreground
static inline void
cell_fg_default(cell* c){
notcurses_fg_default_prep(&c->channels);
}
// is the cell using the terminal's default foreground color for its foreground?
static inline bool
cell_fg_default_p(const cell* c){
return !(c->channels & CELL_FGDEFAULT_MASK);
cell_set_fg_default(cell* c){
channels_set_fg_default(&c->channels);
}
// use the default color for the background
static inline void
cell_bg_default(cell* c){
notcurses_bg_default_prep(&c->channels);
}
static inline bool
notcurses_fg_default_p(uint64_t channels){
return !(channels & CELL_FGDEFAULT_MASK);
}
static inline bool
notcurses_bg_default_p(uint64_t channels){
return !(channels & CELL_BGDEFAULT_MASK);
}
// is the cell using the terminal's default background color for its background?
static inline bool
cell_bg_default_p(const cell* c){
return !(c->channels & CELL_BGDEFAULT_MASK);
cell_set_bg_default(cell* c){
channels_set_bg_default(&c->channels);
}
static inline int
cell_fg_set_alpha(cell* c, int alpha){
return notcurses_fg_set_alpha(&c->channels, alpha);
cell_set_fg_alpha(cell* c, int alpha){
return channels_set_fg_alpha(&c->channels, alpha);
}
static inline int
cell_bg_set_alpha(cell *c, int alpha){
return notcurses_bg_set_alpha(&c->channels, alpha);
}
static inline int
cell_fg_alpha(const cell* c){
return notcurses_fg_alpha(c->channels);
}
static inline int
cell_bg_alpha(const cell* c){
return notcurses_bg_alpha(c->channels);
cell_set_bg_alpha(cell *c, int alpha){
return channels_set_bg_alpha(&c->channels, alpha);
}
// does the cell contain an East Asian Wide codepoint?

View File

@ -27,7 +27,7 @@ int box_demo(struct notcurses* nc){
const int targy = 7;
int ytargbase = (ylen - targy) / 2;
ncplane_set_fg_rgb(n, 180, 40, 180);
ncplane_bg_default(n);
ncplane_set_bg_default(n);
if(ncplane_putstr_aligned(n, ytargbase++, "┏━━┳━━┓", NCALIGN_CENTER) < 0){
return -1;
}
@ -55,18 +55,18 @@ int box_demo(struct notcurses* nc){
int y = 0, x = 0;
ncplane_dim_yx(n, &ylen, &xlen);
while(ylen - y >= targy && xlen - x >= targx){
cell_set_fg(&ul, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_bg(&ul, zbonus, 20 + y, 20 + y);
cell_set_fg(&ur, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_bg(&ur, zbonus, 20 + y, 20 + y);
cell_set_fg(&hl, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_bg(&hl, 20, zbonus, 20);
cell_set_fg(&ll, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_bg(&ll, zbonus, 20 + y, 20 + y);
cell_set_fg(&lr, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_bg(&lr, zbonus, 20 + y, 20 + y);
cell_set_fg(&vl, 20, zbonus, 20);
cell_set_bg(&vl, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_fg_rgb(&ul, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_bg_rgb(&ul, zbonus, 20 + y, 20 + y);
cell_set_fg_rgb(&ur, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_bg_rgb(&ur, zbonus, 20 + y, 20 + y);
cell_set_fg_rgb(&hl, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_bg_rgb(&hl, 20, zbonus, 20);
cell_set_fg_rgb(&ll, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_bg_rgb(&ll, zbonus, 20 + y, 20 + y);
cell_set_fg_rgb(&lr, 107 - (y * 2), zbonus, 107 + (y * 2));
cell_set_bg_rgb(&lr, zbonus, 20 + y, 20 + y);
cell_set_fg_rgb(&vl, 20, zbonus, 20);
cell_set_bg_rgb(&vl, 107 - (y * 2), zbonus, 107 + (y * 2));
if(ncplane_cursor_move_yx(n, y, x)){
return -1;
}

View File

@ -69,10 +69,10 @@ intro(struct notcurses* nc){
cell_init(&c);
const char* cstr = "Δ";
cell_load(ncp, &c, cstr);
cell_set_fg(&c, 200, 0, 200);
cell_set_fg_rgb(&c, 200, 0, 200);
int ys = 200 / (rows - 2);
for(y = 5 ; y < rows - 6 ; ++y){
cell_set_bg(&c, 0, y * ys , 0);
cell_set_bg_rgb(&c, 0, y * ys , 0);
for(x = 5 ; x < cols - 6 ; ++x){
if(ncplane_cursor_move_yx(ncp, y, x)){
return -1;
@ -84,8 +84,8 @@ intro(struct notcurses* nc){
}
cell_release(ncp, &c);
uint64_t channels = 0;
notcurses_fg_prep(&channels, 90, 0, 90);
notcurses_bg_prep(&channels, 0, 0, 180);
channels_set_fg_rgb(&channels, 90, 0, 90);
channels_set_bg_rgb(&channels, 0, 0, 180);
if(ncplane_cursor_move_yx(ncp, 4, 4)){
return -1;
}

View File

@ -87,46 +87,46 @@ gridswitch_demo(struct notcurses* nc, struct ncplane *n){
return -1;
}
// top line
cell_set_fg(&ul, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg(&ul, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&ul, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg_rgb(&ul, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &ul);
for(x = 1 ; x < maxx - 1 ; ++x){
cell_set_fg(&uc, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg(&uc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&uc, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg_rgb(&uc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &uc);
}
cell_set_fg(&ur, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg(&ur, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&ur, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg_rgb(&ur, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &ur);
// center
for(y = 1 ; y < maxy - 1 ; ++y){
x = 0;
cell_set_fg(&cl, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg(&cl, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&cl, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg_rgb(&cl, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &cl);
for(x = 1 ; x < maxx - 1 ; ++x){
cell_set_fg(&cc, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg(&cc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&cc, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg_rgb(&cc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &cc);
}
cell_set_fg(&cr, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg(&cr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&cr, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg_rgb(&cr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &cr);
}
// bottom line
x = 0;
cell_set_fg(&ll, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg(&ll, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&ll, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg_rgb(&ll, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &ll);
for(x = 1 ; x < maxx - 1 ; ++x){
cell_set_fg(&lc, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg(&lc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&lc, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg_rgb(&lc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &lc);
}
cell_set_fg(&lr, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg(&lr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&lr, 255 - rs * y, 255 - gs * (x + y), 255 - bs * x);
cell_set_bg_rgb(&lr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &lr);
// render!
@ -152,46 +152,46 @@ gridinv_demo(struct notcurses* nc, struct ncplane *n){
return -1;
}
// top line
cell_set_fg(&ul, 0, 0, 0);
cell_set_bg(&ul, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&ul, 0, 0, 0);
cell_set_bg_rgb(&ul, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &ul);
for(x = 1 ; x < maxx - 1 ; ++x){
cell_set_fg(&uc, 0, 0, 0);
cell_set_bg(&uc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&uc, 0, 0, 0);
cell_set_bg_rgb(&uc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &uc);
}
cell_set_fg(&ur, 0, 0, 0);
cell_set_bg(&ur, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&ur, 0, 0, 0);
cell_set_bg_rgb(&ur, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &ur);
// center
for(y = 1 ; y < maxy - 1 ; ++y){
x = 0;
cell_set_fg(&cl, 0, 0, 0);
cell_set_bg(&cl, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&cl, 0, 0, 0);
cell_set_bg_rgb(&cl, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &cl);
for(x = 1 ; x < maxx - 1 ; ++x){
cell_set_fg(&cc, 0, 0, 0);
cell_set_bg(&cc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&cc, 0, 0, 0);
cell_set_bg_rgb(&cc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &cc);
}
cell_set_fg(&cr, 0, 0, 0);
cell_set_bg(&cr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&cr, 0, 0, 0);
cell_set_bg_rgb(&cr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &cr);
}
// bottom line
x = 0;
cell_set_fg(&ll, 0, 0, 0);
cell_set_bg(&ll, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&ll, 0, 0, 0);
cell_set_bg_rgb(&ll, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &ll);
for(x = 1 ; x < maxx - 1 ; ++x){
cell_set_fg(&lc, 0, 0, 0);
cell_set_bg(&lc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&lc, 0, 0, 0);
cell_set_bg_rgb(&lc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &lc);
}
cell_set_fg(&lr, 0, 0, 0);
cell_set_bg(&lr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&lr, 0, 0, 0);
cell_set_bg_rgb(&lr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &lr);
// render!
@ -218,46 +218,46 @@ int grid_demo(struct notcurses* nc){
// top line
x = 0;
cell_set_bg(&ul, y, y, y);
cell_set_bg(&uc, y, y, y);
cell_set_bg(&ur, y, y, y);
cell_set_fg(&ul, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_bg_rgb(&ul, y, y, y);
cell_set_bg_rgb(&uc, y, y, y);
cell_set_bg_rgb(&ur, y, y, y);
cell_set_fg_rgb(&ul, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &ul);
for(x = 1 ; x < maxx - 1 ; ++x){
cell_set_fg(&uc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&uc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &uc);
}
cell_set_fg(&ur, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&ur, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &ur);
// center
for(y = 1 ; y < maxy - 1 ; ++y){
x = 0;
cell_set_bg(&cl, y, y, y);
cell_set_bg(&cc, y, y, y);
cell_set_bg(&cr, y, y, y);
cell_set_fg(&cl, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_bg_rgb(&cl, y, y, y);
cell_set_bg_rgb(&cc, y, y, y);
cell_set_bg_rgb(&cr, y, y, y);
cell_set_fg_rgb(&cl, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &cl);
for(x = 1 ; x < maxx - 1 ; ++x){
cell_set_fg(&cc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&cc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &cc);
}
cell_set_fg(&cr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&cr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &cr);
}
// bottom line
x = 0;
cell_set_bg(&ll, y, y, y);
cell_set_bg(&lc, y, y, y);
cell_set_bg(&lr, y, y, y);
cell_set_fg(&ll, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_bg_rgb(&ll, y, y, y);
cell_set_bg_rgb(&lc, y, y, y);
cell_set_bg_rgb(&lr, y, y, y);
cell_set_fg_rgb(&ll, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &ll);
for(x = 1 ; x < maxx - 1 ; ++x){
cell_set_fg(&lc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&lc, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &lc);
}
cell_set_fg(&lr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
cell_set_fg_rgb(&lr, 255 - rs * x, 255 - gs * (x + y), 255 - bs * y);
ncplane_putc(n, &lr);
// render!

View File

@ -107,27 +107,27 @@ static const char luigi3[] = "0000001111100000"
static int
draw_luigi(struct ncplane* n, const char* sprite){
cell bgc = CELL_TRIVIAL_INITIALIZER;
cell_bg_set_alpha(&bgc, 3);
cell_set_bg_alpha(&bgc, 3);
ncplane_set_background(n, &bgc);
cell_release(n, &bgc);
size_t s;
int sbytes;
uint64_t channels = 0;
// optimization so we can elide more color changes, see README's "#perf"
notcurses_bg_prep(&channels, 0x00, 0x00, 0x00);
channels_set_bg_rgb(&channels, 0x00, 0x00, 0x00);
for(s = 0 ; sprite[s] ; ++s){
switch(sprite[s]){
case '0':
ncplane_cursor_move_yx(n, (s + 1) / 16, (s + 1) % 16);
break;
case '1':
notcurses_fg_prep(&channels, 0xff, 0xff, 0xff);
channels_set_fg_rgb(&channels, 0xff, 0xff, 0xff);
break;
case '2':
notcurses_fg_prep(&channels, 0xe3, 0x9d, 0x25);
channels_set_fg_rgb(&channels, 0xe3, 0x9d, 0x25);
break;
case '3':
notcurses_fg_prep(&channels, 0x3a, 0x84, 0x00);
channels_set_fg_rgb(&channels, 0x3a, 0x84, 0x00);
break;
}
if(sprite[s] != '0'){

View File

@ -3,9 +3,9 @@
static void
grow_rgb(uint32_t* rgb){
int r = cell_rgb_red(*rgb);
int g = cell_rgb_green(*rgb);
int b = cell_rgb_blue(*rgb);
int r = channel_get_r(*rgb);
int g = channel_get_g(*rgb);
int b = channel_get_b(*rgb);
int delta = (*rgb & 0x80000000ul) ? -1 : 1;
if(b == r){
b += delta;
@ -34,8 +34,8 @@ int maxcolor_demo(struct notcurses* nc){
struct ncplane* n = notcurses_stdplane(nc);
ncplane_set_fg_rgb(n, 255, 255, 255);
uint64_t channels = 0;
notcurses_fg_prep(&channels, 0, 128, 128);
notcurses_bg_prep(&channels, 90, 0, 90);
channels_set_fg_rgb(&channels, 0, 128, 128);
channels_set_bg_rgb(&channels, 90, 0, 90);
int y = 0, x = 0;
ncplane_cursor_move_yx(n, y, x);
if(ncplane_rounded_box_sized(n, 0, channels, maxy, maxx, 0)){
@ -48,10 +48,9 @@ int maxcolor_demo(struct notcurses* nc){
return -1;
}
while(x < maxx - 1){
notcurses_fg_prep(&channels, (rgb & 0xff0000) >> 16u,
(rgb & 0xff00) >> 8u, rgb & 0xff);
notcurses_bg_prep(&channels, 0, 10, 0);
ncplane_putsimple(n, x % 10 + '0', 0, channels);
ncplane_set_fg_rgb(n, (rgb & 0xff0000) >> 16u, (rgb & 0xff00) >> 8u, rgb & 0xff);
ncplane_set_bg_rgb(n, 0, 10, 0);
ncplane_putsimple(n, x % 10 + '0');
grow_rgb(&rgb);
++x;
}

View File

@ -20,38 +20,38 @@ outro_message(struct notcurses* nc, int* rows, int* cols){
return NULL;
}
cell bgcell = CELL_TRIVIAL_INITIALIZER;
notcurses_bg_prep(&bgcell.channels, 0x58, 0x36, 0x58);
channels_set_bg_rgb(&bgcell.channels, 0x58, 0x36, 0x58);
ncplane_set_background(on, &bgcell);
ncplane_dim_yx(on, rows, cols);
int ybase = 0;
// bevel the upper corners
uint64_t channel = 0;
if(notcurses_bg_set_alpha(&channel, 3)){
if(channels_set_bg_alpha(&channel, 3)){
return NULL;
}
if(ncplane_cursor_move_yx(on, ybase, 0)){
return NULL;
}
if(ncplane_putsimple(on, ' ', 0, channel) < 0 || ncplane_putsimple(on, ' ', 0, channel) < 0){
if(ncplane_putsimple(on, ' ') < 0 || ncplane_putsimple(on, ' ') < 0){
return NULL;
}
if(ncplane_cursor_move_yx(on, ybase, *cols - 2)){
return NULL;
}
if(ncplane_putsimple(on, ' ', 0, channel) < 0 || ncplane_putsimple(on, ' ', 0, channel) < 0){
if(ncplane_putsimple(on, ' ') < 0 || ncplane_putsimple(on, ' ') < 0){
return NULL;
}
// ...and now the lower corners
if(ncplane_cursor_move_yx(on, *rows - 1, 0)){
return NULL;
}
if(ncplane_putsimple(on, ' ', 0, channel) < 0 || ncplane_putsimple(on, ' ', 0, channel) < 0){
if(ncplane_putsimple(on, ' ') < 0 || ncplane_putsimple(on, ' ') < 0){
return NULL;
}
if(ncplane_cursor_move_yx(on, *rows - 1, *cols - 2)){
return NULL;
}
if(ncplane_putsimple(on, ' ', 0, channel) < 0 || ncplane_putsimple(on, ' ', 0, channel) < 0){
if(ncplane_putsimple(on, ' ') < 0 || ncplane_putsimple(on, ' ') < 0){
return NULL;
}
if(ncplane_set_fg_rgb(on, 0, 0, 0)){

View File

@ -76,7 +76,7 @@ tabletup(struct ncplane* w, int begx, int begy, int maxx, int maxy,
ncplane_cursor_move_yx(w, y, begx);
snprintf(cchbuf, sizeof(cchbuf) / sizeof(*cchbuf), "%x", idx % 16);
cell_load(w, &c, cchbuf);
cell_set_fg(&c, (rgb >> 16u) % 0xffu, (rgb >> 8u) % 0xffu, rgb % 0xffu);
cell_set_fg_rgb(&c, (rgb >> 16u) % 0xffu, (rgb >> 8u) % 0xffu, rgb % 0xffu);
int x;
for(x = begx ; x <= maxx ; ++x){
// lower-right corner always returns an error unless scrollok() is used
@ -104,7 +104,7 @@ tabletdown(struct ncplane* w, int begx, int begy, int maxx, int maxy,
ncplane_cursor_move_yx(w, y, begx);
snprintf(cchbuf, sizeof(cchbuf) / sizeof(*cchbuf), "%x", y % 16);
cell_load(w, &c, cchbuf);
cell_set_fg(&c, (rgb >> 16u) % 0xffu, (rgb >> 8u) % 0xffu, rgb % 0xffu);
cell_set_fg_rgb(&c, (rgb >> 16u) % 0xffu, (rgb >> 8u) % 0xffu, rgb % 0xffu);
int x;
for(x = begx ; x <= maxx ; ++x){
// lower-right corner always returns an error unless scrollok() is used
@ -265,12 +265,12 @@ panelreel_demo_core(struct notcurses* nc, int efd, tabletctx** tctxs){
.boff = y,
.bgchannel = 0,
};
cell_set_fg(&popts.focusedattr, 58, 150, 221);
cell_set_bg(&popts.focusedattr, 97, 214, 214);
cell_set_fg(&popts.tabletattr, 19, 161, 14);
cell_set_fg(&popts.borderattr, 136, 23, 152);
cell_set_bg(&popts.borderattr, 0, 0, 0);
if(notcurses_bg_set_alpha(&popts.bgchannel, 3)){
cell_set_fg_rgb(&popts.focusedattr, 58, 150, 221);
cell_set_bg_rgb(&popts.focusedattr, 97, 214, 214);
cell_set_fg_rgb(&popts.tabletattr, 19, 161, 14);
cell_set_fg_rgb(&popts.borderattr, 136, 23, 152);
cell_set_bg_rgb(&popts.borderattr, 0, 0, 0);
if(channels_set_bg_alpha(&popts.bgchannel, 3)){
return NULL;
}
struct ncplane* w = notcurses_stdplane(nc);
@ -282,7 +282,7 @@ panelreel_demo_core(struct notcurses* nc, int efd, tabletctx** tctxs){
// Press a for a new panel above the current, c for a new one below the
// current, and b for a new block at arbitrary placement. q quits.
ncplane_set_fg_rgb(w, 58, 150, 221);
ncplane_bg_default(w);
ncplane_set_bg_default(w);
ncplane_cursor_move_yx(w, 1, 1);
ncplane_printf(w, "a, b, c create tablets, DEL deletes, q quits.");
// FIXME clrtoeol();

View File

@ -104,7 +104,7 @@ fill_chunk(struct ncplane* n, int idx){
int r = 64 + hidx * 10;
int b = 64 + vidx * 30;
int g = 225 - ((hidx + vidx) * 12);
notcurses_fg_prep(&channels, r, g, b);
channels_set_fg_rgb(&channels, r, g, b);
if(ncplane_double_box(n, 0, channels, maxy - 1, maxx - 1, 0)){
return -1;
}
@ -117,7 +117,7 @@ fill_chunk(struct ncplane* n, int idx){
}
cell style;
cell_init(&style);
cell_set_fg(&style, r, g, b);
cell_set_fg_rgb(&style, r, g, b);
cell_prime(n, &style, "", 0, channels);
ncplane_set_background(n, &style);
cell_release(n, &style);
@ -128,8 +128,8 @@ static int
draw_bounding_box(struct ncplane* n, int yoff, int xoff, int chunky, int chunkx){
int ret;
uint64_t channels = 0;
notcurses_fg_prep(&channels, 180, 80, 180);
//notcurses_bg_prep(&channels, 0, 0, 0);
channels_set_fg_rgb(&channels, 180, 80, 180);
//channels_set_bg_rgb(&channels, 0, 0, 0);
ncplane_cursor_move_yx(n, yoff, xoff);
ret = ncplane_rounded_box(n, 0, channels,
CHUNKS_VERT * chunky + yoff + 1,

View File

@ -23,8 +23,12 @@ draw_block(struct ncplane* nn, uint32_t blockstart){
cell ll = CELL_TRIVIAL_INITIALIZER, lr = CELL_TRIVIAL_INITIALIZER;
cell hl = CELL_TRIVIAL_INITIALIZER, vl = CELL_TRIVIAL_INITIALIZER;
cells_rounded_box(nn, 0, 0, &ul, &ur, &ll, &lr, &hl, &vl);
cell_set_bg(&hl, 0, 0, 0);
cell_set_bg(&vl, 0, 0, 0);
cell_set_bg_alpha(&ul, 3);
cell_set_bg_alpha(&ur, 3);
cell_set_bg_alpha(&ll, 3);
cell_set_bg_alpha(&lr, 3);
cell_set_bg_rgb(&hl, 0, 0, 0);
cell_set_bg_rgb(&vl, 0, 0, 0);
if(ncplane_box_sized(nn, &ul, &ur, &ll, &lr, &hl, &vl,
BLOCKSIZE / CHUNKSIZE + 2,
(CHUNKSIZE * 2) + 2, 0)){
@ -65,8 +69,8 @@ draw_block(struct ncplane* nn, uint32_t blockstart){
if(cell_load(nn, &c, utf8arr) < 0){ // FIXME check full len was eaten?
return -1;;
}
cell_set_fg(&c, 0xad + z * 2, 0xd8, 0xe6 - z * 2);
cell_set_bg(&c, 8 * chunk, 8 * chunk + z, 8 * chunk);
cell_set_fg_rgb(&c, 0xad + z * 2, 0xd8, 0xe6 - z * 2);
cell_set_bg_rgb(&c, 8 * chunk, 8 * chunk + z, 8 * chunk);
if(ncplane_putc(nn, &c) < 0){
return -1;
}

View File

@ -81,11 +81,11 @@ wall_p(const struct ncplane* n, const cell* c){
static inline void
lighten(cell* c){
unsigned r, g, b;
cell_get_fg(c, &r, &g, &b);
cell_get_fg_rgb(c, &r, &g, &b);
r += (255 - r) / 3;
g += (255 - g) / 3;
b += (255 - b) / 3;
cell_set_fg(c, r, g, b);
cell_set_fg_rgb(c, r, g, b);
}
static int
@ -217,8 +217,8 @@ snake_thread(void* vnc){
y = (random() % (dimy / 2)) + (dimy / 2);
cell head = CELL_TRIVIAL_INITIALIZER;
uint64_t channels = 0;
notcurses_fg_prep(&channels, 255, 255, 255);
notcurses_bg_prep(&channels, 20, 20, 20);
channels_set_fg_rgb(&channels, 255, 255, 255);
channels_set_bg_rgb(&channels, 20, 20, 20);
cell_prime(n, &head, "א", 0, channels);
cell c = CELL_TRIVIAL_INITIALIZER;
struct timespec iterdelay = { .tv_sec = 0, .tv_nsec = 1000000000ul / 20, };
@ -283,15 +283,15 @@ message(struct ncplane* n, int maxy, int maxx, int num, int total,
int bytes_out, int egs_out, int cols_out){
cell c = CELL_TRIVIAL_INITIALIZER;
cell_load(n, &c, " ");
cell_fg_set_alpha(&c, 3);
cell_bg_set_alpha(&c, 3);
cell_set_fg_alpha(&c, 3);
cell_set_bg_alpha(&c, 3);
ncplane_set_background(n, &c);
cell_release(n, &c);
uint64_t channels = 0;
ncplane_set_fg_rgb(n, 64, 128, 240);
ncplane_set_bg_rgb(n, 32, 64, 32);
notcurses_fg_prep(&channels, 255, 255, 255);
notcurses_bg_prep(&channels, 32, 64, 32);
channels_set_fg_rgb(&channels, 255, 255, 255);
channels_set_bg_rgb(&channels, 32, 64, 32);
ncplane_cursor_move_yx(n, 2, 0);
if(ncplane_rounded_box(n, 0, channels, 4, 56, 0)){
return -1;
@ -611,16 +611,14 @@ int widecolor_demo(struct notcurses* nc){
do{ // we fill up the entire screen, however large, walking our strtable
s = strs;
uint64_t channels = 0;
notcurses_bg_prep(&channels, 20, 20, 20);
channels_set_bg_rgb(&channels, 20, 20, 20);
for(s = strs ; *s ; ++s){
size_t idx = 0;
ncplane_cursor_yx(n, &y, &x);
// fprintf(stderr, "%02d %s\n", y, *s);
while((*s)[idx]){ // each multibyte char of string
if(notcurses_fg_prep(&channels,
cell_rgb_red(rgb),
cell_rgb_green(rgb),
cell_rgb_blue(rgb))){
if(channels_set_fg_rgb(&channels, channel_get_r(rgb),
channel_get_g(rgb), channel_get_b(rgb))){
return -1;
}
if(y >= maxy || x >= maxx){

View File

@ -65,7 +65,7 @@ int main(void){
notcurses_stop(nc);
return EXIT_FAILURE;
}
ncplane_bg_default(n);
ncplane_set_bg_default(n);
int y = 1;
std::deque<wchar_t> cells;
wchar_t r;

View File

@ -752,10 +752,10 @@ notcurses* notcurses_init(const notcurses_options* opts, FILE* outfp){
bprefix(ret->stats.fbbytes, 1, prefixbuf, 0),
ret->colors, ret->RGBflag ? "direct" : "palette");
if(!ret->RGBflag){ // FIXME
if(ret->colors > 16){
if(ret->colors >= 16){
putp(tiparm(ret->setaf, 207));
}else{
putp(tiparm(ret->setaf, 9));
putp(tiparm(ret->setaf, 3));
}
fprintf(ret->ttyfp, "\nWarning: you will not have colors until this is resolved:\n");
fprintf(ret->ttyfp, " https://github.com/dankamongmen/notcurses/issues/4\n");
@ -827,20 +827,28 @@ int notcurses_stop(notcurses* nc){
return ret;
}
void ncplane_fg_default(struct ncplane* n){
n->channels &= ~(CELL_FGDEFAULT_MASK);
uint64_t ncplane_get_channels(const ncplane* n){
return n->channels;
}
void ncplane_bg_default(struct ncplane* n){
n->channels &= ~(CELL_BGDEFAULT_MASK);
uint32_t ncplane_get_attr(const ncplane* n){
return n->attrword;
}
void ncplane_set_fg_default(struct ncplane* n){
channels_set_fg_default(&n->channels);
}
void ncplane_set_bg_default(struct ncplane* n){
channels_set_bg_default(&n->channels);
}
int ncplane_set_bg_rgb(ncplane* n, int r, int g, int b){
return notcurses_bg_prep(&n->channels, r, g, b);
return channels_set_bg_rgb(&n->channels, r, g, b);
}
int ncplane_set_fg_rgb(ncplane* n, int r, int g, int b){
return notcurses_fg_prep(&n->channels, r, g, b);
return channels_set_fg_rgb(&n->channels, r, g, b);
}
void ncplane_set_fg(ncplane* n, uint32_t halfchannel){
@ -1065,7 +1073,7 @@ visible_cell(int y, int x, ncplane** retp){
vis = &p->background;
}
// FIXME do this more rigorously, PoC
if(cell_fg_alpha(vis) || cell_bg_alpha(vis)){
if(cell_get_fg_alpha(vis) || cell_get_bg_alpha(vis)){
*retp = p->z;
const cell* trans = visible_cell(y, x, retp);
if(trans){
@ -1248,7 +1256,7 @@ notcurses_render_internal(notcurses* nc){
// we can elide the foreground set iff the previous used fg and matched
if(!cell_fg_default_p(c)){
cell_get_fg(c, &r, &g, &b);
cell_get_fg_rgb(c, &r, &g, &b);
if(fgelidable && lastr == r && lastg == g && lastb == b){
++nc->stats.fgelisions;
}else{
@ -1260,7 +1268,7 @@ notcurses_render_internal(notcurses* nc){
defaultelidable = false;
}
if(!cell_bg_default_p(c)){
cell_get_bg(c, &br, &bg, &bb);
cell_get_bg_rgb(c, &br, &bg, &bb);
if(bgelidable && lastbr == br && lastbg == bg && lastbb == bb){
++nc->stats.bgelisions;
}else{
@ -1385,15 +1393,11 @@ int ncplane_putc(ncplane* n, const cell* c){
return cols;
}
uint64_t ncplane_get_channels(const ncplane* n){
return n->channels;
}
int ncplane_putsimple(struct ncplane* n, char c, uint32_t attr, uint64_t channels){
int ncplane_putsimple(struct ncplane* n, char c){
cell ce = {
.gcluster = c,
.attrword = attr,
.channels = channels,
.attrword = ncplane_get_attr(n),
.channels = ncplane_get_channels(n),
};
if(!cell_simple_p(&ce)){
return -1;
@ -1563,10 +1567,10 @@ int ncplane_hline_interp(ncplane* n, const cell* c, int len,
uint64_t c1, uint64_t c2){
unsigned r1, g1, b1, r2, g2, b2;
unsigned br1, bg1, bb1, br2, bg2, bb2;
cell_rgb_get_fg(c1, &r1, &g1, &b1);
cell_rgb_get_fg(c2, &r2, &g2, &b2);
cell_rgb_get_bg(c1, &br1, &bg1, &bb1);
cell_rgb_get_bg(c2, &br2, &bg2, &bb2);
channels_get_fg_rgb(c1, &r1, &g1, &b1);
channels_get_fg_rgb(c2, &r2, &g2, &b2);
channels_get_bg_rgb(c1, &br1, &bg1, &bb1);
channels_get_bg_rgb(c2, &br2, &bg2, &bb2);
int deltr = ((unsigned)r2 - r1) / (len + 1);
int deltg = ((unsigned)g2 - g1) / (len + 1);
int deltb = ((unsigned)b2 - b1) / (len + 1);
@ -1593,10 +1597,10 @@ int ncplane_hline_interp(ncplane* n, const cell* c, int len,
bg1 += deltbg;
bb1 += deltbb;
if(!fgdef){
notcurses_fg_prep(&c1, r1, g1, b1);
channels_set_fg_rgb(&c1, r1, g1, b1);
}
if(!bgdef){
notcurses_bg_prep(&c1, br1, bg1, bb1);
channels_set_bg_rgb(&c1, br1, bg1, bb1);
}
dupc.channels = c1;
if(ncplane_putc(n, &dupc) <= 0){
@ -1611,10 +1615,10 @@ int ncplane_vline_interp(ncplane* n, const cell* c, int len,
uint64_t c1, uint64_t c2){
unsigned r1, g1, b1, r2, g2, b2;
unsigned br1, bg1, bb1, br2, bg2, bb2;
cell_rgb_get_fg(c1, &r1, &g1, &b1);
cell_rgb_get_fg(c2, &r2, &g2, &b2);
cell_rgb_get_bg(c1, &br1, &bg1, &bb1);
cell_rgb_get_bg(c2, &br2, &bg2, &bb2);
channels_get_fg_rgb(c1, &r1, &g1, &b1);
channels_get_fg_rgb(c2, &r2, &g2, &b2);
channels_get_bg_rgb(c1, &br1, &bg1, &bb1);
channels_get_bg_rgb(c2, &br2, &bg2, &bb2);
int deltr = ((unsigned)r2 - r1) / (len + 1);
int deltg = ((unsigned)g2 - g1) / (len + 1);
int deltb = ((unsigned)b2 - b1) / (len + 1);
@ -1645,10 +1649,10 @@ int ncplane_vline_interp(ncplane* n, const cell* c, int len,
bg1 += deltbg;
bb1 += deltbb;
if(!fgdef){
notcurses_fg_prep(&c1, r1, g1, b1);
channels_set_fg_rgb(&c1, r1, g1, b1);
}
if(!bgdef){
notcurses_bg_prep(&c1, br1, bg1, bb1);
channels_set_bg_rgb(&c1, br1, bg1, bb1);
}
dupc.channels = c1;
if(ncplane_putc(n, &dupc) <= 0){
@ -1857,26 +1861,26 @@ int ncvisual_render(const ncvisual* ncv){
// use the default for the background, as that's the only way it's
// effective in that case anyway
if(!rgbbase_up[3] || !rgbbase_down[3]){
cell_bg_default(&c);
cell_set_bg_default(&c);
if(!rgbbase_up[3] && !rgbbase_down[3]){
if(cell_load(ncv->ncp, &c, " ") <= 0){
return -1;
}
cell_fg_default(&c);
cell_set_fg_default(&c);
}else if(!rgbbase_up[3]){ // down has the color
if(cell_load(ncv->ncp, &c, "\u2584") <= 0){ // lower half block
return -1;
}
cell_set_fg(&c, rgbbase_down[0], rgbbase_down[1], rgbbase_down[2]);
cell_set_fg_rgb(&c, rgbbase_down[0], rgbbase_down[1], rgbbase_down[2]);
}else{ // up has the color
if(cell_load(ncv->ncp, &c, "\u2580") <= 0){ // upper half block
return -1;
}
cell_set_fg(&c, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2]);
cell_set_fg_rgb(&c, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2]);
}
}else{
cell_set_fg(&c, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2]);
cell_set_bg(&c, rgbbase_down[0], rgbbase_down[1], rgbbase_down[2]);
cell_set_fg_rgb(&c, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2]);
cell_set_bg_rgb(&c, rgbbase_down[0], rgbbase_down[1], rgbbase_down[2]);
if(cell_load(ncv->ncp, &c, "\u2580") <= 0){ // upper half block
return -1;
}
@ -1921,7 +1925,7 @@ alloc_ncplane_palette(ncplane* n, planepalette* pp){
for(x = 0 ; x < pp->cols ; ++x){
channels = n->fb[fbcellidx(n, y, x)].channels;
pp->channels[y * pp->cols + x] = channels;
cell_rgb_get_fg(channels, &r, &g, &b);
channels_get_fg_rgb(channels, &r, &g, &b);
if(r > pp->maxr){
pp->maxr = r;
}
@ -1931,7 +1935,7 @@ alloc_ncplane_palette(ncplane* n, planepalette* pp){
if(b > pp->maxb){
pp->maxb = b;
}
cell_rgb_get_bg(channels, &br, &bg, &bb);
channels_get_bg_rgb(channels, &br, &bg, &bb);
if(br > pp->maxbr){
pp->maxbr = br;
}
@ -1946,7 +1950,7 @@ alloc_ncplane_palette(ncplane* n, planepalette* pp){
// FIXME factor this duplication out
channels = n->background.channels;
pp->channels[y * pp->cols] = channels;
cell_rgb_get_fg(channels, &r, &g, &b);
channels_get_fg_rgb(channels, &r, &g, &b);
if(r > pp->maxr){
pp->maxr = r;
}
@ -1956,7 +1960,7 @@ alloc_ncplane_palette(ncplane* n, planepalette* pp){
if(b > pp->maxb){
pp->maxb = b;
}
cell_rgb_get_bg(channels, &br, &bg, &bb);
channels_get_bg_rgb(channels, &br, &bg, &bb);
if(br > pp->maxbr){
pp->maxbr = br;
}
@ -2007,21 +2011,21 @@ int ncplane_fadein(ncplane* n, const struct timespec* ts){
for(y = 0 ; y < pp.rows && y < dimy ; ++y){
for(x = 0 ; x < pp.cols && x < dimx; ++x){
unsigned r, g, b;
cell_rgb_get_fg(pp.channels[pp.cols * y + x], &r, &g, &b);
channels_get_fg_rgb(pp.channels[pp.cols * y + x], &r, &g, &b);
unsigned br, bg, bb;
cell_rgb_get_bg(pp.channels[pp.cols * y + x], &br, &bg, &bb);
channels_get_bg_rgb(pp.channels[pp.cols * y + x], &br, &bg, &bb);
cell* c = &n->fb[dimx * y + x];
if(!cell_fg_default_p(c)){
r = r * iter / maxsteps;
g = g * iter / maxsteps;
b = b * iter / maxsteps;
cell_set_fg(c, r, g, b);
cell_set_fg_rgb(c, r, g, b);
}
if(!cell_bg_default_p(c)){
br = br * iter / maxsteps;
bg = bg * iter / maxsteps;
bb = bb * iter / maxsteps;
cell_set_bg(c, br, bg, bb);
cell_set_bg_rgb(c, br, bg, bb);
}
}
}
@ -2079,35 +2083,35 @@ int ncplane_fadeout(ncplane* n, const struct timespec* ts){
for(x = 0 ; x < pp.cols && x < dimx; ++x){
cell* c = &n->fb[dimx * y + x];
if(!cell_fg_default_p(c)){
cell_rgb_get_fg(pp.channels[pp.cols * y + x], &r, &g, &b);
channels_get_fg_rgb(pp.channels[pp.cols * y + x], &r, &g, &b);
r = r * (maxsteps - iter) / maxsteps;
g = g * (maxsteps - iter) / maxsteps;
b = b * (maxsteps - iter) / maxsteps;
cell_set_fg(c, r, g, b);
cell_set_fg_rgb(c, r, g, b);
}
if(!cell_bg_default_p(c)){
cell_rgb_get_bg(pp.channels[pp.cols * y + x], &br, &bg, &bb);
channels_get_bg_rgb(pp.channels[pp.cols * y + x], &br, &bg, &bb);
br = br * (maxsteps - iter) / maxsteps;
bg = bg * (maxsteps - iter) / maxsteps;
bb = bb * (maxsteps - iter) / maxsteps;
cell_set_bg(c, br, bg, bb);
cell_set_bg_rgb(c, br, bg, bb);
}
}
}
cell* c = &n->background;
if(!cell_fg_default_p(c)){
cell_rgb_get_fg(pp.channels[pp.cols * y], &r, &g, &b);
channels_get_fg_rgb(pp.channels[pp.cols * y], &r, &g, &b);
r = r * (maxsteps - iter) / maxsteps;
g = g * (maxsteps - iter) / maxsteps;
b = b * (maxsteps - iter) / maxsteps;
cell_set_fg(&n->background, r, g, b);
cell_set_fg_rgb(&n->background, r, g, b);
}
if(!cell_bg_default_p(c)){
cell_rgb_get_bg(pp.channels[pp.cols * y], &br, &bg, &bb);
channels_get_bg_rgb(pp.channels[pp.cols * y], &br, &bg, &bb);
br = br * (maxsteps - iter) / maxsteps;
bg = bg * (maxsteps - iter) / maxsteps;
bb = bb * (maxsteps - iter) / maxsteps;
cell_set_bg(&n->background, br, bg, bb);
cell_set_bg_rgb(&n->background, br, bg, bb);
}
notcurses_render(n->nc);
uint64_t nextwake = (iter + 1) * nanosecs_step + startns;
@ -2170,6 +2174,9 @@ void notcurses_cursor_disable(notcurses* nc){
}
int notcurses_refresh(notcurses* nc){
if(nc->stats.renders == 0){
return -1; // haven't rendered yet, and thus don't know what should be there
}
// FIXME
return 0;
}

View File

@ -12,26 +12,28 @@ int main(void){
memset(&opts, 0, sizeof(opts));
opts.inhibit_alternate_screen = true;
struct notcurses* nc = notcurses_init(&opts, stdout);
if(nc == NULL){
return EXIT_FAILURE;
}
int y, x, dimy, dimx;
struct ncplane* n = notcurses_stdplane(nc);
ncplane_dim_yx(n, &dimy, &dimx);
uint64_t channels = 0;
int r , g, b;
r = 0;
g = 0x80;
b = 0;
for(y = 0 ; y < dimy ; ++y){
for(x = 0 ; x < dimx ; ++x){
notcurses_fg_prep(&channels, r, g, b);
ncplane_putsimple(n, 'x', 0, channels);
if(r % 2){
ncplane_set_fg_rgb(n, r, g, b);
ncplane_putsimple(n, 'x');
if(g % 2){
if(b-- == 0){
++r;
++g;
b = 0;
}
}else{
if(b++ >= 256){
++r;
++g;
b = 256;
}
}

View File

@ -40,7 +40,7 @@ TEST_F(CellTest, SetItalic) {
notcurses_term_dim_yx(nc_, &dimy, &dimx);
cell_styles_set(&c, CELL_STYLE_ITALIC);
ASSERT_EQ(1, cell_load(n_, &c, "i"));
cell_set_fg(&c, 255, 255, 255);
cell_set_fg_rgb(&c, 255, 255, 255);
ncplane_set_background(n_, &c);
cell_release(n_, &c);
EXPECT_EQ(0, notcurses_render(nc_));
@ -54,7 +54,7 @@ TEST_F(CellTest, SetBold) {
notcurses_term_dim_yx(nc_, &dimy, &dimx);
cell_styles_set(&c, CELL_STYLE_BOLD);
ASSERT_EQ(1, cell_load(n_, &c, "b"));
cell_set_fg(&c, 255, 255, 255);
cell_set_fg_rgb(&c, 255, 255, 255);
ncplane_set_background(n_, &c);
cell_release(n_, &c);
EXPECT_EQ(0, notcurses_render(nc_));
@ -68,7 +68,7 @@ TEST_F(CellTest, SetUnderline) {
notcurses_term_dim_yx(nc_, &dimy, &dimx);
cell_styles_set(&c, CELL_STYLE_UNDERLINE);
ASSERT_EQ(1, cell_load(n_, &c, "u"));
cell_set_fg(&c, 255, 255, 255);
cell_set_fg_rgb(&c, 255, 255, 255);
ncplane_set_background(n_, &c);
cell_release(n_, &c);
EXPECT_EQ(0, notcurses_render(nc_));
@ -91,24 +91,24 @@ TEST_F(CellTest, SetUnderline) {
TEST_F(CellTest, CellSetFGAlpha){
cell c = CELL_TRIVIAL_INITIALIZER;
EXPECT_GT(0, cell_fg_set_alpha(&c, -1));
EXPECT_GT(0, cell_fg_set_alpha(&c, 4));
EXPECT_EQ(0, cell_fg_set_alpha(&c, 0));
EXPECT_EQ(0, cell_fg_alpha(&c));
EXPECT_EQ(0, cell_fg_set_alpha(&c, 3));
EXPECT_EQ(3, cell_fg_alpha(&c));
EXPECT_GT(0, cell_set_fg_alpha(&c, -1));
EXPECT_GT(0, cell_set_fg_alpha(&c, 4));
EXPECT_EQ(0, cell_set_fg_alpha(&c, 0));
EXPECT_EQ(0, cell_get_fg_alpha(&c));
EXPECT_EQ(0, cell_set_fg_alpha(&c, 3));
EXPECT_EQ(3, cell_get_fg_alpha(&c));
EXPECT_TRUE(cell_fg_default_p(&c));
EXPECT_TRUE(cell_bg_default_p(&c));
}
TEST_F(CellTest, CellSetBGAlpha){
cell c = CELL_TRIVIAL_INITIALIZER;
EXPECT_GT(0, cell_bg_set_alpha(&c, -1));
EXPECT_GT(0, cell_bg_set_alpha(&c, 4));
EXPECT_EQ(0, cell_bg_set_alpha(&c, 0));
EXPECT_EQ(0, cell_bg_alpha(&c));
EXPECT_EQ(0, cell_bg_set_alpha(&c, 3));
EXPECT_EQ(3, cell_bg_alpha(&c));
EXPECT_GT(0, cell_set_bg_alpha(&c, -1));
EXPECT_GT(0, cell_set_bg_alpha(&c, 4));
EXPECT_EQ(0, cell_set_bg_alpha(&c, 0));
EXPECT_EQ(0, cell_get_bg_alpha(&c));
EXPECT_EQ(0, cell_set_bg_alpha(&c, 3));
EXPECT_EQ(3, cell_get_bg_alpha(&c));
EXPECT_TRUE(cell_fg_default_p(&c));
EXPECT_TRUE(cell_bg_default_p(&c));
}

75
tests/channel.cpp Normal file
View File

@ -0,0 +1,75 @@
#include <notcurses.h>
#include "main.h"
class ChannelTest : public :: testing::Test {
protected:
void SetUp() override {
setlocale(LC_ALL, "");
}
};
TEST_F(ChannelTest, ChannelGetRGB){
const struct t {
uint32_t channel;
int r, g, b;
} test[] = {
{ .channel = 0x000000, .r = 0x00, .g = 0x00, .b = 0x00, },
{ .channel = 0x808080, .r = 0x80, .g = 0x80, .b = 0x80, },
{ .channel = 0x080808, .r = 0x08, .g = 0x08, .b = 0x08, },
{ .channel = 0xffffff, .r = 0xff, .g = 0xff, .b = 0xff, },
};
for(auto i = 0u ; i < sizeof(test) / sizeof(*test) ; ++i){
unsigned r, g, b;
EXPECT_EQ(test[i].channel, channel_get_rgb(test[i].channel, &r, &g, &b));
EXPECT_EQ(test[i].r, r);
EXPECT_EQ(test[i].g, g);
EXPECT_EQ(test[i].b, b);
}
}
TEST_F(ChannelTest, ChannelGetAlpha){
const struct t {
uint32_t channel;
int a;
} test[] = {
{ .channel = 0x00000000, .a = 0, },
{ .channel = 0x10808080, .a = 1, },
{ .channel = 0x20080808, .a = 2, },
{ .channel = 0xe0080808, .a = 2, },
{ .channel = 0x3fffffff, .a = 3, },
{ .channel = 0xffffffff, .a = 3, },
};
for(auto i = 0u ; i < sizeof(test) / sizeof(*test) ; ++i){
EXPECT_EQ(test[i].a, channel_get_alpha(test[i].channel));
}
}
TEST_F(ChannelTest, ChannelGetDefault){
const struct t {
uint32_t channel;
bool def;
} test[] = {
{ .channel = 0x00000000, .def = true, },
{ .channel = 0x0fffffff, .def = true, },
{ .channel = 0xbfffffff, .def = true, },
{ .channel = 0x40000000, .def = false, },
{ .channel = 0x40080808, .def = false, },
{ .channel = 0xffffffff, .def = false, },
};
for(auto i = 0u ; i < sizeof(test) / sizeof(*test) ; ++i){
EXPECT_EQ(test[i].def, channel_default_p(test[i].channel));
}
}
TEST_F(ChannelTest, ChannelSetDefault){
const uint32_t channels[] = {
0x40000000, 0x4fffffff, 0xcfffffff,
0x40808080, 0x40080808, 0xffffffff,
};
for(auto i = 0u ; i < sizeof(channels) / sizeof(*channels) ; ++i){
uint32_t channel = channels[i];
EXPECT_FALSE(channel_default_p(channel));
channel_set_default(&channel);
EXPECT_TRUE(channel_default_p(channel));
}
}

View File

@ -22,7 +22,7 @@ class FadeTest : public :: testing::Test {
ncplane_dim_yx(n_, &dimy, &dimx);
cell c = CELL_TRIVIAL_INITIALIZER;
c.gcluster = '*';
cell_set_fg(&c, 0xff, 0xff, 0xff);
cell_set_fg_rgb(&c, 0xff, 0xff, 0xff);
unsigned rgb = 0xffffffu;
for(int y = 0 ; y < dimy ; ++y){
for(int x = 0 ; x < dimx ; ++x){
@ -30,8 +30,8 @@ class FadeTest : public :: testing::Test {
if(rgb < 32){
rgb = 0xffffffu;
}
cell_set_fg(&c, (rgb >> 16u) & 0xff, (rgb >> 8u) & 0xff, rgb & 0xff);
cell_set_bg(&c, rgb & 0xff, (rgb >> 16u) & 0xff, (rgb >> 8u) & 0xff);
cell_set_fg_rgb(&c, (rgb >> 16u) & 0xff, (rgb >> 8u) & 0xff, rgb & 0xff);
cell_set_bg_rgb(&c, rgb & 0xff, (rgb >> 16u) & 0xff, (rgb >> 8u) & 0xff);
EXPECT_LT(0, ncplane_putc(n_, &c));
}
}

View File

@ -649,14 +649,14 @@ TEST_F(NcplaneTest, BoxGradients) {
ASSERT_LT(40, dimx);
cell ul{}, ll{}, lr{}, ur{}, hl{}, vl{};
ASSERT_EQ(0, cells_double_box(n_, 0, 0, &ul, &ur, &ll, &lr, &hl, &vl));
EXPECT_EQ(0, notcurses_fg_prep(&ul.channels, 255, 0, 0));
EXPECT_EQ(0, notcurses_fg_prep(&ur.channels, 0, 255, 0));
EXPECT_EQ(0, notcurses_fg_prep(&ll.channels, 0, 0, 255));
EXPECT_EQ(0, notcurses_fg_prep(&lr.channels, 255, 255, 255));
EXPECT_EQ(0, notcurses_bg_prep(&ul.channels, 0, 255, 255));
EXPECT_EQ(0, notcurses_bg_prep(&ur.channels, 255, 0, 255));
EXPECT_EQ(0, notcurses_bg_prep(&ll.channels, 255, 255, 0));
EXPECT_EQ(0, notcurses_bg_prep(&lr.channels, 0, 0, 0));
EXPECT_EQ(0, channels_set_fg_rgb(&ul.channels, 255, 0, 0));
EXPECT_EQ(0, channels_set_fg_rgb(&ur.channels, 0, 255, 0));
EXPECT_EQ(0, channels_set_fg_rgb(&ll.channels, 0, 0, 255));
EXPECT_EQ(0, channels_set_fg_rgb(&lr.channels, 255, 255, 255));
EXPECT_EQ(0, channels_set_bg_rgb(&ul.channels, 0, 255, 255));
EXPECT_EQ(0, channels_set_bg_rgb(&ur.channels, 255, 0, 255));
EXPECT_EQ(0, channels_set_bg_rgb(&ll.channels, 255, 255, 0));
EXPECT_EQ(0, channels_set_bg_rgb(&lr.channels, 0, 0, 0));
// we'll try all 16 gradmasks in sideszXsidesz configs in a 4x4 map
unsigned gradmask = 0;
for(auto y0 = 0 ; y0 < 4 ; ++y0){
@ -688,18 +688,18 @@ TEST_F(NcplaneTest, BoxSideColors) {
cell ul{}, ll{}, lr{}, ur{}, hl{}, vl{};
ASSERT_EQ(0, cells_rounded_box(n_, 0, 0, &ul, &ur, &ll, &lr, &hl, &vl));
// we'll try all 16 boxmasks in sideszXsidesz configurations in a 4x4 map
EXPECT_EQ(0, notcurses_fg_prep(&ul.channels, 255, 0, 0));
EXPECT_EQ(0, notcurses_fg_prep(&ur.channels, 0, 255, 0));
EXPECT_EQ(0, notcurses_fg_prep(&ll.channels, 0, 0, 255));
EXPECT_EQ(0, notcurses_fg_prep(&lr.channels, 0, 0, 0));
EXPECT_EQ(0, notcurses_bg_prep(&ul.channels, 0, 255, 255));
EXPECT_EQ(0, notcurses_bg_prep(&ur.channels, 255, 0, 255));
EXPECT_EQ(0, notcurses_bg_prep(&ll.channels, 255, 255, 0));
EXPECT_EQ(0, notcurses_bg_prep(&lr.channels, 0, 0, 0));
EXPECT_EQ(0, notcurses_fg_prep(&hl.channels, 255, 0, 255));
EXPECT_EQ(0, notcurses_fg_prep(&vl.channels, 255, 255, 255));
EXPECT_EQ(0, notcurses_bg_prep(&hl.channels, 0, 255, 0));
EXPECT_EQ(0, notcurses_bg_prep(&vl.channels, 0, 0, 0));
EXPECT_EQ(0, channels_set_fg_rgb(&ul.channels, 255, 0, 0));
EXPECT_EQ(0, channels_set_fg_rgb(&ur.channels, 0, 255, 0));
EXPECT_EQ(0, channels_set_fg_rgb(&ll.channels, 0, 0, 255));
EXPECT_EQ(0, channels_set_fg_rgb(&lr.channels, 0, 0, 0));
EXPECT_EQ(0, channels_set_bg_rgb(&ul.channels, 0, 255, 255));
EXPECT_EQ(0, channels_set_bg_rgb(&ur.channels, 255, 0, 255));
EXPECT_EQ(0, channels_set_bg_rgb(&ll.channels, 255, 255, 0));
EXPECT_EQ(0, channels_set_bg_rgb(&lr.channels, 0, 0, 0));
EXPECT_EQ(0, channels_set_fg_rgb(&hl.channels, 255, 0, 255));
EXPECT_EQ(0, channels_set_fg_rgb(&vl.channels, 255, 255, 255));
EXPECT_EQ(0, channels_set_bg_rgb(&hl.channels, 0, 255, 0));
EXPECT_EQ(0, channels_set_bg_rgb(&vl.channels, 0, 0, 0));
for(auto y0 = 0 ; y0 < 4 ; ++y0){
for(auto x0 = 0 ; x0 < 4 ; ++x0){
EXPECT_EQ(0, ncplane_cursor_move_yx(n_, y0 * sidesz, x0 * (sidesz + 1)));

View File

@ -117,24 +117,24 @@ TEST_F(NotcursesTest, TileScreenWithPlanes) {
TEST_F(NotcursesTest, ChannelSetFGAlpha){
uint64_t channel = 0;
EXPECT_GT(0, notcurses_fg_set_alpha(&channel, -1));
EXPECT_GT(0, notcurses_fg_set_alpha(&channel, 4));
EXPECT_EQ(0, notcurses_fg_set_alpha(&channel, 0));
EXPECT_EQ(0, notcurses_fg_alpha(channel));
EXPECT_EQ(0, notcurses_fg_set_alpha(&channel, 3));
EXPECT_EQ(3, notcurses_fg_alpha(channel));
EXPECT_TRUE(notcurses_fg_default_p(channel));
EXPECT_TRUE(notcurses_bg_default_p(channel));
EXPECT_GT(0, channels_set_fg_alpha(&channel, -1));
EXPECT_GT(0, channels_set_fg_alpha(&channel, 4));
EXPECT_EQ(0, channels_set_fg_alpha(&channel, 0));
EXPECT_EQ(0, channels_get_fg_alpha(channel));
EXPECT_EQ(0, channels_set_fg_alpha(&channel, 3));
EXPECT_EQ(3, channels_get_fg_alpha(channel));
EXPECT_TRUE(channels_fg_default_p(channel));
EXPECT_TRUE(channels_bg_default_p(channel));
}
TEST_F(NotcursesTest, ChannelSetBGAlpha){
uint64_t channel = 0;
EXPECT_GT(0, notcurses_bg_set_alpha(&channel, -1));
EXPECT_GT(0, notcurses_bg_set_alpha(&channel, 4));
EXPECT_EQ(0, notcurses_bg_set_alpha(&channel, 0));
EXPECT_EQ(0, notcurses_bg_alpha(channel));
EXPECT_EQ(0, notcurses_bg_set_alpha(&channel, 3));
EXPECT_EQ(3, notcurses_bg_alpha(channel));
EXPECT_TRUE(notcurses_fg_default_p(channel));
EXPECT_TRUE(notcurses_bg_default_p(channel));
EXPECT_GT(0, channels_set_bg_alpha(&channel, -1));
EXPECT_GT(0, channels_set_bg_alpha(&channel, 4));
EXPECT_EQ(0, channels_set_bg_alpha(&channel, 0));
EXPECT_EQ(0, channels_get_bg_alpha(channel));
EXPECT_EQ(0, channels_set_bg_alpha(&channel, 3));
EXPECT_EQ(3, channels_get_bg_alpha(channel));
EXPECT_TRUE(channels_fg_default_p(channel));
EXPECT_TRUE(channels_bg_default_p(channel));
}

View File

@ -251,7 +251,7 @@ TEST_F(PanelReelTest, SubwinNoOffsetGeom) {
TEST_F(PanelReelTest, TransparentBackground) {
panelreel_options p{};
notcurses_bg_set_alpha(&p.bgchannel, 3);
channels_set_bg_alpha(&p.bgchannel, 3);
struct panelreel* pr = panelreel_create(n_, &p, -1);
ASSERT_NE(nullptr, pr);
// FIXME