apple_cf/cg/size.rs
1//! `CGSize` type for 2D dimensions
2
3use std::fmt;
4
5/// `CGSize` representation
6///
7/// Represents a 2D size with width and height.
8///
9/// # Examples
10///
11/// ```
12/// use apple_cf::cg::CGSize;
13///
14/// let size = CGSize::new(1920.0, 1080.0);
15/// assert_eq!(size.aspect_ratio(), 1920.0 / 1080.0);
16/// assert_eq!(size.area(), 1920.0 * 1080.0);
17/// ```
18#[repr(C)]
19#[derive(Debug, Clone, Copy, PartialEq)]
20pub struct CGSize {
21 pub width: f64,
22 pub height: f64,
23}
24
25impl std::hash::Hash for CGSize {
26 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
27 self.width.to_bits().hash(state);
28 self.height.to_bits().hash(state);
29 }
30}
31
32impl Eq for CGSize {}
33
34impl CGSize {
35 /// Create a new size
36 ///
37 /// # Examples
38 ///
39 /// ```
40 /// use apple_cf::cg::CGSize;
41 ///
42 /// let size = CGSize::new(800.0, 600.0);
43 /// assert_eq!(size.width, 800.0);
44 /// ```
45 #[must_use]
46 pub const fn new(width: f64, height: f64) -> Self {
47 Self { width, height }
48 }
49
50 /// Create a zero-sized size
51 ///
52 /// # Examples
53 ///
54 /// ```
55 /// use apple_cf::cg::CGSize;
56 ///
57 /// let size = CGSize::zero();
58 /// assert!(size.is_null());
59 /// ```
60 #[must_use]
61 pub const fn zero() -> Self {
62 Self::new(0.0, 0.0)
63 }
64
65 /// Get the area (width * height)
66 #[must_use]
67 pub const fn area(&self) -> f64 {
68 self.width * self.height
69 }
70
71 /// Get the aspect ratio (width / height)
72 #[must_use]
73 pub fn aspect_ratio(&self) -> f64 {
74 if self.height == 0.0 {
75 0.0
76 } else {
77 self.width / self.height
78 }
79 }
80
81 /// Check if this is a square (width == height)
82 /// Note: Uses exact comparison, may not work well with computed values
83 #[allow(clippy::float_cmp)]
84 #[must_use]
85 pub const fn is_square(&self) -> bool {
86 self.width == self.height
87 }
88
89 /// Returns whether the size has a non-positive width or height.
90 #[must_use]
91 pub fn is_empty(&self) -> bool {
92 self.width <= 0.0 || self.height <= 0.0
93 }
94
95 /// Check if size is null (both dimensions are zero)
96 #[must_use]
97 pub const fn is_null(&self) -> bool {
98 self.width == 0.0 && self.height == 0.0
99 }
100}
101
102impl Default for CGSize {
103 fn default() -> Self {
104 Self::zero()
105 }
106}
107
108impl fmt::Display for CGSize {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 write!(f, "{}x{}", self.width, self.height)
111 }
112}