core_graphics2/
gradient.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::ptr::{null, null_mut};

use core_foundation::{
    array::{CFArray, CFArrayRef},
    base::{CFTypeID, TCFType},
};
use libc::{c_void, size_t};

use crate::{
    base::CGFloat,
    color::CGColor,
    color_space::{CGColorSpace, CGColorSpaceRef},
};

#[repr(C)]
pub struct __CGGradient(c_void);

pub type CGGradientRef = *const __CGGradient;

bitflags! {
    #[repr(C)]
    #[derive(Clone, Copy, Debug, Default, PartialEq)]
    pub struct CGGradientDrawingOptions: u32 {
        #[doc(alias = "kCGGradientDrawsBeforeStartLocation")]
        const BeforeStartLocation = (1 << 0);
        #[doc(alias = "kCGGradientDrawsAfterEndLocation")]
        const AfterEndLocation = (1 << 1);
    }
}

extern "C" {
    pub fn CGGradientGetTypeID() -> CFTypeID;
    pub fn CGGradientCreateWithColorComponents(
        space: CGColorSpaceRef,
        components: *const CGFloat,
        locations: *const CGFloat,
        count: size_t,
    ) -> CGGradientRef;
    pub fn CGGradientCreateWithColors(space: CGColorSpaceRef, colors: CFArrayRef, locations: *const CGFloat) -> CGGradientRef;
    pub fn CGGradientRetain(gradient: CGGradientRef) -> CGGradientRef;
    pub fn CGGradientRelease(gradient: CGGradientRef);
}

pub struct CGGradient(CGGradientRef);

impl Drop for CGGradient {
    fn drop(&mut self) {
        unsafe { CGGradientRelease(self.0) }
    }
}

impl_TCFType!(CGGradient, CGGradientRef, CGGradientGetTypeID);
impl_CFTypeDescription!(CGGradient);

impl CGGradient {
    pub fn from_color_components(
        color_space: Option<&CGColorSpace>,
        components: Option<&[CGFloat]>,
        locations: Option<&[CGFloat]>,
    ) -> Option<CGGradient> {
        unsafe {
            let gradient = CGGradientCreateWithColorComponents(
                color_space.map_or(null_mut(), |cs| cs.as_concrete_TypeRef()),
                components.map_or(null(), |c| c.as_ptr()),
                locations.map_or(null(), |l| l.as_ptr()),
                locations.map_or(0, |l| l.len() as size_t),
            );
            if gradient.is_null() {
                None
            } else {
                Some(TCFType::wrap_under_create_rule(gradient))
            }
        }
    }

    pub fn from_colors(color_space: Option<&CGColorSpace>, colors: Option<&CFArray<CGColor>>, locations: Option<&[CGFloat]>) -> Option<CGGradient> {
        unsafe {
            let gradient = CGGradientCreateWithColors(
                color_space.map_or(null_mut(), |cs| cs.as_concrete_TypeRef()),
                colors.map_or(null(), |c| c.as_concrete_TypeRef()),
                locations.map_or(null(), |l| l.as_ptr()),
            );
            if gradient.is_null() {
                None
            } else {
                Some(TCFType::wrap_under_create_rule(gradient))
            }
        }
    }
}