1use super::*;
2
3#[repr(C)]
4#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
5pub struct Size {
6 pub width: i32,
7 pub height: i32,
8}
9
10impl Size {
11 pub const fn new(width: i32, height: i32) -> Self {
12 assert!(width > 0, "width must be greater than 0");
13 assert!(height > 0, "height must be greater than 0");
14 Self { width, height }
15 }
16
17 pub const fn from_raw_parts(width: i32, height: i32) -> Self {
18 Self { width, height }
19 }
20
21 pub fn create(width: i32, height: i32) -> Result<Self> {
22 let size = Self::from_raw_parts(width, height);
23 size.validate()?;
24 Ok(size)
25 }
26
27 pub const fn is_positive(self) -> bool {
28 self.width > 0 && self.height > 0
29 }
30
31 pub fn validate(self) -> Result<()> {
32 if self.width <= 0 {
33 return Err(Error::ValueNotPositive {
34 name: "width".into(),
35 });
36 }
37 if self.height <= 0 {
38 return Err(Error::ValueNotPositive {
39 name: "height".into(),
40 });
41 }
42 Ok(())
43 }
44
45 pub fn rectangle(self) -> Rectangle {
46 Rectangle {
47 x: 0,
48 y: 0,
49 width: self.width,
50 height: self.height,
51 }
52 }
53
54 pub fn centered_rectangle(self) -> Rectangle {
55 let side = self.width.min(self.height);
56 Rectangle {
57 x: ((self.width - side) / 2),
58 y: ((self.height - side) / 2),
59 width: side,
60 height: side,
61 }
62 }
63}
64
65impl From<Size> for sys::NppiSize {
66 fn from(value: Size) -> Self {
67 Self {
68 width: value.width,
69 height: value.height,
70 }
71 }
72}
73
74impl From<sys::NppiSize> for Size {
75 fn from(value: sys::NppiSize) -> Self {
76 Self::from_raw_parts(value.width, value.height)
77 }
78}
79
80impl Display for Size {
81 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
82 write!(f, "{}x{}", self.width, self.height)
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn size_create_rejects_nonpositive_width() {
92 assert!(matches!(
93 Size::create(0, 1),
94 Err(Error::ValueNotPositive { name }) if name == "width"
95 ));
96 }
97
98 #[test]
99 fn size_create_rejects_nonpositive_height() {
100 assert!(matches!(
101 Size::create(1, -1),
102 Err(Error::ValueNotPositive { name }) if name == "height"
103 ));
104 }
105
106 #[test]
107 fn size_raw_parts_preserves_ffi_values() {
108 let size = Size::from_raw_parts(0, -1);
109 assert_eq!(size.width, 0);
110 assert_eq!(size.height, -1);
111 assert!(!size.is_positive());
112 }
113}
114
115#[repr(C)]
116#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Default)]
117pub struct Rectangle {
118 pub x: i32,
119 pub y: i32,
120 pub width: i32,
121 pub height: i32,
122}
123
124impl Rectangle {
125 pub fn size(self) -> Size {
126 Size::from_raw_parts(self.width, self.height)
127 }
128}
129
130impl From<Rectangle> for sys::NppiRect {
131 fn from(value: Rectangle) -> Self {
132 Self {
133 x: value.x,
134 y: value.y,
135 width: value.width,
136 height: value.height,
137 }
138 }
139}
140
141impl From<sys::NppiRect> for Rectangle {
142 fn from(value: sys::NppiRect) -> Self {
143 Self {
144 x: value.x,
145 y: value.y,
146 width: value.width,
147 height: value.height,
148 }
149 }
150}
151
152#[repr(C)]
153#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Default)]
154pub struct Point {
155 pub x: i32,
156 pub y: i32,
157}
158
159impl Point {
160 pub const ZERO: Point = Point::new(0, 0);
161
162 pub const fn new(x: i32, y: i32) -> Self {
163 Point { x, y }
164 }
165}
166
167impl From<Point> for sys::NppiPoint {
168 fn from(value: Point) -> Self {
169 Self {
170 x: value.x,
171 y: value.y,
172 }
173 }
174}
175
176impl From<sys::NppiPoint> for Point {
177 fn from(value: sys::NppiPoint) -> Self {
178 Self {
179 x: value.x,
180 y: value.y,
181 }
182 }
183}
184
185#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Default)]
186pub struct Point32f {
187 pub x: f32,
188 pub y: f32,
189}
190
191impl From<Point32f> for sys::NppiPoint32f {
192 fn from(value: Point32f) -> Self {
193 Self {
194 x: value.x,
195 y: value.y,
196 }
197 }
198}
199
200impl From<sys::NppiPoint32f> for Point32f {
201 fn from(value: sys::NppiPoint32f) -> Self {
202 Self {
203 x: value.x,
204 y: value.y,
205 }
206 }
207}
208
209#[repr(C)]
210#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Default)]
211pub struct Point64f {
212 pub x: f64,
213 pub y: f64,
214}
215
216impl From<Point64f> for sys::NppiPoint64f {
217 fn from(value: Point64f) -> Self {
218 Self {
219 x: value.x,
220 y: value.y,
221 }
222 }
223}
224
225impl From<sys::NppiPoint64f> for Point64f {
226 fn from(value: sys::NppiPoint64f) -> Self {
227 Self {
228 x: value.x,
229 y: value.y,
230 }
231 }
232}
233
234impl From<[f64; 2]> for Point64f {
235 fn from(value: [f64; 2]) -> Self {
236 Self {
237 x: value[0],
238 y: value[1],
239 }
240 }
241}
242
243impl From<Point64f> for [f64; 2] {
244 fn from(value: Point64f) -> Self {
245 [value.x, value.y]
246 }
247}
248
249impl Point64f {
250 pub const fn to_array(self) -> [f64; 2] {
251 [self.x, self.y]
252 }
253}
254
255pub type PointF64 = Point64f;
256
257#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Default)]
258pub struct PointPolar {
259 pub rho: f32,
260 pub theta: f32,
261}
262
263impl From<PointPolar> for sys::NppPointPolar {
264 fn from(value: PointPolar) -> Self {
265 Self {
266 rho: value.rho,
267 theta: value.theta,
268 }
269 }
270}
271
272impl From<sys::NppPointPolar> for PointPolar {
273 fn from(value: sys::NppPointPolar) -> Self {
274 Self {
275 rho: value.rho,
276 theta: value.theta,
277 }
278 }
279}
280
281#[repr(C)]
282#[derive(Debug, Clone, Copy, PartialEq)]
283pub struct BoundF64 {
284 pub lower: PointF64,
285 pub upper: PointF64,
286}
287
288impl From<[[f64; 2]; 2]> for BoundF64 {
289 fn from(value: [[f64; 2]; 2]) -> Self {
290 Self {
291 lower: value[0].into(),
292 upper: value[1].into(),
293 }
294 }
295}
296
297impl From<BoundF64> for [[f64; 2]; 2] {
298 fn from(value: BoundF64) -> Self {
299 [value.lower.into(), value.upper.into()]
300 }
301}
302
303impl BoundF64 {
304 pub const fn as_ptr(&self) -> *const [f64; 2] {
305 (&self.lower as *const PointF64).cast()
306 }
307
308 pub const fn as_mut_ptr(&mut self) -> *mut [f64; 2] {
309 (&mut self.lower as *mut PointF64).cast()
310 }
311}
312
313#[repr(C)]
314#[derive(Debug, Clone, Copy, PartialEq)]
315pub struct QuadrangleF64 {
316 pub points: [PointF64; 4],
317}
318
319impl From<[[f64; 2]; 4]> for QuadrangleF64 {
320 fn from(value: [[f64; 2]; 4]) -> Self {
321 Self {
322 points: value.map(PointF64::from),
323 }
324 }
325}
326
327impl From<QuadrangleF64> for [[f64; 2]; 4] {
328 fn from(value: QuadrangleF64) -> Self {
329 value.points.map(Into::into)
330 }
331}
332
333impl QuadrangleF64 {
334 pub const fn as_ptr(&self) -> *const [f64; 2] {
335 self.points.as_ptr().cast()
336 }
337
338 pub fn as_mut_ptr(&mut self) -> *mut [f64; 2] {
339 self.points.as_mut_ptr().cast()
340 }
341}
342
343#[derive(Debug, Clone, Copy, PartialEq, Default)]
344pub struct AffineCoefficients {
345 pub values: [[f64; 3]; 2],
346}
347
348impl From<[[f64; 3]; 2]> for AffineCoefficients {
349 fn from(value: [[f64; 3]; 2]) -> Self {
350 Self { values: value }
351 }
352}
353
354impl From<AffineCoefficients> for [[f64; 3]; 2] {
355 fn from(value: AffineCoefficients) -> Self {
356 value.values
357 }
358}
359
360impl AffineCoefficients {
361 pub const fn as_ptr(&self) -> *const [f64; 3] {
362 self.values.as_ptr()
363 }
364
365 pub fn as_mut_ptr(&mut self) -> *mut [f64; 3] {
366 self.values.as_mut_ptr()
367 }
368}
369
370#[derive(Debug, Clone, Copy, PartialEq, Default)]
371pub struct PerspectiveCoefficients {
372 pub values: [[f64; 3]; 3],
373}
374
375impl From<[[f64; 3]; 3]> for PerspectiveCoefficients {
376 fn from(value: [[f64; 3]; 3]) -> Self {
377 Self { values: value }
378 }
379}
380
381impl From<PerspectiveCoefficients> for [[f64; 3]; 3] {
382 fn from(value: PerspectiveCoefficients) -> Self {
383 value.values
384 }
385}
386
387impl PerspectiveCoefficients {
388 pub const fn as_ptr(&self) -> *const [f64; 3] {
389 self.values.as_ptr()
390 }
391
392 pub fn as_mut_ptr(&mut self) -> *mut [f64; 3] {
393 self.values.as_mut_ptr()
394 }
395}