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