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