Skip to main content

core_graphics2/
function.rs

1use std::ptr::null;
2
3use core_foundation::{
4    base::{CFTypeID, TCFType},
5    impl_CFTypeDescription, impl_TCFType,
6};
7use libc::c_void;
8
9use crate::base::CGFloat;
10
11#[repr(C)]
12pub struct __CGFunction(c_void);
13
14pub type CGFunctionRef = *const __CGFunction;
15
16pub type CGFunctionEvaluateCallback = extern "C" fn(*const c_void, *const CGFloat, *mut CGFloat);
17pub type CGFunctionReleaseInfoCallback = extern "C" fn(*mut c_void);
18
19#[repr(C)]
20pub struct CGFunctionCallbacks {
21    pub version: u32,
22    pub evaluate: CGFunctionEvaluateCallback,
23    pub releaseInfo: CGFunctionReleaseInfoCallback,
24}
25
26extern "C" {
27    pub fn CGFunctionGetTypeID() -> CFTypeID;
28    pub fn CGFunctionCreate(
29        info: *mut c_void,
30        domainDimension: usize,
31        domain: *const CGFloat,
32        rangeDimension: usize,
33        range: *const CGFloat,
34        callbacks: *const CGFunctionCallbacks,
35    ) -> CGFunctionRef;
36    pub fn CGFunctionRetain(function: CGFunctionRef) -> CGFunctionRef;
37    pub fn CGFunctionRelease(function: CGFunctionRef);
38}
39
40pub struct CGFunction(CGFunctionRef);
41
42impl Drop for CGFunction {
43    fn drop(&mut self) {
44        unsafe { CGFunctionRelease(self.0) }
45    }
46}
47
48impl_TCFType!(CGFunction, CGFunctionRef, CGFunctionGetTypeID);
49impl_CFTypeDescription!(CGFunction);
50
51impl CGFunction {
52    pub unsafe fn new(
53        info: *mut c_void,
54        domain: Option<&[CGFloat]>,
55        range: Option<&[CGFloat]>,
56        callbacks: Option<&CGFunctionCallbacks>,
57    ) -> Option<Self> {
58        let domain_dimension = domain.map_or(0, |d| d.len());
59        let domain = domain.map_or(null(), |d| d.as_ptr());
60        let range_dimension = range.map_or(0, |r| r.len());
61        let range = range.map_or(null(), |r| r.as_ptr());
62        let callbacks = callbacks.map_or(null(), |c| c as *const _);
63        let function = CGFunctionCreate(info, domain_dimension, domain, range_dimension, range, callbacks);
64        if function.is_null() {
65            None
66        } else {
67            Some(TCFType::wrap_under_create_rule(function))
68        }
69    }
70}