libnotcurses_sys/visual/
geometry.rs

1//!
2
3#[cfg(not(feature = "std"))]
4use alloc::string::String;
5
6use crate::NcBlitter;
7
8/// Describes all the geometries of an [`NcVisual`].
9///
10/// It includes both inherent geometries and those which are dependent upon a
11/// given rendering regime.
12///
13/// Inner values are calculated at the time of the call. A font change,
14/// for example, could make all the fields invalid,
15/// except for [`pix_yx`][Self#structfield.pix_yx].
16///
17/// This type is is returned by the [`NcVisual.geom`] method and by the
18/// [`Nc.visual_geom`] method.
19///
20/// # See also
21///
22/// - [`NcPixelGeometry`][crate::NcPixelGeometry]
23/// - [`NcVisualOptions`][crate::NcVisualOptions]
24/// - [`NcVGeom`][crate::c_api::NcVGeom]
25///
26/// [`NcVisual`]: crate::NcVisual
27/// [`ncdirectf_geom`]: crate::NcVisual#method.ncdirectf_geom
28/// [`NcVisual.geom`]: crate::NcVisual#method.ncdirectf_geom
29/// [`Nc.visual_geom`]: crate::Nc#method.visual_geom
30#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
31pub struct NcVisualGeometry {
32    /// The true internal pixel geometry of [`NcVisual`] data, taken directly
33    /// from the load, and updated by `ncvisual_resize`.
34    ///
35    /// *Corresponds to the `NcVGeom` fields ([`pixy`], [`pixx`]).*
36    ///
37    /// [`NcVisual`]: crate::NcVisual
38    /// [`pixy`]: crate::c_api::ffi::ncvgeom#structfield.pixy
39    /// [`pixx`]: crate::c_api::ffi::ncvgeom#structfield.pixx
40    pub pix_yx: Option<(u32, u32)>,
41
42    /// *Terminal* **cell** geometry at the time of the call. This is the size
43    /// of a cell in pixels.
44    ///
45    /// This can change with a font change, in which case all field values
46    /// are invalidated (except for [`pix_yx`]).
47    ///
48    /// *Corresponds to the `NcVGeom` fields ([`cdimy`], [`cdimx`]), and to the
49    /// `NcPixelGeometry` fields ([`cell_y`], [`cell_x`])*
50    ///
51    /// [`pix_yx`]: Self#structfield.pix_yx
52    /// [`cdimy`]: crate::c_api::ffi::ncvgeom#structfield.cdimy
53    /// [`cdimx`]: crate::c_api::ffi::ncvgeom#structfield.cdimx
54    /// [`cell_y`]: crate::NcPixelGeometry#structfield.cell_y
55    /// [`cell_x`]: crate::NcPixelGeometry#structfield.cell_x
56    pub cdim_yx: Option<(u32, u32)>,
57
58    /// Rendered **pixel** geometry, per `NcVisualOptions`.
59    /// as handed to the blitter, following any scaling.
60    ///
61    /// *Corresponds to the `NcVGeom` fields ([`rpixy`], [`rpixx`]).*
62    ///
63    /// [`rpixy`]: crate::c_api::ffi::ncvgeom#structfield.rpixy
64    /// [`rpixx`]: crate::c_api::ffi::ncvgeom#structfield.rpixx
65    pub rpix_yx: Option<(u32, u32)>,
66
67    /// Rendered **cell** geometry, per `NcVisualOptions`.
68    ///
69    /// As written by the blitter, following any padding (there is padding
70    /// whenever `rpix{y, x}` is not evenly divided by `scale{y, x}`,
71    /// and also sometimes for Sixel).
72    ///
73    /// *Corresponds to the `NcVGeom` fields ([`rcelly`], [`rcellx`]).*
74    ///
75    /// [`rcelly`]: crate::c_api::ffi::ncvgeom#structfield.rcelly
76    /// [`rcellx`]: crate::c_api::ffi::ncvgeom#structfield.rcellx
77    pub rcell_yx: Option<(u32, u32)>,
78
79    /// The number of input pixels drawn to a single cell.
80    ///
81    /// When using `NcBlitter::Pixel`, they are equivalent to [`cdim_yx`].
82    ///
83    /// *Corresponds to the `NcVGeom` fields ([`scaley`], [`scalex`]).*
84    ///
85    /// [`scaley`]: crate::c_api::ffi::ncvgeom#structfield.scaley
86    /// [`scalex`]: crate::c_api::ffi::ncvgeom#structfield.scalex
87    /// [`cdim_yx`]: Self#structfield.cdim_yx
88    pub scale_yx: Option<(u32, u32)>,
89
90    /// The largest bitmap geometry that the terminal is willing to accept.
91    ///
92    /// It is only defined when using `NcBlitter::Pixel`.
93    ///
94    /// *Corresponds to the `NcVGeom` fields ([`maxpixely`], [`maxpixelx`]).*
95    ///
96    /// [`maxpixely`]: crate::c_api::ffi::ncvgeom#structfield.maxmaxpixely
97    /// [`maxpixelx`]: crate::c_api::ffi::ncvgeom#structfield.maxpixelx
98    pub maxpixel_yx: Option<(u32, u32)>,
99
100    /// The upper-left corner of the used section.
101    ///
102    /// *Corresponds to the `NcVGeom` fields ([`begy`], [`begx`]), and the
103    /// `NcVisualOptions` fields ([`begy`][vo#begy], [`begx`][vo#begx]).*
104    ///
105    /// [`begy`]: crate::c_api::ffi::ncvgeom#structfield.begy
106    /// [`begx`]: crate::c_api::ffi::ncvgeom#structfield.begx
107    /// [vo#begx]: crate::c_api::ffi::ncvisual_options#structfield.begx
108    /// [vo#begy]: crate::c_api::ffi::ncvisual_options#structfield.begy
109    pub beg_yx: Option<(u32, u32)>,
110
111    /// The geometry of the used section.
112    ///
113    /// *Corresponds to the `NcVGeom` fields ([`leny`], [`lenx`]), and the
114    /// `NcVisualOptions` fields ([`leny`][vo#leny], [`lenx`][vo#lenx]).*
115    ///
116    /// [`leny`]: crate::c_api::ffi::ncvgeom#structfield.leny
117    /// [`lenx`]: crate::c_api::ffi::ncvgeom#structfield.lenx
118    /// [vo#lenx]: crate::c_api::ffi::ncvisual_options#structfield.lenx
119    /// [vo#leny]: crate::c_api::ffi::ncvisual_options#structfield.leny
120    pub len_yx: Option<(u32, u32)>,
121
122    /// The [`NcBlitter`] which will be used.
123    ///
124    /// A function of the requested blitter and the blitters actually supported
125    /// by this environment.
126    pub blitter: NcBlitter,
127}
128
129impl NcVisualGeometry {
130    /// The name of the blitter which will be used.
131    ///
132    /// A function of the requested blitter and the blitters actually supported
133    /// by this environment.
134    pub fn blitter_name(&self) -> String {
135        crate::Nc::str_blitter(self.blitter)
136    }
137}
138
139/// # Getter methods for the `NcVGeom` fields
140///
141/// Each of the following methods return the corresponding [`NcVGeom`] field
142/// with the same name.
143///
144/// [`NcVGeom`]: crate::c_api::NcVGeom
145///
146impl NcVisualGeometry {
147    pub fn pixy(&self) -> u32 {
148        self.pix_yx.unwrap_or((0, 0)).0
149    }
150    pub fn pixx(&self) -> u32 {
151        self.pix_yx.unwrap_or((0, 0)).1
152    }
153    pub fn cdimy(&self) -> u32 {
154        self.cdim_yx.unwrap_or((0, 0)).0
155    }
156    pub fn cdimx(&self) -> u32 {
157        self.cdim_yx.unwrap_or((0, 0)).1
158    }
159    pub fn rpixy(&self) -> u32 {
160        self.rpix_yx.unwrap_or((0, 0)).0
161    }
162    pub fn rpixx(&self) -> u32 {
163        self.rpix_yx.unwrap_or((0, 0)).1
164    }
165    pub fn rcelly(&self) -> u32 {
166        self.rcell_yx.unwrap_or((0, 0)).0
167    }
168    pub fn rcellx(&self) -> u32 {
169        self.rcell_yx.unwrap_or((0, 0)).1
170    }
171    pub fn scaley(&self) -> u32 {
172        self.scale_yx.unwrap_or((0, 0)).0
173    }
174    pub fn scalex(&self) -> u32 {
175        self.scale_yx.unwrap_or((0, 0)).1
176    }
177    pub fn maxpixely(&self) -> u32 {
178        self.maxpixel_yx.unwrap_or((0, 0)).0
179    }
180    pub fn maxpixelx(&self) -> u32 {
181        self.maxpixel_yx.unwrap_or((0, 0)).1
182    }
183    pub fn begy(&self) -> u32 {
184        self.beg_yx.unwrap_or((0, 0)).0
185    }
186    pub fn begx(&self) -> u32 {
187        self.beg_yx.unwrap_or((0, 0)).1
188    }
189    pub fn leny(&self) -> u32 {
190        self.len_yx.unwrap_or((0, 0)).0
191    }
192    pub fn lenx(&self) -> u32 {
193        self.len_yx.unwrap_or((0, 0)).1
194    }
195}
196
197mod core_impls {
198    use super::{c_api::NcVGeom, NcBlitter, NcVisualGeometry};
199
200    impl From<NcVGeom> for NcVisualGeometry {
201        /// Since we don't know the origin of the `NcVGeom` struct, when some fields
202        /// are 0, we can't really know whether that's a valid value or not.
203        /// That should be determined manually by other means.
204        ///
205        /// Specifically [`len_yx`], [`beg_yx`] & [`maxpixel_yx`] wont be `None`
206        /// even if the corresponding `NcVGeom` fields are 0. But they would be
207        /// `None` if the NcVisualGeometry had been created by the
208        ///
209        /// [`len_yx`]: Self#structfield.len_yx
210        /// [`beg_yx`]: Self#structfield.beg_yx
211        /// [`maxpixel_yx`]: Self#structfield.maxpixel_yx
212        /// See: <https://github.com/dankamongmen/notcurses/pull/2320#issuecomment-962170075>
213        fn from(vg: NcVGeom) -> Self {
214            // The following values following values can't have a valid 0 value:
215
216            let (pix_yx, cdim_yx, rpix_yx, rcell_yx, scale_yx, maxpixel_yx);
217
218            if vg.pixy == 0 || vg.pixx == 0 {
219                pix_yx = None;
220            } else {
221                pix_yx = Some((vg.pixy, vg.pixx));
222            }
223            if vg.cdimy == 0 || vg.cdimx == 0 {
224                cdim_yx = None;
225            } else {
226                cdim_yx = Some((vg.cdimy, vg.cdimx));
227            }
228            if vg.rpixy == 0 || vg.rpixx == 0 {
229                // MAYBE double CHECK this case
230                rpix_yx = None;
231            } else {
232                rpix_yx = Some((vg.rpixy, vg.rpixx));
233            }
234            if vg.rcelly == 0 || vg.rcellx == 0 {
235                rcell_yx = None;
236            } else {
237                rcell_yx = Some((vg.rcelly, vg.rcellx));
238            }
239            if vg.scaley == 0 || vg.scalex == 0 {
240                scale_yx = None;
241            } else {
242                scale_yx = Some((vg.scaley, vg.scalex));
243            }
244
245            // maxpixel_yx is only defined when using NcBlitter::Pixel
246            if vg.blitter == NcBlitter::Pixel.into() {
247                maxpixel_yx = Some((vg.maxpixely, vg.maxpixelx));
248            } else {
249                maxpixel_yx = None;
250            }
251
252            NcVisualGeometry {
253                pix_yx,
254                cdim_yx,
255                rpix_yx,
256                rcell_yx,
257                scale_yx,
258                maxpixel_yx,
259
260                len_yx: Some((vg.leny, vg.lenx)),
261                beg_yx: Some((vg.begy, vg.begx)),
262
263                blitter: vg.blitter.into(),
264            }
265        }
266    }
267}
268
269pub(crate) mod c_api {
270    use crate::{c_api::ffi, NcBlitter};
271
272    /// Describes all geometries of an [`NcVisual`].
273    ///
274    /// Both those which are inherent,
275    /// and those dependent upon a given rendering regime.
276    ///
277    /// It's recommended to use [`NcVisualGeometry`] instead.
278    ///
279    /// The inner values are calculated at the time of the call, and a font
280    /// change could make all the fields invalid, except for `pixx`/`pixy`.
281    ///
282    /// This type is created by the [`ncvisual_geom`] & [`ncdirectf_geom`]
283    /// functions.
284    ///
285    /// [`NcVisual`]: crate::NcVisual
286    /// [`NcVisualGeometry`]: crate::NcVisualGeometry
287    /// [`ncdirectf_geom`]: crate::c_api::ncdirectf_geom
288    /// [`ncvisual_geom`]: crate::c_api::ncvisual_geom
289    pub type NcVGeom = ffi::ncvgeom;
290
291    /// # Constructors
292    impl NcVGeom {
293        /// Returns a new `NcVGeom` with zeroed fields.
294        pub fn new() -> Self {
295            Self {
296                pixy: 0,
297                pixx: 0,
298                cdimy: 0,
299                cdimx: 0,
300                rpixy: 0,
301                rpixx: 0,
302                rcelly: 0,
303                rcellx: 0,
304                scaley: 0,
305                scalex: 0,
306                maxpixely: 0,
307                maxpixelx: 0,
308                begy: 0,
309                begx: 0,
310                leny: 0,
311                lenx: 0,
312                blitter: NcBlitter::Default.into(),
313            }
314        }
315    }
316}