1use crate::sys;
4use std::convert::{AsMut, AsRef};
5use std::hash::{Hash, Hasher};
6use std::mem;
7use std::ops::{
8 Add, AddAssign, BitAnd, BitOr, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Sub,
9 SubAssign,
10};
11use std::ptr;
12
13pub fn max_int_value() -> u32 {
18 i32::MAX as u32 / 2
19}
20
21pub fn min_int_value() -> i32 {
27 i32::MIN / 2
28}
29
30fn clamp_size(val: u32) -> u32 {
31 if val == 0 {
32 1
33 } else if val > max_int_value() {
34 max_int_value()
35 } else {
36 val
37 }
38}
39
40fn clamp_position(val: i32) -> i32 {
41 if val > max_int_value() as i32 {
42 max_int_value() as i32
43 } else if val < min_int_value() {
44 min_int_value()
45 } else {
46 val
47 }
48}
49
50fn clamped_mul(a: i32, b: i32) -> i32 {
51 match a.checked_mul(b) {
52 Some(val) => val,
53 None => {
54 if (a < 0) ^ (b < 0) {
55 min_int_value()
56 } else {
57 max_int_value() as i32
58 }
59 }
60 }
61}
62
63fn clamp_f32_size(val: f32) -> f32 {
64 if val <= 0.0 {
65 1.0
66 } else {
67 val
68 }
69}
70
71#[repr(transparent)]
81#[derive(Clone, Copy)]
82pub struct Rect {
83 raw: sys::SDL_Rect,
84}
85
86impl ::std::fmt::Debug for Rect {
87 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
88 fmt.debug_struct("Rect")
89 .field("x", &self.raw.x)
90 .field("y", &self.raw.y)
91 .field("w", &self.raw.w)
92 .field("h", &self.raw.h)
93 .finish()
94 }
95}
96
97impl PartialEq for Rect {
98 fn eq(&self, other: &Rect) -> bool {
99 self.raw.x == other.raw.x
100 && self.raw.y == other.raw.y
101 && self.raw.w == other.raw.w
102 && self.raw.h == other.raw.h
103 }
104}
105
106impl Eq for Rect {}
107
108impl Hash for Rect {
109 fn hash<H: Hasher>(&self, state: &mut H) {
110 self.raw.x.hash(state);
111 self.raw.y.hash(state);
112 self.raw.w.hash(state);
113 self.raw.h.hash(state);
114 }
115}
116
117impl Rect {
118 pub fn new(x: i32, y: i32, width: u32, height: u32) -> Rect {
129 let raw = sys::SDL_Rect {
130 x: clamp_position(x),
131 y: clamp_position(y),
132 w: clamp_size(width) as i32,
133 h: clamp_size(height) as i32,
134 };
135 Rect { raw }
136 }
137
138 pub fn from_center<P>(center: P, width: u32, height: u32) -> Rect
149 where
150 P: Into<Point>,
151 {
152 let raw = sys::SDL_Rect {
153 x: 0,
154 y: 0,
155 w: clamp_size(width) as i32,
156 h: clamp_size(height) as i32,
157 };
158 let mut rect = Rect { raw };
159 rect.center_on(center.into());
160 rect
161 }
162
163 #[inline]
165 pub fn x(&self) -> i32 {
166 self.raw.x
167 }
168
169 #[inline]
171 pub fn y(&self) -> i32 {
172 self.raw.y
173 }
174
175 pub fn width(&self) -> u32 {
177 self.raw.w as u32
178 }
179
180 pub fn height(&self) -> u32 {
182 self.raw.h as u32
183 }
184
185 pub fn size(&self) -> (u32, u32) {
187 (self.width(), self.height())
188 }
189
190 pub fn set_x(&mut self, x: i32) {
193 self.raw.x = clamp_position(x);
194 }
195
196 pub fn set_y(&mut self, y: i32) {
199 self.raw.y = clamp_position(y);
200 }
201
202 pub fn set_width(&mut self, width: u32) {
208 self.raw.w = clamp_size(width) as i32;
209 }
210
211 pub fn set_height(&mut self, height: u32) {
217 self.raw.h = clamp_size(height) as i32;
218 }
219
220 pub fn left(&self) -> i32 {
222 self.raw.x
223 }
224
225 pub fn right(&self) -> i32 {
227 self.raw.x + self.raw.w
228 }
229
230 pub fn top(&self) -> i32 {
232 self.raw.y
233 }
234
235 pub fn bottom(&self) -> i32 {
237 self.raw.y + self.raw.h
238 }
239
240 pub fn origin(&self) -> (i32, i32) {
247 (self.left(), self.top())
248 }
249
250 pub fn left_shifted(mut self, offset: i32) -> Rect {
259 self.offset(-offset, 0);
260 self
261 }
262
263 pub fn right_shifted(mut self, offset: i32) -> Rect {
272 self.offset(offset, 0);
273 self
274 }
275
276 pub fn top_shifted(mut self, offset: i32) -> Rect {
285 self.offset(0, -offset);
286 self
287 }
288
289 pub fn bottom_shifted(mut self, offset: i32) -> Rect {
298 self.offset(0, offset);
299 self
300 }
301
302 pub fn center(&self) -> Point {
315 let x = self.raw.x + (self.raw.w / 2);
316 let y = self.raw.y + (self.raw.h / 2);
317 Point::new(x, y)
318 }
319
320 pub fn top_left(&self) -> Point {
330 Point::new(self.left(), self.top())
331 }
332
333 pub fn top_right(&self) -> Point {
343 Point::new(self.right(), self.top())
344 }
345
346 pub fn bottom_left(&self) -> Point {
356 Point::new(self.left(), self.bottom())
357 }
358
359 pub fn bottom_right(&self) -> Point {
369 Point::new(self.right(), self.bottom())
370 }
371
372 pub fn set_right(&mut self, right: i32) {
375 self.raw.x = clamp_position(clamp_position(right) - self.raw.w);
376 }
377
378 pub fn set_bottom(&mut self, bottom: i32) {
381 self.raw.y = clamp_position(clamp_position(bottom) - self.raw.h);
382 }
383
384 #[inline]
386 pub fn center_on<P>(&mut self, point: P)
387 where
388 P: Into<(i32, i32)>,
389 {
390 let (x, y) = point.into();
391 self.raw.x = clamp_position(clamp_position(x) - self.raw.w / 2);
392 self.raw.y = clamp_position(clamp_position(y) - self.raw.h / 2);
393 }
394
395 #[inline]
397 pub fn centered_on<P>(mut self, point: P) -> Rect
398 where
399 P: Into<(i32, i32)>,
400 {
401 self.center_on(point);
402 self
403 }
404
405 #[inline]
408 pub fn offset(&mut self, x: i32, y: i32) {
409 match self.raw.x.checked_add(x) {
410 Some(val) => self.raw.x = clamp_position(val),
411 None => {
412 if x >= 0 {
413 self.raw.x = max_int_value() as i32;
414 } else {
415 self.raw.x = i32::MIN;
416 }
417 }
418 }
419 match self.raw.y.checked_add(y) {
420 Some(val) => self.raw.y = clamp_position(val),
421 None => {
422 if y >= 0 {
423 self.raw.y = max_int_value() as i32;
424 } else {
425 self.raw.y = i32::MIN;
426 }
427 }
428 }
429 }
430
431 pub fn reposition<P>(&mut self, point: P)
433 where
434 P: Into<(i32, i32)>,
435 {
436 let (x, y) = point.into();
437 self.raw.x = clamp_position(x);
438 self.raw.y = clamp_position(y);
439 }
440
441 pub fn resize(&mut self, width: u32, height: u32) {
443 self.raw.w = clamp_size(width) as i32;
444 self.raw.h = clamp_size(height) as i32;
445 }
446
447 pub fn contains_point<P>(&self, point: P) -> bool
467 where
468 P: Into<(i32, i32)>,
469 {
470 let (x, y) = point.into();
471 let inside_x = x >= self.left() && x < self.right();
472 inside_x && (y >= self.top() && y < self.bottom())
473 }
474
475 pub fn contains_rect(&self, other: Rect) -> bool {
492 other.left() >= self.left()
493 && other.right() <= self.right()
494 && other.top() >= self.top()
495 && other.bottom() <= self.bottom()
496 }
497
498 #[allow(clippy::trivially_copy_pass_by_ref)]
502 pub fn raw(&self) -> *const sys::SDL_Rect {
503 &self.raw
504 }
505
506 pub fn raw_mut(&mut self) -> *mut sys::SDL_Rect {
507 &mut self.raw
508 }
509
510 #[doc(alias = "SDL_Rect")]
511 pub fn raw_slice(slice: &[Rect]) -> *const sys::SDL_Rect {
512 slice.as_ptr() as *const sys::SDL_Rect
513 }
514
515 pub fn from_ll(raw: sys::SDL_Rect) -> Rect {
516 Rect::new(raw.x, raw.y, raw.w as u32, raw.h as u32)
517 }
518
519 #[doc(alias = "SDL_EnclosePoints")]
523 pub fn from_enclose_points<R>(points: &[Point], clipping_rect: R) -> Option<Rect>
524 where
525 R: Into<Option<Rect>>,
526 {
527 let clipping_rect = clipping_rect.into();
528
529 if points.is_empty() {
530 return None;
531 }
532
533 let mut out = mem::MaybeUninit::uninit();
534
535 let clip_ptr = match clipping_rect.as_ref() {
536 Some(r) => r.raw(),
537 None => ptr::null(),
538 };
539
540 let result = unsafe {
541 sys::SDL_EnclosePoints(
542 Point::raw_slice(points),
543 points.len() as i32,
544 clip_ptr,
545 out.as_mut_ptr(),
546 ) != sys::SDL_bool::SDL_FALSE
547 };
548
549 if result {
550 let out = unsafe { out.assume_init() };
551
552 Some(Rect::from_ll(out))
554 } else {
555 None
556 }
557 }
558
559 #[doc(alias = "SDL_HasIntersection")]
574 pub fn has_intersection(&self, other: Rect) -> bool {
575 unsafe { sys::SDL_HasIntersection(self.raw(), other.raw()) != sys::SDL_bool::SDL_FALSE }
576 }
577
578 #[doc(alias = "SDL_IntersectRect")]
597 pub fn intersection(&self, other: Rect) -> Option<Rect> {
598 let mut out = mem::MaybeUninit::uninit();
599
600 let success = unsafe {
601 sys::SDL_IntersectRect(self.raw(), other.raw(), out.as_mut_ptr())
602 != sys::SDL_bool::SDL_FALSE
603 };
604
605 if success {
606 let out = unsafe { out.assume_init() };
607 Some(Rect::from_ll(out))
608 } else {
609 None
610 }
611 }
612
613 #[doc(alias = "SDL_UnionRect")]
628 pub fn union(&self, other: Rect) -> Rect {
629 let mut out = mem::MaybeUninit::uninit();
630
631 unsafe {
632 sys::SDL_UnionRect(self.raw(), other.raw(), out.as_mut_ptr())
635 };
636
637 let out = unsafe { out.assume_init() };
638
639 Rect::from_ll(out)
640 }
641
642 #[doc(alias = "SDL_IntersectRectAndLine")]
645 pub fn intersect_line(&self, start: Point, end: Point) -> Option<(Point, Point)> {
646 let (mut start_x, mut start_y) = (start.x(), start.y());
647 let (mut end_x, mut end_y) = (end.x(), end.y());
648
649 let intersected = unsafe {
650 sys::SDL_IntersectRectAndLine(
651 self.raw(),
652 &mut start_x,
653 &mut start_y,
654 &mut end_x,
655 &mut end_y,
656 ) != sys::SDL_bool::SDL_FALSE
657 };
658
659 if intersected {
660 Some((Point::new(start_x, start_y), Point::new(end_x, end_y)))
661 } else {
662 None
663 }
664 }
665}
666
667impl Deref for Rect {
668 type Target = sys::SDL_Rect;
669
670 fn deref(&self) -> &sys::SDL_Rect {
678 &self.raw
679 }
680}
681
682impl DerefMut for Rect {
683 fn deref_mut(&mut self) -> &mut sys::SDL_Rect {
692 &mut self.raw
693 }
694}
695
696impl From<Rect> for sys::SDL_Rect {
697 fn from(val: Rect) -> Self {
698 val.raw
699 }
700}
701
702impl From<Rect> for (i32, i32, u32, u32) {
703 fn from(val: Rect) -> Self {
704 (val.raw.x, val.raw.y, val.raw.w as u32, val.raw.h as u32)
705 }
706}
707
708impl From<sys::SDL_Rect> for Rect {
709 fn from(raw: sys::SDL_Rect) -> Rect {
710 Rect { raw }
711 }
712}
713
714impl From<(i32, i32, u32, u32)> for Rect {
715 fn from((x, y, width, height): (i32, i32, u32, u32)) -> Rect {
716 Rect::new(x, y, width, height)
717 }
718}
719
720impl AsRef<sys::SDL_Rect> for Rect {
721 fn as_ref(&self) -> &sys::SDL_Rect {
722 &self.raw
723 }
724}
725
726impl AsMut<sys::SDL_Rect> for Rect {
727 fn as_mut(&mut self) -> &mut sys::SDL_Rect {
728 &mut self.raw
729 }
730}
731
732impl BitAnd<Rect> for Rect {
734 type Output = Option<Rect>;
735 #[doc(alias = "SDL_Point")]
736 fn bitand(self, rhs: Rect) -> Option<Rect> {
737 self.intersection(rhs)
738 }
739}
740
741impl BitOr<Rect> for Rect {
743 type Output = Rect;
744 fn bitor(self, rhs: Rect) -> Rect {
745 self.union(rhs)
746 }
747}
748
749#[repr(transparent)]
753#[derive(Copy, Clone)]
754pub struct Point {
755 raw: sys::SDL_Point,
756}
757
758impl ::std::fmt::Debug for Point {
759 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
760 fmt.debug_struct("Point")
761 .field("x", &self.raw.x)
762 .field("y", &self.raw.y)
763 .finish()
764 }
765}
766
767impl PartialEq for Point {
768 fn eq(&self, other: &Point) -> bool {
769 self.raw.x == other.raw.x && self.raw.y == other.raw.y
770 }
771}
772
773impl Eq for Point {}
774
775impl Hash for Point {
776 fn hash<H: Hasher>(&self, state: &mut H) {
777 self.raw.x.hash(state);
778 self.raw.y.hash(state);
779 }
780}
781
782impl Deref for Point {
783 type Target = sys::SDL_Point;
784
785 fn deref(&self) -> &sys::SDL_Point {
793 &self.raw
794 }
795}
796
797impl DerefMut for Point {
798 fn deref_mut(&mut self) -> &mut sys::SDL_Point {
807 &mut self.raw
808 }
809}
810
811impl AsRef<sys::SDL_Point> for Point {
812 fn as_ref(&self) -> &sys::SDL_Point {
813 &self.raw
814 }
815}
816
817impl AsMut<sys::SDL_Point> for Point {
818 fn as_mut(&mut self) -> &mut sys::SDL_Point {
819 &mut self.raw
820 }
821}
822
823impl From<sys::SDL_Point> for Point {
824 fn from(prim: sys::SDL_Point) -> Point {
825 Point { raw: prim }
826 }
827}
828
829impl From<(i32, i32)> for Point {
830 fn from((x, y): (i32, i32)) -> Point {
831 Point::new(x, y)
832 }
833}
834
835impl From<Point> for sys::SDL_Point {
836 fn from(val: Point) -> Self {
837 val.raw
838 }
839}
840
841impl From<Point> for (i32, i32) {
842 fn from(val: Point) -> Self {
843 (val.x(), val.y())
844 }
845}
846
847impl Point {
848 pub fn new(x: i32, y: i32) -> Point {
850 Point {
851 raw: sys::SDL_Point {
852 x: clamp_position(x),
853 y: clamp_position(y),
854 },
855 }
856 }
857
858 pub fn from_ll(raw: sys::SDL_Point) -> Point {
859 Point::new(raw.x, raw.y)
860 }
861
862 #[doc(alias = "SDL_Point")]
863 pub fn raw_slice(slice: &[Point]) -> *const sys::SDL_Point {
864 slice.as_ptr() as *const sys::SDL_Point
865 }
866 #[allow(clippy::trivially_copy_pass_by_ref)]
869 pub fn raw(&self) -> *const sys::SDL_Point {
870 &self.raw
871 }
872
873 pub fn offset(self, x: i32, y: i32) -> Point {
876 let x = match self.raw.x.checked_add(x) {
877 Some(val) => val,
878 None => {
879 if x < 0 {
880 min_int_value()
881 } else {
882 max_int_value() as i32
883 }
884 }
885 };
886 let y = match self.raw.y.checked_add(y) {
887 Some(val) => val,
888 None => {
889 if y < 0 {
890 min_int_value()
891 } else {
892 max_int_value() as i32
893 }
894 }
895 };
896 Point::new(x, y)
897 }
898
899 pub fn scale(self, f: i32) -> Point {
902 Point::new(clamped_mul(self.raw.x, f), clamped_mul(self.raw.y, f))
903 }
904
905 pub fn x(self) -> i32 {
907 self.raw.x
908 }
909
910 pub fn y(self) -> i32 {
912 self.raw.y
913 }
914}
915
916impl Add for Point {
917 type Output = Point;
918
919 fn add(self, rhs: Point) -> Point {
920 self.offset(rhs.x(), rhs.y())
921 }
922}
923
924impl AddAssign for Point {
925 fn add_assign(&mut self, rhs: Point) {
926 self.raw.x = clamp_position(self.x() + rhs.x());
927 self.raw.y = clamp_position(self.y() + rhs.y());
928 }
929}
930
931impl Neg for Point {
932 type Output = Point;
933
934 fn neg(self) -> Point {
935 Point::new(-self.x(), -self.y())
936 }
937}
938
939impl Sub for Point {
940 type Output = Point;
941
942 fn sub(self, rhs: Point) -> Point {
943 self.offset(-rhs.x(), -rhs.y())
944 }
945}
946
947impl SubAssign for Point {
948 fn sub_assign(&mut self, rhs: Point) {
949 self.raw.x = clamp_position(self.x() - rhs.x());
950 self.raw.y = clamp_position(self.y() - rhs.y());
951 }
952}
953
954impl Mul<i32> for Point {
955 type Output = Point;
956
957 fn mul(self, rhs: i32) -> Point {
958 self.scale(rhs)
959 }
960}
961
962impl MulAssign<i32> for Point {
963 fn mul_assign(&mut self, rhs: i32) {
964 self.raw.x = clamped_mul(self.x(), rhs);
965 self.raw.y = clamped_mul(self.y(), rhs);
966 }
967}
968
969impl Div<i32> for Point {
970 type Output = Point;
971
972 fn div(self, rhs: i32) -> Point {
973 Point::new(self.x() / rhs, self.y() / rhs)
974 }
975}
976
977impl DivAssign<i32> for Point {
978 fn div_assign(&mut self, rhs: i32) {
979 self.raw.x /= rhs;
980 self.raw.y /= rhs;
981 }
982}
983
984impl std::iter::Sum for Point {
985 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
986 iter.fold(Point::new(0, 0), Point::add)
987 }
988}
989
990#[repr(transparent)]
1000#[derive(Clone, Copy)]
1001pub struct FRect {
1002 raw: sys::SDL_FRect,
1003}
1004
1005impl ::std::fmt::Debug for FRect {
1006 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
1007 fmt.debug_struct("FRect")
1008 .field("x", &self.raw.x)
1009 .field("y", &self.raw.y)
1010 .field("w", &self.raw.w)
1011 .field("h", &self.raw.h)
1012 .finish()
1013 }
1014}
1015
1016impl PartialEq for FRect {
1017 fn eq(&self, other: &FRect) -> bool {
1018 self.raw.x == other.raw.x
1019 && self.raw.y == other.raw.y
1020 && self.raw.w == other.raw.w
1021 && self.raw.h == other.raw.h
1022 }
1023}
1024
1025impl FRect {
1026 pub fn new(x: f32, y: f32, width: f32, height: f32) -> FRect {
1031 let raw = sys::SDL_FRect {
1032 x,
1033 y,
1034 w: clamp_f32_size(width),
1035 h: clamp_f32_size(height),
1036 };
1037 FRect { raw }
1038 }
1039
1040 pub fn from_center<P>(center: P, width: f32, height: f32) -> FRect
1045 where
1046 P: Into<FPoint>,
1047 {
1048 let raw = sys::SDL_FRect {
1049 x: 0.0,
1050 y: 0.0,
1051 w: clamp_f32_size(width),
1052 h: clamp_f32_size(height),
1053 };
1054 let mut rect = FRect { raw };
1055 rect.center_on(center.into());
1056 rect
1057 }
1058
1059 #[inline]
1061 pub fn x(&self) -> f32 {
1062 self.raw.x
1063 }
1064
1065 #[inline]
1067 pub fn y(&self) -> f32 {
1068 self.raw.y
1069 }
1070
1071 pub fn width(&self) -> f32 {
1073 self.raw.w
1074 }
1075
1076 pub fn height(&self) -> f32 {
1078 self.raw.h
1079 }
1080
1081 pub fn size(&self) -> (f32, f32) {
1083 (self.width(), self.height())
1084 }
1085
1086 pub fn set_x(&mut self, x: f32) {
1089 self.raw.x = x;
1090 }
1091
1092 pub fn set_y(&mut self, y: f32) {
1095 self.raw.y = y;
1096 }
1097
1098 pub fn set_width(&mut self, width: f32) {
1104 self.raw.w = clamp_f32_size(width);
1105 }
1106
1107 pub fn set_height(&mut self, height: f32) {
1113 self.raw.h = clamp_f32_size(height);
1114 }
1115
1116 pub fn left(&self) -> f32 {
1118 self.raw.x
1119 }
1120
1121 pub fn right(&self) -> f32 {
1123 self.raw.x + self.raw.w
1124 }
1125
1126 pub fn top(&self) -> f32 {
1128 self.raw.y
1129 }
1130
1131 pub fn bottom(&self) -> f32 {
1133 self.raw.y + self.raw.h
1134 }
1135
1136 pub fn left_shifted(mut self, offset: f32) -> FRect {
1145 self.offset(-offset, self.y());
1146 self
1147 }
1148
1149 pub fn right_shifted(mut self, offset: f32) -> FRect {
1158 self.offset(offset, self.y());
1159 self
1160 }
1161
1162 pub fn top_shifted(mut self, offset: f32) -> FRect {
1171 self.offset(self.x(), -offset);
1172 self
1173 }
1174
1175 pub fn bottom_shifted(mut self, offset: f32) -> FRect {
1184 self.offset(self.x(), offset);
1185 self
1186 }
1187
1188 pub fn center(&self) -> FPoint {
1201 let x = self.raw.x + (self.raw.w / 2.0);
1202 let y = self.raw.y + (self.raw.h / 2.0);
1203 FPoint::new(x, y)
1204 }
1205
1206 pub fn top_left(&self) -> FPoint {
1216 FPoint::new(self.left(), self.top())
1217 }
1218
1219 pub fn top_right(&self) -> FPoint {
1229 FPoint::new(self.right(), self.top())
1230 }
1231
1232 pub fn bottom_left(&self) -> FPoint {
1242 FPoint::new(self.left(), self.bottom())
1243 }
1244
1245 pub fn bottom_right(&self) -> FPoint {
1255 FPoint::new(self.right(), self.bottom())
1256 }
1257
1258 pub fn set_right(&mut self, right: f32) {
1261 self.raw.x = clamp_f32_size(clamp_f32_size(right) - self.raw.w);
1262 }
1263
1264 pub fn set_bottom(&mut self, bottom: f32) {
1267 self.raw.y = clamp_f32_size(clamp_f32_size(bottom) - self.raw.h);
1268 }
1269
1270 #[inline]
1272 pub fn center_on<P>(&mut self, point: P)
1273 where
1274 P: Into<(f32, f32)>,
1275 {
1276 let (x, y) = point.into();
1277 self.raw.x = x - self.raw.w / 2.0;
1278 self.raw.y = y - self.raw.h / 2.0;
1279 }
1280
1281 #[inline]
1283 pub fn centered_on<P>(mut self, point: P) -> FRect
1284 where
1285 P: Into<(f32, f32)>,
1286 {
1287 self.center_on(point);
1288 self
1289 }
1290
1291 #[inline]
1293 pub fn offset(&mut self, x: f32, y: f32) {
1294 self.raw.x += x;
1295 self.raw.y += y;
1296 }
1297
1298 pub fn reposition<P>(&mut self, point: P)
1300 where
1301 P: Into<(f32, f32)>,
1302 {
1303 let (x, y) = point.into();
1304 self.raw.x = x;
1305 self.raw.y = y;
1306 }
1307
1308 pub fn resize(&mut self, width: f32, height: f32) {
1310 self.raw.w = clamp_f32_size(width);
1311 self.raw.h = clamp_f32_size(height);
1312 }
1313
1314 pub fn contains_point<P>(&self, point: P) -> bool
1333 where
1334 P: Into<(f32, f32)>,
1335 {
1336 let (x, y) = point.into();
1337 let inside_x = x >= self.left() && x < self.right();
1338 inside_x && (y >= self.top() && y < self.bottom())
1339 }
1340
1341 pub fn contains_rect(&self, other: FRect) -> bool {
1358 other.left() >= self.left()
1359 && other.right() <= self.right()
1360 && other.top() >= self.top()
1361 && other.bottom() <= self.bottom()
1362 }
1363
1364 #[allow(clippy::trivially_copy_pass_by_ref)]
1368 pub fn raw(&self) -> *const sys::SDL_FRect {
1369 &self.raw
1370 }
1371
1372 pub fn raw_mut(&mut self) -> *mut sys::SDL_FRect {
1373 &mut self.raw
1374 }
1375
1376 #[doc(alias = "SDL_FRect")]
1377 pub fn raw_slice(slice: &[FRect]) -> *const sys::SDL_FRect {
1378 slice.as_ptr() as *const sys::SDL_FRect
1379 }
1380
1381 pub fn from_ll(raw: sys::SDL_FRect) -> FRect {
1382 FRect::new(raw.x, raw.y, raw.w, raw.h)
1383 }
1384
1385 #[doc(alias = "SDL_EncloseFPoints")]
1389 pub fn from_enclose_points<R>(points: &[FPoint], clipping_rect: R) -> Option<FRect>
1390 where
1391 R: Into<Option<FRect>>,
1392 {
1393 let clipping_rect = clipping_rect.into();
1394
1395 if points.is_empty() {
1396 return None;
1397 }
1398
1399 let mut out = mem::MaybeUninit::uninit();
1400
1401 let clip_ptr = match clipping_rect.as_ref() {
1402 Some(r) => r.raw(),
1403 None => ptr::null(),
1404 };
1405
1406 let result = unsafe {
1407 sys::SDL_EncloseFPoints(
1408 FPoint::raw_slice(points),
1409 points.len() as i32,
1410 clip_ptr,
1411 out.as_mut_ptr(),
1412 ) != sys::SDL_bool::SDL_FALSE
1413 };
1414
1415 if result {
1416 let out = unsafe { out.assume_init() };
1417
1418 Some(FRect::from_ll(out))
1420 } else {
1421 None
1422 }
1423 }
1424
1425 #[doc(alias = "SDL_HasIntersectionF")]
1440 pub fn has_intersection(&self, other: FRect) -> bool {
1441 unsafe { sys::SDL_HasIntersectionF(self.raw(), other.raw()) != sys::SDL_bool::SDL_FALSE }
1442 }
1443
1444 #[doc(alias = "SDL_IntersectFRect")]
1463 pub fn intersection(&self, other: FRect) -> Option<FRect> {
1464 let mut out = mem::MaybeUninit::uninit();
1465
1466 let success = unsafe {
1467 sys::SDL_IntersectFRect(self.raw(), other.raw(), out.as_mut_ptr())
1468 != sys::SDL_bool::SDL_FALSE
1469 };
1470
1471 if success {
1472 let out = unsafe { out.assume_init() };
1473 Some(FRect::from_ll(out))
1474 } else {
1475 None
1476 }
1477 }
1478
1479 #[doc(alias = "SDL_UnionFRect")]
1494 pub fn union(&self, other: FRect) -> FRect {
1495 let mut out = mem::MaybeUninit::uninit();
1496
1497 unsafe {
1498 sys::SDL_UnionFRect(self.raw(), other.raw(), out.as_mut_ptr())
1501 };
1502
1503 let out = unsafe { out.assume_init() };
1504
1505 FRect::from_ll(out)
1506 }
1507
1508 #[doc(alias = "SDL_IntersectFRectAndLine")]
1511 pub fn intersect_line(&self, start: FPoint, end: FPoint) -> Option<(FPoint, FPoint)> {
1512 let (mut start_x, mut start_y) = (start.x(), start.y());
1513 let (mut end_x, mut end_y) = (end.x(), end.y());
1514
1515 let intersected = unsafe {
1516 sys::SDL_IntersectFRectAndLine(
1517 self.raw(),
1518 &mut start_x,
1519 &mut start_y,
1520 &mut end_x,
1521 &mut end_y,
1522 ) != sys::SDL_bool::SDL_FALSE
1523 };
1524
1525 if intersected {
1526 Some((FPoint::new(start_x, start_y), FPoint::new(end_x, end_y)))
1527 } else {
1528 None
1529 }
1530 }
1531}
1532
1533impl Deref for FRect {
1534 type Target = sys::SDL_FRect;
1535
1536 fn deref(&self) -> &sys::SDL_FRect {
1544 &self.raw
1545 }
1546}
1547
1548impl DerefMut for FRect {
1549 fn deref_mut(&mut self) -> &mut sys::SDL_FRect {
1558 &mut self.raw
1559 }
1560}
1561
1562impl From<FRect> for sys::SDL_FRect {
1563 fn from(val: FRect) -> Self {
1564 val.raw
1565 }
1566}
1567
1568impl From<FRect> for (f32, f32, f32, f32) {
1569 fn from(val: FRect) -> Self {
1570 (val.raw.x, val.raw.y, val.raw.w, val.raw.h)
1571 }
1572}
1573
1574impl From<sys::SDL_FRect> for FRect {
1575 fn from(raw: sys::SDL_FRect) -> FRect {
1576 FRect { raw }
1577 }
1578}
1579
1580impl From<(f32, f32, f32, f32)> for FRect {
1581 fn from((x, y, width, height): (f32, f32, f32, f32)) -> FRect {
1582 FRect::new(x, y, width, height)
1583 }
1584}
1585
1586impl AsRef<sys::SDL_FRect> for FRect {
1587 fn as_ref(&self) -> &sys::SDL_FRect {
1588 &self.raw
1589 }
1590}
1591
1592impl AsMut<sys::SDL_FRect> for FRect {
1593 fn as_mut(&mut self) -> &mut sys::SDL_FRect {
1594 &mut self.raw
1595 }
1596}
1597
1598impl BitAnd<FRect> for FRect {
1600 type Output = Option<FRect>;
1601 #[doc(alias = "SDL_FPoint")]
1602 fn bitand(self, rhs: FRect) -> Option<FRect> {
1603 self.intersection(rhs)
1604 }
1605}
1606
1607impl BitOr<FRect> for FRect {
1609 type Output = FRect;
1610 fn bitor(self, rhs: FRect) -> FRect {
1611 self.union(rhs)
1612 }
1613}
1614
1615#[repr(transparent)]
1619#[derive(Copy, Clone)]
1620pub struct FPoint {
1621 raw: sys::SDL_FPoint,
1622}
1623
1624impl ::std::fmt::Debug for FPoint {
1625 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
1626 fmt.debug_struct("FPoint")
1627 .field("x", &self.raw.x)
1628 .field("y", &self.raw.y)
1629 .finish()
1630 }
1631}
1632
1633impl PartialEq for FPoint {
1634 fn eq(&self, other: &FPoint) -> bool {
1635 self.raw.x == other.raw.x && self.raw.y == other.raw.y
1636 }
1637}
1638
1639impl Deref for FPoint {
1640 type Target = sys::SDL_FPoint;
1641
1642 fn deref(&self) -> &sys::SDL_FPoint {
1650 &self.raw
1651 }
1652}
1653
1654impl DerefMut for FPoint {
1655 fn deref_mut(&mut self) -> &mut sys::SDL_FPoint {
1664 &mut self.raw
1665 }
1666}
1667
1668impl AsRef<sys::SDL_FPoint> for FPoint {
1669 fn as_ref(&self) -> &sys::SDL_FPoint {
1670 &self.raw
1671 }
1672}
1673
1674impl AsMut<sys::SDL_FPoint> for FPoint {
1675 fn as_mut(&mut self) -> &mut sys::SDL_FPoint {
1676 &mut self.raw
1677 }
1678}
1679
1680impl From<sys::SDL_FPoint> for FPoint {
1681 fn from(prim: sys::SDL_FPoint) -> FPoint {
1682 FPoint { raw: prim }
1683 }
1684}
1685
1686impl From<(f32, f32)> for FPoint {
1687 fn from((x, y): (f32, f32)) -> FPoint {
1688 FPoint::new(x, y)
1689 }
1690}
1691
1692impl From<FPoint> for sys::SDL_FPoint {
1693 fn from(val: FPoint) -> Self {
1694 val.raw
1695 }
1696}
1697
1698impl From<FPoint> for (f32, f32) {
1699 fn from(val: FPoint) -> Self {
1700 (val.x(), val.y())
1701 }
1702}
1703
1704impl FPoint {
1705 pub fn new(x: f32, y: f32) -> FPoint {
1707 FPoint {
1708 raw: sys::SDL_FPoint { x, y },
1709 }
1710 }
1711
1712 pub fn from_ll(raw: sys::SDL_FPoint) -> FPoint {
1713 FPoint::new(raw.x, raw.y)
1714 }
1715
1716 #[doc(alias = "SDL_FPoint")]
1717 pub fn raw_slice(slice: &[FPoint]) -> *const sys::SDL_FPoint {
1718 slice.as_ptr() as *const sys::SDL_FPoint
1719 }
1720
1721 #[allow(clippy::trivially_copy_pass_by_ref)]
1724 pub fn raw(&self) -> *const sys::SDL_FPoint {
1725 &self.raw
1726 }
1727
1728 pub fn offset(self, x: f32, y: f32) -> FPoint {
1731 let x = self.raw.x + x;
1732 let y = self.raw.y + y;
1733 FPoint::new(x, y)
1734 }
1735
1736 pub fn scale(self, f: f32) -> FPoint {
1739 FPoint::new(self.raw.x * f, self.raw.y * f)
1740 }
1741
1742 pub fn x(self) -> f32 {
1744 self.raw.x
1745 }
1746
1747 pub fn y(self) -> f32 {
1749 self.raw.y
1750 }
1751}
1752
1753impl Add for FPoint {
1754 type Output = FPoint;
1755
1756 fn add(self, rhs: FPoint) -> FPoint {
1757 self.offset(rhs.x(), rhs.y())
1758 }
1759}
1760
1761impl AddAssign for FPoint {
1762 fn add_assign(&mut self, rhs: FPoint) {
1763 self.raw.x = self.x() + rhs.x();
1764 self.raw.y = self.y() + rhs.y();
1765 }
1766}
1767
1768impl Neg for FPoint {
1769 type Output = FPoint;
1770
1771 fn neg(self) -> FPoint {
1772 FPoint::new(-self.x(), -self.y())
1773 }
1774}
1775
1776impl Sub for FPoint {
1777 type Output = FPoint;
1778
1779 fn sub(self, rhs: FPoint) -> FPoint {
1780 self.offset(-rhs.x(), -rhs.y())
1781 }
1782}
1783
1784impl SubAssign for FPoint {
1785 fn sub_assign(&mut self, rhs: FPoint) {
1786 self.raw.x = self.x() - rhs.x();
1787 self.raw.y = self.y() - rhs.y();
1788 }
1789}
1790
1791impl Mul<f32> for FPoint {
1792 type Output = FPoint;
1793
1794 fn mul(self, rhs: f32) -> FPoint {
1795 self.scale(rhs)
1796 }
1797}
1798
1799impl MulAssign<f32> for FPoint {
1800 fn mul_assign(&mut self, rhs: f32) {
1801 self.raw.x = self.x() * rhs;
1802 self.raw.y = self.y() * rhs;
1803 }
1804}
1805
1806impl Div<f32> for FPoint {
1807 type Output = FPoint;
1808
1809 fn div(self, rhs: f32) -> FPoint {
1810 FPoint::new(self.x() / rhs, self.y() / rhs)
1811 }
1812}
1813
1814impl DivAssign<f32> for FPoint {
1815 fn div_assign(&mut self, rhs: f32) {
1816 self.raw.x /= rhs;
1817 self.raw.y /= rhs;
1818 }
1819}
1820
1821impl std::iter::Sum for FPoint {
1822 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1823 iter.fold(FPoint::new(0.0, 0.0), FPoint::add)
1824 }
1825}
1826
1827#[cfg(test)]
1828mod test {
1829 use super::{max_int_value, min_int_value, FPoint, FRect, Point, Rect};
1830
1831 fn tuple(x: i32, y: i32, w: u32, h: u32) -> (i32, i32, u32, u32) {
1833 (x, y, w, h)
1834 }
1835
1836 #[test]
1837 fn centered() {
1838 assert_eq!(
1840 Rect::new(0, 0, 10, 10).centered_on((0, 0)),
1841 Rect::new(-5, -5, 10, 10)
1842 );
1843 }
1844
1845 #[test]
1846 fn enclose_points_valid() {
1847 assert_eq!(
1848 Some(tuple(2, 4, 4, 6)),
1849 Rect::from_enclose_points(&[Point::new(2, 4), Point::new(5, 9)], None)
1850 .map(|r| r.into())
1851 );
1852 }
1853
1854 #[test]
1855 fn enclose_points_outside_clip_rect() {
1856 assert_eq!(
1857 Rect::from_enclose_points(
1858 &[Point::new(0, 0), Point::new(10, 10)],
1859 Some(Rect::new(3, 3, 1, 1))
1860 ),
1861 None
1862 );
1863 }
1864
1865 #[test]
1866 fn enclose_points_max_values() {
1867 assert_eq!(
1869 Some(tuple(
1870 min_int_value(),
1871 min_int_value(),
1872 max_int_value(),
1873 max_int_value()
1874 )),
1875 Rect::from_enclose_points(
1876 &[
1877 Point::new(i32::MIN, i32::MIN),
1878 Point::new(i32::MAX, i32::MAX)
1879 ],
1880 None
1881 )
1882 .map(|r| r.into())
1883 );
1884 }
1885
1886 #[test]
1887 fn has_intersection() {
1888 let rect = Rect::new(0, 0, 10, 10);
1889 assert!(rect.has_intersection(Rect::new(9, 9, 10, 10)));
1890 assert!(!rect.has_intersection(Rect::new(10, 10, 10, 10)));
1892 assert!(!rect.has_intersection(Rect::new(11, 11, 10, 10)));
1894 }
1895
1896 #[test]
1897 fn intersection() {
1898 let rect = Rect::new(0, 0, 10, 10);
1899 assert_eq!(rect & Rect::new(9, 9, 10, 10), Some(Rect::new(9, 9, 1, 1)));
1900 assert_eq!(rect & Rect::new(11, 11, 10, 10), None);
1901 }
1902
1903 #[test]
1904 fn union() {
1905 assert_eq!(
1906 Rect::new(0, 0, 1, 1) | Rect::new(9, 9, 1, 1),
1907 Rect::new(0, 0, 10, 10)
1908 );
1909 }
1910
1911 #[test]
1912 fn intersect_line() {
1913 assert_eq!(
1914 Rect::new(1, 1, 5, 5).intersect_line(Point::new(0, 0), Point::new(10, 10)),
1915 Some((Point::new(1, 1), Point::new(5, 5)))
1916 );
1917 }
1918
1919 #[test]
1920 fn clamp_size_zero() {
1921 assert_eq!(tuple(0, 0, 1, 1), Rect::new(0, 0, 0, 0).into());
1922 }
1923
1924 #[test]
1925 fn clamp_position_min() {
1926 assert_eq!(
1927 tuple(min_int_value(), min_int_value(), 1, 1),
1928 Rect::new(i32::MIN, i32::MIN, 1, 1).into()
1929 );
1930 }
1931
1932 #[test]
1933 fn clamp_size_max() {
1934 assert_eq!(
1935 tuple(0, 0, max_int_value(), max_int_value()),
1936 Rect::new(0, 0, max_int_value() + 1, max_int_value() + 1).into()
1937 );
1938 }
1939
1940 #[test]
1941 fn clamp_i32_max() {
1942 assert_eq!(
1943 tuple(0, 0, max_int_value(), max_int_value()),
1944 Rect::new(0, 0, i32::MAX as u32, i32::MAX as u32).into()
1945 )
1946 }
1947
1948 #[test]
1949 fn clamp_position_max() {
1950 assert_eq!(
1951 tuple(max_int_value() as i32, max_int_value() as i32, 1, 1),
1952 Rect::new(max_int_value() as i32 + 1, max_int_value() as i32 + 1, 1, 1).into()
1953 );
1954 }
1955
1956 #[test]
1957 fn shifted() {
1958 let rect = Rect::new(5, 5, 10, 10)
1960 .left_shifted(5)
1961 .right_shifted(5)
1962 .top_shifted(5)
1963 .bottom_shifted(5);
1964 assert_eq!(rect, Rect::new(5, 5, 10, 10));
1965 }
1966
1967 #[test]
1968 fn rect_into() {
1969 let test: (i32, i32, u32, u32) = (-11, 5, 50, 20);
1970 assert_eq!(test, Rect::new(-11, 5, 50, 20).into());
1971 }
1972
1973 #[test]
1974 fn rect_from() {
1975 assert_eq!(Rect::from((-11, 5, 50, 20)), Rect::new(-11, 5, 50, 20));
1976 }
1977
1978 #[test]
1979 fn point_into() {
1980 let test: (i32, i32) = (-11, 5);
1981 assert_eq!(test, Point::new(-11, 5).into());
1982 }
1983
1984 #[test]
1985 fn point_from() {
1986 let test: (i32, i32) = (-11, 5);
1987 assert_eq!(test, Point::new(-11, 5).into());
1988 }
1989
1990 #[test]
1991 fn point_add() {
1992 assert_eq!(Point::new(-5, 7), Point::new(-11, 5) + Point::new(6, 2));
1993 }
1994
1995 #[test]
1996 fn point_add_assign() {
1997 let mut point = Point::new(-11, 5);
1998 point += Point::new(6, 2);
1999 assert_eq!(point, Point::new(-11, 5) + Point::new(6, 2));
2000 }
2001
2002 #[test]
2003 fn point_sub() {
2004 assert_eq!(Point::new(-17, 3), Point::new(-11, 5) - Point::new(6, 2));
2005 }
2006
2007 #[test]
2008 fn point_sub_assign() {
2009 let mut point = Point::new(-11, 5);
2010 point -= Point::new(6, 2);
2011 assert_eq!(point, Point::new(-11, 5) - Point::new(6, 2));
2012 }
2013
2014 #[test]
2015 fn point_mul() {
2016 assert_eq!(Point::new(-33, 15), Point::new(-11, 5) * 3);
2017 }
2018
2019 #[test]
2020 fn point_mul_assign() {
2021 let mut point = Point::new(-11, 5);
2022 point *= 3;
2023 assert_eq!(point, Point::new(-11, 5) * 3);
2024 }
2025
2026 #[test]
2027 fn point_mul_clamp() {
2028 assert_eq!(
2029 Point::new(0x7fffffff, -0x7fffffff),
2030 Point::new(-1000000, 5000000) * -3000000
2031 );
2032 }
2033
2034 #[test]
2035 fn point_mul_assign_clamp() {
2036 let mut point = Point::new(-1000000, 5000000);
2037 point *= -3000000;
2038 assert_eq!(point, Point::new(-1000000, 5000000) * -3000000);
2039 }
2040
2041 #[test]
2042 fn point_div() {
2043 assert_eq!(Point::new(-3, 1), Point::new(-11, 5) / 3);
2044 }
2045
2046 #[test]
2047 fn point_div_assign() {
2048 let mut point = Point::new(-11, 5);
2049 point /= 3;
2050 assert_eq!(point, Point::new(-11, 5) / 3);
2051 }
2052
2053 #[test]
2054 fn point_sum() {
2055 let points_sum: Point = vec![Point::new(-11, 5), Point::new(6, 2)].into_iter().sum();
2056 assert_eq!(Point::new(-5, 7), points_sum);
2057 }
2058
2059 #[test]
2060 fn frect_centered() {
2061 assert_eq!(
2063 FRect::new(0.0, 0.0, 10.0, 10.0).centered_on((0.0, 0.0)),
2064 FRect::new(-5.0, -5.0, 10.0, 10.0)
2065 );
2066 }
2067
2068 #[test]
2069 fn frect_enclose_points_valid() {
2070 assert_eq!(
2071 Some((2.0, 4.0, 4.0, 6.0)),
2072 FRect::from_enclose_points(&[FPoint::new(2.0, 4.0), FPoint::new(5.0, 9.0)], None)
2073 .map(|r| r.into())
2074 );
2075 }
2076
2077 #[test]
2078 fn frect_enclose_points_outside_clip_rect() {
2079 assert_eq!(
2080 FRect::from_enclose_points(
2081 &[FPoint::new(0.0, 0.0), FPoint::new(10.0, 10.0)],
2082 Some(FRect::new(3.0, 3.0, 1.0, 1.0))
2083 ),
2084 None
2085 );
2086 }
2087
2088 #[test]
2089 fn frect_has_intersection() {
2090 let rect = FRect::new(0.0, 0.0, 10.0, 10.0);
2091 assert!(rect.has_intersection(FRect::new(9.0, 9.0, 10.0, 10.0)));
2092 assert!(!rect.has_intersection(FRect::new(10.0, 10.0, 10.0, 10.0)));
2094 assert!(!rect.has_intersection(FRect::new(11.0, 11.0, 10.0, 10.0)));
2096 }
2097
2098 #[test]
2099 fn frect_intersection() {
2100 let rect = FRect::new(0.0, 0.0, 10.0, 10.0);
2101 assert_eq!(
2102 rect & FRect::new(9.0, 9.0, 10.0, 10.0),
2103 Some(FRect::new(9.0, 9.0, 1.0, 1.0))
2104 );
2105 assert_eq!(rect & FRect::new(11.0, 11.0, 10.0, 10.0), None);
2106 }
2107
2108 #[test]
2109 fn frect_union() {
2110 assert_eq!(
2111 FRect::new(0.0, 0.0, 1.0, 1.0) | FRect::new(9.0, 9.0, 1.0, 1.0),
2112 FRect::new(0.0, 0.0, 10.0, 10.0)
2113 );
2114 }
2115
2116 #[test]
2117 fn frect_intersect_line() {
2118 assert_eq!(
2119 FRect::new(1.0, 1.0, 5.0, 5.0)
2120 .intersect_line(FPoint::new(0.0, 0.0), FPoint::new(10.0, 10.0)),
2121 Some((FPoint::new(1.0, 1.0), FPoint::new(5.0, 5.0)))
2122 );
2123 }
2124
2125 #[test]
2126 fn frect_shifted() {
2127 let rect = FRect::new(0.0, 0.0, 10.0, 10.0)
2129 .left_shifted(5.0)
2130 .right_shifted(5.0)
2131 .top_shifted(5.0)
2132 .bottom_shifted(5.0);
2133 assert_eq!(rect, FRect::new(0.0, 0.0, 10.0, 10.0));
2134 }
2135
2136 #[test]
2137 fn frect_into() {
2138 let test: (f32, f32, f32, f32) = (-11.0, 5.0, 50.0, 20.0);
2139 assert_eq!(test, FRect::new(-11.0, 5.0, 50.0, 20.0).into());
2140 }
2141
2142 #[test]
2143 fn frect_from() {
2144 assert_eq!(
2145 FRect::from((-11.0, 5.0, 50.0, 20.0)),
2146 FRect::new(-11.0, 5.0, 50.0, 20.0)
2147 );
2148 }
2149
2150 #[test]
2151 fn fpoint_into() {
2152 let test: (f32, f32) = (-11.0, 5.0);
2153 assert_eq!(test, FPoint::new(-11.0, 5.0).into());
2154 }
2155
2156 #[test]
2157 fn fpoint_from() {
2158 let test: (f32, f32) = (-11.0, 5.0);
2159 assert_eq!(test, FPoint::new(-11.0, 5.0).into());
2160 }
2161
2162 #[test]
2163 fn fpoint_add() {
2164 assert_eq!(
2165 FPoint::new(-5.0, 7.0),
2166 FPoint::new(-11.0, 5.0) + FPoint::new(6.0, 2.0)
2167 );
2168 }
2169
2170 #[test]
2171 fn fpoint_add_assign() {
2172 let mut point = FPoint::new(-11.0, 5.0);
2173 point += FPoint::new(6.0, 2.0);
2174 assert_eq!(point, FPoint::new(-11.0, 5.0) + FPoint::new(6.0, 2.0));
2175 }
2176
2177 #[test]
2178 fn fpoint_sub() {
2179 assert_eq!(
2180 FPoint::new(-17.0, 3.0),
2181 FPoint::new(-11.0, 5.0) - FPoint::new(6.0, 2.0)
2182 );
2183 }
2184
2185 #[test]
2186 fn fpoint_sub_assign() {
2187 let mut point = FPoint::new(-11.0, 5.0);
2188 point -= FPoint::new(6.0, 2.0);
2189 assert_eq!(point, FPoint::new(-11.0, 5.0) - FPoint::new(6.0, 2.0));
2190 }
2191
2192 #[test]
2193 fn fpoint_mul() {
2194 assert_eq!(FPoint::new(-33.0, 15.0), FPoint::new(-11.0, 5.0) * 3.0);
2195 }
2196
2197 #[test]
2198 fn fpoint_mul_assign() {
2199 let mut point = FPoint::new(-11.0, 5.0);
2200 point *= 3.0;
2201 assert_eq!(point, FPoint::new(-11.0, 5.0) * 3.0);
2202 }
2203
2204 #[test]
2205 fn fpoint_div() {
2206 assert_eq!(FPoint::new(-3.0, 1.0), FPoint::new(-9.0, 3.0) / 3.0);
2207 }
2208
2209 #[test]
2210 fn fpoint_div_assign() {
2211 let mut point = FPoint::new(-11.0, 5.0);
2212 point /= 3.0;
2213 assert_eq!(point, FPoint::new(-11.0, 5.0) / 3.0);
2214 }
2215
2216 #[test]
2217 fn fpoint_sum() {
2218 let points_sum: FPoint = vec![FPoint::new(-11.0, 5.0), FPoint::new(6.0, 2.0)]
2219 .into_iter()
2220 .sum();
2221 assert_eq!(FPoint::new(-5.0, 7.0), points_sum);
2222 }
2223}