Skip to main content

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    #[must_use] 
90    pub fn is_empty(&self) -> bool {
91        self.width <= 0.0 || self.height <= 0.0
92    }
93
94    /// Check if size is null (both dimensions are zero)
95    #[must_use] 
96    pub const fn is_null(&self) -> bool {
97        self.width == 0.0 && self.height == 0.0
98    }
99}
100
101impl Default for CGSize {
102    fn default() -> Self {
103        Self::zero()
104    }
105}
106
107impl fmt::Display for CGSize {
108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109        write!(f, "{}x{}", self.width, self.height)
110    }
111}