rust: more tests, refactors & improvements

- separate tests and constructors into submodules for cells and channels
- add missing functions channels_set_bg_palindex & channels_set_fg_palindex
- fix bug in channel_palindex_p function
- wrap NCSTYLE_* constants
- add more missing cell tests
- improve many doc comments
- fix some types
pull/1170/head
joseLuís 4 years ago
parent 535fffa9d5
commit 279f36ec93

@ -1,4 +1,4 @@
//! Curated re-exports of the `bindgen` bindings
//! Curated re-exports of the [`bindgen`] bindings
//!
//! The full list of bindings is under the
//! [`bindgen`] submodule
@ -17,9 +17,9 @@ pub mod bindgen {
//! Automatically generated Rust FFI bindings
//!
//! All of the notcurses functions and some of the constants are reexported
//! by the [`bindings`] module.
//! by the [`bindings`][crate::bindings] module.
//! While the structs, enums and some other constants are type aliased in
//! the [`types`] module, in order to follow the
//! the [`types`][crate::types] module, in order to follow the
//! Rust API Guidelines as much as possible.
//!
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
@ -576,23 +576,22 @@ pub use bindgen::{
// ncstats,
// ncstyle ---------------------------------------------------------------------
#[doc(inline)]
pub use bindgen::{
// constants
NCSTYLE_BLINK,
NCSTYLE_BOLD,
NCSTYLE_DIM,
NCSTYLE_INVIS,
NCSTYLE_ITALIC,
NCSTYLE_MASK,
NCSTYLE_NONE,
NCSTYLE_PROTECT,
NCSTYLE_REVERSE,
NCSTYLE_STANDOUT,
NCSTYLE_STRUCK,
NCSTYLE_UNDERLINE,
};
//
// already wrapped:
//
// // constants
// NCSTYLE_BLINK,
// NCSTYLE_BOLD,
// NCSTYLE_DIM,
// NCSTYLE_INVIS,
// NCSTYLE_ITALIC,
// NCSTYLE_MASK,
// NCSTYLE_NONE,
// NCSTYLE_PROTECT,
// NCSTYLE_REVERSE,
// NCSTYLE_STANDOUT,
// NCSTYLE_STRUCK,
// NCSTYLE_UNDERLINE,
// nctablet --------------------------------------------------------------------
//

@ -0,0 +1,29 @@
//! Handy [`NcCell`] constructors
pub use crate::{NcCell, NcChannels, NcCharBackstop, NcStyleMask};
impl NcCell {
/// [`NcCell`] constructor expecting [`char`], [`NcStyleMask`] and [`NcChannels`]
#[inline]
pub const fn new(ch: char, stylemask: NcStyleMask, channels: NcChannels) -> Self {
NcCell {
gcluster: ch as u32,
gcluster_backstop: 0 as NcCharBackstop,
reserved: 0,
stylemask,
channels,
}
}
/// [`NcCell`] simple constructor just expecting a [`char`]
#[inline]
pub const fn with_char(ch: char) -> Self {
Self::new(ch, 0 as NcStyleMask, 0 as NcChannels)
}
/// [`NcCell`] simple constructor for an empty cell
#[inline]
pub const fn new_blank() -> Self {
Self::with_char(0 as char)
}
}

@ -1,4 +1,4 @@
//! NcCell constructors and cell_* static functions reimplementations
//! [`NcCell`] `cell*_*` static functions reimplementations
// functions already exported by bindgen : 6
// -----------------------------------------
@ -13,41 +13,41 @@
// ------------------------------------------ (implement / remaining)
// (X) wont: 2
// (+) done: 40 / 0
// (#) test: 0 / 40
// (#) test: 26 / 14
// ------------------------------------------
//+ cell_bchannel
//+ cell_bg_alpha
//+ cell_bg_default_p
//+ cell_bg_palindex
//+ cell_bg_palindex_p
//+ cell_bg_rgb
//+ cell_bg_rgb8
//# cell_bchannel
//# cell_bg_alpha
//# cell_bg_default_p
//# cell_bg_palindex
//# cell_bg_palindex_p
//# cell_bg_rgb
//# cell_bg_rgb8
//+ cellcmp
//+ cell_double_wide_p
//+ cell_extract
//+ cell_fchannel
//+ cell_fg_alpha
//+ cell_fg_default_p
//+ cell_fg_palindex
//+ cell_fg_palindex_p
//+ cell_fg_rgb
//+ cell_fg_rgb8
//# cell_fchannel
//# cell_fg_alpha
//# cell_fg_default_p
//# cell_fg_palindex
//# cell_fg_palindex_p
//# cell_fg_rgb
//# cell_fg_rgb8
//+ cell_init
//+ cell_load_char
//+ cell_prime
//+ cell_set_bchannel
//+ cell_set_bg_alpha
//+ cell_set_bg_default
//+ cell_set_bg_palindex
//+ cell_set_bg_rgb
//+ cell_set_bg_rgb8
//# cell_set_bchannel
//# cell_set_bg_alpha
//# cell_set_bg_default
//# cell_set_bg_palindex
//# cell_set_bg_rgb
//# cell_set_bg_rgb8
//X cell_set_bg_rgb8_clipped // unneeded
//+ cell_set_fchannel
//+ cell_set_fg_alpha
//+ cell_set_fg_default
//+ cell_set_fg_palindex
//+ cell_set_fg_rgb
//+ cell_set_fg_rgb8
//# cell_set_fchannel
//# cell_set_fg_alpha
//# cell_set_fg_default
//# cell_set_fg_palindex
//# cell_set_fg_rgb
//# cell_set_fg_rgb8
//X cell_set_fg_rgb8_clipped // unneeded
//+ cells_load_box
//+ cell_strdup
@ -58,6 +58,12 @@
//+ cell_wide_left_p
//+ cell_wide_right_p
#[cfg(test)]
mod tests;
mod constructors;
pub use constructors::*;
use libc::strcmp;
use crate::{
@ -68,50 +74,14 @@ use crate::{
channels_set_bg_default, channels_set_bg_rgb, channels_set_bg_rgb8, channels_set_fchannel,
channels_set_fg_alpha, channels_set_fg_default, channels_set_fg_rgb, channels_set_fg_rgb8,
types::{
NcAlphaBits, NcCell, NcChannel, NcChannels, NcChar, NcCharBackstop, NcColor,
NcPaletteIndex, NcPlane, NcResult, NcStyleMask, NCCELL_ALPHA_OPAQUE, NCCELL_BGDEFAULT_MASK,
NcAlphaBits, NcCell, NcChannel, NcChannels, NcChar, NcColor, NcPaletteIndex, NcPlane,
NcResult, NcRgb, NcStyleMask, NCCELL_ALPHA_OPAQUE, NCCELL_BGDEFAULT_MASK,
NCCELL_BG_PALETTE, NCCELL_FGDEFAULT_MASK, NCCELL_FG_PALETTE, NCCELL_NOBACKGROUND_MASK,
NCCELL_WIDEASIAN_MASK, NCRESULT_ERR, NCRESULT_OK,
},
NCSTYLE_MASK,
};
// Constructors ----------------------------------------------------------------
impl NcCell {
/// [`NcCell`] constructor expecting [`char`], [`NcStyleMask`] and [`NcChannels`]
///
/// This is analogous to the [`cell_initializer`] macro
#[inline]
pub const fn new(ch: char, stylemask: NcStyleMask, channels: NcChannels) -> Self {
NcCell {
gcluster: ch as u32,
gcluster_backstop: 0 as NcCharBackstop,
reserved: 0,
stylemask,
channels,
}
}
/// [`NcCell`] simple constructor just expecting a [`char`]
///
/// This is analogous to the [`cell_char_initializer`] macro
#[inline]
pub const fn with_char(ch: char) -> Self {
Self::new(ch, 0 as NcStyleMask, 0 as NcChannels)
}
/// [`NcCell`] simple constructor for an empty cell
///
/// This is analogous to the [`cell_trivial_initializer`] macro
#[inline]
pub const fn new_blank() -> Self {
Self::with_char(0 as char)
}
}
// Static Functions ------------------------------------------------------------
/// cell_load(), plus blast the styling with 'style' and 'channels'.
///
/// - Breaks the UTF-8 string in 'gcluster' down, setting up the cell 'cell'.
@ -136,7 +106,7 @@ pub unsafe fn cell_prime(
unsafe { cell_load(plane, cell, gcluster as u32 as *const i8) }
}
/// load up six cells with the [NcChar]s necessary to draw a box.
/// load up six cells with the [`NcChar`]s necessary to draw a box.
///
/// returns 0 on success, -1 on error.
///
@ -212,64 +182,63 @@ pub unsafe fn cells_load_box(
NCRESULT_ERR
}
///
/// Initialize (zero out) the [`NcCell`].
#[inline]
pub fn cell_init(cell: &mut NcCell) {
*cell = unsafe { core::mem::zeroed() }
}
/// Set the specified style bits for the cell 'c', whether they're actively
/// supported or not. Only the lower 16 bits are meaningful.
/// static inline void
/// Set *only* the specified [`NcStyleMask`] bits for the [`NcCell`],
/// whether they're actively supported or not.
#[inline]
pub fn cell_styles_set(cell: &mut NcCell, stylebits: NcStyleMask) {
cell.stylemask = stylebits & NCSTYLE_MASK as u16;
}
/// Extract the style bits from the cell.
/// Extract the [`NcStyleMask`] bits from the [`NcCell`].
#[inline]
pub fn cell_styles(cell: &NcCell) -> NcStyleMask {
cell.stylemask
}
/// Add the specified styles (in the LSBs) to the cell's existing spec, whether
/// they're actively supported or not.
/// Add the specified [`NcStyleMask`] bits to the [`NcCell`]'s existing spec,
/// whether they're actively supported or not.
#[inline]
pub fn cell_styles_on(cell: &mut NcCell, stylebits: NcStyleMask) {
cell.stylemask |= stylebits & NCSTYLE_MASK as u16;
}
/// Remove the specified styles (in the LSBs) from the cell's existing spec.
/// Remove the specified [`NcStyleMask`] bits from the cell's existing spec.
#[inline]
pub fn cell_styles_off(cell: &mut NcCell, stylebits: NcStyleMask) {
cell.stylemask &= !(stylebits & NCSTYLE_MASK as u16);
}
/// Use the default color for the foreground.
/// Use the default color for the foreground [`NcChannel`] of this [`NcCell`].
#[inline]
pub fn cell_set_fg_default(cell: &mut NcCell) {
channels_set_fg_default(&mut cell.channels);
}
/// Use the default color for the background.
/// Use the default color for the background [`NcChannel`] of this [`NcCell`].
#[inline]
pub fn cell_set_bg_default(cell: &mut NcCell) {
channels_set_bg_default(&mut cell.channels);
}
/// Set the foreground alpha.
/// Set the foreground [`NcAlphaBits`].
#[inline]
pub fn cell_set_fg_alpha(cell: &mut NcCell, alpha: NcAlphaBits) {
channels_set_fg_alpha(&mut cell.channels, alpha);
}
/// Set the background alpha.
/// Set the background [`NcAlphaBits`].
#[inline]
pub fn cell_set_bg_alpha(cell: &mut NcCell, alpha: NcAlphaBits) {
channels_set_bg_alpha(&mut cell.channels, alpha);
}
/// Does the cell contain an East Asian Wide codepoint?
/// Does the [`NcCell`] contain an East Asian Wide codepoint?
// NOTE: remove casting when fixed: https://github.com/rust-lang/rust-bindgen/issues/1875
#[inline]
pub fn cell_double_wide_p(cell: &NcCell) -> bool {
@ -301,7 +270,8 @@ pub fn cell_strdup(plane: &NcPlane, cell: &NcCell) -> NcChar {
// }
}
/// Extract the three elements of a cell.
/// Extract the three elements of a cell: save the [`NcStyleMask`] and
/// [`NcChannels`], and return the [`NcChar`].
#[inline]
pub fn cell_extract(
plane: &NcPlane,
@ -351,55 +321,59 @@ pub fn cell_load_char(plane: &mut NcPlane, cell: &mut NcCell, ch: NcChar) -> i32
1
}
/// Extract the 32-bit background channel from a cell.
/// Extract the 32-bit background channel from an [`NcCell`].
#[inline]
pub fn cell_bchannel(cell: &NcCell) -> NcChannel {
channels_bchannel(cell.channels)
}
/// Extract the 32-bit foreground channel from a cell.
/// Extract the 32-bit foreground channel from an [`NcCell`].
#[inline]
pub fn cell_fchannel(cell: &NcCell) -> NcChannel {
channels_fchannel(cell.channels)
}
/// Set the 32-bit background channel of a cell.
/// Set the 32-bit background [`NcChannel`] of an [`NcCell`] and return the
/// [`NcChannels`].
#[inline]
pub fn cell_set_bchannel(cell: &mut NcCell, channel: NcChannel) -> NcChannels {
channels_set_bchannel(&mut cell.channels, channel)
}
/// Set the 32-bit foreground channel of a cell.
/// Set the 32-bit foreground [`NcChannel`] of an [`NcCell`] and return the
/// [`NcChannels`].
#[inline]
pub fn cell_set_fchannel(cell: &mut NcCell, channel: NcChannel) -> NcChannels {
channels_set_fchannel(&mut cell.channels, channel)
}
/// Extract 24 bits of foreground RGB from 'cell', shifted to LSBs.
/// Extract 24 bits of foreground [`NcRgb`] from the [`NcCell`] (shifted to LSBs).
#[inline]
pub fn cell_fg_rgb(cell: &NcCell) -> NcChannel {
pub fn cell_fg_rgb(cell: &NcCell) -> NcRgb {
channels_fg_rgb(cell.channels)
}
/// Extract 24 bits of background RGB from 'cell', shifted to LSBs.
/// Extract 24 bits of background RGB from the [`NcCell`] (shifted to LSBs).
#[inline]
pub fn cell_bg_rgb(cell: &NcCell) -> NcChannel {
pub fn cell_bg_rgb(cell: &NcCell) -> NcRgb {
channels_bg_rgb(cell.channels)
}
/// Extract 2 bits of foreground alpha from 'cell', shifted to LSBs.
/// Extract 2 bits of foreground alpha from the [`NcCell`] (shifted to LSBs).
#[inline]
pub fn cell_fg_alpha(cell: &NcCell) -> NcAlphaBits {
channels_fg_alpha(cell.channels)
}
/// Extract 2 bits of background alpha from 'cell', shifted to LSBs.
/// Extract 2 bits of background alpha from the [`NcCell`] (shifted to LSBs).
#[inline]
pub fn cell_bg_alpha(cell: &NcCell) -> NcAlphaBits {
channels_bg_alpha(cell.channels)
}
/// Extract 24 bits of foreground RGB from 'cell', split into components.
/// Extract 24 bits of foreground [`NcRgb`] from the [`NcCell`] and save split
/// into [`NcColor`] components. Also return the corresponding [`NcChannel`]
/// (which can have some extra bits set).
#[inline]
pub fn cell_fg_rgb8(
cell: &NcCell,
@ -410,7 +384,9 @@ pub fn cell_fg_rgb8(
channels_fg_rgb8(cell.channels, red, green, blue)
}
/// Extract 24 bits of background RGB from 'cell', split into components.
/// Extract 24 bits of background [`NcRgb`] from the [`NcCell`] and save split
/// into [`NcColor`] components. Also return the corresponding [`NcChannel`]
/// (which can have some extra bits set).
#[inline]
pub fn cell_bg_rgb8(
cell: &NcCell,
@ -421,23 +397,25 @@ pub fn cell_bg_rgb8(
channels_bg_rgb8(cell.channels, red, green, blue)
}
/// 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.
/// Set the RGB [`NcColor`] components for the foreground [`NcChannel`] of this
/// [`NcCell`], and mark it as not using the default color.
#[inline]
pub fn cell_set_fg_rgb8(cell: &mut NcCell, red: NcColor, green: NcColor, blue: NcColor) {
channels_set_fg_rgb8(&mut cell.channels, red, green, blue);
}
/// Same as `cell_set_fg_rgb8()` but with an assembled 24-bit RGB value.
/// Set the [`NcRgb`] 24-bit value for the foreground [`NcChannel`] of this
/// [`NcCell`], and mark it as not using the default color.
#[inline]
pub fn cell_set_fg_rgb(cell: &mut NcCell, channel: NcChannel) {
channels_set_fg_rgb(&mut cell.channels, channel);
pub fn cell_set_fg_rgb(cell: &mut NcCell, rgb: NcRgb) {
channels_set_fg_rgb(&mut cell.channels, rgb);
}
/// Set the cell's foreground palette index, set the foreground palette index
/// bit, set it foreground-opaque, and clear the foreground default color bit.
/// Set the cell's foreground [`NcPaletteIndex`], set the foreground palette index
/// bit ([`NCCELL_FG_PALETTE`]), set it foreground-opaque ([`NCCELL_ALPHA_OPAQUE`]),
/// and clear the foreground default color bit ([`NCCELL_FGDEFAULT_MASK`]).
///
// NOTE: this function now can't fail
// NOTE: unlike the original C function, this one can't fail
#[inline]
pub fn cell_set_fg_palindex(cell: &mut NcCell, index: NcPaletteIndex) {
cell.channels |= NCCELL_FGDEFAULT_MASK;
@ -447,31 +425,32 @@ pub fn cell_set_fg_palindex(cell: &mut NcCell, index: NcPaletteIndex) {
cell.channels |= (index as NcChannels) << 32;
}
///
/// Return the [`NcPaletteIndex`] of the foreground [`NcChannel`] of the
/// [`NcCell`]
#[inline]
pub fn cell_fg_palindex(cell: &NcCell) -> NcPaletteIndex {
((cell.channels & 0xff00000000 as NcChannels) >> 32) as NcPaletteIndex
}
/// 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.
///
/// Set the RGB [`NcColor`] components for the background [`NcChannel`] of this
/// [`NcCell`], and mark it as not using the default color.
#[inline]
pub fn cell_set_bg_rgb8(cell: &mut NcCell, red: NcColor, green: NcColor, blue: NcColor) {
channels_set_bg_rgb8(&mut cell.channels, red, green, blue);
}
/// Same as `cell_set_fg_rgb8()` but with an assembled 24-bit RGB value.
///
/// Set the [`NcRgb`] 24-bit value for the background [`NcChannel`] of this
/// [`NcCell`], and mark it as not using the default color.
#[inline]
pub fn cell_set_bg_rgb(cell: &mut NcCell, channel: NcChannel) {
channels_set_bg_rgb(&mut cell.channels, channel);
pub fn cell_set_bg_rgb(cell: &mut NcCell, rgb: NcRgb) {
channels_set_bg_rgb(&mut cell.channels, rgb);
}
/// Set the cell's background palette index, set the background palette index
/// bit, set it background-opaque, and clear the background default color bit.
/// Set the cell's background [`NcPaletteIndex`], set the background palette index
/// bit ([`NCCELL_BG_PALETTE`]), set it background-opaque ([`NCCELL_ALPHA_OPAQUE`]),
/// and clear the background default color bit ([`NCCELL_BGDEFAULT_MASK`]).
///
// NOTE: this function now can't fail
// NOTE: unlike the original C function, this one can't fail
#[inline]
pub fn cell_set_bg_palindex(cell: &mut NcCell, index: NcPaletteIndex) {
cell.channels |= NCCELL_BGDEFAULT_MASK as NcChannels;
@ -481,46 +460,40 @@ pub fn cell_set_bg_palindex(cell: &mut NcCell, index: NcPaletteIndex) {
cell.channels |= index as NcChannels;
}
///
/// Return the [`NcPaletteIndex`] of the background [`NcChannel`] of the
/// [`NcCell`]
#[inline]
pub fn cell_bg_palindex(cell: &NcCell) -> NcPaletteIndex {
(cell.channels & 0xff) as NcPaletteIndex
}
/// Is the foreground using the "default foreground color"?
/// Is the foreground [`NcChannel`] of this [`NcCell`] using the
/// "default foreground color"?
#[inline]
pub fn cell_fg_default_p(cell: &NcCell) -> bool {
channels_fg_default_p(cell.channels)
}
///
/// Is the foreground [`NcChannel`] of this [`NcCell`] using an
/// [`NcPaletteIndex`] indexed [`NcPalette`][crate::NcPalette] color?
#[inline]
pub fn cell_fg_palindex_p(cell: &NcCell) -> bool {
channels_fg_palindex_p(cell.channels)
}
/// Is the background using the "default background color"? The "default
/// background color" must generally be used to take advantage of
/// Is the background [`NcChannel`] of this [`NcCell`] using the
/// "default background color"?
///
/// The "default background color" must generally be used to take advantage of
/// terminal-effected transparency.
#[inline]
pub fn cell_bg_default_p(cell: &NcCell) -> bool {
channels_bg_default_p(cell.channels)
}
///
/// Is the background [`NcChannel`] of this [`NcCell`] using an
/// [`NcPaletteIndex`] indexed [`NcPalette`][`crate::NcPalette] color?
#[inline]
pub fn cell_bg_palindex_p(cell: &NcCell) -> bool {
channels_bg_palindex_p(cell.channels)
}
#[cfg(test)]
mod test {
// use super::nc;
// use serial_test::serial;
/*
#[test]
#[serial]
fn () {
}
*/
}

@ -0,0 +1,130 @@
//! [`NcCell`] tests
use crate::NcCell;
use serial_test::serial;
#[test]
#[serial]
fn constructors() {
let _c1 = NcCell::new_blank();
let _c2 = NcCell::with_char('C');
let _c3 = NcCell::new('c', 0, 0);
}
#[test]
#[serial]
fn channels() {
let mut c1 = NcCell::new_blank();
assert_eq![0, crate::cell_fchannel(&c1)];
assert_eq![0, crate::cell_bchannel(&c1)];
crate::cell_set_fchannel(&mut c1, 0x77112233);
assert_eq![0x77112233, crate::cell_fchannel(&c1)];
crate::cell_set_bchannel(&mut c1, 0x88445566);
assert_eq![0x88445566, crate::cell_bchannel(&c1)];
let c2 = NcCell::new(' ', 0, 0x0011223300445566);
assert_eq![0x112233, crate::cell_fchannel(&c2)];
assert_eq![0x445566, crate::cell_bchannel(&c2)];
}
#[test]
#[serial]
fn rgb() {
// rgb
let mut c1 = NcCell::new_blank();
assert_eq![0, crate::cell_fg_rgb(&c1)];
assert_eq![0, crate::cell_bg_rgb(&c1)];
crate::cell_set_fg_rgb(&mut c1, 0x99112233);
assert_eq![0x112233, crate::cell_fg_rgb(&c1)];
crate::cell_set_bg_rgb(&mut c1, 0x99445566);
assert_eq![0x445566, crate::cell_bg_rgb(&c1)];
// rgb8
let mut c2 = NcCell::new_blank();
let (mut r, mut g, mut b) = (0, 0, 0);
crate::cell_set_fg_rgb8(&mut c2, 0x11, 0x22, 0x33);
let fchannel = crate::cell_fg_rgb8(&c2, &mut r, &mut g, &mut b);
assert_eq!((0x11, 0x22, 0x33), (r, g, b));
assert_eq![0x112233, fchannel & !crate::NCCELL_BGDEFAULT_MASK];
crate::cell_set_bg_rgb8(&mut c2, 0x44, 0x55, 0x66);
let bchannel = crate::cell_bg_rgb8(&c2, &mut r, &mut g, &mut b);
assert_eq!((0x44, 0x55, 0x66), (r, g, b));
assert_eq![0x445566, bchannel & !crate::NCCELL_BGDEFAULT_MASK];
}
#[test]
#[serial]
fn alpha() {
let mut c1 = NcCell::new_blank();
assert_eq![0, crate::cell_fg_alpha(&c1)];
assert_eq![0, crate::cell_bg_alpha(&c1)];
crate::cell_set_fg_alpha(&mut c1, crate::NCCELL_ALPHA_TRANSPARENT);
assert_eq![crate::NCCELL_ALPHA_TRANSPARENT, crate::cell_fg_alpha(&c1)];
crate::cell_set_bg_alpha(&mut c1, crate::NCCELL_ALPHA_BLEND);
assert_eq![crate::NCCELL_ALPHA_BLEND, crate::cell_bg_alpha(&c1)];
}
#[test]
#[serial]
fn default() {
let mut c1 = NcCell::new_blank();
assert_eq![true, crate::cell_fg_default_p(&c1)];
assert_eq![true, crate::cell_bg_default_p(&c1)];
// rgb
crate::cell_set_fg_rgb(&mut c1, 0x112233);
crate::cell_set_bg_rgb(&mut c1, 0x445566);
assert_eq![false, crate::cell_fg_default_p(&c1)];
assert_eq![false, crate::cell_bg_default_p(&c1)];
// reset
crate::cell_set_fg_default(&mut c1);
crate::cell_set_bg_default(&mut c1);
assert_eq![true, crate::cell_fg_default_p(&c1)];
assert_eq![true, crate::cell_bg_default_p(&c1)];
// rgb8
crate::cell_set_fg_rgb8(&mut c1, 0x11, 0x22, 0x33);
crate::cell_set_bg_rgb8(&mut c1, 0x44, 0x55, 0x66);
assert_eq![false, crate::cell_fg_default_p(&c1)];
assert_eq![false, crate::cell_bg_default_p(&c1)];
// reset
crate::cell_set_fg_default(&mut c1);
crate::cell_set_bg_default(&mut c1);
// palette
crate::cell_set_fg_palindex(&mut c1, 5);
crate::cell_set_bg_palindex(&mut c1, 6);
assert_eq![false, crate::cell_fg_default_p(&c1)];
assert_eq![false, crate::cell_bg_default_p(&c1)];
}
#[test]
#[serial]
fn palette() {
let mut c1 = NcCell::new_blank();
assert_eq![false, crate::cell_fg_palindex_p(&c1)];
assert_eq![false, crate::cell_bg_palindex_p(&c1)];
assert_eq![0, crate::cell_fg_palindex(&c1)];
assert_eq![0, crate::cell_bg_palindex(&c1)];
crate::cell_set_fg_palindex(&mut c1, 5);
crate::cell_set_bg_palindex(&mut c1, 6);
assert_eq![true, crate::cell_fg_palindex_p(&c1)];
assert_eq![true, crate::cell_bg_palindex_p(&c1)];
assert_eq![5, crate::cell_fg_palindex(&c1)];
assert_eq![6, crate::cell_bg_palindex(&c1)];
}

@ -1,3 +1,5 @@
//! [`NcChannel`] & [`NcChannels`] `channel*_*` static_function reinmplementations
// -----------------------------------------------------------------------------
// - The channel components are u8 instead of u32.
// Because of type enforcing, some runtime checks are now unnecessary.
@ -18,19 +20,19 @@
// ------------------------------------------ (implement / remaining)
// (X) wont: 3
// (+) done: 34 / 2
// (#) test: 14 / 22
// (#) test: 19 / 17
// ------------------------------------------
//# channel_alpha
//# channel_b
//# channel_default_p
//# channel_g
//+ channel_palindex_p
//# channel_palindex_p
//# channel_r
//# channel_rgb8
//# channels_bchannel
//+ channels_bg_alpha
//+ channels_bg_default_p
//+ channels_bg_palindex_p
//# channels_bg_palindex_p
//+ channels_bg_rgb
//+ channels_bg_rgb8
//# channels_combine
@ -42,28 +44,31 @@
//# channels_fchannel
//+ channels_fg_alpha
//+ channels_fg_default_p
//+ channels_fg_palindex_p
//# channels_fg_palindex_p
//+ channels_fg_rgb
//+ channels_fg_rgb8
//# channels_set_bchannel
//+ channels_set_bg_alpha
//+ channels_set_bg_default
// channels_set_bg_palindex
//# channels_set_bg_palindex
//+ channels_set_bg_rgb
//+ channels_set_bg_rgb8
//X channels_set_bg_rgb8_clipped
//# channels_set_fchannel
//+ channels_set_fg_alpha
//+ channels_set_fg_default
// channels_set_fg_palindex
//# channels_set_fg_palindex
//+ channels_set_fg_rgb
//+ channels_set_fg_rgb8
//X channels_set_fg_rgb8_clipped
#[cfg(test)]
mod tests;
use crate::types::{
NcAlphaBits, NcChannel, NcChannels, NcColor, NcRgb, NCCELL_ALPHA_HIGHCONTRAST,
NcAlphaBits, NcChannel, NcChannels, NcColor, NcPaletteIndex, NcRgb, NCCELL_ALPHA_HIGHCONTRAST,
NCCELL_ALPHA_OPAQUE, NCCELL_BGDEFAULT_MASK, NCCELL_BG_PALETTE, NCCELL_BG_RGB_MASK,
NCCHANNEL_ALPHA_MASK,
NCCELL_FGDEFAULT_MASK, NCCELL_FG_PALETTE, NCCHANNEL_ALPHA_MASK,
};
/// Extract the 8-bit red component from a 32-bit channel.
@ -139,7 +144,7 @@ pub fn channel_default_p(channel: NcChannel) -> bool {
/// Is this channel using palette-indexed color rather than RGB?
#[inline]
pub fn channel_palindex_p(channel: NcChannel) -> bool {
!channel_default_p(channel) && (channel & NCCELL_BG_PALETTE) == 0
!(channel_default_p(channel) && (channel & NCCELL_BG_PALETTE) == 0)
}
/// Mark the channel as using its default color, which also marks it opaque.
@ -311,6 +316,28 @@ pub fn channels_bg_palindex_p(channels: NcChannels) -> bool {
channel_palindex_p(channels_bchannel(channels))
}
/// Set the cell's background palette index, set the background palette index
/// bit, set it background-opaque, and clear the background default color bit.
#[inline]
pub fn channels_set_bg_palindex(channels: &mut NcChannels, index: NcPaletteIndex) {
*channels |= NCCELL_BGDEFAULT_MASK as NcChannels;
*channels |= NCCELL_BG_PALETTE as NcChannels;
channels_set_bg_alpha(channels, NCCELL_ALPHA_OPAQUE);
*channels &= 0xffffffffff000000;
*channels |= index as NcChannels;
}
/// Set the cell's foreground palette index, set the foreground palette index
/// bit, set it foreground-opaque, and clear the foreground default color bit.
#[inline]
pub fn channels_set_fg_palindex(channels: &mut NcChannels, index: NcPaletteIndex) {
*channels |= NCCELL_FGDEFAULT_MASK;
*channels |= NCCELL_FG_PALETTE as NcChannels;
channels_set_fg_alpha(channels, NCCELL_ALPHA_OPAQUE);
*channels &= 0xff000000ffffffff as NcChannels;
*channels |= (index as NcChannels) << 32;
}
/// Mark the foreground channel as using its default color.
#[inline]
pub fn channels_set_fg_default(channels: &mut NcChannels) -> NcChannels {
@ -328,134 +355,3 @@ pub fn channels_set_bg_default(channels: &mut NcChannels) -> NcChannels {
channels_set_bchannel(channels, channel);
*channels
}
#[cfg(test)]
mod test {
use super::{NcChannel, NcChannels};
use crate::types::{
NCCELL_ALPHA_BLEND, NCCELL_ALPHA_HIGHCONTRAST, NCCELL_ALPHA_OPAQUE,
NCCELL_ALPHA_TRANSPARENT,
};
use serial_test::serial;
#[test]
#[serial]
fn channel_r() {
let c: NcChannel = 0x112233;
assert_eq!(super::channel_r(c), 0x11);
}
#[test]
#[serial]
fn channel_g() {
let c: NcChannel = 0x112233;
assert_eq!(super::channel_g(c), 0x22);
}
#[test]
#[serial]
fn channel_b() {
let c: NcChannel = 0x112233;
assert_eq!(super::channel_b(c), 0x33);
}
#[test]
#[serial]
fn channel_rgb8() {
let c: NcChannel = 0x112233;
let mut r = 0;
let mut g = 0;
let mut b = 0;
super::channel_rgb8(c, &mut r, &mut g, &mut b);
assert_eq!(r, 0x11);
assert_eq!(g, 0x22);
assert_eq!(b, 0x33);
}
#[test]
#[serial]
fn channel_set_rgb8() {
let mut c: NcChannel = 0x000000;
super::channel_set_rgb8(&mut c, 0x11, 0x22, 0x33);
assert_eq!(super::channel_r(c), 0x11);
assert_eq!(super::channel_g(c), 0x22);
assert_eq!(super::channel_b(c), 0x33);
}
#[test]
#[serial]
fn channel_alpha() {
let c: NcChannel = 0x112233 | NCCELL_ALPHA_TRANSPARENT;
assert_eq!(super::channel_alpha(c), NCCELL_ALPHA_TRANSPARENT);
}
#[test]
#[serial]
fn channel_set_alpha() {
let mut c: NcChannel = 0x112233;
super::channel_set_alpha(&mut c, NCCELL_ALPHA_HIGHCONTRAST);
assert_eq!(NCCELL_ALPHA_HIGHCONTRAST, super::channel_alpha(c));
super::channel_set_alpha(&mut c, NCCELL_ALPHA_TRANSPARENT);
assert_eq!(NCCELL_ALPHA_TRANSPARENT, super::channel_alpha(c));
super::channel_set_alpha(&mut c, NCCELL_ALPHA_BLEND);
assert_eq!(NCCELL_ALPHA_BLEND, super::channel_alpha(c));
super::channel_set_alpha(&mut c, NCCELL_ALPHA_OPAQUE);
assert_eq!(NCCELL_ALPHA_OPAQUE, super::channel_alpha(c));
// TODO: CHECK for NCCELL_BGDEFAULT_MASK
}
#[test]
#[serial]
fn channel_set_default() {
const DEFAULT: NcChannel = 0x112233;
let mut c: NcChannel = DEFAULT | NCCELL_ALPHA_TRANSPARENT;
assert!(c != DEFAULT);
super::channel_set_default(&mut c);
assert_eq!(c, DEFAULT);
}
#[test]
#[serial]
fn channel_default_p() {
let mut c: NcChannel = 0x112233;
assert_eq!(true, crate::channel_default_p(c));
let _ = crate::channel_set_alpha(&mut c, NCCELL_ALPHA_OPAQUE);
assert_eq!(true, crate::channel_default_p(c));
crate::channel_set(&mut c, 0x112233);
assert_eq!(false, super::channel_default_p(c));
}
#[test]
#[serial]
#[allow(non_snake_case)]
fn channels_set_fchannel__channels_fchannel() {
let fc: NcChannel = 0x112233;
let mut cp: NcChannels = 0;
super::channels_set_fchannel(&mut cp, fc);
assert_eq!(super::channels_fchannel(cp), fc);
}
#[test]
#[serial]
#[allow(non_snake_case)]
fn channels_set_bchannel__channels_bchannel() {
let bc: NcChannel = 0x112233;
let mut cp: NcChannels = 0;
super::channels_set_bchannel(&mut cp, bc);
assert_eq!(super::channels_bchannel(cp), bc);
}
#[test]
#[serial]
fn channels_combine() {
let bc: NcChannel = 0x112233;
let fc: NcChannel = 0x445566;
let mut cp1: NcChannels = 0;
let mut _cp2: NcChannels = 0;
super::channels_set_bchannel(&mut cp1, bc);
super::channels_set_fchannel(&mut cp1, fc);
_cp2 = super::channels_combine(fc, bc);
assert_eq!(cp1, _cp2);
}
}

@ -0,0 +1,153 @@
//! [`NcChannel`] & [`NcChannels`] tests
use crate::{
NcChannel, NcChannels, NCCELL_ALPHA_BLEND, NCCELL_ALPHA_HIGHCONTRAST, NCCELL_ALPHA_OPAQUE,
NCCELL_ALPHA_TRANSPARENT,
};
use serial_test::serial;
#[test]
#[serial]
fn channel_r() {
let c: NcChannel = 0x112233;
assert_eq!(crate::channel_r(c), 0x11);
}
#[test]
#[serial]
fn channel_g() {
let c: NcChannel = 0x112233;
assert_eq!(crate::channel_g(c), 0x22);
}
#[test]
#[serial]
fn channel_b() {
let c: NcChannel = 0x112233;
assert_eq!(crate::channel_b(c), 0x33);
}
#[test]
#[serial]
fn channel_rgb8() {
let c: NcChannel = 0x112233;
let mut r = 0;
let mut g = 0;
let mut b = 0;
crate::channel_rgb8(c, &mut r, &mut g, &mut b);
assert_eq!(r, 0x11);
assert_eq!(g, 0x22);
assert_eq!(b, 0x33);
}
#[test]
#[serial]
fn channel_set_rgb8() {
let mut c: NcChannel = 0x000000;
crate::channel_set_rgb8(&mut c, 0x11, 0x22, 0x33);
assert_eq!(crate::channel_r(c), 0x11);
assert_eq!(crate::channel_g(c), 0x22);
assert_eq!(crate::channel_b(c), 0x33);
}
#[test]
#[serial]
fn channel_alpha() {
let c: NcChannel = 0x112233 | NCCELL_ALPHA_TRANSPARENT;
assert_eq!(crate::channel_alpha(c), NCCELL_ALPHA_TRANSPARENT);
}
#[test]
#[serial]
fn channel_set_alpha() {
let mut c: NcChannel = 0x112233;
crate::channel_set_alpha(&mut c, NCCELL_ALPHA_HIGHCONTRAST);
assert_eq!(NCCELL_ALPHA_HIGHCONTRAST, crate::channel_alpha(c));
crate::channel_set_alpha(&mut c, NCCELL_ALPHA_TRANSPARENT);
assert_eq!(NCCELL_ALPHA_TRANSPARENT, crate::channel_alpha(c));
crate::channel_set_alpha(&mut c, NCCELL_ALPHA_BLEND);
assert_eq!(NCCELL_ALPHA_BLEND, crate::channel_alpha(c));
crate::channel_set_alpha(&mut c, NCCELL_ALPHA_OPAQUE);
assert_eq!(NCCELL_ALPHA_OPAQUE, crate::channel_alpha(c));
// TODO: CHECK for NCCELL_BGDEFAULT_MASK
}
#[test]
#[serial]
fn channel_set_default() {
const DEFAULT: NcChannel = 0x112233;
let mut c: NcChannel = DEFAULT | NCCELL_ALPHA_TRANSPARENT;
assert!(c != DEFAULT);
crate::channel_set_default(&mut c);
assert_eq!(c, DEFAULT);
}
#[test]
#[serial]
fn channel_default_p() {
let mut c: NcChannel = 0x112233;
assert_eq!(true, crate::channel_default_p(c));
let _ = crate::channel_set_alpha(&mut c, NCCELL_ALPHA_OPAQUE);
assert_eq!(true, crate::channel_default_p(c));
crate::channel_set(&mut c, 0x112233);
assert_eq!(false, crate::channel_default_p(c));
}
#[test]
#[serial]
#[allow(non_snake_case)]
fn channels_set_fchannel__channels_fchannel() {
let fc: NcChannel = 0x112233;
let mut cp: NcChannels = 0;
crate::channels_set_fchannel(&mut cp, fc);
assert_eq!(crate::channels_fchannel(cp), fc);
}
#[test]
#[serial]
#[allow(non_snake_case)]
fn channels_set_bchannel__channels_bchannel() {
let bc: NcChannel = 0x112233;
let mut cp: NcChannels = 0;
crate::channels_set_bchannel(&mut cp, bc);
assert_eq!(crate::channels_bchannel(cp), bc);
}
#[test]
#[serial]
fn channels_combine() {
let bc: NcChannel = 0x112233;
let fc: NcChannel = 0x445566;
let mut cp1: NcChannels = 0;
let mut _cp2: NcChannels = 0;
crate::channels_set_bchannel(&mut cp1, bc);
crate::channels_set_fchannel(&mut cp1, fc);
_cp2 = crate::channels_combine(fc, bc);
assert_eq!(cp1, _cp2);
}
#[test]
#[serial]
fn channels_palette() {
let bc: NcChannel = 0x112233;
let fc: NcChannel = 0x445566;
assert_eq!(false, crate::channel_palindex_p(bc));
assert_eq!(false, crate::channel_palindex_p(fc));
let mut channels = crate::channels_combine(fc, bc);
assert_eq!(false, crate::channels_fg_palindex_p(channels));
assert_eq!(false, crate::channels_bg_palindex_p(channels));
crate::channels_set_fg_palindex(&mut channels, 5);
crate::channels_set_bg_palindex(&mut channels, 6);
assert_eq!(true, crate::channels_fg_palindex_p(channels));
assert_eq!(true, crate::channels_bg_palindex_p(channels));
}

@ -47,11 +47,11 @@ impl NotcursesOptions {
/// can be added without reshaping the struct.
/// Undefined bits must be set to 0.
///
/// - [`NCOPTION_INHIBIT_SETLOCALE`]
/// - [`NCOPTION_INHIBIT_SETLOCALE`][crate::NCOPTION_INHIBIT_SETLOCALE]
/// - [`NCOPTION_NO_ALTERNATE_SCREEN`]
/// - [`NCOPTION_NO_FONT_CHANGES`]
/// - [`NCOPTION_NO_QUIT_SIGHANDLERS`]
/// - [`NCOPTION_NO_WINCH_SIGHANDLER`]
/// - [`NCOPTION_NO_FONT_CHANGES`][crate::NCOPTION_NO_FONT_CHANGES]
/// - [`NCOPTION_NO_QUIT_SIGHANDLERS`][crate::NCOPTION_NO_QUIT_SIGHANDLERS]
/// - [`NCOPTION_NO_WINCH_SIGHANDLER`][crate::NCOPTION_NO_WINCH_SIGHANDLER]
/// - [`NCOPTION_SUPPRESS_BANNERS`]
///
pub fn with_all_options(

@ -1,9 +1,28 @@
#[allow(unused_imports)] // for docblocks
use crate::NcPlane;
use crate::{NcAlphaBits, NcChannel, NcPlane};
// NcCell
/// A coordinate on an [`NcPlane`] storing 128 bits of data
///
/// An `NcCell` corresponds to a single character cell on some [`NcPlane`],
/// which can be occupied by a single [`NcChar`] grapheme cluster (some root
/// spacing glyph, along with possible combining characters, which might span
/// multiple columns).
///
/// At any `NcCell`, we can have a theoretically arbitrarily long UTF-8 string,
/// a foreground color, a background color, and an [`NcStyleMask`] attribute set.
///
/// Valid grapheme cluster contents include:
///
/// - A NUL terminator,
/// - A single [control character](https://en.wikipedia.org/wiki/Control_character),
/// followed by a NUL terminator,
/// - At most one [spacing
/// character](https://en.wikipedia.org/wiki/Graphic_character#Spacing_character),
/// followed by zero or more nonspacing characters, followed by a NUL terminator.
///
/// ## Diagram
///
/// ```txt
/// NcCell: 128 bits structure comprised of the following 5 elements:
///
@ -33,21 +52,13 @@ use crate::NcPlane;
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB|~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB
/// ```
///
/// An NcCell corresponds to a single character cell on some plane, which can be
/// occupied by a single grapheme cluster (some root spacing glyph, along with
/// possible combining characters, which might span multiple columns). At any
/// cell, we can have a theoretically arbitrarily long UTF-8 string, a
/// foreground color, a background color, and an attribute set.
///
/// Valid grapheme cluster contents include:
/// `type in C: cell (struct)`
///
/// - A NUL terminator,
/// - A single control character, followed by a NUL terminator,
/// - At most one spacing character, followed by zero or more nonspacing
/// characters, followed by a NUL terminator.
/// ## Size
///
/// Multi-column characters can only have a single style/color throughout.
/// wcwidth() is not reliable. It's just quoting whether or not the NcChar
/// [`wcwidth()`](https://www.man7.org/linux/man-pages/man3/wcwidth.3.html)
/// is not reliable. It's just quoting whether or not the [`NcChar`]
/// contains a "Wide Asian" double-width character.
/// This is set for some things, like most emoji, and not set for
/// other things, like cuneiform.
@ -57,115 +68,168 @@ use crate::NcPlane;
/// Dynamic requirements (the egcpool) can add up to 16MB to an ncplane, but
/// such large pools are unlikely in common use.
///
/// ## Alpha Compositing
///
/// We implement some small alpha compositing. Foreground and background both
/// have two bits of inverted alpha. The actual grapheme written to a cell is
/// the topmost non-zero grapheme.
///
/// - If its alpha is 00 (CELL_ALPHA_OPAQUE) its foreground color is used unchanged.
/// - If its alpha is 00 ([`NCCELL_ALPHA_OPAQUE`]) its foreground color is used unchanged.
///
/// - If its alpha is 10 (CELL_ALPHA_TRANSPARENT) its foreground color is derived
/// - If its alpha is 10 ([`NCCELL_ALPHA_TRANSPARENT`]) its foreground color is derived
/// entirely from cells underneath it.
///
/// - Otherwise, the result will be a composite (CELL_ALPHA_BLEND).
/// - If its alpha is 01 ([`NCCELL_ALPHA_BLEND`]) the result will be a composite.
///
/// Likewise for the background. If the bottom of a coordinate's zbuffer is
/// reached with a cumulative alpha of zero, the default is used. In this way,
/// a terminal configured with transparent background can be supported through
/// multiple occluding ncplanes.
///
/// A foreground alpha of 11 (CELL_ALPHA_HIGHCONTRAST) requests high-contrast
/// A foreground alpha of 11 ([`NCCELL_ALPHA_HIGHCONTRAST`]) requests high-contrast
/// text (relative to the computed background).
/// A background alpha of 11 is currently forbidden.
///
/// Default color takes precedence over palette or RGB, and cannot be used with
/// transparency. Indexed palette takes precedence over RGB. It cannot
/// meaningfully set transparency, but it can be mixed into a cascading color.
/// RGB is used if neither default terminal colors nor palette indexing are in
/// play, and fully supports all transparency options.
/// ## Precedence
///
/// `type in C: cell (struct)`
/// - Default color takes precedence over palette or RGB, and cannot be used with
/// transparency.
/// - Indexed palette takes precedence over RGB. It cannot meaningfully set
/// transparency, but it can be mixed into a cascading color.
/// - RGB is used if neither default terminal colors nor palette indexing are in
/// play, and fully supports all transparency options.
///
pub type NcCell = crate::bindings::bindgen::cell;
///
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground or background color will be a composite between
/// its color and the `NcCell`s' corresponding colors underneath it
pub const NCCELL_ALPHA_BLEND: u32 = crate::bindings::bindgen::CELL_ALPHA_BLEND;
/// Background cannot be highcontrast, only foreground
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground color will be high-contrast (relative to the
/// computed background). Background cannot be highcontrast
pub const NCCELL_ALPHA_HIGHCONTRAST: u32 = crate::bindings::bindgen::CELL_ALPHA_HIGHCONTRAST;
///
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground or background color is used unchanged
pub const NCCELL_ALPHA_OPAQUE: u32 = crate::bindings::bindgen::CELL_ALPHA_OPAQUE;
///
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground or background color is derived entirely from the
/// `NcCell`s underneath it
pub const NCCELL_ALPHA_TRANSPARENT: u32 = crate::bindings::bindgen::CELL_ALPHA_TRANSPARENT;
/// If this bit is set, we are *not* using the default background color
///
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BGDEFAULT_MASK: u32 = crate::bindings::bindgen::CELL_BGDEFAULT_MASK;
/// Extract these bits to get the background alpha mask
/// ([`NcAlphaBits`])
///
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BG_ALPHA_MASK: u32 = crate::bindings::bindgen::CELL_BG_ALPHA_MASK;
/// If this bit *and* [`CELL_BGDEFAULT_MASK`] are set, we're using a
/// If this bit *and* [`NCCELL_BGDEFAULT_MASK`] are set, we're using a
/// palette-indexed background color
///
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BG_PALETTE: u32 = crate::bindings::bindgen::CELL_BG_PALETTE;
/// Extract these bits to get the background RGB value
/// Extract these bits to get the background [`NcRgb`][crate::NcRgb] value
///
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BG_RGB_MASK: u32 = crate::bindings::bindgen::CELL_BG_RGB_MASK;
/// If this bit is set, we are *not* using the default foreground color
///
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BGDEFAULT_MASK`];
pub const NCCELL_FGDEFAULT_MASK: u64 = crate::bindings::bindgen::CELL_FGDEFAULT_MASK;
/// Extract these bits to get the foreground alpha mask
/// ([`NcAlphaBits`])
///
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BG_ALPHA_MASK`];
pub const NCCELL_FG_ALPHA_MASK: u64 = crate::bindings::bindgen::CELL_FG_ALPHA_MASK;
/// If this bit *and* [`CELL_BGDEFAULT_MASK`] are set, we're using a
/// If this bit *and* [`NCCELL_BGDEFAULT_MASK`] are set, we're using a
/// palette-indexed background color
///
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BG_PALETTE`];
pub const NCCELL_FG_PALETTE: u64 = crate::bindings::bindgen::CELL_FG_PALETTE;
/// Extract these bits to get the foreground RGB value
/// Extract these bits to get the foreground [`NcRgb`][crate::NcRgb] value
///
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BG_RGB_MASK`];
pub const NCCELL_FG_RGB_MASK: u64 = crate::bindings::bindgen::CELL_FG_RGB_MASK;
/// Indicates the glyph is entirely foreground
///
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
pub const NCCELL_NOBACKGROUND_MASK: u64 = crate::bindings::bindgen::CELL_NOBACKGROUND_MASK;
/// If this bit is set, the cell is part of a multicolumn glyph.
///
/// Whether a cell is the left or right side of the glyph can be determined
/// by checking whether ->gcluster is zero.
///
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
pub const NCCELL_WIDEASIAN_MASK: u64 = crate::bindings::bindgen::CELL_WIDEASIAN_MASK as u64;
// NcChar
//
/// Extended Grapheme Cluster. A 32-bit `Char` type
///
/// - https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
/// Extended Grapheme Cluster. A 32-bit [`char`]-like type
///
/// This 32 bit char, together with the associated plane's associated egcpool,
/// completely define this cell's `NcChar`. Unless the `NcChar` requires more than
/// four bytes to encode as UTF-8, it will be inlined here:
///
/// ## Diagram 1
///
/// ```txt
/// UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU
/// extended grapheme cluster <= 4bytes
/// ```
///
/// `type in C: uint32_t`
///
/// If more than four bytes are required, it will be spilled into the egcpool.
/// In either case, there's a NUL-terminated string available without copying,
/// because (1) the egcpool is all NUL-terminated sequences and (2) the fifth
/// byte of this struct (the GClusterBackStop field, see below) is
/// guaranteed to be zero, as are any unused bytes in gcluster.
///
/// A spilled NcChar is indicated by the value `0x01iiiiii`. This cannot alias a
/// A spilled `NcChar` is indicated by the value `0x01iiiiii`. This cannot alias a
/// true supra-ASCII NcChar, because UTF-8 only encodes bytes <= 0x80 when they
/// are single-byte ASCII-derived values. The `iiiiii` is interpreted as a 24-bit
/// index into the egcpool (which may thus be up to 16MB):
///
/// ## Diagram 2
///
/// ```txt
/// 00000001 iiiiiiii iiiiiiii iiiiiiii
/// sign 24bit index to egcpool
/// ```
/// `type in C: uint32_t`
///
/// The cost of this scheme is that the character 0x01 (SOH) cannot be encoded
/// The cost of this scheme is that the character 0x01 (`SOH`) cannot be encoded
/// in a cell, and therefore it must not be allowed through the API.
///
/// -----
@ -175,13 +239,19 @@ pub const NCCELL_WIDEASIAN_MASK: u64 = crate::bindings::bindgen::CELL_WIDEASIAN_
/// and the remaining 24 bits are an index into the plane's egcpool,
/// which is carved into NUL-terminated chunks of arbitrary length.
///
/// `type in C: uint32_t`
/// ## Links
///
/// - [Grapheme Cluster
/// Boundaries](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
///
///
pub type NcChar = char;
// NcCharBackStop
/// An `u8` always at zero, part of the [`NcCell`] struct
///
/// ## Diagram
///
/// ```txt
/// 00000000
/// ```
@ -192,7 +262,25 @@ pub type NcCharBackstop = u8;
// NcStyleMask
///
/// An `u16` of `NCSTYLE_*` boolean styling attributes
/// An `u16` of `NCSTYLE_*` boolean styling attribute flags
///
/// ## Attributes
///
/// - [`NCSTYLE_BLINK`]
/// - [`NCSTYLE_BOLD`]
/// - [`NCSTYLE_DIM`]
/// - [`NCSTYLE_INVIS`]
/// - [`NCSTYLE_ITALIC`]
/// - [`NCSTYLE_MASK`]
/// - [`NCSTYLE_NONE`]
/// - [`NCSTYLE_PROTECT`]
/// - [`NCSTYLE_REVERSE`]
/// - [`NCSTYLE_STANDOUT`]
/// - [`NCSTYLE_STRUCK`]
/// - [`NCSTYLE_UNDERLINE`]
///
///
/// ## Diagram
///
/// ```txt
/// 11111111 11111111
@ -201,3 +289,39 @@ pub type NcCharBackstop = u8;
/// `type in C: uint16_t`
///
pub type NcStyleMask = u16;
///
pub const NCSTYLE_BLINK: u16 = crate::bindings::bindgen::NCSTYLE_BLINK as u16;
///
pub const NCSTYLE_BOLD: u16 = crate::bindings::bindgen::NCSTYLE_BOLD as u16;
///
pub const NCSTYLE_DIM: u16 = crate::bindings::bindgen::NCSTYLE_DIM as u16;
///
pub const NCSTYLE_INVIS: u16 = crate::bindings::bindgen::NCSTYLE_INVIS as u16;
///
pub const NCSTYLE_ITALIC: u16 = crate::bindings::bindgen::NCSTYLE_ITALIC as u16;
///
pub const NCSTYLE_MASK: u16 = crate::bindings::bindgen::NCSTYLE_MASK as u16;
///
pub const NCSTYLE_NONE: u16 = crate::bindings::bindgen::NCSTYLE_NONE as u16;
///
pub const NCSTYLE_PROTECT: u16 = crate::bindings::bindgen::NCSTYLE_PROTECT as u16;
///
pub const NCSTYLE_REVERSE: u16 = crate::bindings::bindgen::NCSTYLE_REVERSE as u16;
///
pub const NCSTYLE_STANDOUT: u16 = crate::bindings::bindgen::NCSTYLE_STANDOUT as u16;
///
pub const NCSTYLE_STRUCK: u16 = crate::bindings::bindgen::NCSTYLE_STRUCK as u16;
///
pub const NCSTYLE_UNDERLINE: u16 = crate::bindings::bindgen::NCSTYLE_UNDERLINE as u16;

@ -6,17 +6,19 @@ use crate::NcChar;
/// 32 bits of context-dependent info
/// containing RGB + 2 bits of alpha + extra
///
/// ```txt
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB
/// ```
///
/// It is:
/// - an RGB value
/// - plus 2 bits of alpha
/// - plus context-dependent info
/// - a 24-bit [`NcRgb`] value
/// - plus 8 bits divided in:
/// - 2 bits of [`NcAlphaBits`]
/// - 6 bits of context-dependent info
///
/// The context details are documented in [`NcChannels`]
///
/// ## Diagram
///
/// ```txt
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB
/// ```
/// `type in C: channel (uint32_t)`
///
pub type NcChannel = u32;
@ -29,6 +31,8 @@ pub const NCCHANNEL_ALPHA_MASK: u32 = crate::bindings::bindgen::CHANNEL_ALPHA_MA
/// 2 bits of alpha (surrounded by context dependent bits).
/// It is part of an [`NcChannel`].
///
/// ## Diagram
///
/// ```txt
/// ~~AA~~~~ -------- -------- --------
/// ```
@ -41,64 +45,86 @@ pub type NcAlphaBits = u32;
//
/// 64 bits containing a foreground and background [`NcChannel`]
///
/// At render time, both 24-bit [`NcRgb`] values are quantized down to terminal
/// capabilities, if necessary. There's a clear path to 10-bit support should
/// we one day need it.
///
/// ## Default Color
///
/// The "default color" is best explained by
/// [color(3NCURSES)](https://manpages.debian.org/stretch/ncurses-doc/color.3ncurses.en.html).
/// Ours is the same concept.
///
/// **Until the "not default color" bit is set, any color you load will be ignored.**
///
/// ## Diagram
///
/// ```txt
/// ~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB|~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB
/// ↑↑↑↑↑↑↑↑↑↑↑↑ foreground ↑↑↑↑↑↑↑↑↑↑↑|↑↑↑↑↑↑↑↑↑↑↑↑ background ↑↑↑↑↑↑↑↑↑↑↑
/// ```
///
/// Detailed info (specially on the context-dependent bits on each
/// `NcChannel`'s 4th byte):
/// [`NcChannel`]'s 4th byte):
///
/// ```txt
/// ~foreground channel~
/// part of a wide glyph: ↓bits view↓ ↓hex mask↓
/// NCCELL_WIDEASIAN_MASK: part of a wide glyph ↓bits view↓ ↓hex mask↓
/// 1······· ········ ········ ········ ········ ········ ········ ········ = 8······· ········
///
/// foreground is *not* "default color":
/// NCCELL_FGDEFAULT_MASK: foreground is NOT "default color"
/// ·1······ ········ ········ ········ ········ ········ ········ ········ = 4······· ········
///
/// foreground alpha (2bits):
/// NCCELL_FG_ALPHA_MASK: foreground alpha (2bits)
/// ··11···· ········ ········ ········ ········ ········ ········ ········ = 3······· ········
///
/// foreground uses palette index:
/// NCCELL_FG_PALETTE: foreground uses palette index
/// ····1··· ········ ········ ········ ········ ········ ········ ········ = ·8······ ········
///
/// glyph is entirely foreground:
/// NCCELL_NOBACKGROUND_MASK: glyph is entirely foreground
/// ·····1·· ········ ········ ········ ········ ········ ········ ········ = ·4······ ········
///
/// reserved, must be 0:
/// reserved, must be 0
/// ······00 ········ ········ ········ ········ ········ ········ ········ = ·3······ ········
///
/// foreground in 3x8 RGB (rrggbb):
/// NCCELL_FG_RGB_MASK: foreground in 3x8 RGB (rrggbb)
/// ········ 11111111 11111111 11111111 ········ ········ ········ ········ = ··FFFFFF ········
///
/// ```
/// ```txt
/// ~background channel~
/// reserved, must be 0: ↓bits view↓ ↓hex mask↓
/// reserved, must be 0 ↓bits view↓ ↓hex mask↓
/// ········ ········ ········ ········ 0······· ········ ········ ········ = ········ 8·······
///
/// background is *not* "default color":
/// NCCELL_BGDEFAULT_MASK: background is NOT "default color"
/// ········ ········ ········ ········ ·1······ ········ ········ ········ = ········ 4·······
///
/// background alpha (2 bits):
/// NCCELL_BG_ALPHA_MASK: background alpha (2 bits)
/// ········ ········ ········ ········ ··11···· ········ ········ ········ = ········ 3·······
///
/// background uses palette index:
/// NCCELL_BG_PALETTE: background uses palette index
/// ········ ········ ········ ········ ····1··· ········ ········ ········ = ········ ·8······
///
/// reserved, must be 0:
/// reserved, must be 0
/// ········ ········ ········ ········ ·····000 ········ ········ ········ = ········ ·7······
///
/// background in 3x8 RGB (rrggbb):
/// NCCELL_BG_RGB_MASK: background in 3x8 RGB (rrggbb)
/// 0········ ········ ········ ········ ········11111111 11111111 11111111 = ········ ··FFFFFF
/// ```
/// `type in C: channels (uint64_t)`
///
/// At render time, these 24-bit values are quantized down to terminal
/// capabilities, if necessary. There's a clear path to 10-bit support should
/// we one day need it, but keep things cagey for now. "default color" is
/// best explained by color(3NCURSES). ours is the same concept. until the
/// "not default color" bit is set, any color you load will be ignored.
/// ## `NcCell` Mask Flags
///
/// `type in C: channels (uint64_t)`
/// - [`NCCELL_BGDEFAULT_MASK`][crate::NCCELL_BGDEFAULT_MASK]
/// - [`NCCELL_BG_ALPHA_MASK`][crate::NCCELL_BG_ALPHA_MASK]
/// - [`NCCELL_BG_PALETTE`][crate::NCCELL_BG_PALETTE]
/// - [`NCCELL_BG_RGB_MASK`][crate::NCCELL_BG_RGB_MASK]
/// - [`NCCELL_FGDEFAULT_MASK`][crate::NCCELL_FGDEFAULT_MASK]
/// - [`NCCELL_FG_ALPHA_MASK`][crate::NCCELL_FG_ALPHA_MASK]
/// - [`NCCELL_FG_PALETTE`][crate::NCCELL_FG_PALETTE]
/// - [`NCCELL_FG_RGB_MASK`][crate::NCCELL_FG_RGB_MASK]
/// - [`NCCELL_NOBACKGROUND_MASK`][crate::NCCELL_NOBACKGROUND_MASK]
/// - [`NCCELL_WIDEASIAN_MASK`][crate::NCCELL_WIDEASIAN_MASK]
///
pub type NcChannels = u64;
@ -106,6 +132,10 @@ pub type NcChannels = u64;
//
/// 24 bits broken into 3x 8bpp channels.
///
/// Unlike with [`NcChannel`], operations involving `NcRgb` ignores the last 4th byte
///
/// ## Diagram
///
/// ```txt
/// -------- RRRRRRRR GGGGGGGG BBBBBBBB
/// ```
@ -118,6 +148,8 @@ pub type NcRgb = u32;
//
/// 8 bits representing a R/G/B color or alpha channel
///
/// ## Diagram
///
/// ```txt
/// CCCCCCCC (1 Byte)
/// ```
@ -129,16 +161,17 @@ pub type NcColor = u8;
// NcPixel (RGBA)
/// 32 bits broken into RGB + 8-bit alpha
///
/// ```txt
/// AAAAAAAA GGGGGGGG BBBBBBBB RRRRRRRR
/// ```
///
/// NcPixel has 8 bits of alpha, more or less linear, contributing
/// directly to the usual alpha blending equation.
///
/// We map the 8 bits of alpha to 2 bits of alpha via a level function:
/// https://nick-black.com/dankwiki/index.php?title=Notcurses#Transparency.2FContrasting
///
/// ## Diagram
///
/// ```txt
/// AAAAAAAA GGGGGGGG BBBBBBBB RRRRRRRR
/// ```
/// `type in C: ncpixel (uint32_t)`
///
// NOTE: the order of the colors is different than in NcChannel.

@ -26,6 +26,9 @@ pub use cell::{
NCCELL_ALPHA_OPAQUE, NCCELL_ALPHA_TRANSPARENT, NCCELL_BGDEFAULT_MASK, NCCELL_BG_ALPHA_MASK,
NCCELL_BG_PALETTE, NCCELL_BG_RGB_MASK, NCCELL_FGDEFAULT_MASK, NCCELL_FG_ALPHA_MASK,
NCCELL_FG_PALETTE, NCCELL_FG_RGB_MASK, NCCELL_NOBACKGROUND_MASK, NCCELL_WIDEASIAN_MASK,
NCSTYLE_BLINK, NCSTYLE_BOLD, NCSTYLE_DIM, NCSTYLE_INVIS, NCSTYLE_ITALIC, NCSTYLE_MASK,
NCSTYLE_NONE, NCSTYLE_PROTECT, NCSTYLE_REVERSE, NCSTYLE_STANDOUT, NCSTYLE_STRUCK,
NCSTYLE_UNDERLINE,
};
pub use channel::{
NcAlphaBits, NcBlitSet, NcChannel, NcChannels, NcColor, NcFadeCtx, NcPalette, NcPaletteIndex,

@ -80,6 +80,19 @@ pub const NCALIGN_UNALIGNED: NcAlign = crate::bindings::bindgen::ncalign_e_NCALI
///
/// We never blit full blocks, but instead spaces (more efficient) with the
/// background set to the desired foreground.
///
/// ## Modes
///
/// - [`NCBLIT_1x1`]
/// - [`NCBLIT_2x1`]
/// - [`NCBLIT_2x2`]
/// - [`NCBLIT_3x2`]
/// - [`NCBLIT_4x1`]
/// - [`NCBLIT_8x1`]
/// - [`NCBLIT_BRAILLE`]
/// - [`NCBLIT_DEFAULT`]
/// - [`NCBLIT_SIXEL`]
///
pub type NcBlitter = crate::bindings::bindgen::ncblitter_e;
/// [`NcBlitter`] mode using: space, compatible with ASCII

Loading…
Cancel
Save