libnotcurses_sys/channel/
channel.rs

1//! `NcChannel`
2// #![allow(clippy::unnecessary_cast)] // CHECK
3
4use crate::{
5    c_api::{self, NcChannel_u32},
6    NcAlpha, NcChannels, NcPaletteIndex, NcRgb,
7};
8
9// NcChannel
10//
11/// 32 bits of context-dependent info containing [`NcRgb`] + [`NcAlpha`] + extra
12///
13/// It is composed of:
14/// - a 24-bit [`NcRgb`] value
15/// - plus 8 bits divided in:
16///   - 2 bits of [`NcAlpha`]
17///   - 6 bits of context-dependent info
18///
19/// The context details are documented in [`NcChannels`]
20///
21/// ## Diagram
22///
23/// ```txt
24/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB
25/// ```
26/// `type in C: channel (uint32_t)`
27///
28/// # See also
29/// - [`NcRgb`]
30/// - [`NcRgba`]
31///
32/// [`NcRgb`]: crate::NcRgb
33/// [`NcRgba`]: crate::NcRgba
34/// [`NcAlpha`]: crate::NcAlpha
35#[repr(transparent)]
36#[derive(Clone, Copy, Debug, PartialEq, Eq)]
37pub struct NcChannel(pub NcChannel_u32);
38
39mod core_impls {
40    use super::{NcChannel, NcChannel_u32};
41
42    impl Default for NcChannel {
43        fn default() -> Self {
44            Self::with_default()
45        }
46    }
47
48    impl From<NcChannel> for [u8; 3] {
49        #[inline]
50        fn from(rgb: NcChannel) -> Self {
51            rgb.into()
52        }
53    }
54    impl From<[u8; 3]> for NcChannel {
55        fn from(array: [u8; 3]) -> Self {
56            Self::from_rgb(array)
57        }
58    }
59
60    impl From<NcChannel> for (u8, u8, u8) {
61        #[inline]
62        fn from(rgb: NcChannel) -> Self {
63            rgb.into()
64        }
65    }
66    impl From<(u8, u8, u8)> for NcChannel {
67        fn from(tuple: (u8, u8, u8)) -> Self {
68            Self::from_rgb(tuple)
69        }
70    }
71
72    crate::from_primitive![NcChannel, NcChannel_u32];
73    crate::unit_impl_from![NcChannel, NcChannel_u32];
74    crate::unit_impl_fmt![bases+display; NcChannel];
75}
76
77/// # Constants
78impl NcChannel {
79    /// If this bit is set, we are *not* using the default color.
80    ///
81    /// Note: this is equivalent to
82    /// [`NcChannels::BG_DEFAULT_MASK`][NcChannels#associatedconstant.BG_DEFAULT_MASK]
83    pub const DEFAULT_MASK: u32 = super::c_api::NC_BGDEFAULT_MASK;
84
85    /// Extract these bits to get the (background) [`NcAlpha`] mask.
86    ///
87    /// Note: this is equivalent to
88    /// [`NcChannels::BG_ALPHA_MASK`][NcChannels#associatedconstant.BG_ALPHA_MASK]
89    pub const ALPHA_MASK: u32 = super::c_api::NC_BG_ALPHA_MASK;
90
91    /// If this bit *and*
92    /// [`DEFAULT_MASK`][NcChannel#associatedconstant.DEFAULT_MASK] are set,
93    /// we're using a palette-indexed background color
94    ///
95    /// Note: this is equivalent to
96    /// [`NcChannels::BG_PALETTE_MASK`][NcChannels#associatedconstant.BG_PALETTE_MASK]
97    pub const PALETTE_MASK: u32 = super::c_api::NC_BG_PALETTE;
98
99    /// Extract these bits to get the background [`NcRgb`][crate::NcRgb] value.
100    ///
101    /// Note: this is equivalent to
102    /// [`NcChannels::BG_RGB_MASK`][NcChannels#associatedconstant.BG_RGB_MASK]
103    pub const RGB_MASK: u32 = super::c_api::NC_BG_RGB_MASK;
104}
105
106/// # Constructors
107impl NcChannel {
108    /// New `NcChannel`, set to black and NOT using the "default color".
109    pub fn new() -> Self {
110        Self(c_api::NC_BGDEFAULT_MASK)
111    }
112
113    /// New `NcChannel`, set to black and using the "default color".
114    pub fn with_default() -> Self {
115        Self(0)
116    }
117
118    /// New `NcChannel`, expects [`NcRgb`].
119    pub fn from_rgb(rgb: impl Into<NcRgb>) -> Self {
120        Self::new().set(rgb.into())
121    }
122
123    /// New `NcChannel`, expects [`NcRgb`] & [`NcAlpha`].
124    pub fn from_rgb_alpha(rgb: impl Into<NcRgb>, alpha: NcAlpha) -> Self {
125        Self::new().set(rgb.into()).set_alpha(alpha)
126    }
127}
128
129/// # Methods
130impl NcChannel {
131    // Combine
132
133    /// Combines this [`NcChannel`] as foreground, with another as background
134    /// into an [`NcChannels`].
135    ///
136    /// *C style function: [channels_combine()][c_api::ncchannels_combine].*
137    //
138    // Not in the C API
139    pub fn fcombine(&self, bchannel: impl Into<NcChannel>) -> NcChannels {
140        c_api::ncchannels_combine(self.0, bchannel.into().0).into()
141    }
142
143    /// Combines this [`NcChannel`] as background, with another as foreground
144    /// into an [`NcChannels`].
145    ///
146    /// *C style function: [channels_combine()][c_api::ncchannels_combine].*
147    //
148    // Not in the C API
149    pub fn bcombine(&self, fchannel: impl Into<NcChannel>) -> NcChannels {
150        c_api::ncchannels_combine(fchannel.into().0, self.0).into()
151    }
152
153    // Alpha
154
155    /// Gets the [`NcAlpha`].
156    ///
157    /// *C style function: [ncchannel_alpha()][c_api::ncchannel_alpha].*
158    pub fn alpha(&self) -> NcAlpha {
159        c_api::ncchannel_alpha(self.0).into()
160    }
161
162    /// Sets the [`NcAlpha`].
163    ///
164    /// *C style function: [ncchannel_set_alpha()][c_api::ncchannel_set_alpha].*
165    pub fn set_alpha(&mut self, alpha: impl Into<NcAlpha>) -> Self {
166        c_api::ncchannel_set_alpha(&mut self.0, alpha.into());
167        *self
168    }
169
170    // NcRgb
171
172    /// Returns true if the channel is set to RGB color.
173    ///
174    /// *C style function: [ncchannel_rgb_p()][c_api::ncchannel_rgb_p].*
175    pub fn rgb_p(&self) -> bool {
176        c_api::ncchannel_rgb_p(self.0)
177    }
178
179    /// Gets the [`NcRgb`].
180    ///
181    /// *C style function: [ncchannel_rgb()][c_api::ncchannel_rgb].*
182    //
183    // Not in the C API
184    pub fn rgb(&self) -> NcRgb {
185        c_api::ncchannel_rgb(self.0).into()
186    }
187
188    /// Sets the [`NcRgb`], and marks the NcChannel as NOT using the
189    /// "default color", retaining the other bits unchanged.
190    ///
191    /// *C style function: [ncchannel_set()][c_api::ncchannel_set].*
192    pub fn set(&mut self, rgb: impl Into<NcRgb>) -> Self {
193        c_api::ncchannel_set(&mut self.0, rgb.into());
194        *self
195    }
196
197    // u8
198
199    /// Gets the three components.
200    ///
201    /// *C style function: [ncchannel_rgb8()][c_api::ncchannel_rgb8].*
202    pub fn rgb8(&self) -> (u8, u8, u8) {
203        let (mut r, mut g, mut b) = (0, 0, 0);
204        c_api::ncchannel_rgb8(self.0, &mut r, &mut g, &mut b);
205        (r, g, b)
206    }
207
208    /// Sets the three components, and
209    /// marks the NcChannel as NOT using the "default color".
210    ///
211    /// *C style function: [ncchannel_set_rgb8()][c_api::ncchannel_set_rgb8].*
212    pub fn set_rgb(&mut self, rgb: impl Into<NcRgb>) -> Self {
213        let (r, g, b) = rgb.into().into();
214        c_api::ncchannel_set_rgb8(&mut self.0, r, g, b);
215        *self
216    }
217
218    /// Gets the red component.
219    ///
220    /// *C style function: [ncchannel_r()][c_api::ncchannel_r].*
221    pub fn r(&self) -> u8 {
222        c_api::ncchannel_r(self.0)
223    }
224
225    /// Gets the green component.
226    ///
227    /// *C style function: [ncchannel_g()][c_api::ncchannel_g].*
228    pub fn g(&self) -> u8 {
229        c_api::ncchannel_g(self.0)
230    }
231
232    /// Gets the blue component.
233    ///
234    /// *C style function: [ncchannel_b()][c_api::ncchannel_b].*
235    pub fn b(&self) -> u8 {
236        c_api::ncchannel_b(self.0)
237    }
238
239    /// Sets the red component, and returns the new `NcChannel`.
240    ///
241    /// *C style function: [ncchannel_set_r()][c_api::ncchannel_set_r].*
242    //
243    // Not in the C API
244    pub fn set_r(&mut self, r: impl Into<u8>) -> Self {
245        c_api::ncchannel_set_r(&mut self.0, r.into()).into()
246    }
247
248    /// Sets the green component, and returns the new `NcChannel`.
249    ///
250    /// *C style function: [ncchannel_set_g()][c_api::ncchannel_set_g].*
251    //
252    // Not in the C API
253    pub fn set_g(&mut self, g: impl Into<u8>) -> Self {
254        c_api::ncchannel_set_g(&mut self.0, g.into()).into()
255    }
256
257    /// Sets the blue component, and returns the new `NcChannel`.
258    ///
259    /// *C style function: [ncchannel_set_b()][c_api::ncchannel_set_b].*
260    //
261    // Not in the C API
262    pub fn set_b(&mut self, b: impl Into<u8>) -> Self {
263        c_api::ncchannel_set_b(&mut self.0, b.into()).into()
264    }
265
266    // default color
267
268    /// Is this `NcChannel` using the "default color" rather than RGB/palette-indexed?
269    ///
270    /// *C style function: [ncchannel_default_p()][c_api::ncchannel_default_p].*
271    pub fn default_p(&self) -> bool {
272        c_api::ncchannel_default_p(self.0)
273    }
274
275    /// Marks this `NcChannel` as using its "default color",
276    /// which also marks it opaque.
277    ///
278    /// *C style function: [ncchannel_set_default()][c_api::ncchannel_set_default].*
279    pub fn set_default(&mut self) -> Self {
280        c_api::ncchannel_set_default(&mut self.0).into()
281    }
282
283    /// Marks this `NcChannel` as *not* using its "default color".
284    ///
285    /// The following methods also marks the channel as NOT using the "default color":
286    /// - [`new`][NcChannel#method.new]
287    /// - [`set`][NcChannel#method.set]
288    /// - [`set_rgb`][NcChannel#method.set_rgb]
289    ///
290    /// *C style function: [ncchannel_set_not_default()][c_api::ncchannel_set_not_default].*
291    //
292    // Not in the C API
293    pub fn set_not_default(&mut self) -> Self {
294        c_api::ncchannel_set_not_default(&mut self.0).into()
295    }
296
297    // NcPaletteIndex
298
299    /// Extracts the [`NcPaletteIndex`] from the [`NcChannel`].
300    ///
301    /// The channel must be palette-indexed, or the return value is meaningless.
302    /// Verify palette indexing with [`palindex_p`][NcChannel#method.palindex_p].
303    ///
304    /// *C style function: [ncchannel_palindex()][c_api::ncchannel_palindex].*
305    pub fn palindex(&self) -> NcPaletteIndex {
306        c_api::ncchannel_palindex(self.0)
307    }
308
309    /// Is this NcChannel using palette-indexed color rather a than RGB?
310    ///
311    /// *C style function: [ncchannel_palindex_p()][c_api::ncchannel_palindex_p].*
312    pub fn palindex_p(&self) -> bool {
313        c_api::ncchannel_palindex_p(self.0)
314    }
315
316    /// Sets the [`NcPaletteIndex`] of the [`NcChannel`], and the channel into
317    /// palette-indexed mode.
318    ///
319    /// *C style function: [ncchannel_set_palindex()][c_api::ncchannel_set_palindex].*
320    pub fn set_palindex(&mut self, index: impl Into<NcPaletteIndex>) -> Self {
321        c_api::ncchannel_set_palindex(&mut self.0, index.into());
322        *self
323    }
324}