1 // Copyright 2017 The Servo Project Developers. See the COPYRIGHT 2 // file at the top-level directory of this distribution. 3 // 4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 7 // option. This file may not be copied, modified, or distributed 8 // except according to those terms. 9 10 pub use sys::CGPathRef as SysCGPathRef; 11 12 use core_foundation::base::{CFRelease, CFRetain, CFTypeID}; 13 use foreign_types::ForeignType; 14 use geometry::{CGAffineTransform, CGPoint, CGRect}; 15 use libc::c_void; 16 use std::fmt::{self, Debug, Formatter}; 17 use std::marker::PhantomData; 18 use std::ops::Deref; 19 use std::ptr; 20 use std::slice; 21 22 foreign_type! { 23 #[doc(hidden)] 24 type CType = ::sys::CGPath; 25 fn drop = |p| CFRelease(p as *mut _); 26 fn clone = |p| CFRetain(p as *const _) as *mut _; 27 pub struct CGPath; 28 pub struct CGPathRef; 29 } 30 31 impl CGPath { from_rect(rect: CGRect, transform: Option<&CGAffineTransform>) -> CGPath32 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(CGPathCreateWithRect(rect, transform)) 39 } 40 } 41 type_id() -> CFTypeID42 pub fn type_id() -> CFTypeID { 43 unsafe { 44 CGPathGetTypeID() 45 } 46 } 47 apply<'a, F>(&'a self, mut closure: &'a F) where F: FnMut(CGPathElementRef<'a>)48 pub fn apply<'a, F>(&'a self, mut closure: &'a F) where F: FnMut(CGPathElementRef<'a>) { 49 unsafe { 50 CGPathApply(self.as_ptr(), &mut closure as *mut _ as *mut c_void, do_apply::<F>); 51 } 52 53 unsafe extern "C" fn do_apply<'a, F>(info: *mut c_void, element: *const CGPathElement) 54 where F: FnMut(CGPathElementRef<'a>) { 55 let closure = info as *mut *mut F; 56 (**closure)(CGPathElementRef::new(element)) 57 } 58 } 59 } 60 61 #[repr(i32)] 62 #[derive(Clone, Copy, Debug, PartialEq)] 63 pub enum CGPathElementType { 64 MoveToPoint = 0, 65 AddLineToPoint = 1, 66 AddQuadCurveToPoint = 2, 67 AddCurveToPoint = 3, 68 CloseSubpath = 4, 69 } 70 71 pub struct CGPathElementRef<'a> { 72 element: *const CGPathElement, 73 phantom: PhantomData<&'a CGPathElement>, 74 } 75 76 impl<'a> CGPathElementRef<'a> { new<'b>(element: *const CGPathElement) -> CGPathElementRef<'b>77 fn new<'b>(element: *const CGPathElement) -> CGPathElementRef<'b> { 78 CGPathElementRef { 79 element: element, 80 phantom: PhantomData, 81 } 82 } 83 } 84 85 impl<'a> Deref for CGPathElementRef<'a> { 86 type Target = CGPathElement; deref(&self) -> &CGPathElement87 fn deref(&self) -> &CGPathElement { 88 unsafe { 89 &*self.element 90 } 91 } 92 } 93 94 #[repr(C)] 95 pub struct CGPathElement { 96 pub element_type: CGPathElementType, 97 points: *mut CGPoint, 98 } 99 100 impl Debug for CGPathElement { fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error>101 fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> { 102 write!(formatter, "{:?}: {:?}", self.element_type, self.points()) 103 } 104 } 105 106 impl CGPathElement { points(&self) -> &[CGPoint]107 pub fn points(&self) -> &[CGPoint] { 108 unsafe { 109 match self.element_type { 110 CGPathElementType::CloseSubpath => &[], 111 CGPathElementType::MoveToPoint | CGPathElementType::AddLineToPoint => { 112 slice::from_raw_parts(self.points, 1) 113 } 114 CGPathElementType::AddQuadCurveToPoint => slice::from_raw_parts(self.points, 2), 115 CGPathElementType::AddCurveToPoint => slice::from_raw_parts(self.points, 3), 116 } 117 } 118 } 119 } 120 121 type CGPathApplierFunction = unsafe extern "C" fn(info: *mut c_void, 122 element: *const CGPathElement); 123 124 #[link(name = "CoreGraphics", kind = "framework")] 125 extern { CGPathCreateWithRect(rect: CGRect, transform: *const CGAffineTransform) -> ::sys::CGPathRef126 fn CGPathCreateWithRect(rect: CGRect, transform: *const CGAffineTransform) -> ::sys::CGPathRef; CGPathApply(path: ::sys::CGPathRef, info: *mut c_void, function: CGPathApplierFunction)127 fn CGPathApply(path: ::sys::CGPathRef, info: *mut c_void, function: CGPathApplierFunction); CGPathGetTypeID() -> CFTypeID128 fn CGPathGetTypeID() -> CFTypeID; 129 } 130