mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 09:09:03 -04:00
* orthogonalize channel/channels/cells APIs #119 * sync README.md with new ncplane channels api #119
This commit is contained in:
parent
e3dd36a1a4
commit
ff463d464e
546
README.md
546
README.md
@ -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
|
||||
|
||||
|
@ -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?
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
108
src/demo/grid.c
108
src/demo/grid.c
@ -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!
|
||||
|
@ -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'){
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)){
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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){
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
75
tests/channel.cpp
Normal 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));
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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)));
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user