1use ffi;
6use font::{FontExtents, FontFace, FontOptions, Glyph, ScaledFont, TextCluster, TextExtents};
7#[cfg(feature = "use_glib")]
8use glib::translate::*;
9use libc::c_int;
10use matrices::Matrix;
11use paths::Path;
12use std::ffi::CString;
13use std::fmt;
14use std::ops;
15use std::slice;
16use Rectangle;
17use {
18 Antialias, Content, FillRule, FontSlant, FontWeight, LineCap, LineJoin, Operator, Status,
19 TextClusterFlags,
20};
21
22use ffi::{cairo_rectangle_list_t, cairo_t};
23use patterns::Pattern;
24use surface::Surface;
25
26pub struct RectangleList {
27 ptr: *mut cairo_rectangle_list_t,
28}
29
30impl ops::Deref for RectangleList {
31 type Target = [Rectangle];
32
33 fn deref(&self) -> &[Rectangle] {
34 unsafe {
35 let ptr = (*self.ptr).rectangles as *mut Rectangle;
36 let len = (*self.ptr).num_rectangles;
37
38 if ptr.is_null() || len == 0 {
39 &[]
40 } else {
41 slice::from_raw_parts(ptr, len as usize)
42 }
43 }
44 }
45}
46
47impl Drop for RectangleList {
48 fn drop(&mut self) {
49 unsafe {
50 ffi::cairo_rectangle_list_destroy(self.ptr);
51 }
52 }
53}
54
55impl fmt::Debug for RectangleList {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 f.debug_tuple("RectangleList").field(&*self).finish()
58 }
59}
60
61impl fmt::Display for RectangleList {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 write!(f, "RectangleList")
64 }
65}
66
67#[derive(Debug)]
68pub struct Context(*mut cairo_t, bool);
69
70#[cfg(feature = "use_glib")]
71impl<'a> ToGlibPtr<'a, *mut ffi::cairo_t> for &'a Context {
72 type Storage = &'a Context;
73
74 #[inline]
75 fn to_glib_none(&self) -> Stash<'a, *mut ffi::cairo_t, &'a Context> {
76 Stash(self.0, *self)
77 }
78
79 #[inline]
80 fn to_glib_full(&self) -> *mut ffi::cairo_t {
81 unsafe { ffi::cairo_reference(self.0) }
82 }
83}
84
85#[cfg(feature = "use_glib")]
86impl FromGlibPtrNone<*mut ffi::cairo_t> for Context {
87 #[inline]
88 unsafe fn from_glib_none(ptr: *mut ffi::cairo_t) -> Context {
89 Self::from_raw_none(ptr)
90 }
91}
92
93#[cfg(feature = "use_glib")]
94impl FromGlibPtrBorrow<*mut ffi::cairo_t> for Context {
95 #[inline]
96 unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_t) -> Context {
97 Self::from_raw_borrow(ptr)
98 }
99}
100
101#[cfg(feature = "use_glib")]
102impl FromGlibPtrFull<*mut ffi::cairo_t> for Context {
103 #[inline]
104 unsafe fn from_glib_full(ptr: *mut ffi::cairo_t) -> Context {
105 Self::from_raw_full(ptr)
106 }
107}
108
109#[cfg(feature = "use_glib")]
110gvalue_impl!(
111 Context,
112 cairo_t,
113 ffi::gobject::cairo_gobject_context_get_type
114);
115
116impl Clone for Context {
117 fn clone(&self) -> Context {
118 unsafe { Self::from_raw_none(self.to_raw_none()) }
119 }
120}
121
122impl Drop for Context {
123 fn drop(&mut self) {
124 if !self.1 {
125 unsafe {
126 ffi::cairo_destroy(self.0);
127 }
128 }
129 }
130}
131
132impl Context {
133 #[inline]
134 pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_t) -> Context {
135 assert!(!ptr.is_null());
136 ffi::cairo_reference(ptr);
137 Context(ptr, false)
138 }
139
140 #[inline]
141 pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_t) -> Context {
142 assert!(!ptr.is_null());
143 Context(ptr, true)
144 }
145
146 #[inline]
147 pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_t) -> Context {
148 assert!(!ptr.is_null());
149 Context(ptr, false)
150 }
151
152 pub fn to_raw_none(&self) -> *mut ffi::cairo_t {
153 self.0
154 }
155
156 pub fn ensure_status(&self) {
157 self.status().ensure_valid();
158 }
159
160 pub fn new(target: &Surface) -> Context {
161 unsafe { Self::from_raw_full(ffi::cairo_create(target.to_raw_none())) }
162 }
163
164 pub fn status(&self) -> Status {
165 unsafe { Status::from(ffi::cairo_status(self.0)) }
166 }
167
168 pub fn save(&self) {
169 unsafe { ffi::cairo_save(self.0) }
170 self.ensure_status()
171 }
172
173 pub fn restore(&self) {
174 unsafe { ffi::cairo_restore(self.0) }
175 self.ensure_status()
176 }
177
178 pub fn get_target(&self) -> Surface {
179 unsafe { Surface::from_raw_none(ffi::cairo_get_target(self.0)) }
180 }
181
182 pub fn push_group(&self) {
183 unsafe { ffi::cairo_push_group(self.0) }
184 }
185
186 pub fn push_group_with_content(&self, content: Content) {
187 unsafe { ffi::cairo_push_group_with_content(self.0, content.into()) }
188 }
189
190 pub fn pop_group(&self) -> Pattern {
191 unsafe { Pattern::from_raw_full(ffi::cairo_pop_group(self.0)) }
192 }
193
194 pub fn pop_group_to_source(&self) {
195 unsafe { ffi::cairo_pop_group_to_source(self.0) }
196 }
197
198 pub fn get_group_target(&self) -> Surface {
199 unsafe { Surface::from_raw_none(ffi::cairo_get_group_target(self.0)) }
200 }
201
202 pub fn set_source_rgb(&self, red: f64, green: f64, blue: f64) {
203 unsafe { ffi::cairo_set_source_rgb(self.0, red, green, blue) }
204 }
205
206 pub fn set_source_rgba(&self, red: f64, green: f64, blue: f64, alpha: f64) {
207 unsafe { ffi::cairo_set_source_rgba(self.0, red, green, blue, alpha) }
208 }
209
210 pub fn set_source(&self, source: &Pattern) {
211 unsafe {
212 ffi::cairo_set_source(self.0, source.to_raw_none());
213 }
214 self.ensure_status();
215 }
216
217 pub fn get_source(&self) -> Pattern {
218 unsafe { Pattern::from_raw_none(ffi::cairo_get_source(self.0)) }
219 }
220
221 pub fn set_source_surface(&self, surface: &Surface, x: f64, y: f64) {
222 unsafe {
223 ffi::cairo_set_source_surface(self.0, surface.to_raw_none(), x, y);
224 }
225 }
226
227 pub fn set_antialias(&self, antialias: Antialias) {
228 unsafe { ffi::cairo_set_antialias(self.0, antialias.into()) }
229 self.ensure_status()
230 }
231
232 pub fn get_antialias(&self) -> Antialias {
233 unsafe { Antialias::from(ffi::cairo_get_antialias(self.0)) }
234 }
235
236 pub fn set_dash(&self, dashes: &[f64], offset: f64) {
237 unsafe { ffi::cairo_set_dash(self.0, dashes.as_ptr(), dashes.len() as i32, offset) }
238 self.ensure_status(); }
240
241 pub fn get_dash_count(&self) -> i32 {
242 unsafe { ffi::cairo_get_dash_count(self.0) }
243 }
244
245 pub fn get_dash(&self) -> (Vec<f64>, f64) {
246 let dash_count = self.get_dash_count() as usize;
247 let mut dashes: Vec<f64> = Vec::with_capacity(dash_count);
248 let mut offset: f64 = 0.0;
249
250 unsafe {
251 ffi::cairo_get_dash(self.0, dashes.as_mut_ptr(), &mut offset);
252 dashes.set_len(dash_count);
253 (dashes, offset)
254 }
255 }
256
257 pub fn get_dash_dashes(&self) -> Vec<f64> {
258 let (dashes, _) = self.get_dash();
259 dashes
260 }
261
262 pub fn get_dash_offset(&self) -> f64 {
263 let (_, offset) = self.get_dash();
264 offset
265 }
266
267 pub fn set_fill_rule(&self, fill_rule: FillRule) {
268 unsafe {
269 ffi::cairo_set_fill_rule(self.0, fill_rule.into());
270 }
271 self.ensure_status();
272 }
273
274 pub fn get_fill_rule(&self) -> FillRule {
275 unsafe { FillRule::from(ffi::cairo_get_fill_rule(self.0)) }
276 }
277
278 pub fn set_line_cap(&self, arg: LineCap) {
279 unsafe { ffi::cairo_set_line_cap(self.0, arg.into()) }
280 self.ensure_status();
281 }
282
283 pub fn get_line_cap(&self) -> LineCap {
284 unsafe { LineCap::from(ffi::cairo_get_line_cap(self.0)) }
285 }
286
287 pub fn set_line_join(&self, arg: LineJoin) {
288 unsafe { ffi::cairo_set_line_join(self.0, arg.into()) }
289 self.ensure_status();
290 }
291
292 pub fn get_line_join(&self) -> LineJoin {
293 unsafe { LineJoin::from(ffi::cairo_get_line_join(self.0)) }
294 }
295
296 pub fn set_line_width(&self, arg: f64) {
297 unsafe { ffi::cairo_set_line_width(self.0, arg) }
298 self.ensure_status();
299 }
300
301 pub fn get_line_width(&self) -> f64 {
302 unsafe { ffi::cairo_get_line_width(self.0) }
303 }
304
305 pub fn set_miter_limit(&self, arg: f64) {
306 unsafe { ffi::cairo_set_miter_limit(self.0, arg) }
307 self.ensure_status();
308 }
309
310 pub fn get_miter_limit(&self) -> f64 {
311 unsafe { ffi::cairo_get_miter_limit(self.0) }
312 }
313
314 pub fn set_operator(&self, op: Operator) {
315 unsafe {
316 ffi::cairo_set_operator(self.0, op.into());
317 }
318 }
319
320 pub fn get_operator(&self) -> Operator {
321 unsafe { Operator::from(ffi::cairo_get_operator(self.0)) }
322 }
323
324 pub fn set_tolerance(&self, arg: f64) {
325 unsafe { ffi::cairo_set_tolerance(self.0, arg) }
326 self.ensure_status();
327 }
328
329 pub fn get_tolerance(&self) -> f64 {
330 unsafe { ffi::cairo_get_tolerance(self.0) }
331 }
332
333 pub fn clip(&self) {
334 unsafe { ffi::cairo_clip(self.0) }
335 }
336
337 pub fn clip_preserve(&self) {
338 unsafe { ffi::cairo_clip_preserve(self.0) }
339 }
340
341 pub fn clip_extents(&self) -> (f64, f64, f64, f64) {
342 let mut x1: f64 = 0.0;
343 let mut y1: f64 = 0.0;
344 let mut x2: f64 = 0.0;
345 let mut y2: f64 = 0.0;
346
347 unsafe {
348 ffi::cairo_clip_extents(self.0, &mut x1, &mut y1, &mut x2, &mut y2);
349 }
350 (x1, y1, x2, y2)
351 }
352
353 pub fn in_clip(&self, x: f64, y: f64) -> bool {
354 unsafe { ffi::cairo_in_clip(self.0, x, y).as_bool() }
355 }
356
357 pub fn reset_clip(&self) {
358 unsafe { ffi::cairo_reset_clip(self.0) }
359 self.ensure_status()
360 }
361
362 pub fn copy_clip_rectangle_list(&self) -> RectangleList {
363 unsafe {
364 let rectangle_list = ffi::cairo_copy_clip_rectangle_list(self.0);
365
366 Status::from((*rectangle_list).status).ensure_valid();
367
368 RectangleList {
369 ptr: rectangle_list,
370 }
371 }
372 }
373
374 pub fn fill(&self) {
375 unsafe { ffi::cairo_fill(self.0) }
376 }
377
378 pub fn fill_preserve(&self) {
379 unsafe { ffi::cairo_fill_preserve(self.0) }
380 }
381
382 pub fn fill_extents(&self) -> (f64, f64, f64, f64) {
383 let mut x1: f64 = 0.0;
384 let mut y1: f64 = 0.0;
385 let mut x2: f64 = 0.0;
386 let mut y2: f64 = 0.0;
387
388 unsafe {
389 ffi::cairo_fill_extents(self.0, &mut x1, &mut y1, &mut x2, &mut y2);
390 }
391 (x1, y1, x2, y2)
392 }
393
394 pub fn in_fill(&self, x: f64, y: f64) -> bool {
395 unsafe { ffi::cairo_in_fill(self.0, x, y).as_bool() }
396 }
397
398 pub fn mask(&self, pattern: &Pattern) {
399 unsafe { ffi::cairo_mask(self.0, pattern.to_raw_none()) }
400 }
401
402 pub fn mask_surface(&self, surface: &Surface, x: f64, y: f64) {
403 unsafe {
404 ffi::cairo_mask_surface(self.0, surface.to_raw_none(), x, y);
405 }
406 }
407
408 pub fn paint(&self) {
409 unsafe { ffi::cairo_paint(self.0) }
410 }
411
412 pub fn paint_with_alpha(&self, alpha: f64) {
413 unsafe { ffi::cairo_paint_with_alpha(self.0, alpha) }
414 }
415
416 pub fn stroke(&self) {
417 unsafe { ffi::cairo_stroke(self.0) }
418 }
419
420 pub fn stroke_preserve(&self) {
421 unsafe { ffi::cairo_stroke_preserve(self.0) }
422 }
423
424 pub fn stroke_extents(&self) -> (f64, f64, f64, f64) {
425 let mut x1: f64 = 0.0;
426 let mut y1: f64 = 0.0;
427 let mut x2: f64 = 0.0;
428 let mut y2: f64 = 0.0;
429
430 unsafe {
431 ffi::cairo_stroke_extents(self.0, &mut x1, &mut y1, &mut x2, &mut y2);
432 }
433 (x1, y1, x2, y2)
434 }
435
436 pub fn in_stroke(&self, x: f64, y: f64) -> bool {
437 unsafe { ffi::cairo_in_stroke(self.0, x, y).as_bool() }
438 }
439
440 pub fn copy_page(&self) {
441 unsafe { ffi::cairo_copy_page(self.0) }
442 }
443
444 pub fn show_page(&self) {
445 unsafe { ffi::cairo_show_page(self.0) }
446 }
447
448 pub fn get_reference_count(&self) -> u32 {
449 unsafe { ffi::cairo_get_reference_count(self.0) }
450 }
451
452 pub fn translate(&self, tx: f64, ty: f64) {
455 unsafe { ffi::cairo_translate(self.0, tx, ty) }
456 }
457
458 pub fn scale(&self, sx: f64, sy: f64) {
459 unsafe { ffi::cairo_scale(self.0, sx, sy) }
460 }
461
462 pub fn rotate(&self, angle: f64) {
463 unsafe { ffi::cairo_rotate(self.0, angle) }
464 }
465
466 pub fn transform(&self, matrix: Matrix) {
467 unsafe {
468 ffi::cairo_transform(self.0, matrix.ptr());
469 }
470 }
471
472 pub fn set_matrix(&self, matrix: Matrix) {
473 unsafe {
474 ffi::cairo_set_matrix(self.0, matrix.ptr());
475 }
476 }
477
478 pub fn get_matrix(&self) -> Matrix {
479 let mut matrix = Matrix::null();
480 unsafe {
481 ffi::cairo_get_matrix(self.0, matrix.mut_ptr());
482 }
483 matrix
484 }
485
486 pub fn identity_matrix(&self) {
487 unsafe { ffi::cairo_identity_matrix(self.0) }
488 }
489
490 pub fn user_to_device(&self, mut x: f64, mut y: f64) -> (f64, f64) {
491 unsafe {
492 ffi::cairo_user_to_device(self.0, &mut x, &mut y);
493 (x, y)
494 }
495 }
496
497 pub fn user_to_device_distance(&self, mut dx: f64, mut dy: f64) -> (f64, f64) {
498 unsafe {
499 ffi::cairo_user_to_device_distance(self.0, &mut dx, &mut dy);
500 (dx, dy)
501 }
502 }
503
504 pub fn device_to_user(&self, mut x: f64, mut y: f64) -> (f64, f64) {
505 unsafe {
506 ffi::cairo_device_to_user(self.0, &mut x, &mut y);
507 (x, y)
508 }
509 }
510
511 pub fn device_to_user_distance(&self, mut dx: f64, mut dy: f64) -> (f64, f64) {
512 unsafe {
513 ffi::cairo_device_to_user_distance(self.0, &mut dx, &mut dy);
514 (dx, dy)
515 }
516 }
517
518 pub fn select_font_face(&self, family: &str, slant: FontSlant, weight: FontWeight) {
521 unsafe {
522 let family = CString::new(family).unwrap();
523 ffi::cairo_select_font_face(self.0, family.as_ptr(), slant.into(), weight.into())
524 }
525 }
526
527 pub fn set_font_size(&self, size: f64) {
528 unsafe { ffi::cairo_set_font_size(self.0, size) }
529 }
530
531 pub fn set_font_matrix(&self, matrix: Matrix) {
533 unsafe { ffi::cairo_set_font_matrix(self.0, matrix.ptr()) }
534 }
535
536 pub fn get_font_matrix(&self) -> Matrix {
537 let mut matrix = Matrix::null();
538 unsafe {
539 ffi::cairo_get_font_matrix(self.0, matrix.mut_ptr());
540 }
541 matrix
542 }
543
544 pub fn set_font_options(&self, options: &FontOptions) {
545 unsafe { ffi::cairo_set_font_options(self.0, options.to_raw_none()) }
546 }
547
548 pub fn get_font_options(&self) -> FontOptions {
549 let out = FontOptions::new();
550 unsafe {
551 ffi::cairo_get_font_options(self.0, out.to_raw_none());
552 }
553 out
554 }
555
556 pub fn set_font_face(&self, font_face: &FontFace) {
557 unsafe { ffi::cairo_set_font_face(self.0, font_face.to_raw_none()) }
558 }
559
560 pub fn get_font_face(&self) -> FontFace {
561 unsafe { FontFace::from_raw_none(ffi::cairo_get_font_face(self.0)) }
562 }
563
564 pub fn set_scaled_font(&self, scaled_font: &ScaledFont) {
565 unsafe { ffi::cairo_set_scaled_font(self.0, scaled_font.to_raw_none()) }
566 }
567
568 pub fn get_scaled_font(&self) -> ScaledFont {
569 unsafe { ScaledFont::from_raw_none(ffi::cairo_get_scaled_font(self.0)) }
570 }
571
572 pub fn show_text(&self, text: &str) {
573 unsafe {
574 let text = CString::new(text).unwrap();
575 ffi::cairo_show_text(self.0, text.as_ptr())
576 }
577 }
578
579 pub fn show_glyphs(&self, glyphs: &[Glyph]) {
580 unsafe { ffi::cairo_show_glyphs(self.0, glyphs.as_ptr(), glyphs.len() as c_int) }
581 }
582
583 pub fn show_text_glyphs(
584 &self,
585 text: &str,
586 glyphs: &[Glyph],
587 clusters: &[TextCluster],
588 cluster_flags: TextClusterFlags,
589 ) {
590 unsafe {
591 let text = CString::new(text).unwrap();
592 ffi::cairo_show_text_glyphs(
593 self.0,
594 text.as_ptr(),
595 -1 as c_int, glyphs.as_ptr(),
597 glyphs.len() as c_int,
598 clusters.as_ptr(),
599 clusters.len() as c_int,
600 cluster_flags.into(),
601 )
602 }
603 }
604
605 pub fn font_extents(&self) -> FontExtents {
606 let mut extents = FontExtents {
607 ascent: 0.0,
608 descent: 0.0,
609 height: 0.0,
610 max_x_advance: 0.0,
611 max_y_advance: 0.0,
612 };
613
614 unsafe {
615 ffi::cairo_font_extents(self.0, &mut extents);
616 }
617
618 extents
619 }
620
621 pub fn text_extents(&self, text: &str) -> TextExtents {
622 let mut extents = TextExtents {
623 x_bearing: 0.0,
624 y_bearing: 0.0,
625 width: 0.0,
626 height: 0.0,
627 x_advance: 0.0,
628 y_advance: 0.0,
629 };
630
631 unsafe {
632 let text = CString::new(text).unwrap();
633 ffi::cairo_text_extents(self.0, text.as_ptr(), &mut extents);
634 }
635 extents
636 }
637
638 pub fn glyph_extents(&self, glyphs: &[Glyph]) -> TextExtents {
639 let mut extents = TextExtents {
640 x_bearing: 0.0,
641 y_bearing: 0.0,
642 width: 0.0,
643 height: 0.0,
644 x_advance: 0.0,
645 y_advance: 0.0,
646 };
647
648 unsafe {
649 ffi::cairo_glyph_extents(self.0, glyphs.as_ptr(), glyphs.len() as c_int, &mut extents);
650 }
651
652 extents
653 }
654
655 pub fn copy_path(&self) -> Path {
658 unsafe { Path::from_raw_full(ffi::cairo_copy_path(self.0)) }
659 }
660
661 pub fn copy_path_flat(&self) -> Path {
662 unsafe { Path::from_raw_full(ffi::cairo_copy_path_flat(self.0)) }
663 }
664
665 pub fn append_path(&self, path: &Path) {
666 unsafe { ffi::cairo_append_path(self.0, path.as_ptr()) }
667 }
668
669 pub fn has_current_point(&self) -> bool {
670 unsafe { ffi::cairo_has_current_point(self.0).as_bool() }
671 }
672
673 pub fn get_current_point(&self) -> (f64, f64) {
674 unsafe {
675 let mut x = 0.0;
676 let mut y = 0.0;
677 ffi::cairo_get_current_point(self.0, &mut x, &mut y);
678 (x, y)
679 }
680 }
681
682 pub fn new_path(&self) {
683 unsafe { ffi::cairo_new_path(self.0) }
684 }
685
686 pub fn new_sub_path(&self) {
687 unsafe { ffi::cairo_new_sub_path(self.0) }
688 }
689
690 pub fn close_path(&self) {
691 unsafe { ffi::cairo_close_path(self.0) }
692 }
693
694 pub fn arc(&self, xc: f64, yc: f64, radius: f64, angle1: f64, angle2: f64) {
695 unsafe { ffi::cairo_arc(self.0, xc, yc, radius, angle1, angle2) }
696 }
697
698 pub fn arc_negative(&self, xc: f64, yc: f64, radius: f64, angle1: f64, angle2: f64) {
699 unsafe { ffi::cairo_arc_negative(self.0, xc, yc, radius, angle1, angle2) }
700 }
701
702 pub fn curve_to(&self, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) {
703 unsafe { ffi::cairo_curve_to(self.0, x1, y1, x2, y2, x3, y3) }
704 }
705
706 pub fn line_to(&self, x: f64, y: f64) {
707 unsafe { ffi::cairo_line_to(self.0, x, y) }
708 }
709
710 pub fn move_to(&self, x: f64, y: f64) {
711 unsafe { ffi::cairo_move_to(self.0, x, y) }
712 }
713
714 pub fn rectangle(&self, x: f64, y: f64, width: f64, height: f64) {
715 unsafe { ffi::cairo_rectangle(self.0, x, y, width, height) }
716 }
717
718 pub fn text_path(&self, str_: &str) {
719 unsafe {
720 let str_ = CString::new(str_).unwrap();
721 ffi::cairo_text_path(self.0, str_.as_ptr())
722 }
723 }
724
725 pub fn glyph_path(&self, glyphs: &[Glyph]) {
726 unsafe { ffi::cairo_glyph_path(self.0, glyphs.as_ptr(), glyphs.len() as i32) }
727 }
728
729 pub fn rel_curve_to(&self, dx1: f64, dy1: f64, dx2: f64, dy2: f64, dx3: f64, dy3: f64) {
730 unsafe { ffi::cairo_rel_curve_to(self.0, dx1, dy1, dx2, dy2, dx3, dy3) }
731 }
732
733 pub fn rel_line_to(&self, dx: f64, dy: f64) {
734 unsafe { ffi::cairo_rel_line_to(self.0, dx, dy) }
735 }
736
737 pub fn rel_move_to(&self, dx: f64, dy: f64) {
738 unsafe { ffi::cairo_rel_move_to(self.0, dx, dy) }
739 }
740
741 pub fn path_extents(&self) -> (f64, f64, f64, f64) {
742 let mut x1: f64 = 0.0;
743 let mut y1: f64 = 0.0;
744 let mut x2: f64 = 0.0;
745 let mut y2: f64 = 0.0;
746
747 unsafe {
748 ffi::cairo_path_extents(self.0, &mut x1, &mut y1, &mut x2, &mut y2);
749 }
750 (x1, y1, x2, y2)
751 }
752
753 #[cfg(any(feature = "v1_16", feature = "dox"))]
754 pub fn tag_begin(&self, tag_name: &str, attributes: &str) {
755 unsafe {
756 let tag_name = CString::new(tag_name).unwrap();
757 let attributes = CString::new(attributes).unwrap();
758 ffi::cairo_tag_begin(self.0, tag_name.as_ptr(), attributes.as_ptr())
759 }
760 }
761
762 #[cfg(any(feature = "v1_16", feature = "dox"))]
763 pub fn tag_end(&self, tag_name: &str) {
764 unsafe {
765 let tag_name = CString::new(tag_name).unwrap();
766 ffi::cairo_tag_end(self.0, tag_name.as_ptr())
767 }
768 }
769}
770
771impl fmt::Display for Context {
772 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
773 write!(f, "Context")
774 }
775}
776
777#[cfg(test)]
778mod tests {
779 use super::*;
780 use enums::Format;
781 use image_surface::ImageSurface;
782 use patterns::LinearGradient;
783
784 fn create_ctx() -> Context {
785 let surface = ImageSurface::create(Format::ARgb32, 10, 10).unwrap();
786 Context::new(&surface)
787 }
788
789 #[test]
790 fn drop_non_reference_pattern_from_ctx() {
791 let ctx = create_ctx();
792 ctx.get_source();
793 }
794
795 #[test]
796 fn drop_non_reference_pattern() {
797 let ctx = create_ctx();
798 let pattern = LinearGradient::new(1.0f64, 2.0f64, 3.0f64, 4.0f64);
799 ctx.set_source(&pattern);
800 }
801}