1 // Copyright 2013 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 use core_foundation::base::{CFRelease, CFRetain, CFTypeID, TCFType};
11 use core_foundation::data::{CFData, CFDataRef};
12 
13 use libc::{size_t, off_t};
14 use std::mem;
15 use std::ptr;
16 use std::sync::Arc;
17 use std::os::raw::c_void;
18 
19 use foreign_types::{ForeignType, ForeignTypeRef};
20 
21 pub type CGDataProviderGetBytesCallback = Option<unsafe extern fn (*mut c_void, *mut c_void, size_t) -> size_t>;
22 pub type CGDataProviderReleaseInfoCallback = Option<unsafe extern fn (*mut c_void)>;
23 pub type CGDataProviderRewindCallback = Option<unsafe extern fn (*mut c_void)>;
24 pub type CGDataProviderSkipBytesCallback = Option<unsafe extern fn (*mut c_void, size_t)>;
25 pub type CGDataProviderSkipForwardCallback = Option<unsafe extern fn (*mut c_void, off_t) -> off_t>;
26 
27 pub type CGDataProviderGetBytePointerCallback = Option<unsafe extern fn (*mut c_void) -> *mut c_void>;
28 pub type CGDataProviderGetBytesAtOffsetCallback = Option<unsafe extern fn (*mut c_void, *mut c_void, size_t, size_t)>;
29 pub type CGDataProviderReleaseBytePointerCallback = Option<unsafe extern fn (*mut c_void, *const c_void)>;
30 pub type CGDataProviderReleaseDataCallback = Option<unsafe extern fn (*mut c_void, *const c_void, size_t)>;
31 pub type CGDataProviderGetBytesAtPositionCallback = Option<unsafe extern fn (*mut c_void, *mut c_void, off_t, size_t)>;
32 
33 foreign_type! {
34     #[doc(hidden)]
35     type CType = ::sys::CGDataProvider;
36     fn drop = |cs| CFRelease(cs as *mut _);
37     fn clone = |p| CFRetain(p as *const _) as *mut _;
38     pub struct CGDataProvider;
39     pub struct CGDataProviderRef;
40 }
41 
42 impl CGDataProvider {
type_id() -> CFTypeID43     pub fn type_id() -> CFTypeID {
44         unsafe {
45             CGDataProviderGetTypeID()
46         }
47     }
48 
49     /// Creates a data provider from the given reference-counted buffer.
50     ///
51     /// The `CGDataProvider` object takes ownership of the reference. Once the data provider
52     /// is destroyed, the reference count of the buffer is automatically decremented.
from_buffer(buffer: Arc<Vec<u8>>) -> Self53     pub fn from_buffer(buffer: Arc<Vec<u8>>) -> Self {
54         unsafe {
55             let ptr = (*buffer).as_ptr() as *const c_void;
56             let len = buffer.len() as size_t;
57             let info = mem::transmute::<Arc<Vec<u8>>, *mut c_void>(buffer);
58             let result = CGDataProviderCreateWithData(info, ptr, len, Some(release));
59             return CGDataProvider::from_ptr(result);
60         }
61 
62         unsafe extern "C" fn release(info: *mut c_void, _: *const c_void, _: size_t) {
63             drop(mem::transmute::<*mut c_void, Arc<Vec<u8>>>(info))
64         }
65     }
66 
67     /// Creates a data prvider from a given slice. The data provider does not own the slice in this
68     /// case, so it's up to the user to ensure the memory safety here.
from_slice(buffer: &[u8]) -> Self69     pub unsafe fn from_slice(buffer: &[u8]) -> Self {
70         let ptr = buffer.as_ptr() as *const c_void;
71         let len = buffer.len() as size_t;
72         let result = CGDataProviderCreateWithData(ptr::null_mut(), ptr, len, None);
73         CGDataProvider::from_ptr(result)
74     }
75 
76     /// Creates a data provider from the given raw pointer, length, and destructor function.
77     ///
78     /// This is double-boxed because the Core Text API requires that the userdata be a single
79     /// pointer.
from_custom_data(custom_data: Box<Box<dyn CustomData>>) -> Self80     pub unsafe fn from_custom_data(custom_data: Box<Box<dyn CustomData>>) -> Self {
81         let (ptr, len) = (custom_data.ptr() as *const c_void, custom_data.len());
82         let userdata = mem::transmute::<Box<Box<dyn CustomData>>, &mut c_void>(custom_data);
83         let data_provider = CGDataProviderCreateWithData(userdata, ptr, len, Some(release));
84         return CGDataProvider::from_ptr(data_provider);
85 
86         unsafe extern "C" fn release(info: *mut c_void, _: *const c_void, _: size_t) {
87             drop(mem::transmute::<*mut c_void, Box<Box<dyn CustomData>>>(info))
88         }
89     }
90 }
91 
92 impl CGDataProviderRef {
93     /// Creates a copy of the data from the underlying `CFDataProviderRef`.
copy_data(&self) -> CFData94     pub fn copy_data(&self) -> CFData {
95         unsafe { CFData::wrap_under_create_rule(CGDataProviderCopyData(self.as_ptr())) }
96     }
97 }
98 
99 /// Encapsulates custom data that can be wrapped.
100 pub trait CustomData {
101     /// Returns a pointer to the start of the custom data. This pointer *must not change* during
102     /// the lifespan of this CustomData.
ptr(&self) -> *const u8103     unsafe fn ptr(&self) -> *const u8;
104     /// Returns the length of this custom data. This value must not change during the lifespan of
105     /// this CustomData.
len(&self) -> usize106     unsafe fn len(&self) -> usize;
107 }
108 
109 #[link(name = "CoreGraphics", kind = "framework")]
110 extern {
CGDataProviderCopyData(provider: ::sys::CGDataProviderRef) -> CFDataRef111     fn CGDataProviderCopyData(provider: ::sys::CGDataProviderRef) -> CFDataRef;
112     //fn CGDataProviderCreateDirect
113     //fn CGDataProviderCreateSequential
114     //fn CGDataProviderCreateWithCFData
CGDataProviderCreateWithData(info: *mut c_void, data: *const c_void, size: size_t, releaseData: CGDataProviderReleaseDataCallback ) -> ::sys::CGDataProviderRef115     fn CGDataProviderCreateWithData(info: *mut c_void,
116                                     data: *const c_void,
117                                     size: size_t,
118                                     releaseData: CGDataProviderReleaseDataCallback
119                                    ) -> ::sys::CGDataProviderRef;
120     //fn CGDataProviderCreateWithFilename(filename: *c_char) -> CGDataProviderRef;
121     //fn CGDataProviderCreateWithURL
CGDataProviderGetTypeID() -> CFTypeID122     fn CGDataProviderGetTypeID() -> CFTypeID;
123     //fn CGDataProviderRelease(provider: CGDataProviderRef);
124     //fn CGDataProviderRetain(provider: CGDataProviderRef) -> CGDataProviderRef;
125 }
126