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 left_shifted(mut self, offset: i32) -> Rect {
249 self.offset(-offset, 0);
250 self
251 }
252
253 pub fn right_shifted(mut self, offset: i32) -> Rect {
262 self.offset(offset, 0);
263 self
264 }
265
266 pub fn top_shifted(mut self, offset: i32) -> Rect {
275 self.offset(0, -offset);
276 self
277 }
278
279 pub fn bottom_shifted(mut self, offset: i32) -> Rect {
288 self.offset(0, offset);
289 self
290 }
291
292 pub fn center(&self) -> Point {
305 let x = self.raw.x + (self.raw.w / 2);
306 let y = self.raw.y + (self.raw.h / 2);
307 Point::new(x, y)
308 }
309
310 pub fn top_left(&self) -> Point {
320 Point::new(self.left(), self.top())
321 }
322
323 pub fn top_right(&self) -> Point {
333 Point::new(self.right(), self.top())
334 }
335
336 pub fn bottom_left(&self) -> Point {
346 Point::new(self.left(), self.bottom())
347 }
348
349 pub fn bottom_right(&self) -> Point {
359 Point::new(self.right(), self.bottom())
360 }
361
362 pub fn set_right(&mut self, right: i32) {
365 self.raw.x = clamp_position(clamp_position(right) - self.raw.w);
366 }
367
368 pub fn set_bottom(&mut self, bottom: i32) {
371 self.raw.y = clamp_position(clamp_position(bottom) - self.raw.h);
372 }
373
374 #[inline]
376 pub fn center_on<P>(&mut self, point: P)
377 where
378 P: Into<(i32, i32)>,
379 {
380 let (x, y) = point.into();
381 self.raw.x = clamp_position(clamp_position(x) - self.raw.w / 2);
382 self.raw.y = clamp_position(clamp_position(y) - self.raw.h / 2);
383 }
384
385 #[inline]
387 pub fn centered_on<P>(mut self, point: P) -> Rect
388 where
389 P: Into<(i32, i32)>,
390 {
391 self.center_on(point);
392 self
393 }
394
395 #[inline]
398 pub fn offset(&mut self, x: i32, y: i32) {
399 match self.raw.x.checked_add(x) {
400 Some(val) => self.raw.x = clamp_position(val),
401 None => {
402 if x >= 0 {
403 self.raw.x = max_int_value() as i32;
404 } else {
405 self.raw.x = i32::MIN;
406 }
407 }
408 }
409 match self.raw.y.checked_add(y) {
410 Some(val) => self.raw.y = clamp_position(val),
411 None => {
412 if y >= 0 {
413 self.raw.y = max_int_value() as i32;
414 } else {
415 self.raw.y = i32::MIN;
416 }
417 }
418 }
419 }
420
421 pub fn reposition<P>(&mut self, point: P)
423 where
424 P: Into<(i32, i32)>,
425 {
426 let (x, y) = point.into();
427 self.raw.x = clamp_position(x);
428 self.raw.y = clamp_position(y);
429 }
430
431 pub fn resize(&mut self, width: u32, height: u32) {
433 self.raw.w = clamp_size(width) as i32;
434 self.raw.h = clamp_size(height) as i32;
435 }
436
437 pub fn contains_point<P>(&self, point: P) -> bool
457 where
458 P: Into<(i32, i32)>,
459 {
460 let (x, y) = point.into();
461 let inside_x = x >= self.left() && x < self.right();
462 inside_x && (y >= self.top() && y < self.bottom())
463 }
464
465 pub fn contains_rect(&self, other: Rect) -> bool {
482 other.left() >= self.left()
483 && other.right() <= self.right()
484 && other.top() >= self.top()
485 && other.bottom() <= self.bottom()
486 }
487
488 #[allow(clippy::trivially_copy_pass_by_ref)]
492 pub fn raw(&self) -> *const sys::SDL_Rect {
493 &self.raw
494 }
495
496 pub fn raw_mut(&mut self) -> *mut sys::SDL_Rect {
497 &mut self.raw
498 }
499
500 #[doc(alias = "SDL_Rect")]
501 pub fn raw_slice(slice: &[Rect]) -> *const sys::SDL_Rect {
502 slice.as_ptr() as *const sys::SDL_Rect
503 }
504
505 pub fn from_ll(raw: sys::SDL_Rect) -> Rect {
506 Rect::new(raw.x, raw.y, raw.w as u32, raw.h as u32)
507 }
508
509 #[doc(alias = "SDL_EnclosePoints")]
513 pub fn from_enclose_points<R>(points: &[Point], clipping_rect: R) -> Option<Rect>
514 where
515 R: Into<Option<Rect>>,
516 {
517 let clipping_rect = clipping_rect.into();
518
519 if points.is_empty() {
520 return None;
521 }
522
523 let mut out = mem::MaybeUninit::uninit();
524
525 let clip_ptr = match clipping_rect.as_ref() {
526 Some(r) => r.raw(),
527 None => ptr::null(),
528 };
529
530 let result = unsafe {
531 sys::SDL_EnclosePoints(
532 Point::raw_slice(points),
533 points.len() as i32,
534 clip_ptr,
535 out.as_mut_ptr(),
536 ) != sys::SDL_bool::SDL_FALSE
537 };
538
539 if result {
540 let out = unsafe { out.assume_init() };
541
542 Some(Rect::from_ll(out))
544 } else {
545 None
546 }
547 }
548
549 #[doc(alias = "SDL_HasIntersection")]
564 pub fn has_intersection(&self, other: Rect) -> bool {
565 unsafe { sys::SDL_HasIntersection(self.raw(), other.raw()) != sys::SDL_bool::SDL_FALSE }
566 }
567
568 #[doc(alias = "SDL_IntersectRect")]
587 pub fn intersection(&self, other: Rect) -> Option<Rect> {
588 let mut out = mem::MaybeUninit::uninit();
589
590 let success = unsafe {
591 sys::SDL_IntersectRect(self.raw(), other.raw(), out.as_mut_ptr())
592 != sys::SDL_bool::SDL_FALSE
593 };
594
595 if success {
596 let out = unsafe { out.assume_init() };
597 Some(Rect::from_ll(out))
598 } else {
599 None
600 }
601 }
602
603 #[doc(alias = "SDL_UnionRect")]
618 pub fn union(&self, other: Rect) -> Rect {
619 let mut out = mem::MaybeUninit::uninit();
620
621 unsafe {
622 sys::SDL_UnionRect(self.raw(), other.raw(), out.as_mut_ptr())
625 };
626
627 let out = unsafe { out.assume_init() };
628
629 Rect::from_ll(out)
630 }
631
632 #[doc(alias = "SDL_IntersectRectAndLine")]
635 pub fn intersect_line(&self, start: Point, end: Point) -> Option<(Point, Point)> {
636 let (mut start_x, mut start_y) = (start.x(), start.y());
637 let (mut end_x, mut end_y) = (end.x(), end.y());
638
639 let intersected = unsafe {
640 sys::SDL_IntersectRectAndLine(
641 self.raw(),
642 &mut start_x,
643 &mut start_y,
644 &mut end_x,
645 &mut end_y,
646 ) != sys::SDL_bool::SDL_FALSE
647 };
648
649 if intersected {
650 Some((Point::new(start_x, start_y), Point::new(end_x, end_y)))
651 } else {
652 None
653 }
654 }
655}
656
657impl Deref for Rect {
658 type Target = sys::SDL_Rect;
659
660 fn deref(&self) -> &sys::SDL_Rect {
668 &self.raw
669 }
670}
671
672impl DerefMut for Rect {
673 fn deref_mut(&mut self) -> &mut sys::SDL_Rect {
682 &mut self.raw
683 }
684}
685
686impl From<Rect> for sys::SDL_Rect {
687 fn from(val: Rect) -> Self {
688 val.raw
689 }
690}
691
692impl From<Rect> for (i32, i32, u32, u32) {
693 fn from(val: Rect) -> Self {
694 (val.raw.x, val.raw.y, val.raw.w as u32, val.raw.h as u32)
695 }
696}
697
698impl From<sys::SDL_Rect> for Rect {
699 fn from(raw: sys::SDL_Rect) -> Rect {
700 Rect { raw }
701 }
702}
703
704impl From<(i32, i32, u32, u32)> for Rect {
705 fn from((x, y, width, height): (i32, i32, u32, u32)) -> Rect {
706 Rect::new(x, y, width, height)
707 }
708}
709
710impl AsRef<sys::SDL_Rect> for Rect {
711 fn as_ref(&self) -> &sys::SDL_Rect {
712 &self.raw
713 }
714}
715
716impl AsMut<sys::SDL_Rect> for Rect {
717 fn as_mut(&mut self) -> &mut sys::SDL_Rect {
718 &mut self.raw
719 }
720}
721
722impl BitAnd<Rect> for Rect {
724 type Output = Option<Rect>;
725 #[doc(alias = "SDL_Point")]
726 fn bitand(self, rhs: Rect) -> Option<Rect> {
727 self.intersection(rhs)
728 }
729}
730
731impl BitOr<Rect> for Rect {
733 type Output = Rect;
734 fn bitor(self, rhs: Rect) -> Rect {
735 self.union(rhs)
736 }
737}
738
739#[repr(transparent)]
743#[derive(Copy, Clone)]
744pub struct Point {
745 raw: sys::SDL_Point,
746}
747
748impl ::std::fmt::Debug for Point {
749 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
750 fmt.debug_struct("Point")
751 .field("x", &self.raw.x)
752 .field("y", &self.raw.y)
753 .finish()
754 }
755}
756
757impl PartialEq for Point {
758 fn eq(&self, other: &Point) -> bool {
759 self.raw.x == other.raw.x && self.raw.y == other.raw.y
760 }
761}
762
763impl Eq for Point {}
764
765impl Hash for Point {
766 fn hash<H: Hasher>(&self, state: &mut H) {
767 self.raw.x.hash(state);
768 self.raw.y.hash(state);
769 }
770}
771
772impl Deref for Point {
773 type Target = sys::SDL_Point;
774
775 fn deref(&self) -> &sys::SDL_Point {
783 &self.raw
784 }
785}
786
787impl DerefMut for Point {
788 fn deref_mut(&mut self) -> &mut sys::SDL_Point {
797 &mut self.raw
798 }
799}
800
801impl AsRef<sys::SDL_Point> for Point {
802 fn as_ref(&self) -> &sys::SDL_Point {
803 &self.raw
804 }
805}
806
807impl AsMut<sys::SDL_Point> for Point {
808 fn as_mut(&mut self) -> &mut sys::SDL_Point {
809 &mut self.raw
810 }
811}
812
813impl From<sys::SDL_Point> for Point {
814 fn from(prim: sys::SDL_Point) -> Point {
815 Point { raw: prim }
816 }
817}
818
819impl From<(i32, i32)> for Point {
820 fn from((x, y): (i32, i32)) -> Point {
821 Point::new(x, y)
822 }
823}
824
825impl From<Point> for sys::SDL_Point {
826 fn from(val: Point) -> Self {
827 val.raw
828 }
829}
830
831impl From<Point> for (i32, i32) {
832 fn from(val: Point) -> Self {
833 (val.x(), val.y())
834 }
835}
836
837impl Point {
838 pub fn new(x: i32, y: i32) -> Point {
840 Point {
841 raw: sys::SDL_Point {
842 x: clamp_position(x),
843 y: clamp_position(y),
844 },
845 }
846 }
847
848 pub fn from_ll(raw: sys::SDL_Point) -> Point {
849 Point::new(raw.x, raw.y)
850 }
851
852 #[doc(alias = "SDL_Point")]
853 pub fn raw_slice(slice: &[Point]) -> *const sys::SDL_Point {
854 slice.as_ptr() as *const sys::SDL_Point
855 }
856 #[allow(clippy::trivially_copy_pass_by_ref)]
859 pub fn raw(&self) -> *const sys::SDL_Point {
860 &self.raw
861 }
862
863 pub fn offset(self, x: i32, y: i32) -> Point {
866 let x = match self.raw.x.checked_add(x) {
867 Some(val) => val,
868 None => {
869 if x < 0 {
870 min_int_value()
871 } else {
872 max_int_value() as i32
873 }
874 }
875 };
876 let y = match self.raw.y.checked_add(y) {
877 Some(val) => val,
878 None => {
879 if y < 0 {
880 min_int_value()
881 } else {
882 max_int_value() as i32
883 }
884 }
885 };
886 Point::new(x, y)
887 }
888
889 pub fn scale(self, f: i32) -> Point {
892 Point::new(clamped_mul(self.raw.x, f), clamped_mul(self.raw.y, f))
893 }
894
895 pub fn x(self) -> i32 {
897 self.raw.x
898 }
899
900 pub fn y(self) -> i32 {
902 self.raw.y
903 }
904}
905
906impl Add for Point {
907 type Output = Point;
908
909 fn add(self, rhs: Point) -> Point {
910 self.offset(rhs.x(), rhs.y())
911 }
912}
913
914impl AddAssign for Point {
915 fn add_assign(&mut self, rhs: Point) {
916 self.raw.x = clamp_position(self.x() + rhs.x());
917 self.raw.y = clamp_position(self.y() + rhs.y());
918 }
919}
920
921impl Neg for Point {
922 type Output = Point;
923
924 fn neg(self) -> Point {
925 Point::new(-self.x(), -self.y())
926 }
927}
928
929impl Sub for Point {
930 type Output = Point;
931
932 fn sub(self, rhs: Point) -> Point {
933 self.offset(-rhs.x(), -rhs.y())
934 }
935}
936
937impl SubAssign for Point {
938 fn sub_assign(&mut self, rhs: Point) {
939 self.raw.x = clamp_position(self.x() - rhs.x());
940 self.raw.y = clamp_position(self.y() - rhs.y());
941 }
942}
943
944impl Mul<i32> for Point {
945 type Output = Point;
946
947 fn mul(self, rhs: i32) -> Point {
948 self.scale(rhs)
949 }
950}
951
952impl MulAssign<i32> for Point {
953 fn mul_assign(&mut self, rhs: i32) {
954 self.raw.x = clamped_mul(self.x(), rhs);
955 self.raw.y = clamped_mul(self.y(), rhs);
956 }
957}
958
959impl Div<i32> for Point {
960 type Output = Point;
961
962 fn div(self, rhs: i32) -> Point {
963 Point::new(self.x() / rhs, self.y() / rhs)
964 }
965}
966
967impl DivAssign<i32> for Point {
968 fn div_assign(&mut self, rhs: i32) {
969 self.raw.x /= rhs;
970 self.raw.y /= rhs;
971 }
972}
973
974impl std::iter::Sum for Point {
975 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
976 iter.fold(Point::new(0, 0), Point::add)
977 }
978}
979
980#[derive(Clone, Copy)]
988pub struct FRect {
989 raw: sys::SDL_FRect,
990}
991
992impl ::std::fmt::Debug for FRect {
993 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
994 return write!(
995 fmt,
996 "FRect {{ x: {}, y: {}, w: {}, h: {} }}",
997 self.raw.x, self.raw.y, self.raw.w, self.raw.h
998 );
999 }
1000}
1001
1002impl PartialEq for FRect {
1003 fn eq(&self, other: &FRect) -> bool {
1004 self.raw.x == other.raw.x
1005 && self.raw.y == other.raw.y
1006 && self.raw.w == other.raw.w
1007 && self.raw.h == other.raw.h
1008 }
1009}
1010
1011impl FRect {
1012 pub fn new(x: f32, y: f32, width: f32, height: f32) -> FRect {
1017 let raw = sys::SDL_FRect {
1018 x,
1019 y,
1020 w: clamp_f32_size(width),
1021 h: clamp_f32_size(height),
1022 };
1023 FRect { raw }
1024 }
1025
1026 pub fn from_center<P>(center: P, width: f32, height: f32) -> FRect
1031 where
1032 P: Into<FPoint>,
1033 {
1034 let raw = sys::SDL_FRect {
1035 x: 0.0,
1036 y: 0.0,
1037 w: clamp_f32_size(width),
1038 h: clamp_f32_size(height),
1039 };
1040 let mut rect = FRect { raw };
1041 rect.center_on(center.into());
1042 rect
1043 }
1044
1045 #[inline]
1047 pub fn x(&self) -> f32 {
1048 self.raw.x
1049 }
1050
1051 #[inline]
1053 pub fn y(&self) -> f32 {
1054 self.raw.y
1055 }
1056
1057 pub fn width(&self) -> f32 {
1059 self.raw.w as f32
1060 }
1061
1062 pub fn height(&self) -> f32 {
1064 self.raw.h as f32
1065 }
1066
1067 pub fn size(&self) -> (f32, f32) {
1069 (self.width(), self.height())
1070 }
1071
1072 pub fn set_x(&mut self, x: f32) {
1075 self.raw.x = x;
1076 }
1077
1078 pub fn set_y(&mut self, y: f32) {
1081 self.raw.y = y;
1082 }
1083
1084 pub fn set_width(&mut self, width: f32) {
1090 self.raw.w = clamp_f32_size(width);
1091 }
1092
1093 pub fn set_height(&mut self, height: f32) {
1099 self.raw.h = clamp_f32_size(height);
1100 }
1101
1102 pub fn left(&self) -> f32 {
1104 self.raw.x
1105 }
1106
1107 pub fn right(&self) -> f32 {
1109 self.raw.x + self.raw.w
1110 }
1111
1112 pub fn top(&self) -> f32 {
1114 self.raw.y
1115 }
1116
1117 pub fn bottom(&self) -> f32 {
1119 self.raw.y + self.raw.h
1120 }
1121
1122 pub fn left_shifted(mut self, offset: f32) -> FRect {
1131 self.offset(-offset, self.y());
1132 self
1133 }
1134
1135 pub fn right_shifted(mut self, offset: f32) -> FRect {
1144 self.offset(offset, self.y());
1145 self
1146 }
1147
1148 pub fn top_shifted(mut self, offset: f32) -> FRect {
1157 self.offset(self.x(), -offset);
1158 self
1159 }
1160
1161 pub fn bottom_shifted(mut self, offset: f32) -> FRect {
1170 self.offset(self.x(), offset);
1171 self
1172 }
1173
1174 pub fn center(&self) -> FPoint {
1187 let x = self.raw.x + (self.raw.w / 2.0);
1188 let y = self.raw.y + (self.raw.h / 2.0);
1189 FPoint::new(x, y)
1190 }
1191
1192 pub fn top_left(&self) -> FPoint {
1202 FPoint::new(self.left(), self.top())
1203 }
1204
1205 pub fn top_right(&self) -> FPoint {
1215 FPoint::new(self.right(), self.top())
1216 }
1217
1218 pub fn bottom_left(&self) -> FPoint {
1228 FPoint::new(self.left(), self.bottom())
1229 }
1230
1231 pub fn bottom_right(&self) -> FPoint {
1241 FPoint::new(self.right(), self.bottom())
1242 }
1243
1244 pub fn set_right(&mut self, right: f32) {
1247 self.raw.x = clamp_f32_size(clamp_f32_size(right) - self.raw.w);
1248 }
1249
1250 pub fn set_bottom(&mut self, bottom: f32) {
1253 self.raw.y = clamp_f32_size(clamp_f32_size(bottom) - self.raw.h);
1254 }
1255
1256 #[inline]
1258 pub fn center_on<P>(&mut self, point: P)
1259 where
1260 P: Into<(f32, f32)>,
1261 {
1262 let (x, y) = point.into();
1263 self.raw.x = x - self.raw.w / 2.0;
1264 self.raw.y = y - self.raw.h / 2.0;
1265 }
1266
1267 #[inline]
1269 pub fn centered_on<P>(mut self, point: P) -> FRect
1270 where
1271 P: Into<(f32, f32)>,
1272 {
1273 self.center_on(point);
1274 self
1275 }
1276
1277 #[inline]
1279 pub fn offset(&mut self, x: f32, y: f32) {
1280 self.raw.x += x;
1281 self.raw.y += y;
1282 }
1283
1284 pub fn reposition<P>(&mut self, point: P)
1286 where
1287 P: Into<(f32, f32)>,
1288 {
1289 let (x, y) = point.into();
1290 self.raw.x = x;
1291 self.raw.y = y;
1292 }
1293
1294 pub fn resize(&mut self, width: f32, height: f32) {
1296 self.raw.w = clamp_f32_size(width);
1297 self.raw.h = clamp_f32_size(height);
1298 }
1299
1300 pub fn contains_point<P>(&self, point: P) -> bool
1319 where
1320 P: Into<(f32, f32)>,
1321 {
1322 let (x, y) = point.into();
1323 let inside_x = x >= self.left() && x < self.right();
1324 inside_x && (y >= self.top() && y < self.bottom())
1325 }
1326
1327 pub fn contains_rect(&self, other: FRect) -> bool {
1344 other.left() >= self.left()
1345 && other.right() <= self.right()
1346 && other.top() >= self.top()
1347 && other.bottom() <= self.bottom()
1348 }
1349
1350 #[allow(clippy::trivially_copy_pass_by_ref)]
1354 pub fn raw(&self) -> *const sys::SDL_FRect {
1355 &self.raw
1356 }
1357
1358 pub fn raw_mut(&mut self) -> *mut sys::SDL_FRect {
1359 self.raw() as *mut _
1360 }
1361
1362 #[doc(alias = "SDL_FRect")]
1363 pub fn raw_slice(slice: &[FRect]) -> *const sys::SDL_FRect {
1364 slice.as_ptr() as *const sys::SDL_FRect
1365 }
1366
1367 pub fn from_ll(raw: sys::SDL_FRect) -> FRect {
1368 FRect::new(raw.x, raw.y, raw.w, raw.h)
1369 }
1370
1371 #[doc(alias = "SDL_EncloseFPoints")]
1375 pub fn from_enclose_points<R: Into<Option<FRect>>>(
1376 points: &[FPoint],
1377 clipping_rect: R,
1378 ) -> Option<FRect>
1379 where
1380 R: Into<Option<FRect>>,
1381 {
1382 let clipping_rect = clipping_rect.into();
1383
1384 if points.is_empty() {
1385 return None;
1386 }
1387
1388 let mut out = mem::MaybeUninit::uninit();
1389
1390 let clip_ptr = match clipping_rect.as_ref() {
1391 Some(r) => r.raw(),
1392 None => ptr::null(),
1393 };
1394
1395 let result = unsafe {
1396 sys::SDL_EncloseFPoints(
1397 FPoint::raw_slice(points),
1398 points.len() as i32,
1399 clip_ptr,
1400 out.as_mut_ptr(),
1401 ) != sys::SDL_bool::SDL_FALSE
1402 };
1403
1404 if result {
1405 let out = unsafe { out.assume_init() };
1406
1407 Some(FRect::from_ll(out))
1409 } else {
1410 None
1411 }
1412 }
1413
1414 #[doc(alias = "SDL_HasIntersectionF")]
1429 pub fn has_intersection(&self, other: FRect) -> bool {
1430 unsafe { sys::SDL_HasIntersectionF(self.raw(), other.raw()) != sys::SDL_bool::SDL_FALSE }
1431 }
1432
1433 #[doc(alias = "SDL_IntersectFRect")]
1452 pub fn intersection(&self, other: FRect) -> Option<FRect> {
1453 let mut out = mem::MaybeUninit::uninit();
1454
1455 let success = unsafe {
1456 sys::SDL_IntersectFRect(self.raw(), other.raw(), out.as_mut_ptr())
1457 != sys::SDL_bool::SDL_FALSE
1458 };
1459
1460 if success {
1461 let out = unsafe { out.assume_init() };
1462 Some(FRect::from_ll(out))
1463 } else {
1464 None
1465 }
1466 }
1467
1468 #[doc(alias = "SDL_UnionFRect")]
1483 pub fn union(&self, other: FRect) -> FRect {
1484 let mut out = mem::MaybeUninit::uninit();
1485
1486 unsafe {
1487 sys::SDL_UnionFRect(self.raw(), other.raw(), out.as_mut_ptr())
1490 };
1491
1492 let out = unsafe { out.assume_init() };
1493
1494 FRect::from_ll(out)
1495 }
1496
1497 #[doc(alias = "SDL_IntersectFRectAndLine")]
1500 pub fn intersect_line(&self, start: FPoint, end: FPoint) -> Option<(FPoint, FPoint)> {
1501 let (mut start_x, mut start_y) = (start.x(), start.y());
1502 let (mut end_x, mut end_y) = (end.x(), end.y());
1503
1504 let intersected = unsafe {
1505 sys::SDL_IntersectFRectAndLine(
1506 self.raw(),
1507 &mut start_x,
1508 &mut start_y,
1509 &mut end_x,
1510 &mut end_y,
1511 ) != sys::SDL_bool::SDL_FALSE
1512 };
1513
1514 if intersected {
1515 Some((FPoint::new(start_x, start_y), FPoint::new(end_x, end_y)))
1516 } else {
1517 None
1518 }
1519 }
1520}
1521
1522impl Deref for FRect {
1523 type Target = sys::SDL_FRect;
1524
1525 fn deref(&self) -> &sys::SDL_FRect {
1533 &self.raw
1534 }
1535}
1536
1537impl DerefMut for FRect {
1538 fn deref_mut(&mut self) -> &mut sys::SDL_FRect {
1547 &mut self.raw
1548 }
1549}
1550
1551impl Into<sys::SDL_FRect> for FRect {
1552 fn into(self) -> sys::SDL_FRect {
1553 self.raw
1554 }
1555}
1556
1557impl Into<(f32, f32, f32, f32)> for FRect {
1558 fn into(self) -> (f32, f32, f32, f32) {
1559 (self.raw.x, self.raw.y, self.raw.w, self.raw.h)
1560 }
1561}
1562
1563impl From<sys::SDL_FRect> for FRect {
1564 fn from(raw: sys::SDL_FRect) -> FRect {
1565 FRect { raw }
1566 }
1567}
1568
1569impl From<(f32, f32, f32, f32)> for FRect {
1570 fn from((x, y, width, height): (f32, f32, f32, f32)) -> FRect {
1571 FRect::new(x, y, width, height)
1572 }
1573}
1574
1575impl AsRef<sys::SDL_FRect> for FRect {
1576 fn as_ref(&self) -> &sys::SDL_FRect {
1577 &self.raw
1578 }
1579}
1580
1581impl AsMut<sys::SDL_FRect> for FRect {
1582 fn as_mut(&mut self) -> &mut sys::SDL_FRect {
1583 &mut self.raw
1584 }
1585}
1586
1587impl BitAnd<FRect> for FRect {
1589 type Output = Option<FRect>;
1590 #[doc(alias = "SDL_FPoint")]
1591 fn bitand(self, rhs: FRect) -> Option<FRect> {
1592 self.intersection(rhs)
1593 }
1594}
1595
1596impl BitOr<FRect> for FRect {
1598 type Output = FRect;
1599 fn bitor(self, rhs: FRect) -> FRect {
1600 self.union(rhs)
1601 }
1602}
1603
1604#[derive(Copy, Clone)]
1606pub struct FPoint {
1607 raw: sys::SDL_FPoint,
1608}
1609
1610impl ::std::fmt::Debug for FPoint {
1611 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
1612 return write!(fmt, "FPoint {{ x: {}, y: {} }}", self.raw.x, self.raw.y);
1613 }
1614}
1615
1616impl PartialEq for FPoint {
1617 fn eq(&self, other: &FPoint) -> bool {
1618 self.raw.x == other.raw.x && self.raw.y == other.raw.y
1619 }
1620}
1621
1622impl Deref for FPoint {
1623 type Target = sys::SDL_FPoint;
1624
1625 fn deref(&self) -> &sys::SDL_FPoint {
1633 &self.raw
1634 }
1635}
1636
1637impl DerefMut for FPoint {
1638 fn deref_mut(&mut self) -> &mut sys::SDL_FPoint {
1647 &mut self.raw
1648 }
1649}
1650
1651impl AsRef<sys::SDL_FPoint> for FPoint {
1652 fn as_ref(&self) -> &sys::SDL_FPoint {
1653 &self.raw
1654 }
1655}
1656
1657impl AsMut<sys::SDL_FPoint> for FPoint {
1658 fn as_mut(&mut self) -> &mut sys::SDL_FPoint {
1659 &mut self.raw
1660 }
1661}
1662
1663impl From<sys::SDL_FPoint> for FPoint {
1664 fn from(prim: sys::SDL_FPoint) -> FPoint {
1665 FPoint { raw: prim }
1666 }
1667}
1668
1669impl From<(f32, f32)> for FPoint {
1670 fn from((x, y): (f32, f32)) -> FPoint {
1671 FPoint::new(x, y)
1672 }
1673}
1674
1675impl Into<sys::SDL_FPoint> for FPoint {
1676 fn into(self) -> sys::SDL_FPoint {
1677 self.raw
1678 }
1679}
1680
1681impl Into<(f32, f32)> for FPoint {
1682 fn into(self) -> (f32, f32) {
1683 (self.x(), self.y())
1684 }
1685}
1686
1687impl FPoint {
1688 pub fn new(x: f32, y: f32) -> FPoint {
1690 FPoint {
1691 raw: sys::SDL_FPoint { x, y },
1692 }
1693 }
1694
1695 pub fn from_ll(raw: sys::SDL_FPoint) -> FPoint {
1696 FPoint::new(raw.x, raw.y)
1697 }
1698
1699 #[doc(alias = "SDL_FPoint")]
1700 pub fn raw_slice(slice: &[FPoint]) -> *const sys::SDL_FPoint {
1701 slice.as_ptr() as *const sys::SDL_FPoint
1702 }
1703
1704 #[allow(clippy::trivially_copy_pass_by_ref)]
1707 pub fn raw(&self) -> *const sys::SDL_FPoint {
1708 &self.raw
1709 }
1710
1711 pub fn offset(self, x: f32, y: f32) -> FPoint {
1714 let x = self.raw.x + x;
1715 let y = self.raw.y + y;
1716 FPoint::new(x, y)
1717 }
1718
1719 pub fn scale(self, f: f32) -> FPoint {
1722 FPoint::new(self.raw.x * f, self.raw.y * f)
1723 }
1724
1725 pub fn x(self) -> f32 {
1727 self.raw.x
1728 }
1729
1730 pub fn y(self) -> f32 {
1732 self.raw.y
1733 }
1734}
1735
1736impl Add for FPoint {
1737 type Output = FPoint;
1738
1739 fn add(self, rhs: FPoint) -> FPoint {
1740 self.offset(rhs.x(), rhs.y())
1741 }
1742}
1743
1744impl AddAssign for FPoint {
1745 fn add_assign(&mut self, rhs: FPoint) {
1746 self.raw.x = self.x() + rhs.x();
1747 self.raw.y = self.y() + rhs.y();
1748 }
1749}
1750
1751impl Neg for FPoint {
1752 type Output = FPoint;
1753
1754 fn neg(self) -> FPoint {
1755 FPoint::new(-self.x(), -self.y())
1756 }
1757}
1758
1759impl Sub for FPoint {
1760 type Output = FPoint;
1761
1762 fn sub(self, rhs: FPoint) -> FPoint {
1763 self.offset(-rhs.x(), -rhs.y())
1764 }
1765}
1766
1767impl SubAssign for FPoint {
1768 fn sub_assign(&mut self, rhs: FPoint) {
1769 self.raw.x = self.x() - rhs.x();
1770 self.raw.y = self.y() - rhs.y();
1771 }
1772}
1773
1774impl Mul<f32> for FPoint {
1775 type Output = FPoint;
1776
1777 fn mul(self, rhs: f32) -> FPoint {
1778 self.scale(rhs)
1779 }
1780}
1781
1782impl MulAssign<f32> for FPoint {
1783 fn mul_assign(&mut self, rhs: f32) {
1784 self.raw.x = self.x() * rhs;
1785 self.raw.y = self.y() * rhs;
1786 }
1787}
1788
1789impl Div<f32> for FPoint {
1790 type Output = FPoint;
1791
1792 fn div(self, rhs: f32) -> FPoint {
1793 FPoint::new(self.x() / rhs, self.y() / rhs)
1794 }
1795}
1796
1797impl DivAssign<f32> for FPoint {
1798 fn div_assign(&mut self, rhs: f32) {
1799 self.raw.x /= rhs;
1800 self.raw.y /= rhs;
1801 }
1802}
1803
1804impl std::iter::Sum for FPoint {
1805 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1806 iter.fold(FPoint::new(0.0, 0.0), FPoint::add)
1807 }
1808}
1809
1810#[cfg(test)]
1811mod test {
1812 use super::{max_int_value, min_int_value, FPoint, FRect, Point, Rect};
1813
1814 fn tuple(x: i32, y: i32, w: u32, h: u32) -> (i32, i32, u32, u32) {
1816 (x, y, w, h)
1817 }
1818
1819 #[test]
1820 fn centered() {
1821 assert_eq!(
1823 Rect::new(0, 0, 10, 10).centered_on((0, 0)),
1824 Rect::new(-5, -5, 10, 10)
1825 );
1826 }
1827
1828 #[test]
1829 fn enclose_points_valid() {
1830 assert_eq!(
1831 Some(tuple(2, 4, 4, 6)),
1832 Rect::from_enclose_points(&[Point::new(2, 4), Point::new(5, 9)], None)
1833 .map(|r| r.into())
1834 );
1835 }
1836
1837 #[test]
1838 fn enclose_points_outside_clip_rect() {
1839 assert_eq!(
1840 Rect::from_enclose_points(
1841 &[Point::new(0, 0), Point::new(10, 10)],
1842 Some(Rect::new(3, 3, 1, 1))
1843 ),
1844 None
1845 );
1846 }
1847
1848 #[test]
1849 fn enclose_points_max_values() {
1850 assert_eq!(
1852 Some(tuple(
1853 min_int_value(),
1854 min_int_value(),
1855 max_int_value(),
1856 max_int_value()
1857 )),
1858 Rect::from_enclose_points(
1859 &[
1860 Point::new(i32::MIN, i32::MIN),
1861 Point::new(i32::MAX, i32::MAX)
1862 ],
1863 None
1864 )
1865 .map(|r| r.into())
1866 );
1867 }
1868
1869 #[test]
1870 fn has_intersection() {
1871 let rect = Rect::new(0, 0, 10, 10);
1872 assert!(rect.has_intersection(Rect::new(9, 9, 10, 10)));
1873 assert!(!rect.has_intersection(Rect::new(10, 10, 10, 10)));
1875 assert!(!rect.has_intersection(Rect::new(11, 11, 10, 10)));
1877 }
1878
1879 #[test]
1880 fn intersection() {
1881 let rect = Rect::new(0, 0, 10, 10);
1882 assert_eq!(rect & Rect::new(9, 9, 10, 10), Some(Rect::new(9, 9, 1, 1)));
1883 assert_eq!(rect & Rect::new(11, 11, 10, 10), None);
1884 }
1885
1886 #[test]
1887 fn union() {
1888 assert_eq!(
1889 Rect::new(0, 0, 1, 1) | Rect::new(9, 9, 1, 1),
1890 Rect::new(0, 0, 10, 10)
1891 );
1892 }
1893
1894 #[test]
1895 fn intersect_line() {
1896 assert_eq!(
1897 Rect::new(1, 1, 5, 5).intersect_line(Point::new(0, 0), Point::new(10, 10)),
1898 Some((Point::new(1, 1), Point::new(5, 5)))
1899 );
1900 }
1901
1902 #[test]
1903 fn clamp_size_zero() {
1904 assert_eq!(tuple(0, 0, 1, 1), Rect::new(0, 0, 0, 0).into());
1905 }
1906
1907 #[test]
1908 fn clamp_position_min() {
1909 assert_eq!(
1910 tuple(min_int_value(), min_int_value(), 1, 1),
1911 Rect::new(i32::MIN, i32::MIN, 1, 1).into()
1912 );
1913 }
1914
1915 #[test]
1916 fn clamp_size_max() {
1917 assert_eq!(
1918 tuple(0, 0, max_int_value(), max_int_value()),
1919 Rect::new(0, 0, max_int_value() + 1, max_int_value() + 1).into()
1920 );
1921 }
1922
1923 #[test]
1924 fn clamp_i32_max() {
1925 assert_eq!(
1926 tuple(0, 0, max_int_value(), max_int_value()),
1927 Rect::new(0, 0, i32::MAX as u32, i32::MAX as u32).into()
1928 )
1929 }
1930
1931 #[test]
1932 fn clamp_position_max() {
1933 assert_eq!(
1934 tuple(max_int_value() as i32, max_int_value() as i32, 1, 1),
1935 Rect::new(max_int_value() as i32 + 1, max_int_value() as i32 + 1, 1, 1).into()
1936 );
1937 }
1938
1939 #[test]
1940 fn shifted() {
1941 let rect = Rect::new(5, 5, 10, 10)
1943 .left_shifted(5)
1944 .right_shifted(5)
1945 .top_shifted(5)
1946 .bottom_shifted(5);
1947 assert_eq!(rect, Rect::new(5, 5, 10, 10));
1948 }
1949
1950 #[test]
1951 fn rect_into() {
1952 let test: (i32, i32, u32, u32) = (-11, 5, 50, 20);
1953 assert_eq!(test, Rect::new(-11, 5, 50, 20).into());
1954 }
1955
1956 #[test]
1957 fn rect_from() {
1958 assert_eq!(Rect::from((-11, 5, 50, 20)), Rect::new(-11, 5, 50, 20));
1959 }
1960
1961 #[test]
1962 fn point_into() {
1963 let test: (i32, i32) = (-11, 5);
1964 assert_eq!(test, Point::new(-11, 5).into());
1965 }
1966
1967 #[test]
1968 fn point_from() {
1969 let test: (i32, i32) = (-11, 5);
1970 assert_eq!(test, Point::new(-11, 5).into());
1971 }
1972
1973 #[test]
1974 fn point_add() {
1975 assert_eq!(Point::new(-5, 7), Point::new(-11, 5) + Point::new(6, 2));
1976 }
1977
1978 #[test]
1979 fn point_add_assign() {
1980 let mut point = Point::new(-11, 5);
1981 point += Point::new(6, 2);
1982 assert_eq!(point, Point::new(-11, 5) + Point::new(6, 2));
1983 }
1984
1985 #[test]
1986 fn point_sub() {
1987 assert_eq!(Point::new(-17, 3), Point::new(-11, 5) - Point::new(6, 2));
1988 }
1989
1990 #[test]
1991 fn point_sub_assign() {
1992 let mut point = Point::new(-11, 5);
1993 point -= Point::new(6, 2);
1994 assert_eq!(point, Point::new(-11, 5) - Point::new(6, 2));
1995 }
1996
1997 #[test]
1998 fn point_mul() {
1999 assert_eq!(Point::new(-33, 15), Point::new(-11, 5) * 3);
2000 }
2001
2002 #[test]
2003 fn point_mul_assign() {
2004 let mut point = Point::new(-11, 5);
2005 point *= 3;
2006 assert_eq!(point, Point::new(-11, 5) * 3);
2007 }
2008
2009 #[test]
2010 fn point_mul_clamp() {
2011 assert_eq!(
2012 Point::new(0x7fffffff, -0x7fffffff),
2013 Point::new(-1000000, 5000000) * -3000000
2014 );
2015 }
2016
2017 #[test]
2018 fn point_mul_assign_clamp() {
2019 let mut point = Point::new(-1000000, 5000000);
2020 point *= -3000000;
2021 assert_eq!(point, Point::new(-1000000, 5000000) * -3000000);
2022 }
2023
2024 #[test]
2025 fn point_div() {
2026 assert_eq!(Point::new(-3, 1), Point::new(-11, 5) / 3);
2027 }
2028
2029 #[test]
2030 fn point_div_assign() {
2031 let mut point = Point::new(-11, 5);
2032 point /= 3;
2033 assert_eq!(point, Point::new(-11, 5) / 3);
2034 }
2035
2036 #[test]
2037 fn point_sum() {
2038 let points_sum: Point = vec![Point::new(-11, 5), Point::new(6, 2)].into_iter().sum();
2039 assert_eq!(Point::new(-5, 7), points_sum);
2040 }
2041
2042 #[test]
2043 fn frect_centered() {
2044 assert_eq!(
2046 FRect::new(0.0, 0.0, 10.0, 10.0).centered_on((0.0, 0.0)),
2047 FRect::new(-5.0, -5.0, 10.0, 10.0)
2048 );
2049 }
2050
2051 #[test]
2052 fn frect_enclose_points_valid() {
2053 assert_eq!(
2054 Some((2.0, 4.0, 4.0, 6.0)),
2055 FRect::from_enclose_points(&[FPoint::new(2.0, 4.0), FPoint::new(5.0, 9.0)], None)
2056 .map(|r| r.into())
2057 );
2058 }
2059
2060 #[test]
2061 fn frect_enclose_points_outside_clip_rect() {
2062 assert_eq!(
2063 FRect::from_enclose_points(
2064 &[FPoint::new(0.0, 0.0), FPoint::new(10.0, 10.0)],
2065 Some(FRect::new(3.0, 3.0, 1.0, 1.0))
2066 ),
2067 None
2068 );
2069 }
2070
2071 #[test]
2072 fn frect_has_intersection() {
2073 let rect = FRect::new(0.0, 0.0, 10.0, 10.0);
2074 assert!(rect.has_intersection(FRect::new(9.0, 9.0, 10.0, 10.0)));
2075 assert!(!rect.has_intersection(FRect::new(10.0, 10.0, 10.0, 10.0)));
2077 assert!(!rect.has_intersection(FRect::new(11.0, 11.0, 10.0, 10.0)));
2079 }
2080
2081 #[test]
2082 fn frect_intersection() {
2083 let rect = FRect::new(0.0, 0.0, 10.0, 10.0);
2084 assert_eq!(
2085 rect & FRect::new(9.0, 9.0, 10.0, 10.0),
2086 Some(FRect::new(9.0, 9.0, 1.0, 1.0))
2087 );
2088 assert_eq!(rect & FRect::new(11.0, 11.0, 10.0, 10.0), None);
2089 }
2090
2091 #[test]
2092 fn frect_union() {
2093 assert_eq!(
2094 FRect::new(0.0, 0.0, 1.0, 1.0) | FRect::new(9.0, 9.0, 1.0, 1.0),
2095 FRect::new(0.0, 0.0, 10.0, 10.0)
2096 );
2097 }
2098
2099 #[test]
2100 fn frect_intersect_line() {
2101 assert_eq!(
2102 FRect::new(1.0, 1.0, 5.0, 5.0)
2103 .intersect_line(FPoint::new(0.0, 0.0), FPoint::new(10.0, 10.0)),
2104 Some((FPoint::new(1.0, 1.0), FPoint::new(5.0, 5.0)))
2105 );
2106 }
2107
2108 #[test]
2109 fn frect_shifted() {
2110 let rect = FRect::new(0.0, 0.0, 10.0, 10.0)
2112 .left_shifted(5.0)
2113 .right_shifted(5.0)
2114 .top_shifted(5.0)
2115 .bottom_shifted(5.0);
2116 assert_eq!(rect, FRect::new(0.0, 0.0, 10.0, 10.0));
2117 }
2118
2119 #[test]
2120 fn frect_into() {
2121 let test: (f32, f32, f32, f32) = (-11.0, 5.0, 50.0, 20.0);
2122 assert_eq!(test, FRect::new(-11.0, 5.0, 50.0, 20.0).into());
2123 }
2124
2125 #[test]
2126 fn frect_from() {
2127 assert_eq!(
2128 FRect::from((-11.0, 5.0, 50.0, 20.0)),
2129 FRect::new(-11.0, 5.0, 50.0, 20.0)
2130 );
2131 }
2132
2133 #[test]
2134 fn fpoint_into() {
2135 let test: (f32, f32) = (-11.0, 5.0);
2136 assert_eq!(test, FPoint::new(-11.0, 5.0).into());
2137 }
2138
2139 #[test]
2140 fn fpoint_from() {
2141 let test: (f32, f32) = (-11.0, 5.0);
2142 assert_eq!(test, FPoint::new(-11.0, 5.0).into());
2143 }
2144
2145 #[test]
2146 fn fpoint_add() {
2147 assert_eq!(
2148 FPoint::new(-5.0, 7.0),
2149 FPoint::new(-11.0, 5.0) + FPoint::new(6.0, 2.0)
2150 );
2151 }
2152
2153 #[test]
2154 fn fpoint_add_assign() {
2155 let mut point = FPoint::new(-11.0, 5.0);
2156 point += FPoint::new(6.0, 2.0);
2157 assert_eq!(point, FPoint::new(-11.0, 5.0) + FPoint::new(6.0, 2.0));
2158 }
2159
2160 #[test]
2161 fn fpoint_sub() {
2162 assert_eq!(
2163 FPoint::new(-17.0, 3.0),
2164 FPoint::new(-11.0, 5.0) - FPoint::new(6.0, 2.0)
2165 );
2166 }
2167
2168 #[test]
2169 fn fpoint_sub_assign() {
2170 let mut point = FPoint::new(-11.0, 5.0);
2171 point -= FPoint::new(6.0, 2.0);
2172 assert_eq!(point, FPoint::new(-11.0, 5.0) - FPoint::new(6.0, 2.0));
2173 }
2174
2175 #[test]
2176 fn fpoint_mul() {
2177 assert_eq!(FPoint::new(-33.0, 15.0), FPoint::new(-11.0, 5.0) * 3.0);
2178 }
2179
2180 #[test]
2181 fn fpoint_mul_assign() {
2182 let mut point = FPoint::new(-11.0, 5.0);
2183 point *= 3.0;
2184 assert_eq!(point, FPoint::new(-11.0, 5.0) * 3.0);
2185 }
2186
2187 #[test]
2188 fn fpoint_div() {
2189 assert_eq!(FPoint::new(-3.0, 1.0), FPoint::new(-9.0, 3.0) / 3.0);
2190 }
2191
2192 #[test]
2193 fn fpoint_div_assign() {
2194 let mut point = FPoint::new(-11.0, 5.0);
2195 point /= 3.0;
2196 assert_eq!(point, FPoint::new(-11.0, 5.0) / 3.0);
2197 }
2198
2199 #[test]
2200 fn fpoint_sum() {
2201 let points_sum: FPoint = vec![FPoint::new(-11.0, 5.0), FPoint::new(6.0, 2.0)]
2202 .into_iter()
2203 .sum();
2204 assert_eq!(FPoint::new(-5.0, 7.0), points_sum);
2205 }
2206}