Skip to main content

core_graphics2/
gradient.rs

1use std::ptr::{null, null_mut};
2
3use bitflags::bitflags;
4use core_foundation::{
5    array::{CFArray, CFArrayRef},
6    base::{CFTypeID, TCFType},
7    impl_CFTypeDescription, impl_TCFType,
8};
9use libc::{c_void, size_t};
10
11use crate::{
12    base::CGFloat,
13    color::CGColor,
14    color_space::{CGColorSpace, CGColorSpaceRef},
15};
16
17#[repr(C)]
18pub struct __CGGradient(c_void);
19
20pub type CGGradientRef = *const __CGGradient;
21
22bitflags! {
23    #[repr(C)]
24    #[derive(Clone, Copy, Debug, Default, PartialEq)]
25    pub struct CGGradientDrawingOptions: u32 {
26        #[doc(alias = "kCGGradientDrawsBeforeStartLocation")]
27        const BeforeStartLocation = (1 << 0);
28        #[doc(alias = "kCGGradientDrawsAfterEndLocation")]
29        const AfterEndLocation = (1 << 1);
30    }
31}
32
33extern "C" {
34    pub fn CGGradientGetTypeID() -> CFTypeID;
35    pub fn CGGradientCreateWithColorComponents(
36        space: CGColorSpaceRef,
37        components: *const CGFloat,
38        locations: *const CGFloat,
39        count: size_t,
40    ) -> CGGradientRef;
41    pub fn CGGradientCreateWithColors(space: CGColorSpaceRef, colors: CFArrayRef, locations: *const CGFloat) -> CGGradientRef;
42    pub fn CGGradientRetain(gradient: CGGradientRef) -> CGGradientRef;
43    pub fn CGGradientRelease(gradient: CGGradientRef);
44}
45
46pub struct CGGradient(CGGradientRef);
47
48impl Drop for CGGradient {
49    fn drop(&mut self) {
50        unsafe { CGGradientRelease(self.0) }
51    }
52}
53
54impl_TCFType!(CGGradient, CGGradientRef, CGGradientGetTypeID);
55impl_CFTypeDescription!(CGGradient);
56
57impl CGGradient {
58    pub fn from_color_components(
59        color_space: Option<&CGColorSpace>,
60        components: Option<&[CGFloat]>,
61        locations: Option<&[CGFloat]>,
62    ) -> Option<CGGradient> {
63        unsafe {
64            let gradient = CGGradientCreateWithColorComponents(
65                color_space.map_or(null_mut(), |cs| cs.as_concrete_TypeRef()),
66                components.map_or(null(), |c| c.as_ptr()),
67                locations.map_or(null(), |l| l.as_ptr()),
68                locations.map_or(0, |l| l.len() as size_t),
69            );
70            if gradient.is_null() {
71                None
72            } else {
73                Some(TCFType::wrap_under_create_rule(gradient))
74            }
75        }
76    }
77
78    pub fn from_colors(color_space: Option<&CGColorSpace>, colors: Option<&CFArray<CGColor>>, locations: Option<&[CGFloat]>) -> Option<CGGradient> {
79        unsafe {
80            let gradient = CGGradientCreateWithColors(
81                color_space.map_or(null_mut(), |cs| cs.as_concrete_TypeRef()),
82                colors.map_or(null(), |c| c.as_concrete_TypeRef()),
83                locations.map_or(null(), |l| l.as_ptr()),
84            );
85            if gradient.is_null() {
86                None
87            } else {
88                Some(TCFType::wrap_under_create_rule(gradient))
89            }
90        }
91    }
92}