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}