cairo/
lib.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![allow(clippy::missing_safety_doc)]
5#![doc = include_str!("../README.md")]
6
7pub use cairo_sys as ffi;
8#[cfg(feature = "freetype")]
9#[cfg_attr(docsrs, doc(cfg(feature = "freetype")))]
10pub use freetype;
11#[cfg(feature = "use_glib")]
12#[cfg_attr(docsrs, doc(cfg(feature = "use_glib")))]
13pub use glib;
14
15// Helper macros for our GValue related trait impls
16#[cfg(feature = "use_glib")]
17#[cfg_attr(docsrs, doc(cfg(feature = "use_glib")))]
18macro_rules! gvalue_impl_inner {
19    ($name:ty, $ffi_name:ty, $get_type:expr) => {
20        #[allow(unused_imports)]
21        use glib::translate::*;
22
23        impl glib::prelude::StaticType for $name {
24            #[inline]
25            fn static_type() -> glib::types::Type {
26                unsafe { from_glib($get_type()) }
27            }
28        }
29
30        impl glib::value::ValueType for $name {
31            type Type = Self;
32        }
33
34        impl glib::value::ValueTypeOptional for $name {}
35    };
36}
37
38#[cfg(feature = "use_glib")]
39#[cfg_attr(docsrs, doc(cfg(feature = "use_glib")))]
40macro_rules! gvalue_impl {
41    ($name:ty, $ffi_name:ty, $get_type:expr) => {
42        gvalue_impl_inner!($name, $ffi_name, $get_type);
43
44        unsafe impl<'a> glib::value::FromValue<'a> for $name {
45            type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
46
47            unsafe fn from_value(value: &'a glib::Value) -> Self {
48                unsafe {
49                    let ptr = glib::gobject_ffi::g_value_dup_boxed(
50                        glib::translate::ToGlibPtr::to_glib_none(value).0,
51                    );
52                    debug_assert!(!ptr.is_null());
53                    <$name as glib::translate::FromGlibPtrFull<*mut $ffi_name>>::from_glib_full(
54                        ptr as *mut $ffi_name,
55                    )
56                }
57            }
58        }
59
60        unsafe impl<'a> glib::value::FromValue<'a> for &'a $name {
61            type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
62
63            unsafe fn from_value(value: &'a glib::Value) -> Self {
64                unsafe {
65                    debug_assert_eq!(
66                        std::mem::size_of::<Self>(),
67                        std::mem::size_of::<glib::ffi::gpointer>()
68                    );
69                    let value = &*(value as *const glib::Value as *const glib::gobject_ffi::GValue);
70                    let ptr = &value.data[0].v_pointer as *const glib::ffi::gpointer
71                        as *const *const $ffi_name;
72                    debug_assert!(!(*ptr).is_null());
73                    &*(ptr as *const $name)
74                }
75            }
76        }
77
78        impl glib::value::ToValue for $name {
79            fn to_value(&self) -> glib::Value {
80                unsafe {
81                    let mut value = glib::Value::from_type_unchecked(
82                        <$name as glib::prelude::StaticType>::static_type(),
83                    );
84                    glib::gobject_ffi::g_value_take_boxed(
85                        value.to_glib_none_mut().0,
86                        self.to_glib_full() as *mut _,
87                    );
88                    value
89                }
90            }
91
92            fn value_type(&self) -> glib::Type {
93                <$name as glib::prelude::StaticType>::static_type()
94            }
95        }
96
97        impl From<$name> for glib::Value {
98            fn from(v: $name) -> Self {
99                unsafe {
100                    let mut value = glib::Value::from_type_unchecked(
101                        <$name as glib::prelude::StaticType>::static_type(),
102                    );
103                    glib::gobject_ffi::g_value_take_boxed(
104                        value.to_glib_none_mut().0,
105                        glib::translate::IntoGlibPtr::into_glib_ptr(v) as *mut _,
106                    );
107                    value
108                }
109            }
110        }
111
112        impl glib::value::ToValueOptional for $name {
113            fn to_value_optional(s: Option<&Self>) -> glib::Value {
114                let mut value = glib::Value::for_value_type::<Self>();
115                unsafe {
116                    glib::gobject_ffi::g_value_take_boxed(
117                        value.to_glib_none_mut().0,
118                        glib::translate::ToGlibPtr::to_glib_full(&s) as *mut _,
119                    );
120                }
121
122                value
123            }
124        }
125    };
126}
127
128#[cfg(feature = "use_glib")]
129#[cfg_attr(docsrs, doc(cfg(feature = "use_glib")))]
130macro_rules! gvalue_impl_inline {
131    ($name:ty, $ffi_name:ty, $get_type:expr) => {
132        gvalue_impl_inner!($name, $ffi_name, $get_type);
133
134        unsafe impl<'a> glib::value::FromValue<'a> for $name {
135            type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
136
137            unsafe fn from_value(value: &'a glib::Value) -> Self {
138                unsafe {
139                    let ptr = glib::gobject_ffi::g_value_get_boxed(
140                        glib::translate::ToGlibPtr::to_glib_none(value).0,
141                    );
142                    debug_assert!(!ptr.is_null());
143                    <$name as glib::translate::FromGlibPtrNone<*mut $ffi_name>>::from_glib_none(
144                        ptr as *mut $ffi_name,
145                    )
146                }
147            }
148        }
149
150        unsafe impl<'a> glib::value::FromValue<'a> for &'a $name {
151            type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
152
153            unsafe fn from_value(value: &'a glib::Value) -> Self {
154                unsafe {
155                    let ptr = glib::gobject_ffi::g_value_get_boxed(
156                        glib::translate::ToGlibPtr::to_glib_none(value).0,
157                    );
158                    debug_assert!(!ptr.is_null());
159                    &*(ptr as *mut $name)
160                }
161            }
162        }
163
164        impl glib::value::ToValue for $name {
165            fn to_value(&self) -> glib::Value {
166                unsafe {
167                    let ptr =
168                        glib::ffi::g_malloc0(std::mem::size_of::<$ffi_name>()) as *mut $ffi_name;
169                    ptr.write(self.0);
170                    let mut value = glib::Value::from_type_unchecked(
171                        <$name as glib::prelude::StaticType>::static_type(),
172                    );
173                    glib::gobject_ffi::g_value_take_boxed(
174                        value.to_glib_none_mut().0,
175                        ptr as *mut _,
176                    );
177                    value
178                }
179            }
180
181            fn value_type(&self) -> glib::Type {
182                <$name as glib::prelude::StaticType>::static_type()
183            }
184        }
185
186        impl glib::value::ToValueOptional for $name {
187            fn to_value_optional(s: Option<&Self>) -> glib::Value {
188                let ptr: *mut $ffi_name = match s {
189                    Some(s) => unsafe {
190                        let ptr = glib::ffi::g_malloc0(std::mem::size_of::<$ffi_name>())
191                            as *mut $ffi_name;
192                        ptr.write(s.0);
193                        ptr
194                    },
195                    None => std::ptr::null_mut(),
196                };
197                let mut value = glib::Value::for_value_type::<Self>();
198                unsafe {
199                    glib::gobject_ffi::g_value_take_boxed(
200                        value.to_glib_none_mut().0,
201                        ptr as *mut _,
202                    );
203                }
204
205                value
206            }
207        }
208    };
209}
210
211#[cfg(feature = "pdf")]
212#[cfg_attr(docsrs, doc(cfg(feature = "pdf")))]
213pub use pdf::PdfSurface;
214#[cfg(feature = "ps")]
215#[cfg_attr(docsrs, doc(cfg(feature = "ps")))]
216pub use ps::PsSurface;
217#[cfg(any(feature = "pdf", feature = "svg", feature = "ps"))]
218#[cfg_attr(
219    docsrs,
220    doc(cfg(any(feature = "pdf", feature = "svg", feature = "ps")))
221)]
222pub use stream::StreamWithError;
223#[cfg(feature = "svg")]
224#[cfg_attr(docsrs, doc(cfg(feature = "svg")))]
225pub use svg::SvgSurface;
226#[cfg(feature = "xcb")]
227#[cfg_attr(docsrs, doc(cfg(feature = "xcb")))]
228pub use xcb::{
229    XCBConnection, XCBDrawable, XCBPixmap, XCBRenderPictFormInfo, XCBScreen, XCBSurface,
230    XCBVisualType,
231};
232
233pub use crate::{
234    context::{Context, RectangleList},
235    device::Device,
236    enums::*,
237    error::{BorrowError, Error, IoError, Result},
238    font::{
239        Antialias, FontExtents, FontFace, FontOptions, FontSlant, FontType, FontWeight, Glyph,
240        HintMetrics, HintStyle, ScaledFont, SubpixelOrder, TextCluster, TextExtents, UserFontFace,
241    },
242    image_surface::{ImageSurface, ImageSurfaceData, ImageSurfaceDataOwned},
243    matrices::Matrix,
244    paths::{Path, PathSegment, PathSegments},
245    patterns::{
246        Gradient, LinearGradient, Mesh, Pattern, RadialGradient, SolidPattern, SurfacePattern,
247    },
248    recording_surface::RecordingSurface,
249    rectangle::Rectangle,
250    rectangle_int::RectangleInt,
251    region::Region,
252    surface::{MappedImageSurface, Surface},
253    user_data::UserDataKey,
254};
255
256#[macro_use]
257mod surface_macros;
258#[macro_use]
259mod user_data;
260mod constants;
261pub use crate::constants::*;
262mod utils;
263pub use crate::utils::{Version, debug_reset_static_data, version_string};
264mod context;
265mod device;
266mod enums;
267mod error;
268mod font;
269mod image_surface;
270mod matrices;
271mod paths;
272mod patterns;
273mod recording_surface;
274mod rectangle;
275mod rectangle_int;
276mod region;
277mod surface;
278#[cfg(feature = "png")]
279mod surface_png;
280#[cfg(feature = "xcb")]
281mod xcb;
282
283#[cfg(any(feature = "pdf", feature = "svg", feature = "ps"))]
284#[macro_use]
285mod stream;
286#[cfg(feature = "pdf")]
287mod pdf;
288#[cfg(feature = "ps")]
289mod ps;
290#[cfg(feature = "svg")]
291mod svg;
292
293#[cfg(all(target_os = "macos", feature = "quartz-surface"))]
294mod quartz_surface;
295#[cfg(all(target_os = "macos", feature = "quartz-surface"))]
296pub use quartz_surface::QuartzSurface;
297
298#[cfg(all(windows, feature = "win32-surface"))]
299mod win32_surface;
300
301#[cfg(all(windows, feature = "win32-surface"))]
302#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "win32-surface"))))]
303pub use win32_surface::Win32Surface;
304
305#[cfg(not(feature = "use_glib"))]
306#[cfg_attr(docsrs, doc(cfg(not(feature = "use_glib"))))]
307mod borrowed {
308    use std::mem;
309
310    /// Wrapper around values representing borrowed C memory.
311    ///
312    /// This is returned by `from_glib_borrow()` and ensures that the wrapped value
313    /// is never dropped when going out of scope.
314    ///
315    /// Borrowed values must never be passed by value or mutable reference to safe Rust code and must
316    /// not leave the C scope in which they are valid.
317    #[derive(Debug)]
318    pub struct Borrowed<T>(mem::ManuallyDrop<T>);
319
320    impl<T> Borrowed<T> {
321        /// Creates a new borrowed value.
322        #[inline]
323        pub fn new(val: T) -> Self {
324            Self(mem::ManuallyDrop::new(val))
325        }
326
327        /// Extracts the contained value.
328        ///
329        /// The returned value must never be dropped and instead has to be passed to `mem::forget()` or
330        /// be directly wrapped in `mem::ManuallyDrop` or another `Borrowed` wrapper.
331        #[inline]
332        pub unsafe fn into_inner(self) -> T {
333            mem::ManuallyDrop::into_inner(self.0)
334        }
335    }
336
337    impl<T> AsRef<T> for Borrowed<T> {
338        #[inline]
339        fn as_ref(&self) -> &T {
340            &*self.0
341        }
342    }
343
344    impl<T> std::ops::Deref for Borrowed<T> {
345        type Target = T;
346
347        #[inline]
348        fn deref(&self) -> &T {
349            &*self.0
350        }
351    }
352}
353
354#[cfg(not(feature = "use_glib"))]
355#[cfg_attr(docsrs, doc(cfg(not(feature = "use_glib"))))]
356pub use borrowed::Borrowed;
357#[cfg(feature = "use_glib")]
358pub(crate) use glib::translate::Borrowed;