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}