1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 use crate::enums::DeviceType;
4 use crate::error::Error;
5 use crate::utils::status_to_result;
6 
7 use std::fmt;
8 use std::ptr;
9 
10 #[cfg(feature = "use_glib")]
11 use glib::translate::*;
12 
13 #[cfg(any(feature = "script", feature = "dox"))]
14 use crate::enums::Content;
15 #[cfg(any(feature = "script", feature = "dox"))]
16 use crate::enums::ScriptMode;
17 #[cfg(any(feature = "script", feature = "dox"))]
18 use crate::recording_surface::RecordingSurface;
19 #[cfg(any(feature = "script", feature = "dox"))]
20 use crate::surface::Surface;
21 #[cfg(any(feature = "script", feature = "dox"))]
22 use std::ffi::CString;
23 #[cfg(any(feature = "script", feature = "dox"))]
24 use std::path::Path;
25 
26 #[derive(Debug)]
27 pub struct DeviceAcquireGuard<'a>(&'a Device);
28 
29 impl<'a> Drop for DeviceAcquireGuard<'a> {
drop(&mut self)30     fn drop(&mut self) {
31         self.0.release();
32     }
33 }
34 
35 #[derive(Debug)]
36 #[doc(alias = "cairo_device_t")]
37 pub struct Device(ptr::NonNull<ffi::cairo_device_t>);
38 
39 impl Device {
from_raw_none(ptr: *mut ffi::cairo_device_t) -> Device40     pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_device_t) -> Device {
41         assert!(!ptr.is_null());
42         ffi::cairo_device_reference(ptr);
43         Device(ptr::NonNull::new_unchecked(ptr))
44     }
45 
from_raw_borrow(ptr: *mut ffi::cairo_device_t) -> crate::Borrowed<Device>46     pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_device_t) -> crate::Borrowed<Device> {
47         assert!(!ptr.is_null());
48         crate::Borrowed::new(Device(ptr::NonNull::new_unchecked(ptr)))
49     }
50 
from_raw_full(ptr: *mut ffi::cairo_device_t) -> Device51     pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_device_t) -> Device {
52         assert!(!ptr.is_null());
53         Device(ptr::NonNull::new_unchecked(ptr))
54     }
55 
to_raw_none(&self) -> *mut ffi::cairo_device_t56     pub fn to_raw_none(&self) -> *mut ffi::cairo_device_t {
57         self.0.as_ptr()
58     }
59 
60     #[cfg(any(feature = "script", feature = "dox"))]
61     #[doc(alias = "cairo_script_create")]
create<P: AsRef<Path>>(filename: P) -> Option<Device>62     pub fn create<P: AsRef<Path>>(filename: P) -> Option<Device> {
63         unsafe {
64             let filename = filename.as_ref().to_string_lossy().into_owned();
65             let filename = CString::new(filename).unwrap();
66             let p = ffi::cairo_script_create(filename.as_ptr());
67             if p.is_null() {
68                 None
69             } else {
70                 Some(Self::from_raw_full(p))
71             }
72         }
73     }
74 
75     #[cfg(any(feature = "script", feature = "dox"))]
76     #[doc(alias = "cairo_script_from_recording_surface")]
from_recording_surface(&self, surface: &RecordingSurface) -> Result<(), Error>77     pub fn from_recording_surface(&self, surface: &RecordingSurface) -> Result<(), Error> {
78         unsafe {
79             let status =
80                 ffi::cairo_script_from_recording_surface(self.to_raw_none(), surface.to_raw_none());
81             status_to_result(status)
82         }
83     }
84 
85     #[cfg(any(feature = "script", feature = "dox"))]
86     #[doc(alias = "cairo_script_get_mode")]
87     #[doc(alias = "get_mode")]
mode(&self) -> ScriptMode88     pub fn mode(&self) -> ScriptMode {
89         unsafe { ScriptMode::from(ffi::cairo_script_get_mode(self.to_raw_none())) }
90     }
91 
92     #[cfg(any(feature = "script", feature = "dox"))]
93     #[doc(alias = "cairo_script_set_mode")]
set_mode(&self, mode: ScriptMode)94     pub fn set_mode(&self, mode: ScriptMode) {
95         unsafe { ffi::cairo_script_set_mode(self.to_raw_none(), mode.into()) }
96     }
97 
98     #[cfg(any(feature = "script", feature = "dox"))]
99     #[doc(alias = "cairo_script_surface_create")]
surface_create( &self, content: Content, width: f64, height: f64, ) -> Result<Surface, Error>100     pub fn surface_create(
101         &self,
102         content: Content,
103         width: f64,
104         height: f64,
105     ) -> Result<Surface, Error> {
106         unsafe {
107             Surface::from_raw_full(ffi::cairo_script_surface_create(
108                 self.to_raw_none(),
109                 content.into(),
110                 width,
111                 height,
112             ))
113         }
114     }
115 
116     #[cfg(any(feature = "script", feature = "dox"))]
117     #[doc(alias = "cairo_script_surface_create_for_target")]
surface_create_for_target(&self, target: &Surface) -> Result<Surface, Error>118     pub fn surface_create_for_target(&self, target: &Surface) -> Result<Surface, Error> {
119         target.status()?;
120         unsafe {
121             Surface::from_raw_full(ffi::cairo_script_surface_create_for_target(
122                 self.to_raw_none(),
123                 target.to_raw_none(),
124             ))
125         }
126     }
127 
128     #[cfg(any(feature = "script", feature = "dox"))]
129     #[doc(alias = "cairo_script_write_comment")]
write_comment(&self, comment: &str)130     pub fn write_comment(&self, comment: &str) {
131         unsafe {
132             let len = comment.len();
133             let comment = CString::new(comment).unwrap();
134             ffi::cairo_script_write_comment(self.to_raw_none(), comment.as_ptr(), len as i32)
135         }
136     }
137 
138     #[doc(alias = "cairo_device_finish")]
finish(&self)139     pub fn finish(&self) {
140         unsafe { ffi::cairo_device_finish(self.to_raw_none()) }
141     }
142 
143     #[doc(alias = "cairo_device_flush")]
flush(&self)144     pub fn flush(&self) {
145         unsafe { ffi::cairo_device_flush(self.to_raw_none()) }
146     }
147 
148     #[doc(alias = "cairo_device_get_type")]
149     #[doc(alias = "get_type")]
type_(&self) -> DeviceType150     pub fn type_(&self) -> DeviceType {
151         unsafe { DeviceType::from(ffi::cairo_device_get_type(self.to_raw_none())) }
152     }
153 
154     #[doc(alias = "cairo_device_acquire")]
acquire(&self) -> Result<DeviceAcquireGuard, Error>155     pub fn acquire(&self) -> Result<DeviceAcquireGuard, Error> {
156         unsafe {
157             let status = ffi::cairo_device_acquire(self.to_raw_none());
158             status_to_result(status)?;
159         }
160         Ok(DeviceAcquireGuard { 0: self })
161     }
162 
163     #[doc(alias = "cairo_device_release")]
release(&self)164     fn release(&self) {
165         unsafe { ffi::cairo_device_release(self.to_raw_none()) }
166     }
167 
168     #[doc(alias = "cairo_device_observer_elapsed")]
observer_elapsed(&self) -> f64169     pub fn observer_elapsed(&self) -> f64 {
170         unsafe { ffi::cairo_device_observer_elapsed(self.to_raw_none()) }
171     }
172 
173     #[doc(alias = "cairo_device_observer_fill_elapsed")]
observer_fill_elapsed(&self) -> f64174     pub fn observer_fill_elapsed(&self) -> f64 {
175         unsafe { ffi::cairo_device_observer_fill_elapsed(self.to_raw_none()) }
176     }
177 
178     #[doc(alias = "cairo_device_observer_glyphs_elapsed")]
observer_glyphs_elapsed(&self) -> f64179     pub fn observer_glyphs_elapsed(&self) -> f64 {
180         unsafe { ffi::cairo_device_observer_glyphs_elapsed(self.to_raw_none()) }
181     }
182 
183     #[doc(alias = "cairo_device_observer_mask_elapsed")]
observer_mask_elapsed(&self) -> f64184     pub fn observer_mask_elapsed(&self) -> f64 {
185         unsafe { ffi::cairo_device_observer_mask_elapsed(self.to_raw_none()) }
186     }
187 
188     #[doc(alias = "cairo_device_observer_paint_elapsed")]
observer_paint_elapsed(&self) -> f64189     pub fn observer_paint_elapsed(&self) -> f64 {
190         unsafe { ffi::cairo_device_observer_paint_elapsed(self.to_raw_none()) }
191     }
192 
193     #[doc(alias = "cairo_device_observer_stroke_elapsed")]
observer_stroke_elapsed(&self) -> f64194     pub fn observer_stroke_elapsed(&self) -> f64 {
195         unsafe { ffi::cairo_device_observer_stroke_elapsed(self.to_raw_none()) }
196     }
197 
198     #[cfg(any(feature = "xlib", feature = "xcb", feature = "dox"))]
199     #[doc(alias = "cairo_xlib_device_debug_cap_xrender_version")]
200     #[doc(alias = "cairo_xcb_device_debug_cap_xrender_version")]
debug_cap_xrender_version(&self, major_version: i32, minor_version: i32)201     pub fn debug_cap_xrender_version(&self, major_version: i32, minor_version: i32) {
202         unsafe {
203             match self.type_() {
204                 DeviceType::Xlib => {
205                     #[cfg(feature = "xlib")]
206                     {
207                         ffi::cairo_xlib_device_debug_cap_xrender_version(
208                             self.to_raw_none(),
209                             major_version,
210                             minor_version,
211                         )
212                     }
213                     #[cfg(not(feature = "xlib"))]
214                     {
215                         panic!("you need to enable \"xlib\" feature")
216                     }
217                 }
218                 DeviceType::Xcb => {
219                     #[cfg(feature = "xcb")]
220                     {
221                         ffi::cairo_xcb_device_debug_cap_xrender_version(
222                             self.to_raw_none(),
223                             major_version,
224                             minor_version,
225                         )
226                     }
227                     #[cfg(not(feature = "xcb"))]
228                     {
229                         panic!("you need to enable \"xcb\" feature")
230                     }
231                 }
232                 d => panic!("invalid device type: {}", d),
233             }
234         }
235     }
236 
237     #[cfg(any(feature = "xlib", feature = "xcb", feature = "dox"))]
238     #[doc(alias = "cairo_xlib_device_debug_get_precision")]
239     #[doc(alias = "cairo_xcb_device_debug_get_precision")]
debug_get_precision(&self) -> i32240     pub fn debug_get_precision(&self) -> i32 {
241         unsafe {
242             match self.type_() {
243                 DeviceType::Xlib => {
244                     #[cfg(feature = "xlib")]
245                     {
246                         ffi::cairo_xlib_device_debug_get_precision(self.to_raw_none())
247                     }
248                     #[cfg(not(feature = "xlib"))]
249                     {
250                         panic!("you need to enable \"xlib\" feature")
251                     }
252                 }
253                 DeviceType::Xcb => {
254                     #[cfg(feature = "xcb")]
255                     {
256                         ffi::cairo_xcb_device_debug_get_precision(self.to_raw_none())
257                     }
258                     #[cfg(not(feature = "xcb"))]
259                     {
260                         panic!("you need to enable \"xcb\" feature")
261                     }
262                 }
263                 d => panic!("invalid device type: {}", d),
264             }
265         }
266     }
267 
268     #[cfg(any(feature = "xlib", feature = "xcb", feature = "dox"))]
269     #[doc(alias = "cairo_xlib_device_debug_set_precision")]
270     #[doc(alias = "cairo_xcb_device_debug_set_precision")]
debug_set_precision(&self, precision: i32)271     pub fn debug_set_precision(&self, precision: i32) {
272         unsafe {
273             match self.type_() {
274                 DeviceType::Xlib => {
275                     #[cfg(feature = "xlib")]
276                     {
277                         ffi::cairo_xlib_device_debug_set_precision(self.to_raw_none(), precision)
278                     }
279                     #[cfg(not(feature = "xlib"))]
280                     {
281                         panic!("you need to enable \"xlib\" feature")
282                     }
283                 }
284                 DeviceType::Xcb => {
285                     #[cfg(feature = "xcb")]
286                     {
287                         ffi::cairo_xcb_device_debug_set_precision(self.to_raw_none(), precision)
288                     }
289                     #[cfg(not(feature = "xcb"))]
290                     {
291                         panic!("you need to enable \"xcb\" feature")
292                     }
293                 }
294                 d => panic!("invalid device type: {}", d),
295             }
296         }
297     }
298 
299     #[doc(alias = "cairo_device_status")]
status(&self) -> Result<(), Error>300     pub fn status(&self) -> Result<(), Error> {
301         let status = unsafe { ffi::cairo_device_status(self.to_raw_none()) };
302         status_to_result(status)
303     }
304 
305     user_data_methods! {
306         ffi::cairo_device_get_user_data,
307         ffi::cairo_device_set_user_data,
308     }
309 }
310 
311 #[cfg(feature = "use_glib")]
312 impl<'a> ToGlibPtr<'a, *mut ffi::cairo_device_t> for Device {
313     type Storage = &'a Device;
314 
315     #[inline]
to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_device_t, Self>316     fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_device_t, Self> {
317         Stash(self.to_raw_none(), self)
318     }
319 
320     #[inline]
to_glib_full(&self) -> *mut ffi::cairo_device_t321     fn to_glib_full(&self) -> *mut ffi::cairo_device_t {
322         unsafe { ffi::cairo_device_reference(self.to_raw_none()) }
323     }
324 }
325 
326 #[cfg(feature = "use_glib")]
327 impl FromGlibPtrNone<*mut ffi::cairo_device_t> for Device {
328     #[inline]
from_glib_none(ptr: *mut ffi::cairo_device_t) -> Device329     unsafe fn from_glib_none(ptr: *mut ffi::cairo_device_t) -> Device {
330         Self::from_raw_none(ptr)
331     }
332 }
333 
334 #[cfg(feature = "use_glib")]
335 impl FromGlibPtrBorrow<*mut ffi::cairo_device_t> for Device {
336     #[inline]
from_glib_borrow(ptr: *mut ffi::cairo_device_t) -> crate::Borrowed<Device>337     unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_device_t) -> crate::Borrowed<Device> {
338         Self::from_raw_borrow(ptr)
339     }
340 }
341 
342 #[cfg(feature = "use_glib")]
343 impl FromGlibPtrFull<*mut ffi::cairo_device_t> for Device {
344     #[inline]
from_glib_full(ptr: *mut ffi::cairo_device_t) -> Device345     unsafe fn from_glib_full(ptr: *mut ffi::cairo_device_t) -> Device {
346         Self::from_raw_full(ptr)
347     }
348 }
349 
350 #[cfg(feature = "use_glib")]
351 gvalue_impl!(
352     Device,
353     ffi::cairo_device_t,
354     ffi::gobject::cairo_gobject_device_get_type
355 );
356 
357 impl Clone for Device {
clone(&self) -> Device358     fn clone(&self) -> Device {
359         unsafe { Self::from_raw_none(ffi::cairo_device_reference(self.0.as_ptr())) }
360     }
361 }
362 
363 impl Drop for Device {
drop(&mut self)364     fn drop(&mut self) {
365         unsafe {
366             ffi::cairo_device_destroy(self.0.as_ptr());
367         }
368     }
369 }
370 
371 impl fmt::Display for Device {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result372     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
373         write!(f, "Device")
374     }
375 }
376