cairo/
region.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3#[cfg(feature = "use_glib")]
4use std::marker::PhantomData;
5use std::ptr;
6
7#[cfg(feature = "use_glib")]
8use glib::translate::*;
9
10use crate::{Error, RectangleInt, RegionOverlap, ffi, utils::status_to_result};
11
12#[derive(Debug)]
13#[repr(transparent)]
14#[doc(alias = "cairo_region_t")]
15pub struct Region(ptr::NonNull<ffi::cairo_region_t>);
16
17#[cfg(feature = "use_glib")]
18impl IntoGlibPtr<*mut ffi::cairo_region_t> for Region {
19    #[inline]
20    fn into_glib_ptr(self) -> *mut ffi::cairo_region_t {
21        (&*std::mem::ManuallyDrop::new(self)).to_glib_none().0
22    }
23}
24
25#[cfg(feature = "use_glib")]
26#[doc(hidden)]
27impl<'a> ToGlibPtr<'a, *mut ffi::cairo_region_t> for &'a Region {
28    type Storage = PhantomData<&'a Region>;
29
30    #[inline]
31    fn to_glib_none(&self) -> Stash<'a, *mut ffi::cairo_region_t, Self> {
32        Stash(self.0.as_ptr(), PhantomData)
33    }
34
35    #[inline]
36    fn to_glib_full(&self) -> *mut ffi::cairo_region_t {
37        unsafe { ffi::cairo_region_reference(self.0.as_ptr()) }
38    }
39}
40
41#[cfg(feature = "use_glib")]
42#[doc(hidden)]
43impl<'a> ToGlibPtrMut<'a, *mut ffi::cairo_region_t> for Region {
44    type Storage = PhantomData<&'a mut Self>;
45
46    // FIXME: This is unsafe: regions are reference counted, so we could get multiple mutable
47    // references here
48    #[inline]
49    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::cairo_region_t, Self> {
50        StashMut(self.0.as_ptr(), PhantomData)
51    }
52}
53
54#[cfg(feature = "use_glib")]
55#[doc(hidden)]
56impl FromGlibPtrNone<*mut ffi::cairo_region_t> for Region {
57    #[inline]
58    unsafe fn from_glib_none(ptr: *mut ffi::cairo_region_t) -> Region {
59        unsafe { Self::from_raw_none(ptr) }
60    }
61}
62
63#[cfg(feature = "use_glib")]
64#[doc(hidden)]
65impl FromGlibPtrBorrow<*mut ffi::cairo_region_t> for Region {
66    #[inline]
67    unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_region_t) -> crate::Borrowed<Region> {
68        unsafe { Self::from_raw_borrow(ptr) }
69    }
70}
71
72#[cfg(feature = "use_glib")]
73#[doc(hidden)]
74impl FromGlibPtrFull<*mut ffi::cairo_region_t> for Region {
75    #[inline]
76    unsafe fn from_glib_full(ptr: *mut ffi::cairo_region_t) -> Region {
77        unsafe { Self::from_raw_full(ptr) }
78    }
79}
80
81#[cfg(feature = "use_glib")]
82gvalue_impl!(
83    Region,
84    ffi::cairo_region_t,
85    ffi::gobject::cairo_gobject_region_get_type
86);
87
88impl Clone for Region {
89    #[inline]
90    fn clone(&self) -> Region {
91        unsafe { Self::from_raw_none(self.to_raw_none()) }
92    }
93}
94
95impl Drop for Region {
96    #[inline]
97    fn drop(&mut self) {
98        unsafe {
99            ffi::cairo_region_destroy(self.0.as_ptr());
100        }
101    }
102}
103
104impl PartialEq for Region {
105    #[doc(alias = "cairo_region_equal")]
106    #[inline]
107    fn eq(&self, other: &Region) -> bool {
108        unsafe { ffi::cairo_region_equal(self.0.as_ptr(), other.0.as_ptr()).as_bool() }
109    }
110}
111
112impl Eq for Region {}
113
114impl Region {
115    #[inline]
116    pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_region_t) -> Region {
117        unsafe {
118            debug_assert!(!ptr.is_null());
119            ffi::cairo_region_reference(ptr);
120            Region(ptr::NonNull::new_unchecked(ptr))
121        }
122    }
123
124    #[inline]
125    pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_region_t) -> crate::Borrowed<Region> {
126        unsafe {
127            debug_assert!(!ptr.is_null());
128            crate::Borrowed::new(Region(ptr::NonNull::new_unchecked(ptr)))
129        }
130    }
131
132    #[inline]
133    pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_region_t) -> Region {
134        unsafe {
135            debug_assert!(!ptr.is_null());
136            Region(ptr::NonNull::new_unchecked(ptr))
137        }
138    }
139
140    #[inline]
141    pub fn to_raw_none(&self) -> *mut ffi::cairo_region_t {
142        self.0.as_ptr()
143    }
144
145    #[doc(alias = "cairo_region_create")]
146    pub fn create() -> Region {
147        unsafe { Self::from_raw_full(ffi::cairo_region_create()) }
148    }
149
150    #[doc(alias = "cairo_region_create_rectangle")]
151    pub fn create_rectangle(rectangle: &RectangleInt) -> Region {
152        unsafe { Self::from_raw_full(ffi::cairo_region_create_rectangle(rectangle.to_raw_none())) }
153    }
154
155    #[doc(alias = "cairo_region_create_rectangles")]
156    pub fn create_rectangles(rectangles: &[RectangleInt]) -> Region {
157        unsafe {
158            Self::from_raw_full(ffi::cairo_region_create_rectangles(
159                rectangles.as_ptr() as *mut ffi::cairo_rectangle_int_t,
160                rectangles.len() as i32,
161            ))
162        }
163    }
164
165    #[doc(alias = "cairo_region_copy")]
166    #[must_use]
167    pub fn copy(&self) -> Region {
168        unsafe { Self::from_raw_full(ffi::cairo_region_copy(self.0.as_ptr())) }
169    }
170
171    #[doc(alias = "get_extents")]
172    #[doc(alias = "cairo_region_get_extents")]
173    pub fn extents(&self, rectangle: &RectangleInt) {
174        unsafe { ffi::cairo_region_get_extents(self.0.as_ptr(), rectangle.to_raw_none()) }
175    }
176
177    #[doc(alias = "cairo_region_num_rectangles")]
178    pub fn num_rectangles(&self) -> i32 {
179        unsafe { ffi::cairo_region_num_rectangles(self.0.as_ptr()) }
180    }
181
182    #[doc(alias = "get_rectangle")]
183    #[doc(alias = "cairo_region_get_rectangle")]
184    pub fn rectangle(&self, nth: i32) -> RectangleInt {
185        let total_rectangles = self.num_rectangles();
186        assert!(nth >= 0 && nth < total_rectangles, "nth is out of range");
187        unsafe {
188            let rectangle: RectangleInt = ::std::mem::zeroed();
189            ffi::cairo_region_get_rectangle(self.0.as_ptr(), nth, rectangle.to_raw_none());
190            rectangle
191        }
192    }
193
194    #[doc(alias = "cairo_region_is_empty")]
195    pub fn is_empty(&self) -> bool {
196        unsafe { ffi::cairo_region_is_empty(self.0.as_ptr()).as_bool() }
197    }
198
199    #[doc(alias = "cairo_region_contains_point")]
200    pub fn contains_point(&self, x: i32, y: i32) -> bool {
201        unsafe { ffi::cairo_region_contains_point(self.0.as_ptr(), x, y).as_bool() }
202    }
203
204    #[doc(alias = "cairo_region_contains_rectangle")]
205    pub fn contains_rectangle(&self, rectangle: &RectangleInt) -> RegionOverlap {
206        unsafe {
207            RegionOverlap::from(ffi::cairo_region_contains_rectangle(
208                self.0.as_ptr(),
209                rectangle.to_raw_none(),
210            ))
211        }
212    }
213
214    #[doc(alias = "cairo_region_translate")]
215    pub fn translate(&self, dx: i32, dy: i32) {
216        unsafe { ffi::cairo_region_translate(self.0.as_ptr(), dx, dy) }
217    }
218
219    #[doc(alias = "cairo_region_intersect")]
220    pub fn intersect(&self, other: &Region) -> Result<(), Error> {
221        unsafe {
222            let status = ffi::cairo_region_intersect(self.0.as_ptr(), other.0.as_ptr());
223            status_to_result(status)
224        }
225    }
226
227    #[doc(alias = "cairo_region_intersect_rectangle")]
228    pub fn intersect_rectangle(&self, rectangle: &RectangleInt) -> Result<(), Error> {
229        unsafe {
230            let status =
231                ffi::cairo_region_intersect_rectangle(self.0.as_ptr(), rectangle.to_raw_none());
232            status_to_result(status)
233        }
234    }
235
236    #[doc(alias = "cairo_region_subtract")]
237    pub fn subtract(&self, other: &Region) -> Result<(), Error> {
238        unsafe {
239            let status = ffi::cairo_region_subtract(self.0.as_ptr(), other.0.as_ptr());
240            status_to_result(status)
241        }
242    }
243
244    #[doc(alias = "cairo_region_subtract_rectangle")]
245    pub fn subtract_rectangle(&self, rectangle: &RectangleInt) -> Result<(), Error> {
246        unsafe {
247            let status =
248                ffi::cairo_region_subtract_rectangle(self.0.as_ptr(), rectangle.to_raw_none());
249            status_to_result(status)
250        }
251    }
252
253    #[doc(alias = "cairo_region_union")]
254    pub fn union(&self, other: &Region) -> Result<(), Error> {
255        unsafe {
256            let status = ffi::cairo_region_union(self.0.as_ptr(), other.0.as_ptr());
257            status_to_result(status)
258        }
259    }
260
261    #[doc(alias = "cairo_region_union_rectangle")]
262    pub fn union_rectangle(&self, rectangle: &RectangleInt) -> Result<(), Error> {
263        unsafe {
264            let status =
265                ffi::cairo_region_union_rectangle(self.0.as_ptr(), rectangle.to_raw_none());
266            status_to_result(status)
267        }
268    }
269
270    #[doc(alias = "cairo_region_xor")]
271    pub fn xor(&self, other: &Region) -> Result<(), Error> {
272        unsafe {
273            let status = ffi::cairo_region_xor(self.0.as_ptr(), other.0.as_ptr());
274            status_to_result(status)
275        }
276    }
277
278    #[doc(alias = "cairo_region_xor_rectangle")]
279    pub fn xor_rectangle(&self, rectangle: &RectangleInt) -> Result<(), Error> {
280        unsafe {
281            let status = ffi::cairo_region_xor_rectangle(self.0.as_ptr(), rectangle.to_raw_none());
282            status_to_result(status)
283        }
284    }
285
286    #[doc(alias = "cairo_region_status")]
287    pub fn status(&self) -> Result<(), Error> {
288        let status = unsafe { ffi::cairo_region_status(self.0.as_ptr()) };
289        status_to_result(status)
290    }
291}