1pub use crate::sys::CGPathRef as SysCGPathRef;
11
12use crate::geometry::{CGAffineTransform, CGPoint, CGRect};
13use core_foundation::base::{CFRelease, CFRetain, CFTypeID};
14use foreign_types::{foreign_type, ForeignType};
15use libc::c_void;
16use std::fmt::{self, Debug, Formatter};
17use std::marker::PhantomData;
18use std::ops::Deref;
19use std::ptr;
20use std::slice;
21
22foreign_type! {
23 #[doc(hidden)]
24 pub unsafe type CGPath {
25 type CType = crate::sys::CGPath;
26 fn drop = |p| CFRelease(p as *mut _);
27 fn clone = |p| CFRetain(p as *const _) as *mut _;
28 }
29}
30
31impl CGPath {
32 pub fn from_rect(rect: CGRect, transform: Option<&CGAffineTransform>) -> CGPath {
33 unsafe {
34 let transform = match transform {
35 None => ptr::null(),
36 Some(transform) => transform as *const CGAffineTransform,
37 };
38 CGPath::from_ptr(CGPathCreateWithRect(rect, transform))
39 }
40 }
41
42 pub fn type_id() -> CFTypeID {
43 unsafe { CGPathGetTypeID() }
44 }
45
46 pub fn apply<'a, F>(&'a self, mut closure: &'a F)
47 where
48 F: FnMut(CGPathElementRef<'a>),
49 {
50 unsafe {
51 CGPathApply(
52 self.as_ptr(),
53 &mut closure as *mut _ as *mut c_void,
54 do_apply::<F>,
55 );
56 }
57
58 unsafe extern "C" fn do_apply<'a, F>(info: *mut c_void, element: *const CGPathElement)
59 where
60 F: FnMut(CGPathElementRef<'a>),
61 {
62 let closure = info as *mut *mut F;
63 (**closure)(CGPathElementRef::new(element))
64 }
65 }
66}
67
68#[repr(i32)]
69#[derive(Clone, Copy, Debug, PartialEq)]
70pub enum CGPathElementType {
71 MoveToPoint = 0,
72 AddLineToPoint = 1,
73 AddQuadCurveToPoint = 2,
74 AddCurveToPoint = 3,
75 CloseSubpath = 4,
76}
77
78pub struct CGPathElementRef<'a> {
79 element: *const CGPathElement,
80 phantom: PhantomData<&'a CGPathElement>,
81}
82
83impl<'a> CGPathElementRef<'a> {
84 fn new<'b>(element: *const CGPathElement) -> CGPathElementRef<'b> {
85 CGPathElementRef {
86 element,
87 phantom: PhantomData,
88 }
89 }
90}
91
92impl<'a> Deref for CGPathElementRef<'a> {
93 type Target = CGPathElement;
94 fn deref(&self) -> &CGPathElement {
95 unsafe { &*self.element }
96 }
97}
98
99#[repr(C)]
100pub struct CGPathElement {
101 pub element_type: CGPathElementType,
102 points: *mut CGPoint,
103}
104
105impl Debug for CGPathElement {
106 fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
107 write!(formatter, "{:?}: {:?}", self.element_type, self.points())
108 }
109}
110
111impl CGPathElement {
112 pub fn points(&self) -> &[CGPoint] {
113 unsafe {
114 match self.element_type {
115 CGPathElementType::CloseSubpath => &[],
116 CGPathElementType::MoveToPoint | CGPathElementType::AddLineToPoint => {
117 slice::from_raw_parts(self.points, 1)
118 }
119 CGPathElementType::AddQuadCurveToPoint => slice::from_raw_parts(self.points, 2),
120 CGPathElementType::AddCurveToPoint => slice::from_raw_parts(self.points, 3),
121 }
122 }
123 }
124}
125
126type CGPathApplierFunction = unsafe extern "C" fn(info: *mut c_void, element: *const CGPathElement);
127
128#[cfg_attr(feature = "link", link(name = "CoreGraphics", kind = "framework"))]
129extern "C" {
130 fn CGPathCreateWithRect(
131 rect: CGRect,
132 transform: *const CGAffineTransform,
133 ) -> crate::sys::CGPathRef;
134 fn CGPathApply(path: crate::sys::CGPathRef, info: *mut c_void, function: CGPathApplierFunction);
135 fn CGPathGetTypeID() -> CFTypeID;
136}