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