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