1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 // e.g. declare_surface(ImageSurface, SurfaceType::Image)
4 macro_rules! declare_surface {
5     ($surf_name:ident, $surf_type:expr) => {
6         #[derive(Debug)]
7         pub struct $surf_name(Surface);
8 
9         impl TryFrom<Surface> for $surf_name {
10             type Error = Surface;
11 
12             fn try_from(surface: Surface) -> Result<$surf_name, Surface> {
13                 if surface.type_() == $surf_type {
14                     Ok($surf_name(surface))
15                 } else {
16                     Err(surface)
17                 }
18             }
19         }
20 
21         impl $surf_name {
22             pub unsafe fn from_raw_full(
23                 ptr: *mut ffi::cairo_surface_t,
24             ) -> Result<$surf_name, crate::error::Error> {
25                 let surface = Surface::from_raw_full(ptr)?;
26                 Self::try_from(surface).map_err(|_| crate::error::Error::SurfaceTypeMismatch)
27             }
28 
29             pub unsafe fn from_raw_none(
30                 ptr: *mut ffi::cairo_surface_t,
31             ) -> Result<$surf_name, crate::error::Error> {
32                 let surface = Surface::from_raw_none(ptr);
33                 Self::try_from(surface).map_err(|_| crate::error::Error::SurfaceTypeMismatch)
34             }
35         }
36 
37         #[cfg(feature = "use_glib")]
38         impl<'a> ToGlibPtr<'a, *mut ffi::cairo_surface_t> for $surf_name {
39             type Storage = &'a Surface;
40 
41             #[inline]
42             fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_surface_t, Self> {
43                 let stash = self.0.to_glib_none();
44                 Stash(stash.0, stash.1)
45             }
46 
47             #[inline]
48             fn to_glib_full(&self) -> *mut ffi::cairo_surface_t {
49                 unsafe { ffi::cairo_surface_reference(self.to_glib_none().0) }
50             }
51         }
52 
53         #[cfg(feature = "use_glib")]
54         impl FromGlibPtrNone<*mut ffi::cairo_surface_t> for $surf_name {
55             #[inline]
56             unsafe fn from_glib_none(ptr: *mut ffi::cairo_surface_t) -> $surf_name {
57                 Self::try_from(from_glib_none::<_, Surface>(ptr)).unwrap()
58             }
59         }
60 
61         #[cfg(feature = "use_glib")]
62         impl FromGlibPtrBorrow<*mut ffi::cairo_surface_t> for $surf_name {
63             #[inline]
64             unsafe fn from_glib_borrow(
65                 ptr: *mut ffi::cairo_surface_t,
66             ) -> crate::Borrowed<$surf_name> {
67                 let surface = from_glib_borrow::<_, Surface>(ptr);
68                 let surface = Self::try_from(surface.into_inner())
69                     .map_err(std::mem::forget)
70                     .unwrap();
71                 crate::Borrowed::new(surface)
72             }
73         }
74 
75         #[cfg(feature = "use_glib")]
76         impl FromGlibPtrFull<*mut ffi::cairo_surface_t> for $surf_name {
77             #[inline]
78             unsafe fn from_glib_full(ptr: *mut ffi::cairo_surface_t) -> $surf_name {
79                 Self::from_raw_full(ptr).unwrap()
80             }
81         }
82 
83         #[cfg(feature = "use_glib")]
84         gvalue_impl!(
85             $surf_name,
86             ffi::cairo_surface_t,
87             ffi::gobject::cairo_gobject_surface_get_type
88         );
89 
90         impl Deref for $surf_name {
91             type Target = Surface;
92 
93             fn deref(&self) -> &Surface {
94                 &self.0
95             }
96         }
97 
98         impl Clone for $surf_name {
99             fn clone(&self) -> $surf_name {
100                 $surf_name(self.0.clone())
101             }
102         }
103 
104         impl fmt::Display for $surf_name {
105             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106                 f.write_str(stringify!($surf_name))
107             }
108         }
109     };
110 }
111