core_graphics2/
geometry.rs

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