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);