core_graphics2/
gradient.rs

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