Skip to main content

core_graphics2/
geometry.rs

1use cfg_if::cfg_if;
2use core_foundation::{
3    base::TCFType,
4    dictionary::{CFDictionary, CFDictionaryRef},
5};
6#[cfg(feature = "objc")]
7use objc2::encode::{Encode, Encoding, RefEncode};
8
9use crate::{affine_transform::*, base::CGFloat};
10
11#[repr(C)]
12#[derive(Clone, Copy, Debug, Default, PartialEq)]
13pub struct CGPoint {
14    pub x: CGFloat,
15    pub y: CGFloat,
16}
17
18#[repr(C)]
19#[derive(Clone, Copy, Debug, Default, PartialEq)]
20pub struct CGSize {
21    pub width: CGFloat,
22    pub height: CGFloat,
23}
24
25#[repr(C)]
26#[derive(Clone, Copy, Debug, Default, PartialEq)]
27pub struct CGVector {
28    pub dx: CGFloat,
29    pub dy: CGFloat,
30}
31
32#[repr(C)]
33#[derive(Clone, Copy, Debug, Default, PartialEq)]
34pub struct CGRect {
35    pub origin: CGPoint,
36    pub size: CGSize,
37}
38
39#[repr(u32)]
40#[derive(Clone, Copy, Debug, Eq, PartialEq)]
41pub enum CGRectEdge {
42    #[doc(alias = "CGRectMinXEdge")]
43    MinX,
44    #[doc(alias = "CGRectMinYEdge")]
45    MinY,
46    #[doc(alias = "CGRectMaxXEdge")]
47    MaxX,
48    #[doc(alias = "CGRectMaxYEdge")]
49    MaxY,
50}
51
52pub const CGPointZero: CGPoint = CGPoint {
53    x: 0.0,
54    y: 0.0,
55};
56pub const CGSizeZero: CGSize = CGSize {
57    width: 0.0,
58    height: 0.0,
59};
60pub const CGRectZero: CGRect = CGRect {
61    origin: CGPointZero,
62    size: CGSizeZero,
63};
64pub const CGRectNull: CGRect = CGRect {
65    origin: CGPoint {
66        x: CGFloat::MAX,
67        y: CGFloat::MAX,
68    },
69    size: CGSizeZero,
70};
71pub const CGRectInfinite: CGRect = CGRect {
72    origin: CGPoint {
73        x: CGFloat::MIN,
74        y: CGFloat::MIN,
75    },
76    size: CGSize {
77        width: CGFloat::MAX,
78        height: CGFloat::MAX,
79    },
80};
81
82extern "C" {
83    pub fn CGRectGetMinX(rect: CGRect) -> CGFloat;
84    pub fn CGRectGetMidX(rect: CGRect) -> CGFloat;
85    pub fn CGRectGetMaxX(rect: CGRect) -> CGFloat;
86    pub fn CGRectGetMinY(rect: CGRect) -> CGFloat;
87    pub fn CGRectGetMidY(rect: CGRect) -> CGFloat;
88    pub fn CGRectGetMaxY(rect: CGRect) -> CGFloat;
89    pub fn CGRectGetWidth(rect: CGRect) -> CGFloat;
90    pub fn CGRectGetHeight(rect: CGRect) -> CGFloat;
91    pub fn CGRectStandardize(rect: CGRect) -> CGRect;
92    pub fn CGRectIsEmpty(rect: CGRect) -> bool;
93    pub fn CGRectIsNull(rect: CGRect) -> bool;
94    pub fn CGRectIsInfinite(rect: CGRect) -> bool;
95    pub fn CGRectInset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect;
96    pub fn CGRectIntegral(rect: CGRect) -> CGRect;
97    pub fn CGRectUnion(rect1: CGRect, rect2: CGRect) -> CGRect;
98    pub fn CGRectIntersection(rect1: CGRect, rect2: CGRect) -> CGRect;
99    pub fn CGRectOffset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect;
100    pub fn CGRectDivide(rect: CGRect, slice: *mut CGRect, remainder: *mut CGRect, amount: CGFloat, edge: CGRectEdge);
101    pub fn CGRectContainsPoint(rect: CGRect, point: CGPoint) -> bool;
102    pub fn CGRectContainsRect(rect1: CGRect, rect2: CGRect) -> bool;
103    pub fn CGRectIntersectsRect(rect1: CGRect, rect2: CGRect) -> bool;
104    pub fn CGPointCreateDictionaryRepresentation(point: CGPoint) -> CFDictionaryRef;
105    pub fn CGPointMakeWithDictionaryRepresentation(dict: CFDictionaryRef, point: *mut CGPoint) -> bool;
106    pub fn CGSizeCreateDictionaryRepresentation(size: CGSize) -> CFDictionaryRef;
107    pub fn CGSizeMakeWithDictionaryRepresentation(dict: CFDictionaryRef, size: *mut CGSize) -> bool;
108    pub fn CGRectCreateDictionaryRepresentation(rect: CGRect) -> CFDictionaryRef;
109    pub fn CGRectMakeWithDictionaryRepresentation(dict: CFDictionaryRef, rect: *mut CGRect) -> bool;
110}
111
112impl CGPoint {
113    pub fn new(x: CGFloat, y: CGFloat) -> CGPoint {
114        CGPoint {
115            x,
116            y,
117        }
118    }
119
120    pub fn from_dict_representation(dict: &CFDictionary) -> Option<Self> {
121        let mut point = CGPoint::default();
122        let result = unsafe { CGPointMakeWithDictionaryRepresentation(dict.as_concrete_TypeRef(), &mut point) };
123        if result {
124            Some(point)
125        } else {
126            None
127        }
128    }
129
130    pub fn apply_transform(&self, transform: &CGAffineTransform) -> CGPoint {
131        unsafe { CGPointApplyAffineTransform(*self, *transform) }
132    }
133}
134
135impl CGSize {
136    pub fn new(width: CGFloat, height: CGFloat) -> CGSize {
137        CGSize {
138            width,
139            height,
140        }
141    }
142
143    pub fn from_dict_representation(dict: &CFDictionary) -> Option<Self> {
144        let mut size = CGSize::default();
145        let result = unsafe { CGSizeMakeWithDictionaryRepresentation(dict.as_concrete_TypeRef(), &mut size) };
146        if result {
147            Some(size)
148        } else {
149            None
150        }
151    }
152
153    pub fn apply_transform(&self, transform: &CGAffineTransform) -> CGSize {
154        unsafe { CGSizeApplyAffineTransform(*self, *transform) }
155    }
156}
157
158impl CGRect {
159    pub fn new(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) -> CGRect {
160        CGRect {
161            origin: CGPoint::new(x, y),
162            size: CGSize::new(width, height),
163        }
164    }
165
166    pub fn from_dict_representation(dict: &CFDictionary) -> Option<Self> {
167        let mut rect = CGRect::default();
168        let result = unsafe { CGRectMakeWithDictionaryRepresentation(dict.as_concrete_TypeRef(), &mut rect) };
169        if result {
170            Some(rect)
171        } else {
172            None
173        }
174    }
175
176    pub fn min(&self) -> (CGFloat, CGFloat) {
177        unsafe { (CGRectGetMinX(*self), CGRectGetMinY(*self)) }
178    }
179    pub fn mid(&self) -> (CGFloat, CGFloat) {
180        unsafe { (CGRectGetMidX(*self), CGRectGetMidY(*self)) }
181    }
182
183    pub fn max(&self) -> (CGFloat, CGFloat) {
184        unsafe { (CGRectGetMaxX(*self), CGRectGetMaxY(*self)) }
185    }
186
187    pub fn width(&self) -> CGFloat {
188        unsafe { CGRectGetWidth(*self) }
189    }
190
191    pub fn height(&self) -> CGFloat {
192        unsafe { CGRectGetHeight(*self) }
193    }
194
195    pub fn standardize(&self) -> CGRect {
196        unsafe { CGRectStandardize(*self) }
197    }
198
199    pub fn is_empty(&self) -> bool {
200        unsafe { CGRectIsEmpty(*self) }
201    }
202
203    pub fn is_null(&self) -> bool {
204        unsafe { CGRectIsNull(*self) }
205    }
206
207    pub fn is_infinite(&self) -> bool {
208        unsafe { CGRectIsInfinite(*self) }
209    }
210
211    pub fn inset(&self, dx: CGFloat, dy: CGFloat) -> CGRect {
212        unsafe { CGRectInset(*self, dx, dy) }
213    }
214
215    pub fn integral(&self) -> CGRect {
216        unsafe { CGRectIntegral(*self) }
217    }
218
219    pub fn union(&self, rect: &CGRect) -> CGRect {
220        unsafe { CGRectUnion(*self, *rect) }
221    }
222
223    pub fn intersection(&self, rect: &CGRect) -> CGRect {
224        unsafe { CGRectIntersection(*self, *rect) }
225    }
226
227    pub fn offset(&self, dx: CGFloat, dy: CGFloat) -> CGRect {
228        unsafe { CGRectOffset(*self, dx, dy) }
229    }
230
231    pub fn divide(&self, slice: &mut CGRect, remainder: &mut CGRect, amount: CGFloat, edge: CGRectEdge) {
232        unsafe { CGRectDivide(*self, slice, remainder, amount, edge) }
233    }
234
235    pub fn contains_point(&self, point: &CGPoint) -> bool {
236        unsafe { CGRectContainsPoint(*self, *point) }
237    }
238
239    pub fn contains_rect(&self, rect: &CGRect) -> bool {
240        unsafe { CGRectContainsRect(*self, *rect) }
241    }
242
243    pub fn intersects_rect(&self, rect: &CGRect) -> bool {
244        unsafe { CGRectIntersectsRect(*self, *rect) }
245    }
246
247    pub fn apply_transform(&self, transform: &CGAffineTransform) -> CGRect {
248        unsafe { CGRectApplyAffineTransform(*self, *transform) }
249    }
250}
251
252cfg_if!(
253    if #[cfg(feature = "objc")] {
254        unsafe impl Encode for CGPoint {
255            const ENCODING: Encoding =
256                Encoding::Struct("CGPoint", &[CGFloat::ENCODING, CGFloat::ENCODING]);
257        }
258
259        unsafe impl RefEncode for CGPoint {
260            const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
261        }
262
263        unsafe impl Encode for CGSize {
264            const ENCODING: Encoding =
265                Encoding::Struct("CGSize", &[CGFloat::ENCODING, CGFloat::ENCODING]);
266        }
267
268        unsafe impl RefEncode for CGSize {
269            const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
270        }
271
272        unsafe impl Encode for CGVector {
273            const ENCODING: Encoding =
274                Encoding::Struct("CGVector", &[CGFloat::ENCODING, CGFloat::ENCODING]);
275        }
276
277        unsafe impl RefEncode for CGVector {
278            const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
279        }
280
281        unsafe impl Encode for CGRect {
282            const ENCODING: Encoding =
283                Encoding::Struct("CGRect", &[CGPoint::ENCODING, CGSize::ENCODING]);
284        }
285
286        unsafe impl RefEncode for CGRect {
287            const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
288        }
289    }
290);