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