cairo-rs-0.14.9/.cargo_vcs_info.json0000644000000001120000000000100126400ustar { "git": { "sha1": "1a1fd7eab7217d505555a396b57eb9fc3509bdf6" } } cairo-rs-0.14.9/COPYRIGHT000064400000000000000000000012130072674642500127560ustar 00000000000000The gtk-rs Project is licensed under the MIT license, see the LICENSE file or . Copyrights in the gtk-rs Project project are retained by their contributors. No copyright assignment is required to contribute to the gtk-rs Project project. For full authorship information, see the version control history. This project provides interoperability with various GNOME libraries but doesn't distribute any parts of them. Distributing compiled libraries and executables that link to those libraries may be subject to terms of the GNU LGPL or other licenses. For more information check the license of each GNOME library. cairo-rs-0.14.9/Cargo.toml0000644000000031770000000000100106540ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "cairo-rs" version = "0.14.9" authors = ["The gtk-rs Project Developers"] description = "Rust bindings for the Cairo library" homepage = "https://gtk-rs.org/" documentation = "https://gtk-rs.org/gtk-rs-core/stable/latest/docs/cairo/" readme = "README.md" keywords = ["cairo", "gtk-rs", "gnome", "GUI"] license = "MIT" repository = "https://github.com/gtk-rs/gtk-rs-core" [package.metadata.docs.rs] features = ["dox"] [lib] name = "cairo" [dependencies.bitflags] version = "1.0" [dependencies.ffi] version = "0.14.0" package = "cairo-sys-rs" [dependencies.freetype-crate] version = "0.7.0" optional = true package = "freetype" [dependencies.glib] version = "0.14.0" optional = true [dependencies.libc] version = "0.2" [dependencies.thiserror] version = "1.0.10" [dev-dependencies.tempfile] version = "3.0" [features] default = ["use_glib"] dox = ["ffi/dox", "glib/dox", "freetype"] freetype = ["ffi/freetype", "freetype-crate"] pdf = ["ffi/pdf"] png = ["ffi/png"] ps = ["ffi/ps"] script = ["ffi/script"] svg = ["ffi/svg"] use_glib = ["glib", "ffi/use_glib"] v1_16 = ["ffi/v1_16"] win32-surface = ["ffi/win32-surface"] xcb = ["ffi/xcb"] xlib = ["ffi/xlib"] cairo-rs-0.14.9/Cargo.toml.orig000064400000000000000000000022070072674642500143560ustar 00000000000000[package] name = "cairo-rs" license = "MIT" homepage = "https://gtk-rs.org/" authors = ["The gtk-rs Project Developers"] keywords = ["cairo", "gtk-rs", "gnome", "GUI"] readme = "README.md" documentation = "https://gtk-rs.org/gtk-rs-core/stable/latest/docs/cairo/" version = "0.14.9" description = "Rust bindings for the Cairo library" repository = "https://github.com/gtk-rs/gtk-rs-core" edition = "2018" [lib] name = "cairo" [features] png = ["ffi/png"] pdf = ["ffi/pdf"] svg = ["ffi/svg"] ps = ["ffi/ps"] use_glib = ["glib", "ffi/use_glib"] v1_16 = ["ffi/v1_16"] default = ["use_glib"] freetype = ["ffi/freetype", "freetype-crate"] script = ["ffi/script"] xcb = ["ffi/xcb"] xlib = ["ffi/xlib"] dox = ["ffi/dox", "glib/dox", "freetype"] win32-surface = ["ffi/win32-surface"] [package.metadata.docs.rs] features = ["dox"] [dependencies.glib] optional = true version = "0.14.0" path = "./../glib" [dependencies.freetype-crate] package = "freetype" version = "0.7.0" optional = true [dependencies] ffi = {package = "cairo-sys-rs", path = "./sys", version = "0.14.0"} libc = "0.2" bitflags = "1.0" thiserror = "1.0.10" [dev-dependencies] tempfile = "3.0" cairo-rs-0.14.9/LICENSE000064400000000000000000000020000072674642500124630ustar 00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cairo-rs-0.14.9/README.md000064400000000000000000000022370072674642500127510ustar 00000000000000# cairo __Rust__ bindings for Rust and wrappers for __Cairo__, part of [gtk-rs-core](https://github.com/gtk-rs/gtk-rs-core). ![screenshot](https://guillaume-gomez.fr/image/cairo.png) ## Minimum supported Rust version Currently, the minimum supported Rust version is `1.51.0`. ## Documentation * [Rust API - Stable](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/cairo) * [Rust API - Development](https://gtk-rs.org/gtk-rs-core/git/docs/cairo) * [C API](https://www.cairographics.org/documentation/) ## Using We recommend using [crates from crates.io](https://crates.io/keywords/gtk-rs), as [demonstrated here](https://gtk-rs.org/#using). If you want to track the bleeding edge, use the git dependency instead: ```toml [dependencies] cairo-rs = { git = "https://github.com/gtk-rs/gtk-rs-core.git", package = "cairo-rs" } ``` Avoid mixing versioned and git crates like this: ```toml # This will not compile [dependencies] cairo-rs = "0.13" cairo-rs = { git = "https://github.com/gtk-rs/gtk-rs-core.git", package = "cairo-rs" } ``` ### See Also * [glib](https://crates.io/crates/glib) ## License __cairo__ is available under the MIT License, please refer to it. cairo-rs-0.14.9/src/constants.rs000064400000000000000000000024010072674642500146340ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. pub const MIME_TYPE_JPEG: &str = "image/jpeg"; pub const MIME_TYPE_PNG: &str = "image/png"; pub const MIME_TYPE_JP2: &str = "image/jp2"; pub const MIME_TYPE_URI: &str = "text/x-uri"; pub const MIME_TYPE_UNIQUE_ID: &str = "application/x-cairo.uuid"; pub const MIME_TYPE_JBIG2: &str = "application/x-cairo.jbig2"; pub const MIME_TYPE_JBIG2_GLOBAL: &str = "application/x-cairo.jbig2-global"; pub const MIME_TYPE_JBIG2_GLOBAL_ID: &str = "application/x-cairo.jbig2-global-id"; #[cfg(any(feature = "v1_16", feature = "dox"))] pub const MIME_TYPE_CCITT_FAX: &str = "image/g3fax"; #[cfg(any(feature = "v1_16", feature = "dox"))] pub const MIME_TYPE_CCITT_FAX_PARAMS: &str = "application/x-cairo.ccitt.params"; #[cfg(any(feature = "v1_16", feature = "dox"))] pub const MIME_TYPE_EPS: &str = "application/postscript"; #[cfg(any(feature = "v1_16", feature = "dox"))] pub const MIME_TYPE_EPS_PARAMS: &str = "application/x-cairo.eps.params"; #[cfg(any(feature = "v1_16", feature = "dox"))] pub const PDF_OUTLINE_ROOT: i32 = 0; #[cfg(any(feature = "v1_16", feature = "dox"))] pub const CAIRO_TAG_DEST: &str = "cairo.dest"; #[cfg(any(feature = "v1_16", feature = "dox"))] pub const CAIRO_TAG_LINK: &str = "Link"; cairo-rs-0.14.9/src/context.rs000064400000000000000000000732350072674642500143210ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use crate::font::{ FontExtents, FontFace, FontOptions, Glyph, ScaledFont, TextCluster, TextExtents, }; use crate::matrices::Matrix; use crate::paths::Path; use crate::Rectangle; use crate::{ Antialias, Content, FillRule, FontSlant, FontWeight, LineCap, LineJoin, Operator, TextClusterFlags, }; #[cfg(feature = "use_glib")] use glib::translate::*; use libc::c_int; use std::ffi::CString; use std::fmt; use std::ops; use std::ptr; use std::slice; use crate::error::Error; use crate::ffi::{cairo_rectangle_list_t, cairo_t}; use crate::patterns::Pattern; use crate::surface::Surface; use crate::utils::status_to_result; pub struct RectangleList { ptr: *mut cairo_rectangle_list_t, } impl ops::Deref for RectangleList { type Target = [Rectangle]; fn deref(&self) -> &[Rectangle] { unsafe { let ptr = (*self.ptr).rectangles as *mut Rectangle; let len = (*self.ptr).num_rectangles; if ptr.is_null() || len == 0 { &[] } else { slice::from_raw_parts(ptr, len as usize) } } } } impl Drop for RectangleList { fn drop(&mut self) { unsafe { ffi::cairo_rectangle_list_destroy(self.ptr); } } } impl fmt::Debug for RectangleList { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use std::ops::Deref; f.debug_tuple("RectangleList").field(&self.deref()).finish() } } impl fmt::Display for RectangleList { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "RectangleList") } } #[derive(Debug)] pub struct Context(ptr::NonNull); #[cfg(feature = "use_glib")] impl<'a> ToGlibPtr<'a, *mut ffi::cairo_t> for &'a Context { type Storage = &'a Context; #[inline] fn to_glib_none(&self) -> Stash<'a, *mut ffi::cairo_t, &'a Context> { Stash(self.0.as_ptr(), *self) } #[inline] fn to_glib_full(&self) -> *mut ffi::cairo_t { unsafe { ffi::cairo_reference(self.0.as_ptr()) } } } #[cfg(feature = "use_glib")] impl FromGlibPtrNone<*mut ffi::cairo_t> for Context { #[inline] unsafe fn from_glib_none(ptr: *mut ffi::cairo_t) -> Context { Self::from_raw_none(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrBorrow<*mut ffi::cairo_t> for Context { #[inline] unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_t) -> crate::Borrowed { Self::from_raw_borrow(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrFull<*mut ffi::cairo_t> for Context { #[inline] unsafe fn from_glib_full(ptr: *mut ffi::cairo_t) -> Context { Self::from_raw_full(ptr) } } #[cfg(feature = "use_glib")] gvalue_impl!( Context, cairo_t, ffi::gobject::cairo_gobject_context_get_type ); impl Clone for Context { fn clone(&self) -> Context { unsafe { Self::from_raw_none(self.to_raw_none()) } } } impl Drop for Context { fn drop(&mut self) { unsafe { ffi::cairo_destroy(self.0.as_ptr()); } } } impl Context { #[inline] pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_t) -> Context { assert!(!ptr.is_null()); ffi::cairo_reference(ptr); Context(ptr::NonNull::new_unchecked(ptr)) } #[inline] pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_t) -> crate::Borrowed { assert!(!ptr.is_null()); crate::Borrowed::new(Context(ptr::NonNull::new_unchecked(ptr))) } #[inline] pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_t) -> Context { assert!(!ptr.is_null()); Context(ptr::NonNull::new_unchecked(ptr)) } pub fn to_raw_none(&self) -> *mut ffi::cairo_t { self.0.as_ptr() } #[doc(alias = "cairo_status")] pub fn status(&self) -> Result<(), Error> { let status = unsafe { ffi::cairo_status(self.0.as_ptr()) }; status_to_result(status) } pub fn new(target: &Surface) -> Result { let ctx = unsafe { Self::from_raw_full(ffi::cairo_create(target.to_raw_none())) }; ctx.status().map(|_| ctx) } #[doc(alias = "cairo_save")] pub fn save(&self) -> Result<(), Error> { unsafe { ffi::cairo_save(self.0.as_ptr()) } self.status() } #[doc(alias = "cairo_restore")] pub fn restore(&self) -> Result<(), Error> { unsafe { ffi::cairo_restore(self.0.as_ptr()) } self.status() } #[doc(alias = "get_target")] #[doc(alias = "cairo_get_target")] pub fn target(&self) -> Surface { unsafe { Surface::from_raw_none(ffi::cairo_get_target(self.0.as_ptr())) } } #[doc(alias = "cairo_push_group")] pub fn push_group(&self) { unsafe { ffi::cairo_push_group(self.0.as_ptr()) } } #[doc(alias = "cairo_push_group_with_content")] pub fn push_group_with_content(&self, content: Content) { unsafe { ffi::cairo_push_group_with_content(self.0.as_ptr(), content.into()) } } #[doc(alias = "cairo_pop_group")] pub fn pop_group(&self) -> Result { let pattern = unsafe { Pattern::from_raw_full(ffi::cairo_pop_group(self.0.as_ptr())) }; self.status().map(|_| pattern) } #[doc(alias = "cairo_pop_group_to_source")] pub fn pop_group_to_source(&self) -> Result<(), Error> { unsafe { ffi::cairo_pop_group_to_source(self.0.as_ptr()) }; self.status() } #[doc(alias = "get_group_target")] #[doc(alias = "cairo_get_group_target")] pub fn group_target(&self) -> Surface { unsafe { Surface::from_raw_none(ffi::cairo_get_group_target(self.0.as_ptr())) } } #[doc(alias = "cairo_set_source_rgb")] pub fn set_source_rgb(&self, red: f64, green: f64, blue: f64) { unsafe { ffi::cairo_set_source_rgb(self.0.as_ptr(), red, green, blue) } } #[doc(alias = "cairo_set_source_rgba")] pub fn set_source_rgba(&self, red: f64, green: f64, blue: f64, alpha: f64) { unsafe { ffi::cairo_set_source_rgba(self.0.as_ptr(), red, green, blue, alpha) } } #[doc(alias = "cairo_set_source")] pub fn set_source(&self, source: &Pattern) -> Result<(), Error> { source.status()?; unsafe { ffi::cairo_set_source(self.0.as_ptr(), source.to_raw_none()); } self.status() } #[doc(alias = "get_source")] #[doc(alias = "cairo_get_source")] pub fn source(&self) -> Pattern { unsafe { Pattern::from_raw_none(ffi::cairo_get_source(self.0.as_ptr())) } } #[doc(alias = "cairo_set_source_surface")] pub fn set_source_surface(&self, surface: &Surface, x: f64, y: f64) -> Result<(), Error> { surface.status()?; unsafe { ffi::cairo_set_source_surface(self.0.as_ptr(), surface.to_raw_none(), x, y); } self.status() } #[doc(alias = "cairo_set_antialias")] pub fn set_antialias(&self, antialias: Antialias) { unsafe { ffi::cairo_set_antialias(self.0.as_ptr(), antialias.into()) } } #[doc(alias = "get_antialias")] #[doc(alias = "cairo_get_antialias")] pub fn antialias(&self) -> Antialias { unsafe { Antialias::from(ffi::cairo_get_antialias(self.0.as_ptr())) } } #[doc(alias = "cairo_set_dash")] pub fn set_dash(&self, dashes: &[f64], offset: f64) { unsafe { ffi::cairo_set_dash( self.0.as_ptr(), dashes.as_ptr(), dashes.len() as i32, offset, ) } } #[doc(alias = "get_dash_count")] #[doc(alias = "cairo_get_dash_count")] pub fn dash_count(&self) -> i32 { unsafe { ffi::cairo_get_dash_count(self.0.as_ptr()) } } #[doc(alias = "get_dash")] #[doc(alias = "cairo_get_dash")] pub fn dash(&self) -> (Vec, f64) { let dash_count = self.dash_count() as usize; let mut dashes: Vec = Vec::with_capacity(dash_count); let mut offset: f64 = 0.0; unsafe { ffi::cairo_get_dash(self.0.as_ptr(), dashes.as_mut_ptr(), &mut offset); dashes.set_len(dash_count); (dashes, offset) } } #[doc(alias = "get_dash_dashes")] pub fn dash_dashes(&self) -> Vec { let (dashes, _) = self.dash(); dashes } #[doc(alias = "get_dash_offset")] pub fn dash_offset(&self) -> f64 { let (_, offset) = self.dash(); offset } #[doc(alias = "cairo_set_fill_rule")] pub fn set_fill_rule(&self, fill_rule: FillRule) { unsafe { ffi::cairo_set_fill_rule(self.0.as_ptr(), fill_rule.into()); } } #[doc(alias = "get_fill_rule")] #[doc(alias = "cairo_get_fill_rule")] pub fn fill_rule(&self) -> FillRule { unsafe { FillRule::from(ffi::cairo_get_fill_rule(self.0.as_ptr())) } } #[doc(alias = "cairo_set_line_cap")] pub fn set_line_cap(&self, arg: LineCap) { unsafe { ffi::cairo_set_line_cap(self.0.as_ptr(), arg.into()) } } #[doc(alias = "get_line_cap")] #[doc(alias = "cairo_get_line_cap")] pub fn line_cap(&self) -> LineCap { unsafe { LineCap::from(ffi::cairo_get_line_cap(self.0.as_ptr())) } } #[doc(alias = "cairo_set_line_join")] pub fn set_line_join(&self, arg: LineJoin) { unsafe { ffi::cairo_set_line_join(self.0.as_ptr(), arg.into()) } } #[doc(alias = "get_line_join")] #[doc(alias = "cairo_get_line_join")] pub fn line_join(&self) -> LineJoin { unsafe { LineJoin::from(ffi::cairo_get_line_join(self.0.as_ptr())) } } #[doc(alias = "cairo_set_line_width")] pub fn set_line_width(&self, arg: f64) { unsafe { ffi::cairo_set_line_width(self.0.as_ptr(), arg) } } #[doc(alias = "get_line_width")] #[doc(alias = "cairo_get_line_width")] pub fn line_width(&self) -> f64 { unsafe { ffi::cairo_get_line_width(self.0.as_ptr()) } } #[doc(alias = "cairo_set_miter_limit")] pub fn set_miter_limit(&self, arg: f64) { unsafe { ffi::cairo_set_miter_limit(self.0.as_ptr(), arg) } } #[doc(alias = "get_miter_limit")] #[doc(alias = "cairo_get_miter_limit")] pub fn miter_limit(&self) -> f64 { unsafe { ffi::cairo_get_miter_limit(self.0.as_ptr()) } } #[doc(alias = "cairo_set_operator")] pub fn set_operator(&self, op: Operator) { unsafe { ffi::cairo_set_operator(self.0.as_ptr(), op.into()); } } #[doc(alias = "get_operator")] #[doc(alias = "cairo_get_operator")] pub fn operator(&self) -> Operator { unsafe { Operator::from(ffi::cairo_get_operator(self.0.as_ptr())) } } #[doc(alias = "cairo_set_tolerance")] pub fn set_tolerance(&self, arg: f64) { unsafe { ffi::cairo_set_tolerance(self.0.as_ptr(), arg) } } #[doc(alias = "get_tolerance")] #[doc(alias = "cairo_get_tolerance")] pub fn tolerance(&self) -> f64 { unsafe { ffi::cairo_get_tolerance(self.0.as_ptr()) } } #[doc(alias = "cairo_clip")] pub fn clip(&self) { unsafe { ffi::cairo_clip(self.0.as_ptr()) } } #[doc(alias = "cairo_clip_preserve")] pub fn clip_preserve(&self) { unsafe { ffi::cairo_clip_preserve(self.0.as_ptr()) } } #[doc(alias = "cairo_clip_extents")] pub fn clip_extents(&self) -> Result<(f64, f64, f64, f64), Error> { let mut x1: f64 = 0.0; let mut y1: f64 = 0.0; let mut x2: f64 = 0.0; let mut y2: f64 = 0.0; unsafe { ffi::cairo_clip_extents(self.0.as_ptr(), &mut x1, &mut y1, &mut x2, &mut y2); } self.status().map(|_| (x1, y1, x2, y2)) } #[doc(alias = "cairo_in_clip")] pub fn in_clip(&self, x: f64, y: f64) -> Result { let in_clip = unsafe { ffi::cairo_in_clip(self.0.as_ptr(), x, y).as_bool() }; self.status().map(|_| in_clip) } #[doc(alias = "cairo_reset_clip")] pub fn reset_clip(&self) { unsafe { ffi::cairo_reset_clip(self.0.as_ptr()) } } #[doc(alias = "cairo_copy_clip_rectangle_list")] pub fn copy_clip_rectangle_list(&self) -> Result { unsafe { let rectangle_list = ffi::cairo_copy_clip_rectangle_list(self.0.as_ptr()); status_to_result((*rectangle_list).status)?; Ok(RectangleList { ptr: rectangle_list, }) } } #[doc(alias = "cairo_fill")] pub fn fill(&self) -> Result<(), Error> { unsafe { ffi::cairo_fill(self.0.as_ptr()) }; self.status() } #[doc(alias = "cairo_fill_preserve")] pub fn fill_preserve(&self) -> Result<(), Error> { unsafe { ffi::cairo_fill_preserve(self.0.as_ptr()) }; self.status() } #[doc(alias = "cairo_fill_extents")] pub fn fill_extents(&self) -> Result<(f64, f64, f64, f64), Error> { let mut x1: f64 = 0.0; let mut y1: f64 = 0.0; let mut x2: f64 = 0.0; let mut y2: f64 = 0.0; unsafe { ffi::cairo_fill_extents(self.0.as_ptr(), &mut x1, &mut y1, &mut x2, &mut y2); } self.status().map(|_| (x1, y1, x2, y2)) } #[doc(alias = "cairo_in_fill")] pub fn in_fill(&self, x: f64, y: f64) -> Result { let in_fill = unsafe { ffi::cairo_in_fill(self.0.as_ptr(), x, y).as_bool() }; self.status().map(|_| in_fill) } #[doc(alias = "cairo_mask")] pub fn mask(&self, pattern: &Pattern) -> Result<(), Error> { pattern.status()?; unsafe { ffi::cairo_mask(self.0.as_ptr(), pattern.to_raw_none()) }; self.status() } #[doc(alias = "cairo_mask_surface")] pub fn mask_surface(&self, surface: &Surface, x: f64, y: f64) -> Result<(), Error> { surface.status()?; unsafe { ffi::cairo_mask_surface(self.0.as_ptr(), surface.to_raw_none(), x, y); }; self.status() } #[doc(alias = "cairo_paint")] pub fn paint(&self) -> Result<(), Error> { unsafe { ffi::cairo_paint(self.0.as_ptr()) }; self.status() } #[doc(alias = "cairo_paint_with_alpha")] pub fn paint_with_alpha(&self, alpha: f64) -> Result<(), Error> { unsafe { ffi::cairo_paint_with_alpha(self.0.as_ptr(), alpha) }; self.status() } #[doc(alias = "cairo_stroke")] pub fn stroke(&self) -> Result<(), Error> { unsafe { ffi::cairo_stroke(self.0.as_ptr()) }; self.status() } #[doc(alias = "cairo_stroke_preserve")] pub fn stroke_preserve(&self) -> Result<(), Error> { unsafe { ffi::cairo_stroke_preserve(self.0.as_ptr()) }; self.status() } #[doc(alias = "cairo_stroke_extents")] pub fn stroke_extents(&self) -> Result<(f64, f64, f64, f64), Error> { let mut x1: f64 = 0.0; let mut y1: f64 = 0.0; let mut x2: f64 = 0.0; let mut y2: f64 = 0.0; unsafe { ffi::cairo_stroke_extents(self.0.as_ptr(), &mut x1, &mut y1, &mut x2, &mut y2); } self.status().map(|_| (x1, y1, x2, y2)) } #[doc(alias = "cairo_in_stroke")] pub fn in_stroke(&self, x: f64, y: f64) -> Result { let in_stroke = unsafe { ffi::cairo_in_stroke(self.0.as_ptr(), x, y).as_bool() }; self.status().map(|_| in_stroke) } #[doc(alias = "cairo_copy_page")] pub fn copy_page(&self) -> Result<(), Error> { unsafe { ffi::cairo_copy_page(self.0.as_ptr()) }; self.status() } #[doc(alias = "cairo_show_page")] pub fn show_page(&self) -> Result<(), Error> { unsafe { ffi::cairo_show_page(self.0.as_ptr()) }; self.status() } #[doc(alias = "get_reference_count")] pub fn reference_count(&self) -> u32 { unsafe { ffi::cairo_get_reference_count(self.0.as_ptr()) } } // transformations stuff #[doc(alias = "cairo_translate")] pub fn translate(&self, tx: f64, ty: f64) { unsafe { ffi::cairo_translate(self.0.as_ptr(), tx, ty) } } #[doc(alias = "cairo_scale")] pub fn scale(&self, sx: f64, sy: f64) { unsafe { ffi::cairo_scale(self.0.as_ptr(), sx, sy) } } #[doc(alias = "cairo_rotate")] pub fn rotate(&self, angle: f64) { unsafe { ffi::cairo_rotate(self.0.as_ptr(), angle) } } #[doc(alias = "cairo_transform")] pub fn transform(&self, matrix: Matrix) { unsafe { ffi::cairo_transform(self.0.as_ptr(), matrix.ptr()); } } #[doc(alias = "cairo_set_matrix")] pub fn set_matrix(&self, matrix: Matrix) { unsafe { ffi::cairo_set_matrix(self.0.as_ptr(), matrix.ptr()); } } #[doc(alias = "get_matrix")] #[doc(alias = "cairo_get_matrix")] pub fn matrix(&self) -> Matrix { let mut matrix = Matrix::null(); unsafe { ffi::cairo_get_matrix(self.0.as_ptr(), matrix.mut_ptr()); } matrix } #[doc(alias = "cairo_identity_matrix")] pub fn identity_matrix(&self) { unsafe { ffi::cairo_identity_matrix(self.0.as_ptr()) } } #[doc(alias = "cairo_user_to_device")] pub fn user_to_device(&self, mut x: f64, mut y: f64) -> (f64, f64) { unsafe { ffi::cairo_user_to_device(self.0.as_ptr(), &mut x, &mut y); (x, y) } } #[doc(alias = "cairo_user_to_device_distance")] pub fn user_to_device_distance(&self, mut dx: f64, mut dy: f64) -> Result<(f64, f64), Error> { unsafe { ffi::cairo_user_to_device_distance(self.0.as_ptr(), &mut dx, &mut dy); }; self.status().map(|_| (dx, dy)) } #[doc(alias = "cairo_device_to_user")] pub fn device_to_user(&self, mut x: f64, mut y: f64) -> Result<(f64, f64), Error> { unsafe { ffi::cairo_device_to_user(self.0.as_ptr(), &mut x, &mut y); } self.status().map(|_| (x, y)) } #[doc(alias = "cairo_device_to_user_distance")] pub fn device_to_user_distance(&self, mut dx: f64, mut dy: f64) -> Result<(f64, f64), Error> { unsafe { ffi::cairo_device_to_user_distance(self.0.as_ptr(), &mut dx, &mut dy); } self.status().map(|_| (dx, dy)) } // font stuff #[doc(alias = "cairo_select_font_face")] pub fn select_font_face(&self, family: &str, slant: FontSlant, weight: FontWeight) { unsafe { let family = CString::new(family).unwrap(); ffi::cairo_select_font_face( self.0.as_ptr(), family.as_ptr(), slant.into(), weight.into(), ) } } #[doc(alias = "cairo_set_font_size")] pub fn set_font_size(&self, size: f64) { unsafe { ffi::cairo_set_font_size(self.0.as_ptr(), size) } } // FIXME probably needs a heap allocation #[doc(alias = "cairo_set_font_matrix")] pub fn set_font_matrix(&self, matrix: Matrix) { unsafe { ffi::cairo_set_font_matrix(self.0.as_ptr(), matrix.ptr()) } } #[doc(alias = "get_font_matrix")] #[doc(alias = "cairo_get_font_matrix")] pub fn font_matrix(&self) -> Matrix { let mut matrix = Matrix::null(); unsafe { ffi::cairo_get_font_matrix(self.0.as_ptr(), matrix.mut_ptr()); } matrix } #[doc(alias = "cairo_set_font_options")] pub fn set_font_options(&self, options: &FontOptions) { unsafe { ffi::cairo_set_font_options(self.0.as_ptr(), options.to_raw_none()) } } #[doc(alias = "get_font_options")] #[doc(alias = "cairo_get_font_options")] pub fn font_options(&self) -> Result { let out = FontOptions::new()?; unsafe { ffi::cairo_get_font_options(self.0.as_ptr(), out.to_raw_none()); } Ok(out) } #[doc(alias = "cairo_set_font_face")] pub fn set_font_face(&self, font_face: &FontFace) { unsafe { ffi::cairo_set_font_face(self.0.as_ptr(), font_face.to_raw_none()) } } #[doc(alias = "get_font_face")] #[doc(alias = "cairo_get_font_face")] pub fn font_face(&self) -> FontFace { unsafe { FontFace::from_raw_none(ffi::cairo_get_font_face(self.0.as_ptr())) } } #[doc(alias = "cairo_set_scaled_font")] pub fn set_scaled_font(&self, scaled_font: &ScaledFont) { unsafe { ffi::cairo_set_scaled_font(self.0.as_ptr(), scaled_font.to_raw_none()) } } #[doc(alias = "get_scaled_font")] #[doc(alias = "cairo_get_scaled_font")] pub fn scaled_font(&self) -> ScaledFont { unsafe { ScaledFont::from_raw_none(ffi::cairo_get_scaled_font(self.0.as_ptr())) } } #[doc(alias = "cairo_show_text")] pub fn show_text(&self, text: &str) -> Result<(), Error> { unsafe { let text = CString::new(text).unwrap(); ffi::cairo_show_text(self.0.as_ptr(), text.as_ptr()) }; self.status() } #[doc(alias = "cairo_show_glyphs")] pub fn show_glyphs(&self, glyphs: &[Glyph]) -> Result<(), Error> { unsafe { ffi::cairo_show_glyphs(self.0.as_ptr(), glyphs.as_ptr(), glyphs.len() as c_int) }; self.status() } #[doc(alias = "cairo_show_text_glyphs")] pub fn show_text_glyphs( &self, text: &str, glyphs: &[Glyph], clusters: &[TextCluster], cluster_flags: TextClusterFlags, ) -> Result<(), Error> { unsafe { let text = CString::new(text).unwrap(); ffi::cairo_show_text_glyphs( self.0.as_ptr(), text.as_ptr(), -1_i32, //NULL terminated glyphs.as_ptr(), glyphs.len() as c_int, clusters.as_ptr(), clusters.len() as c_int, cluster_flags.into(), ) }; self.status() } #[doc(alias = "cairo_font_extents")] pub fn font_extents(&self) -> Result { let mut extents = FontExtents { ascent: 0.0, descent: 0.0, height: 0.0, max_x_advance: 0.0, max_y_advance: 0.0, }; unsafe { ffi::cairo_font_extents(self.0.as_ptr(), &mut extents); } self.status().map(|_| extents) } #[doc(alias = "cairo_text_extents")] pub fn text_extents(&self, text: &str) -> Result { let mut extents = TextExtents { x_bearing: 0.0, y_bearing: 0.0, width: 0.0, height: 0.0, x_advance: 0.0, y_advance: 0.0, }; unsafe { let text = CString::new(text).unwrap(); ffi::cairo_text_extents(self.0.as_ptr(), text.as_ptr(), &mut extents); } self.status().map(|_| extents) } #[doc(alias = "cairo_glyph_extents")] pub fn glyph_extents(&self, glyphs: &[Glyph]) -> Result { let mut extents = TextExtents { x_bearing: 0.0, y_bearing: 0.0, width: 0.0, height: 0.0, x_advance: 0.0, y_advance: 0.0, }; unsafe { ffi::cairo_glyph_extents( self.0.as_ptr(), glyphs.as_ptr(), glyphs.len() as c_int, &mut extents, ); } self.status().map(|_| extents) } // paths stuff #[doc(alias = "cairo_copy_path")] pub fn copy_path(&self) -> Result { let path = unsafe { Path::from_raw_full(ffi::cairo_copy_path(self.0.as_ptr())) }; self.status().map(|_| path) } #[doc(alias = "cairo_copy_path_flat")] pub fn copy_path_flat(&self) -> Result { let path = unsafe { Path::from_raw_full(ffi::cairo_copy_path_flat(self.0.as_ptr())) }; self.status().map(|_| path) } #[doc(alias = "cairo_append_path")] pub fn append_path(&self, path: &Path) { unsafe { ffi::cairo_append_path(self.0.as_ptr(), path.as_ptr()) } } #[doc(alias = "cairo_has_current_point")] pub fn has_current_point(&self) -> Result { let has_current_point = unsafe { ffi::cairo_has_current_point(self.0.as_ptr()).as_bool() }; self.status().map(|_| has_current_point) } #[doc(alias = "get_current_point")] #[doc(alias = "cairo_get_current_point")] pub fn current_point(&self) -> Result<(f64, f64), Error> { unsafe { let mut x = 0.0; let mut y = 0.0; ffi::cairo_get_current_point(self.0.as_ptr(), &mut x, &mut y); self.status().map(|_| (x, y)) } } #[doc(alias = "cairo_new_path")] pub fn new_path(&self) { unsafe { ffi::cairo_new_path(self.0.as_ptr()) } } #[doc(alias = "cairo_new_sub_path")] pub fn new_sub_path(&self) { unsafe { ffi::cairo_new_sub_path(self.0.as_ptr()) } } #[doc(alias = "cairo_close_path")] pub fn close_path(&self) { unsafe { ffi::cairo_close_path(self.0.as_ptr()) } } #[doc(alias = "cairo_arc")] pub fn arc(&self, xc: f64, yc: f64, radius: f64, angle1: f64, angle2: f64) { unsafe { ffi::cairo_arc(self.0.as_ptr(), xc, yc, radius, angle1, angle2) } } #[doc(alias = "cairo_arc_negative")] pub fn arc_negative(&self, xc: f64, yc: f64, radius: f64, angle1: f64, angle2: f64) { unsafe { ffi::cairo_arc_negative(self.0.as_ptr(), xc, yc, radius, angle1, angle2) } } #[doc(alias = "cairo_curve_to")] pub fn curve_to(&self, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) { unsafe { ffi::cairo_curve_to(self.0.as_ptr(), x1, y1, x2, y2, x3, y3) } } #[doc(alias = "cairo_line_to")] pub fn line_to(&self, x: f64, y: f64) { unsafe { ffi::cairo_line_to(self.0.as_ptr(), x, y) } } #[doc(alias = "cairo_move_to")] pub fn move_to(&self, x: f64, y: f64) { unsafe { ffi::cairo_move_to(self.0.as_ptr(), x, y) } } #[doc(alias = "cairo_rectangle")] pub fn rectangle(&self, x: f64, y: f64, width: f64, height: f64) { unsafe { ffi::cairo_rectangle(self.0.as_ptr(), x, y, width, height) } } #[doc(alias = "cairo_text_path")] pub fn text_path(&self, str_: &str) { unsafe { let str_ = CString::new(str_).unwrap(); ffi::cairo_text_path(self.0.as_ptr(), str_.as_ptr()) } } #[doc(alias = "cairo_glyph_path")] pub fn glyph_path(&self, glyphs: &[Glyph]) { unsafe { ffi::cairo_glyph_path(self.0.as_ptr(), glyphs.as_ptr(), glyphs.len() as i32) } } #[doc(alias = "cairo_rel_curve_to")] pub fn rel_curve_to(&self, dx1: f64, dy1: f64, dx2: f64, dy2: f64, dx3: f64, dy3: f64) { unsafe { ffi::cairo_rel_curve_to(self.0.as_ptr(), dx1, dy1, dx2, dy2, dx3, dy3) } } #[doc(alias = "cairo_rel_line_to")] pub fn rel_line_to(&self, dx: f64, dy: f64) { unsafe { ffi::cairo_rel_line_to(self.0.as_ptr(), dx, dy) } } #[doc(alias = "cairo_rel_move_to")] pub fn rel_move_to(&self, dx: f64, dy: f64) { unsafe { ffi::cairo_rel_move_to(self.0.as_ptr(), dx, dy) } } #[doc(alias = "cairo_path_extents")] pub fn path_extents(&self) -> Result<(f64, f64, f64, f64), Error> { let mut x1: f64 = 0.0; let mut y1: f64 = 0.0; let mut x2: f64 = 0.0; let mut y2: f64 = 0.0; unsafe { ffi::cairo_path_extents(self.0.as_ptr(), &mut x1, &mut y1, &mut x2, &mut y2); } self.status().map(|_| (x1, y1, x2, y2)) } #[cfg(any(feature = "v1_16", feature = "dox"))] #[doc(alias = "cairo_tag_begin")] pub fn tag_begin(&self, tag_name: &str, attributes: &str) { unsafe { let tag_name = CString::new(tag_name).unwrap(); let attributes = CString::new(attributes).unwrap(); ffi::cairo_tag_begin(self.0.as_ptr(), tag_name.as_ptr(), attributes.as_ptr()) } } #[cfg(any(feature = "v1_16", feature = "dox"))] #[doc(alias = "cairo_tag_end")] pub fn tag_end(&self, tag_name: &str) { unsafe { let tag_name = CString::new(tag_name).unwrap(); ffi::cairo_tag_end(self.0.as_ptr(), tag_name.as_ptr()) } } } impl fmt::Display for Context { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Context") } } #[cfg(test)] mod tests { use super::*; use crate::enums::Format; use crate::image_surface::ImageSurface; use crate::patterns::LinearGradient; fn create_ctx() -> Context { let surface = ImageSurface::create(Format::ARgb32, 10, 10).unwrap(); Context::new(&surface).expect("Can't create a Cairo context") } #[test] fn invalid_surface_cant_create_context() { unsafe { // The size here will create an image surface in an error state let image_surf = ffi::cairo_image_surface_create(Format::ARgb32.into(), 100_000, 100_000); // from_raw_none() as from_raw_full() checks the surface status, and we *want* // a surface in an error state. let wrapped = Surface::from_raw_none(image_surf); assert!(Context::new(&wrapped).is_err()); ffi::cairo_surface_destroy(image_surf); } } #[test] fn drop_non_reference_pattern_from_ctx() { let ctx = create_ctx(); ctx.source(); } #[test] fn drop_non_reference_pattern() { let ctx = create_ctx(); let pattern = LinearGradient::new(1.0f64, 2.0f64, 3.0f64, 4.0f64); ctx.set_source(&pattern).expect("Invalid surface state"); } #[test] fn clip_rectangle() { let ctx = create_ctx(); let rect = ctx .copy_clip_rectangle_list() .expect("Failed to copy rectangle list"); assert_eq!( format!("{:?}", rect), "RectangleList([Rectangle { x: 0.0, y: 0.0, width: 10.0, height: 10.0 }])" ); assert_eq!(rect.to_string(), "RectangleList"); } } cairo-rs-0.14.9/src/device.rs000064400000000000000000000277530072674642500141000ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use crate::enums::DeviceType; use crate::error::Error; use crate::utils::status_to_result; use std::fmt; use std::ptr; #[cfg(feature = "use_glib")] use glib::translate::*; #[cfg(any(feature = "script", feature = "dox"))] use crate::enums::Content; #[cfg(any(feature = "script", feature = "dox"))] use crate::enums::ScriptMode; #[cfg(any(feature = "script", feature = "dox"))] use crate::recording_surface::RecordingSurface; #[cfg(any(feature = "script", feature = "dox"))] use crate::surface::Surface; #[cfg(any(feature = "script", feature = "dox"))] use std::ffi::CString; #[cfg(any(feature = "script", feature = "dox"))] use std::path::Path; #[derive(Debug)] pub struct DeviceAcquireGuard<'a>(&'a Device); impl<'a> Drop for DeviceAcquireGuard<'a> { fn drop(&mut self) { self.0.release(); } } #[derive(Debug)] #[doc(alias = "cairo_device_t")] pub struct Device(ptr::NonNull); impl Device { pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_device_t) -> Device { assert!(!ptr.is_null()); ffi::cairo_device_reference(ptr); Device(ptr::NonNull::new_unchecked(ptr)) } pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_device_t) -> crate::Borrowed { assert!(!ptr.is_null()); crate::Borrowed::new(Device(ptr::NonNull::new_unchecked(ptr))) } pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_device_t) -> Device { assert!(!ptr.is_null()); Device(ptr::NonNull::new_unchecked(ptr)) } pub fn to_raw_none(&self) -> *mut ffi::cairo_device_t { self.0.as_ptr() } #[cfg(any(feature = "script", feature = "dox"))] #[doc(alias = "cairo_script_create")] pub fn create>(filename: P) -> Option { unsafe { let filename = filename.as_ref().to_string_lossy().into_owned(); let filename = CString::new(filename).unwrap(); let p = ffi::cairo_script_create(filename.as_ptr()); if p.is_null() { None } else { Some(Self::from_raw_full(p)) } } } #[cfg(any(feature = "script", feature = "dox"))] #[doc(alias = "cairo_script_from_recording_surface")] pub fn from_recording_surface(&self, surface: &RecordingSurface) -> Result<(), Error> { unsafe { let status = ffi::cairo_script_from_recording_surface(self.to_raw_none(), surface.to_raw_none()); status_to_result(status) } } #[cfg(any(feature = "script", feature = "dox"))] #[doc(alias = "cairo_script_get_mode")] #[doc(alias = "get_mode")] pub fn mode(&self) -> ScriptMode { unsafe { ScriptMode::from(ffi::cairo_script_get_mode(self.to_raw_none())) } } #[cfg(any(feature = "script", feature = "dox"))] #[doc(alias = "cairo_script_set_mode")] pub fn set_mode(&self, mode: ScriptMode) { unsafe { ffi::cairo_script_set_mode(self.to_raw_none(), mode.into()) } } #[cfg(any(feature = "script", feature = "dox"))] #[doc(alias = "cairo_script_surface_create")] pub fn surface_create( &self, content: Content, width: f64, height: f64, ) -> Result { unsafe { Surface::from_raw_full(ffi::cairo_script_surface_create( self.to_raw_none(), content.into(), width, height, )) } } #[cfg(any(feature = "script", feature = "dox"))] #[doc(alias = "cairo_script_surface_create_for_target")] pub fn surface_create_for_target(&self, target: &Surface) -> Result { target.status()?; unsafe { Surface::from_raw_full(ffi::cairo_script_surface_create_for_target( self.to_raw_none(), target.to_raw_none(), )) } } #[cfg(any(feature = "script", feature = "dox"))] #[doc(alias = "cairo_script_write_comment")] pub fn write_comment(&self, comment: &str) { unsafe { let len = comment.len(); let comment = CString::new(comment).unwrap(); ffi::cairo_script_write_comment(self.to_raw_none(), comment.as_ptr(), len as i32) } } #[doc(alias = "cairo_device_finish")] pub fn finish(&self) { unsafe { ffi::cairo_device_finish(self.to_raw_none()) } } #[doc(alias = "cairo_device_flush")] pub fn flush(&self) { unsafe { ffi::cairo_device_flush(self.to_raw_none()) } } #[doc(alias = "cairo_device_get_type")] #[doc(alias = "get_type")] pub fn type_(&self) -> DeviceType { unsafe { DeviceType::from(ffi::cairo_device_get_type(self.to_raw_none())) } } #[doc(alias = "cairo_device_acquire")] pub fn acquire(&self) -> Result { unsafe { let status = ffi::cairo_device_acquire(self.to_raw_none()); status_to_result(status)?; } Ok(DeviceAcquireGuard { 0: self }) } #[doc(alias = "cairo_device_release")] fn release(&self) { unsafe { ffi::cairo_device_release(self.to_raw_none()) } } #[doc(alias = "cairo_device_observer_elapsed")] pub fn observer_elapsed(&self) -> f64 { unsafe { ffi::cairo_device_observer_elapsed(self.to_raw_none()) } } #[doc(alias = "cairo_device_observer_fill_elapsed")] pub fn observer_fill_elapsed(&self) -> f64 { unsafe { ffi::cairo_device_observer_fill_elapsed(self.to_raw_none()) } } #[doc(alias = "cairo_device_observer_glyphs_elapsed")] pub fn observer_glyphs_elapsed(&self) -> f64 { unsafe { ffi::cairo_device_observer_glyphs_elapsed(self.to_raw_none()) } } #[doc(alias = "cairo_device_observer_mask_elapsed")] pub fn observer_mask_elapsed(&self) -> f64 { unsafe { ffi::cairo_device_observer_mask_elapsed(self.to_raw_none()) } } #[doc(alias = "cairo_device_observer_paint_elapsed")] pub fn observer_paint_elapsed(&self) -> f64 { unsafe { ffi::cairo_device_observer_paint_elapsed(self.to_raw_none()) } } #[doc(alias = "cairo_device_observer_stroke_elapsed")] pub fn observer_stroke_elapsed(&self) -> f64 { unsafe { ffi::cairo_device_observer_stroke_elapsed(self.to_raw_none()) } } #[cfg(any(feature = "xlib", feature = "xcb", feature = "dox"))] #[doc(alias = "cairo_xlib_device_debug_cap_xrender_version")] #[doc(alias = "cairo_xcb_device_debug_cap_xrender_version")] pub fn debug_cap_xrender_version(&self, major_version: i32, minor_version: i32) { unsafe { match self.type_() { DeviceType::Xlib => { #[cfg(feature = "xlib")] { ffi::cairo_xlib_device_debug_cap_xrender_version( self.to_raw_none(), major_version, minor_version, ) } #[cfg(not(feature = "xlib"))] { panic!("you need to enable \"xlib\" feature") } } DeviceType::Xcb => { #[cfg(feature = "xcb")] { ffi::cairo_xcb_device_debug_cap_xrender_version( self.to_raw_none(), major_version, minor_version, ) } #[cfg(not(feature = "xcb"))] { panic!("you need to enable \"xcb\" feature") } } d => panic!("invalid device type: {}", d), } } } #[cfg(any(feature = "xlib", feature = "xcb", feature = "dox"))] #[doc(alias = "cairo_xlib_device_debug_get_precision")] #[doc(alias = "cairo_xcb_device_debug_get_precision")] pub fn debug_get_precision(&self) -> i32 { unsafe { match self.type_() { DeviceType::Xlib => { #[cfg(feature = "xlib")] { ffi::cairo_xlib_device_debug_get_precision(self.to_raw_none()) } #[cfg(not(feature = "xlib"))] { panic!("you need to enable \"xlib\" feature") } } DeviceType::Xcb => { #[cfg(feature = "xcb")] { ffi::cairo_xcb_device_debug_get_precision(self.to_raw_none()) } #[cfg(not(feature = "xcb"))] { panic!("you need to enable \"xcb\" feature") } } d => panic!("invalid device type: {}", d), } } } #[cfg(any(feature = "xlib", feature = "xcb", feature = "dox"))] #[doc(alias = "cairo_xlib_device_debug_set_precision")] #[doc(alias = "cairo_xcb_device_debug_set_precision")] pub fn debug_set_precision(&self, precision: i32) { unsafe { match self.type_() { DeviceType::Xlib => { #[cfg(feature = "xlib")] { ffi::cairo_xlib_device_debug_set_precision(self.to_raw_none(), precision) } #[cfg(not(feature = "xlib"))] { panic!("you need to enable \"xlib\" feature") } } DeviceType::Xcb => { #[cfg(feature = "xcb")] { ffi::cairo_xcb_device_debug_set_precision(self.to_raw_none(), precision) } #[cfg(not(feature = "xcb"))] { panic!("you need to enable \"xcb\" feature") } } d => panic!("invalid device type: {}", d), } } } #[doc(alias = "cairo_device_status")] pub fn status(&self) -> Result<(), Error> { let status = unsafe { ffi::cairo_device_status(self.to_raw_none()) }; status_to_result(status) } user_data_methods! { ffi::cairo_device_get_user_data, ffi::cairo_device_set_user_data, } } #[cfg(feature = "use_glib")] impl<'a> ToGlibPtr<'a, *mut ffi::cairo_device_t> for Device { type Storage = &'a Device; #[inline] fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_device_t, Self> { Stash(self.to_raw_none(), self) } #[inline] fn to_glib_full(&self) -> *mut ffi::cairo_device_t { unsafe { ffi::cairo_device_reference(self.to_raw_none()) } } } #[cfg(feature = "use_glib")] impl FromGlibPtrNone<*mut ffi::cairo_device_t> for Device { #[inline] unsafe fn from_glib_none(ptr: *mut ffi::cairo_device_t) -> Device { Self::from_raw_none(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrBorrow<*mut ffi::cairo_device_t> for Device { #[inline] unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_device_t) -> crate::Borrowed { Self::from_raw_borrow(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrFull<*mut ffi::cairo_device_t> for Device { #[inline] unsafe fn from_glib_full(ptr: *mut ffi::cairo_device_t) -> Device { Self::from_raw_full(ptr) } } #[cfg(feature = "use_glib")] gvalue_impl!( Device, ffi::cairo_device_t, ffi::gobject::cairo_gobject_device_get_type ); impl Clone for Device { fn clone(&self) -> Device { unsafe { Self::from_raw_none(ffi::cairo_device_reference(self.0.as_ptr())) } } } impl Drop for Device { fn drop(&mut self) { unsafe { ffi::cairo_device_destroy(self.0.as_ptr()); } } } impl fmt::Display for Device { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Device") } } cairo-rs-0.14.9/src/enums.rs000064400000000000000000001760550072674642500137700ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use std::fmt::{self, Debug}; use crate::error::Error; #[cfg(feature = "use_glib")] use glib::translate::*; // Helper macro for our GValue related trait impls #[cfg(feature = "use_glib")] macro_rules! gvalue_impl { ($name:ty, $get_type:expr) => { impl glib::types::StaticType for $name { fn static_type() -> glib::Type { unsafe { from_glib($get_type()) } } } impl glib::value::ValueType for $name { type Type = Self; } unsafe impl<'a> glib::value::FromValue<'a> for $name { type Checker = glib::value::GenericValueTypeChecker; unsafe fn from_value(value: &'a glib::Value) -> Self { Self::from(glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0)) } } impl glib::value::ToValue for $name { fn to_value(&self) -> glib::Value { let mut value = glib::Value::for_value_type::(); unsafe { glib::gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, (*self).into()); } value } fn value_type(&self) -> glib::Type { ::static_type() } } }; } #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_antialias_t")] pub enum Antialias { #[doc(alias = "ANTIALIAS_DEFAULT")] Default, /* method */ #[doc(alias = "ANTIALIAS_NONE")] None, #[doc(alias = "ANTIALIAS_GRAY")] Gray, #[doc(alias = "ANTIALIAS_SUBPIXEL")] Subpixel, /* hints */ #[doc(alias = "ANTIALIAS_FAST")] Fast, #[doc(alias = "ANTIALIAS_GOOD")] Good, #[doc(alias = "ANTIALIAS_BEST")] Best, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_antialias_t { fn from(val: Antialias) -> ffi::cairo_antialias_t { match val { Antialias::Default => ffi::ANTIALIAS_DEFAULT, Antialias::None => ffi::ANTIALIAS_NONE, Antialias::Gray => ffi::ANTIALIAS_GRAY, Antialias::Subpixel => ffi::ANTIALIAS_SUBPIXEL, Antialias::Fast => ffi::ANTIALIAS_FAST, Antialias::Good => ffi::ANTIALIAS_GOOD, Antialias::Best => ffi::ANTIALIAS_BEST, Antialias::__Unknown(value) => value, } } } #[doc(hidden)] impl From for Antialias { fn from(value: ffi::cairo_antialias_t) -> Self { match value { ffi::ANTIALIAS_DEFAULT => Self::Default, ffi::ANTIALIAS_NONE => Self::None, ffi::ANTIALIAS_GRAY => Self::Gray, ffi::ANTIALIAS_SUBPIXEL => Self::Subpixel, ffi::ANTIALIAS_FAST => Self::Fast, ffi::ANTIALIAS_GOOD => Self::Good, ffi::ANTIALIAS_BEST => Self::Best, value => Self::__Unknown(value), } } } impl fmt::Display for Antialias { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Default => "Default", Self::None => "None", Self::Gray => "Gray", Self::Subpixel => "Subpixel", Self::Fast => "Fast", Self::Good => "Good", Self::Best => "Best", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(Antialias, ffi::gobject::cairo_gobject_antialias_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_fill_rule_t")] pub enum FillRule { #[doc(alias = "FILL_RULE_WINDING")] Winding, #[doc(alias = "FILL_RULE_EVEN_ODD")] EvenOdd, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_fill_rule_t { fn from(val: FillRule) -> ffi::cairo_fill_rule_t { match val { FillRule::Winding => ffi::FILL_RULE_WINDING, FillRule::EvenOdd => ffi::FILL_RULE_EVEN_ODD, FillRule::__Unknown(value) => value, } } } #[doc(hidden)] impl From for FillRule { fn from(value: ffi::cairo_fill_rule_t) -> Self { match value { ffi::FILL_RULE_WINDING => Self::Winding, ffi::FILL_RULE_EVEN_ODD => Self::EvenOdd, value => Self::__Unknown(value), } } } impl fmt::Display for FillRule { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Winding => "Winding", Self::EvenOdd => "EvenOdd", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(FillRule, ffi::gobject::cairo_gobject_fill_rule_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_line_cap_t")] pub enum LineCap { #[doc(alias = "LINE_CAP_BUTT")] Butt, #[doc(alias = "LINE_CAP_ROUND")] Round, #[doc(alias = "LINE_CAP_SQUARE")] Square, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_line_cap_t { fn from(val: LineCap) -> ffi::cairo_line_cap_t { match val { LineCap::Butt => ffi::LINE_CAP_BUTT, LineCap::Round => ffi::LINE_CAP_ROUND, LineCap::Square => ffi::LINE_CAP_SQUARE, LineCap::__Unknown(value) => value, } } } #[doc(hidden)] impl From for LineCap { fn from(value: ffi::cairo_line_cap_t) -> Self { match value { ffi::LINE_CAP_BUTT => Self::Butt, ffi::LINE_CAP_ROUND => Self::Round, ffi::LINE_CAP_SQUARE => Self::Square, value => Self::__Unknown(value), } } } impl fmt::Display for LineCap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Butt => "Butt", Self::Round => "Round", Self::Square => "Square", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(LineCap, ffi::gobject::cairo_gobject_line_cap_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_line_join_t")] pub enum LineJoin { #[doc(alias = "LINE_JOIN_MITER")] Miter, #[doc(alias = "LINE_JOIN_ROUND")] Round, #[doc(alias = "LINE_JOIN_BEVEL")] Bevel, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_line_join_t { fn from(val: LineJoin) -> ffi::cairo_line_join_t { match val { LineJoin::Miter => ffi::LINE_JOIN_MITER, LineJoin::Round => ffi::LINE_JOIN_ROUND, LineJoin::Bevel => ffi::LINE_JOIN_BEVEL, LineJoin::__Unknown(value) => value, } } } #[doc(hidden)] impl From for LineJoin { fn from(value: ffi::cairo_line_join_t) -> Self { match value { ffi::LINE_JOIN_MITER => Self::Miter, ffi::LINE_JOIN_ROUND => Self::Round, ffi::LINE_JOIN_BEVEL => Self::Bevel, value => Self::__Unknown(value), } } } impl fmt::Display for LineJoin { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Miter => "Miter", Self::Round => "Round", Self::Bevel => "Bevel", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(LineJoin, ffi::gobject::cairo_gobject_line_join_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_operator_t")] pub enum Operator { #[doc(alias = "OPERATOR_CLEAR")] Clear, #[doc(alias = "OPERATOR_SOURCE")] Source, #[doc(alias = "OPERATOR_OVER")] Over, #[doc(alias = "OPERATOR_IN")] In, #[doc(alias = "OPERATOR_OUT")] Out, #[doc(alias = "OPERATOR_ATOP")] Atop, #[doc(alias = "OPERATOR_DEST")] Dest, #[doc(alias = "OPERATOR_DEST_OVER")] DestOver, #[doc(alias = "OPERATOR_DEST_IN")] DestIn, #[doc(alias = "OPERATOR_DEST_OUT")] DestOut, #[doc(alias = "OPERATOR_DEST_ATOP")] DestAtop, #[doc(alias = "OPERATOR_XOR")] Xor, #[doc(alias = "OPERATOR_ADD")] Add, #[doc(alias = "OPERATOR_SATURATE")] Saturate, #[doc(alias = "OPERATOR_MULTIPLY")] Multiply, #[doc(alias = "OPERATOR_SCREEN")] Screen, #[doc(alias = "OPERATOR_OVERLAY")] Overlay, #[doc(alias = "OPERATOR_DARKEN")] Darken, #[doc(alias = "OPERATOR_LIGHTEN")] Lighten, #[doc(alias = "OPERATOR_COLOR_DODGE")] ColorDodge, #[doc(alias = "OPERATOR_COLOR_BURN")] ColorBurn, #[doc(alias = "OPERATOR_HARD_LIGHT")] HardLight, #[doc(alias = "OPERATOR_SOFT_LIGHT")] SoftLight, #[doc(alias = "OPERATOR_DIFFERENCE")] Difference, #[doc(alias = "OPERATOR_EXCLUSION")] Exclusion, #[doc(alias = "OPERATOR_HSL_HUE")] HslHue, #[doc(alias = "OPERATOR_HSL_SATURATION")] HslSaturation, #[doc(alias = "OPERATOR_HSL_COLOR")] HslColor, #[doc(alias = "OPERATOR_HSL_LUMINOSITY")] HslLuminosity, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_operator_t { fn from(val: Operator) -> ffi::cairo_operator_t { match val { Operator::Clear => ffi::OPERATOR_CLEAR, Operator::Source => ffi::OPERATOR_SOURCE, Operator::Over => ffi::OPERATOR_OVER, Operator::In => ffi::OPERATOR_IN, Operator::Out => ffi::OPERATOR_OUT, Operator::Atop => ffi::OPERATOR_ATOP, Operator::Dest => ffi::OPERATOR_DEST, Operator::DestOver => ffi::OPERATOR_DEST_OVER, Operator::DestIn => ffi::OPERATOR_DEST_IN, Operator::DestOut => ffi::OPERATOR_DEST_OUT, Operator::DestAtop => ffi::OPERATOR_DEST_ATOP, Operator::Xor => ffi::OPERATOR_XOR, Operator::Add => ffi::OPERATOR_ADD, Operator::Saturate => ffi::OPERATOR_SATURATE, Operator::Multiply => ffi::OPERATOR_MULTIPLY, Operator::Screen => ffi::OPERATOR_SCREEN, Operator::Overlay => ffi::OPERATOR_OVERLAY, Operator::Darken => ffi::OPERATOR_DARKEN, Operator::Lighten => ffi::OPERATOR_LIGHTEN, Operator::ColorDodge => ffi::OPERATOR_COLOR_DODGE, Operator::ColorBurn => ffi::OPERATOR_COLOR_BURN, Operator::HardLight => ffi::OPERATOR_HARD_LIGHT, Operator::SoftLight => ffi::OPERATOR_SOFT_LIGHT, Operator::Difference => ffi::OPERATOR_DIFFERENCE, Operator::Exclusion => ffi::OPERATOR_EXCLUSION, Operator::HslHue => ffi::OPERATOR_HSL_HUE, Operator::HslSaturation => ffi::OPERATOR_HSL_SATURATION, Operator::HslColor => ffi::OPERATOR_HSL_COLOR, Operator::HslLuminosity => ffi::OPERATOR_HSL_LUMINOSITY, Operator::__Unknown(value) => value, } } } #[doc(hidden)] impl From for Operator { fn from(value: ffi::cairo_operator_t) -> Self { match value { ffi::OPERATOR_CLEAR => Self::Clear, ffi::OPERATOR_SOURCE => Self::Source, ffi::OPERATOR_OVER => Self::Over, ffi::OPERATOR_IN => Self::In, ffi::OPERATOR_OUT => Self::Out, ffi::OPERATOR_ATOP => Self::Atop, ffi::OPERATOR_DEST => Self::Dest, ffi::OPERATOR_DEST_OVER => Self::DestOver, ffi::OPERATOR_DEST_IN => Self::DestIn, ffi::OPERATOR_DEST_OUT => Self::DestOut, ffi::OPERATOR_DEST_ATOP => Self::DestAtop, ffi::OPERATOR_XOR => Self::Xor, ffi::OPERATOR_ADD => Self::Add, ffi::OPERATOR_SATURATE => Self::Saturate, ffi::OPERATOR_MULTIPLY => Self::Multiply, ffi::OPERATOR_SCREEN => Self::Screen, ffi::OPERATOR_OVERLAY => Self::Overlay, ffi::OPERATOR_DARKEN => Self::Darken, ffi::OPERATOR_LIGHTEN => Self::Lighten, ffi::OPERATOR_COLOR_DODGE => Self::ColorDodge, ffi::OPERATOR_COLOR_BURN => Self::ColorBurn, ffi::OPERATOR_HARD_LIGHT => Self::HardLight, ffi::OPERATOR_SOFT_LIGHT => Self::SoftLight, ffi::OPERATOR_DIFFERENCE => Self::Difference, ffi::OPERATOR_EXCLUSION => Self::Exclusion, ffi::OPERATOR_HSL_HUE => Self::HslHue, ffi::OPERATOR_HSL_SATURATION => Self::HslSaturation, ffi::OPERATOR_HSL_COLOR => Self::HslColor, ffi::OPERATOR_HSL_LUMINOSITY => Self::HslLuminosity, value => Self::__Unknown(value), } } } impl fmt::Display for Operator { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Clear => "Clear", Self::Source => "Source", Self::Over => "Over", Self::In => "In", Self::Out => "Out", Self::Atop => "Atop", Self::Dest => "Dest", Self::DestOver => "DestOver", Self::DestIn => "DestIn", Self::DestOut => "DestOut", Self::DestAtop => "DestAtop", Self::Xor => "Xor", Self::Add => "Add", Self::Saturate => "Saturate", Self::Multiply => "Multiply", Self::Screen => "Screen", Self::Overlay => "Overlay", Self::Darken => "Darken", Self::Lighten => "Lighten", Self::ColorDodge => "ColorDodge", Self::ColorBurn => "ColorBurn", Self::HardLight => "HardLight", Self::SoftLight => "SoftLight", Self::Difference => "Difference", Self::Exclusion => "Exclusion", Self::HslHue => "HslHue", Self::HslSaturation => "HslSaturation", Self::HslColor => "HslColor", Self::HslLuminosity => "HslLuminosity", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(Operator, ffi::gobject::cairo_gobject_operator_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_path_data_type_t")] pub enum PathDataType { #[doc(alias = "PATH_DATA_TYPE_MOVE_TO")] MoveTo, #[doc(alias = "PATH_DATA_TYPE_LINE_TO")] LineTo, #[doc(alias = "PATH_DATA_TYPE_CURVE_TO")] CurveTo, #[doc(alias = "PATH_DATA_TYPE_CLOSE_PATH")] ClosePath, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_path_data_type_t { fn from(val: PathDataType) -> ffi::cairo_path_data_type_t { match val { PathDataType::MoveTo => ffi::PATH_DATA_TYPE_MOVE_TO, PathDataType::LineTo => ffi::PATH_DATA_TYPE_LINE_TO, PathDataType::CurveTo => ffi::PATH_DATA_TYPE_CURVE_TO, PathDataType::ClosePath => ffi::PATH_DATA_TYPE_CLOSE_PATH, PathDataType::__Unknown(value) => value, } } } #[doc(hidden)] impl From for PathDataType { fn from(value: ffi::cairo_path_data_type_t) -> Self { match value { ffi::PATH_DATA_TYPE_MOVE_TO => Self::MoveTo, ffi::PATH_DATA_TYPE_LINE_TO => Self::LineTo, ffi::PATH_DATA_TYPE_CURVE_TO => Self::CurveTo, ffi::PATH_DATA_TYPE_CLOSE_PATH => Self::ClosePath, value => Self::__Unknown(value), } } } impl fmt::Display for PathDataType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::MoveTo => "MoveTo", Self::LineTo => "LineTo", Self::CurveTo => "CurveTo", Self::ClosePath => "ClosePath", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!( PathDataType, ffi::gobject::cairo_gobject_path_data_type_get_type ); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_content_t")] pub enum Content { #[doc(alias = "CONTENT_COLOR")] Color, #[doc(alias = "CONTENT_ALPHA")] Alpha, #[doc(alias = "CONTENT_COLOR_ALPHA")] ColorAlpha, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_content_t { fn from(val: Content) -> ffi::cairo_content_t { match val { Content::Color => ffi::CONTENT_COLOR, Content::Alpha => ffi::CONTENT_ALPHA, Content::ColorAlpha => ffi::CONTENT_COLOR_ALPHA, Content::__Unknown(value) => value, } } } #[doc(hidden)] impl From for Content { fn from(value: ffi::cairo_content_t) -> Self { match value { ffi::CONTENT_COLOR => Self::Color, ffi::CONTENT_ALPHA => Self::Alpha, ffi::CONTENT_COLOR_ALPHA => Self::ColorAlpha, value => Self::__Unknown(value), } } } impl fmt::Display for Content { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Color => "Color", Self::Alpha => "Alpha", Self::ColorAlpha => "ColorAlpha", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(Content, ffi::gobject::cairo_gobject_content_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_extend_t")] pub enum Extend { #[doc(alias = "EXTEND_NONE")] None, #[doc(alias = "EXTEND_REPEAT")] Repeat, #[doc(alias = "EXTEND_REFLECT")] Reflect, #[doc(alias = "EXTEND_PAD")] Pad, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_extend_t { fn from(val: Extend) -> ffi::cairo_extend_t { match val { Extend::None => ffi::EXTEND_NONE, Extend::Repeat => ffi::EXTEND_REPEAT, Extend::Reflect => ffi::EXTEND_REFLECT, Extend::Pad => ffi::EXTEND_PAD, Extend::__Unknown(value) => value, } } } #[doc(hidden)] impl From for Extend { fn from(value: ffi::cairo_extend_t) -> Self { match value { ffi::EXTEND_NONE => Self::None, ffi::EXTEND_REPEAT => Self::Repeat, ffi::EXTEND_REFLECT => Self::Reflect, ffi::EXTEND_PAD => Self::Pad, value => Self::__Unknown(value), } } } impl fmt::Display for Extend { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::None => "None", Self::Repeat => "Repeat", Self::Reflect => "Reflect", Self::Pad => "Pad", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(Extend, ffi::gobject::cairo_gobject_extend_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_filter_t")] pub enum Filter { #[doc(alias = "FILTER_FAST")] Fast, #[doc(alias = "FILTER_GOOD")] Good, #[doc(alias = "FILTER_BEST")] Best, #[doc(alias = "FILTER_NEAREST")] Nearest, #[doc(alias = "FILTER_BILINEAR")] Bilinear, #[doc(alias = "FILTER_GAUSSIAN")] Gaussian, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_filter_t { fn from(val: Filter) -> ffi::cairo_filter_t { match val { Filter::Fast => ffi::FILTER_FAST, Filter::Good => ffi::FILTER_GOOD, Filter::Best => ffi::FILTER_BEST, Filter::Nearest => ffi::FILTER_NEAREST, Filter::Bilinear => ffi::FILTER_BILINEAR, Filter::Gaussian => ffi::FILTER_GAUSSIAN, Filter::__Unknown(value) => value, } } } #[doc(hidden)] impl From for Filter { fn from(value: ffi::cairo_filter_t) -> Self { match value { ffi::FILTER_FAST => Self::Fast, ffi::FILTER_GOOD => Self::Good, ffi::FILTER_BEST => Self::Best, ffi::FILTER_NEAREST => Self::Nearest, ffi::FILTER_BILINEAR => Self::Bilinear, ffi::FILTER_GAUSSIAN => Self::Gaussian, value => Self::__Unknown(value), } } } impl fmt::Display for Filter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Fast => "Fast", Self::Good => "Good", Self::Best => "Best", Self::Nearest => "Nearest", Self::Bilinear => "Bilinear", Self::Gaussian => "Gaussian", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(Filter, ffi::gobject::cairo_gobject_filter_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_pattern_type_t")] pub enum PatternType { #[doc(alias = "PATTERN_TYPE_SOLID")] Solid, #[doc(alias = "PATTERN_TYPE_SURFACE")] Surface, #[doc(alias = "PATTERN_TYPE_LINEAR_GRADIENT")] LinearGradient, #[doc(alias = "PATTERN_TYPE_RADIAL_GRADIENT")] RadialGradient, #[doc(alias = "PATTERN_TYPE_MESH")] Mesh, #[doc(alias = "PATTERN_TYPE_RASTER_SOURCE")] RasterSource, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_pattern_type_t { fn from(val: PatternType) -> ffi::cairo_pattern_type_t { match val { PatternType::Solid => ffi::PATTERN_TYPE_SOLID, PatternType::Surface => ffi::PATTERN_TYPE_SURFACE, PatternType::LinearGradient => ffi::PATTERN_TYPE_LINEAR_GRADIENT, PatternType::RadialGradient => ffi::PATTERN_TYPE_RADIAL_GRADIENT, PatternType::Mesh => ffi::PATTERN_TYPE_MESH, PatternType::RasterSource => ffi::PATTERN_TYPE_RASTER_SOURCE, PatternType::__Unknown(value) => value, } } } #[doc(hidden)] impl From for PatternType { fn from(value: ffi::cairo_pattern_type_t) -> Self { match value { ffi::PATTERN_TYPE_SOLID => Self::Solid, ffi::PATTERN_TYPE_SURFACE => Self::Surface, ffi::PATTERN_TYPE_LINEAR_GRADIENT => Self::LinearGradient, ffi::PATTERN_TYPE_RADIAL_GRADIENT => Self::RadialGradient, ffi::PATTERN_TYPE_MESH => Self::Mesh, ffi::PATTERN_TYPE_RASTER_SOURCE => Self::RasterSource, value => Self::__Unknown(value), } } } impl fmt::Display for PatternType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Solid => "Solid", Self::Surface => "Surface", Self::LinearGradient => "LinearGradient", Self::RadialGradient => "RadialGradient", Self::Mesh => "Mesh", Self::RasterSource => "RasterSource", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!( PatternType, ffi::gobject::cairo_gobject_pattern_type_get_type ); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_font_slant_t")] pub enum FontSlant { #[doc(alias = "FONT_SLANT_NORMAL")] Normal, #[doc(alias = "FONT_SLANT_ITALIC")] Italic, #[doc(alias = "FONT_SLANT_OBLIQUE")] Oblique, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_font_slant_t { fn from(val: FontSlant) -> ffi::cairo_font_slant_t { match val { FontSlant::Normal => ffi::FONT_SLANT_NORMAL, FontSlant::Italic => ffi::FONT_SLANT_ITALIC, FontSlant::Oblique => ffi::FONT_SLANT_OBLIQUE, FontSlant::__Unknown(value) => value, } } } #[doc(hidden)] impl From for FontSlant { fn from(value: ffi::cairo_font_slant_t) -> Self { match value { ffi::FONT_SLANT_NORMAL => Self::Normal, ffi::FONT_SLANT_ITALIC => Self::Italic, ffi::FONT_SLANT_OBLIQUE => Self::Oblique, value => Self::__Unknown(value), } } } impl fmt::Display for FontSlant { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Normal => "Normal", Self::Italic => "Italic", Self::Oblique => "Oblique", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(FontSlant, ffi::gobject::cairo_gobject_font_slant_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_font_weight_t")] pub enum FontWeight { #[doc(alias = "FONT_WEIGHT_NORMAL")] Normal, #[doc(alias = "FONT_WEIGHT_BOLD")] Bold, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_font_weight_t { fn from(val: FontWeight) -> ffi::cairo_font_weight_t { match val { FontWeight::Normal => ffi::FONT_WEIGHT_NORMAL, FontWeight::Bold => ffi::FONT_WEIGHT_BOLD, FontWeight::__Unknown(value) => value, } } } #[doc(hidden)] impl From for FontWeight { fn from(value: ffi::cairo_font_weight_t) -> Self { match value { ffi::FONT_WEIGHT_NORMAL => Self::Normal, ffi::FONT_WEIGHT_BOLD => Self::Bold, value => Self::__Unknown(value), } } } impl fmt::Display for FontWeight { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Normal => "Normal", Self::Bold => "Bold", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(FontWeight, ffi::gobject::cairo_gobject_font_weight_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_text_cluster_flags_t")] pub enum TextClusterFlags { #[doc(alias = "TEXT_CLUSTER_FLAGS_NONE")] None, #[doc(alias = "TEXT_CLUSTER_FLAGS_BACKWARD")] Backward, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_text_cluster_flags_t { fn from(val: TextClusterFlags) -> ffi::cairo_text_cluster_flags_t { match val { TextClusterFlags::None => ffi::TEXT_CLUSTER_FLAGS_NONE, TextClusterFlags::Backward => ffi::TEXT_CLUSTER_FLAGS_BACKWARD, TextClusterFlags::__Unknown(value) => value, } } } #[doc(hidden)] impl From for TextClusterFlags { fn from(value: ffi::cairo_text_cluster_flags_t) -> Self { match value { ffi::TEXT_CLUSTER_FLAGS_NONE => Self::None, ffi::TEXT_CLUSTER_FLAGS_BACKWARD => Self::Backward, value => Self::__Unknown(value), } } } impl fmt::Display for TextClusterFlags { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::None => "None", Self::Backward => "Backward", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!( TextClusterFlags, ffi::gobject::cairo_gobject_text_cluster_flags_get_type ); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_font_type_t")] pub enum FontType { #[doc(alias = "FONT_TYPE_FONT_TYPE_TOY")] FontTypeToy, #[doc(alias = "FONT_TYPE_FONT_TYPE_FT")] FontTypeFt, #[doc(alias = "FONT_TYPE_FONT_TYPE_WIN32")] FontTypeWin32, #[doc(alias = "FONT_TYPE_FONT_TYPE_QUARTZ")] FontTypeQuartz, #[doc(alias = "FONT_TYPE_FONT_TYPE_USER")] FontTypeUser, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_font_type_t { fn from(val: FontType) -> ffi::cairo_font_type_t { match val { FontType::FontTypeToy => ffi::FONT_TYPE_FONT_TYPE_TOY, FontType::FontTypeFt => ffi::FONT_TYPE_FONT_TYPE_FT, FontType::FontTypeWin32 => ffi::FONT_TYPE_FONT_TYPE_WIN32, FontType::FontTypeQuartz => ffi::FONT_TYPE_FONT_TYPE_QUARTZ, FontType::FontTypeUser => ffi::FONT_TYPE_FONT_TYPE_USER, FontType::__Unknown(value) => value, } } } #[doc(hidden)] impl From for FontType { fn from(value: ffi::cairo_font_type_t) -> Self { match value { ffi::FONT_TYPE_FONT_TYPE_TOY => Self::FontTypeToy, ffi::FONT_TYPE_FONT_TYPE_FT => Self::FontTypeFt, ffi::FONT_TYPE_FONT_TYPE_WIN32 => Self::FontTypeWin32, ffi::FONT_TYPE_FONT_TYPE_QUARTZ => Self::FontTypeQuartz, ffi::FONT_TYPE_FONT_TYPE_USER => Self::FontTypeUser, value => Self::__Unknown(value), } } } impl fmt::Display for FontType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::FontTypeToy => "FontTypeToy", Self::FontTypeFt => "FontTypeFt", Self::FontTypeWin32 => "FontTypeWin32", Self::FontTypeQuartz => "FontTypeQuartz", Self::FontTypeUser => "FontTypeUser", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(FontType, ffi::gobject::cairo_gobject_font_type_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_subpixel_order_t")] pub enum SubpixelOrder { #[doc(alias = "SUBPIXEL_ORDER_DEFAULT")] Default, #[doc(alias = "SUBPIXEL_ORDER_RGB")] Rgb, #[doc(alias = "SUBPIXEL_ORDER_BGR")] Bgr, #[doc(alias = "SUBPIXEL_ORDER_VRGB")] Vrgb, #[doc(alias = "SUBPIXEL_ORDER_VBGR")] Vbgr, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_subpixel_order_t { fn from(val: SubpixelOrder) -> ffi::cairo_subpixel_order_t { match val { SubpixelOrder::Default => ffi::SUBPIXEL_ORDER_DEFAULT, SubpixelOrder::Rgb => ffi::SUBPIXEL_ORDER_RGB, SubpixelOrder::Bgr => ffi::SUBPIXEL_ORDER_BGR, SubpixelOrder::Vrgb => ffi::SUBPIXEL_ORDER_VRGB, SubpixelOrder::Vbgr => ffi::SUBPIXEL_ORDER_VBGR, SubpixelOrder::__Unknown(value) => value, } } } #[doc(hidden)] impl From for SubpixelOrder { fn from(value: ffi::cairo_subpixel_order_t) -> Self { match value { ffi::SUBPIXEL_ORDER_DEFAULT => Self::Default, ffi::SUBPIXEL_ORDER_RGB => Self::Rgb, ffi::SUBPIXEL_ORDER_BGR => Self::Bgr, ffi::SUBPIXEL_ORDER_VRGB => Self::Vrgb, ffi::SUBPIXEL_ORDER_VBGR => Self::Vbgr, value => Self::__Unknown(value), } } } impl fmt::Display for SubpixelOrder { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Default => "Default", Self::Rgb => "Rgb", Self::Bgr => "Bgr", Self::Vrgb => "Vrgb", Self::Vbgr => "Vbgr", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!( SubpixelOrder, ffi::gobject::cairo_gobject_subpixel_order_get_type ); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_hint_style_t")] pub enum HintStyle { #[doc(alias = "HINT_STYLE_DEFAULT")] Default, #[doc(alias = "HINT_STYLE_NONE")] None, #[doc(alias = "HINT_STYLE_SLIGHT")] Slight, #[doc(alias = "HINT_STYLE_MEDIUM")] Medium, #[doc(alias = "HINT_STYLE_FULL")] Full, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_hint_style_t { fn from(val: HintStyle) -> ffi::cairo_hint_style_t { match val { HintStyle::Default => ffi::HINT_STYLE_DEFAULT, HintStyle::None => ffi::HINT_STYLE_NONE, HintStyle::Slight => ffi::HINT_STYLE_SLIGHT, HintStyle::Medium => ffi::HINT_STYLE_MEDIUM, HintStyle::Full => ffi::HINT_STYLE_FULL, HintStyle::__Unknown(value) => value, } } } #[doc(hidden)] impl From for HintStyle { fn from(value: ffi::cairo_hint_style_t) -> Self { match value { ffi::HINT_STYLE_DEFAULT => Self::Default, ffi::HINT_STYLE_NONE => Self::None, ffi::HINT_STYLE_SLIGHT => Self::Slight, ffi::HINT_STYLE_MEDIUM => Self::Medium, ffi::HINT_STYLE_FULL => Self::Full, value => Self::__Unknown(value), } } } impl fmt::Display for HintStyle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Default => "Default", Self::None => "None", Self::Slight => "Slight", Self::Medium => "Medium", Self::Full => "Full", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(HintStyle, ffi::gobject::cairo_gobject_hint_style_get_type); #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_hint_metrics_t")] pub enum HintMetrics { #[doc(alias = "HINT_METRICS_DEFAULT")] Default, #[doc(alias = "HINT_METRICS_OFF")] Off, #[doc(alias = "HINT_METRICS_ON")] On, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_hint_metrics_t { fn from(val: HintMetrics) -> ffi::cairo_hint_metrics_t { match val { HintMetrics::Default => ffi::HINT_METRICS_DEFAULT, HintMetrics::Off => ffi::HINT_METRICS_OFF, HintMetrics::On => ffi::HINT_METRICS_ON, HintMetrics::__Unknown(value) => value, } } } #[doc(hidden)] impl From for HintMetrics { fn from(value: ffi::cairo_hint_metrics_t) -> Self { match value { ffi::HINT_METRICS_DEFAULT => Self::Default, ffi::HINT_METRICS_OFF => Self::Off, ffi::HINT_METRICS_ON => Self::On, value => Self::__Unknown(value), } } } impl fmt::Display for HintMetrics { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Default => "Default", Self::Off => "Off", Self::On => "On", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!( HintMetrics, ffi::gobject::cairo_gobject_hint_metrics_get_type ); #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[non_exhaustive] #[doc(alias = "cairo_surface_type_t")] pub enum SurfaceType { #[doc(alias = "SURFACE_TYPE_IMAGE")] Image, #[doc(alias = "SURFACE_TYPE_PDF")] Pdf, #[doc(alias = "SURFACE_TYPE_PS")] Ps, #[doc(alias = "SURFACE_TYPE_XLIB")] Xlib, #[doc(alias = "SURFACE_TYPE_XCB")] Xcb, #[doc(alias = "SURFACE_TYPE_GLITZ")] Glitz, #[doc(alias = "SURFACE_TYPE_QUARTZ")] Quartz, #[doc(alias = "SURFACE_TYPE_WIN32")] Win32, #[doc(alias = "SURFACE_TYPE_BE_OS")] BeOs, #[doc(alias = "SURFACE_TYPE_DIRECT_FB")] DirectFb, #[doc(alias = "SURFACE_TYPE_SVG")] Svg, #[doc(alias = "SURFACE_TYPE_OS2")] Os2, #[doc(alias = "SURFACE_TYPE_WIN32_PRINTING")] Win32Printing, #[doc(alias = "SURFACE_TYPE_QUARTZ_IMAGE")] QuartzImage, #[doc(alias = "SURFACE_TYPE_SCRIPT")] Script, #[doc(alias = "SURFACE_TYPE_QT")] Qt, #[doc(alias = "SURFACE_TYPE_RECORDING")] Recording, #[doc(alias = "SURFACE_TYPE_VG")] Vg, #[doc(alias = "SURFACE_TYPE_GL")] Gl, #[doc(alias = "SURFACE_TYPE_DRM")] Drm, #[doc(alias = "SURFACE_TYPE_TEE")] Tee, #[doc(alias = "SURFACE_TYPE_XML")] Xml, #[doc(alias = "SURFACE_TYPE_SKIA")] Skia, #[doc(alias = "SURFACE_TYPE_SUBSURFACE")] Subsurface, #[doc(alias = "SURFACE_TYPE_COGL")] Cogl, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_surface_type_t { fn from(val: SurfaceType) -> ffi::cairo_surface_type_t { match val { SurfaceType::Image => ffi::SURFACE_TYPE_IMAGE, SurfaceType::Pdf => ffi::SURFACE_TYPE_PDF, SurfaceType::Ps => ffi::SURFACE_TYPE_PS, SurfaceType::Xlib => ffi::SURFACE_TYPE_XLIB, SurfaceType::Xcb => ffi::SURFACE_TYPE_XCB, SurfaceType::Glitz => ffi::SURFACE_TYPE_GLITZ, SurfaceType::Quartz => ffi::SURFACE_TYPE_QUARTZ, SurfaceType::Win32 => ffi::SURFACE_TYPE_WIN32, SurfaceType::BeOs => ffi::SURFACE_TYPE_BE_OS, SurfaceType::DirectFb => ffi::SURFACE_TYPE_DIRECT_FB, SurfaceType::Svg => ffi::SURFACE_TYPE_SVG, SurfaceType::Os2 => ffi::SURFACE_TYPE_OS2, SurfaceType::Win32Printing => ffi::SURFACE_TYPE_WIN32_PRINTING, SurfaceType::QuartzImage => ffi::SURFACE_TYPE_QUARTZ_IMAGE, SurfaceType::Script => ffi::SURFACE_TYPE_SCRIPT, SurfaceType::Qt => ffi::SURFACE_TYPE_QT, SurfaceType::Recording => ffi::SURFACE_TYPE_RECORDING, SurfaceType::Vg => ffi::SURFACE_TYPE_VG, SurfaceType::Gl => ffi::SURFACE_TYPE_GL, SurfaceType::Drm => ffi::SURFACE_TYPE_DRM, SurfaceType::Tee => ffi::SURFACE_TYPE_TEE, SurfaceType::Xml => ffi::SURFACE_TYPE_XML, SurfaceType::Skia => ffi::SURFACE_TYPE_SKIA, SurfaceType::Subsurface => ffi::SURFACE_TYPE_SUBSURFACE, SurfaceType::Cogl => ffi::SURFACE_TYPE_COGL, SurfaceType::__Unknown(value) => value, } } } #[doc(hidden)] impl From for SurfaceType { fn from(value: ffi::cairo_surface_type_t) -> Self { match value { ffi::SURFACE_TYPE_IMAGE => Self::Image, ffi::SURFACE_TYPE_PDF => Self::Pdf, ffi::SURFACE_TYPE_PS => Self::Ps, ffi::SURFACE_TYPE_XLIB => Self::Xlib, ffi::SURFACE_TYPE_XCB => Self::Xcb, ffi::SURFACE_TYPE_GLITZ => Self::Glitz, ffi::SURFACE_TYPE_QUARTZ => Self::Quartz, ffi::SURFACE_TYPE_WIN32 => Self::Win32, ffi::SURFACE_TYPE_BE_OS => Self::BeOs, ffi::SURFACE_TYPE_DIRECT_FB => Self::DirectFb, ffi::SURFACE_TYPE_SVG => Self::Svg, ffi::SURFACE_TYPE_OS2 => Self::Os2, ffi::SURFACE_TYPE_WIN32_PRINTING => Self::Win32Printing, ffi::SURFACE_TYPE_QUARTZ_IMAGE => Self::QuartzImage, ffi::SURFACE_TYPE_SCRIPT => Self::Script, ffi::SURFACE_TYPE_QT => Self::Qt, ffi::SURFACE_TYPE_RECORDING => Self::Recording, ffi::SURFACE_TYPE_VG => Self::Vg, ffi::SURFACE_TYPE_GL => Self::Gl, ffi::SURFACE_TYPE_DRM => Self::Drm, ffi::SURFACE_TYPE_TEE => Self::Tee, ffi::SURFACE_TYPE_XML => Self::Xml, ffi::SURFACE_TYPE_SKIA => Self::Skia, ffi::SURFACE_TYPE_SUBSURFACE => Self::Subsurface, ffi::SURFACE_TYPE_COGL => Self::Cogl, value => Self::__Unknown(value), } } } impl fmt::Display for SurfaceType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Image => "Image", Self::Pdf => "Pdf", Self::Ps => "Ps", Self::Xlib => "Xlib", Self::Xcb => "Xcb", Self::Glitz => "Glitz", Self::Quartz => "Quartz", Self::Win32 => "Win32", Self::BeOs => "BeOs", Self::DirectFb => "DirectFb", Self::Svg => "Svg", Self::Os2 => "Os2", Self::Win32Printing => "Win32Printing", Self::QuartzImage => "QuartzImage", Self::Script => "Script", Self::Qt => "Qt", Self::Recording => "Recording", Self::Vg => "Vg", Self::Gl => "Gl", Self::Drm => "Drm", Self::Tee => "Tee", Self::Xml => "Xml", Self::Skia => "Skia", Self::Subsurface => "Subsurface", Self::Cogl => "Cogl", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!( SurfaceType, ffi::gobject::cairo_gobject_surface_type_get_type ); #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[cfg(any(all(feature = "svg", feature = "v1_16"), feature = "dox"))] #[non_exhaustive] #[doc(alias = "cairo_svg_unit_t")] pub enum SvgUnit { #[doc(alias = "SVG_UNIT_USER")] User, #[doc(alias = "SVG_UNIT_EM")] Em, #[doc(alias = "SVG_UNIT_EX")] Ex, #[doc(alias = "SVG_UNIT_PX")] Px, #[doc(alias = "SVG_UNIT_IN")] In, #[doc(alias = "SVG_UNIT_CM")] Cm, #[doc(alias = "SVG_UNIT_MM")] Mm, #[doc(alias = "SVG_UNIT_PT")] Pt, #[doc(alias = "SVG_UNIT_PC")] Pc, #[doc(alias = "SVG_UNIT_PERCENT")] Percent, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] #[cfg(any(all(feature = "svg", feature = "v1_16"), feature = "dox"))] impl From for ffi::cairo_svg_unit_t { fn from(val: SvgUnit) -> ffi::cairo_svg_unit_t { match val { SvgUnit::User => ffi::SVG_UNIT_USER, SvgUnit::Em => ffi::SVG_UNIT_EM, SvgUnit::Ex => ffi::SVG_UNIT_EX, SvgUnit::Px => ffi::SVG_UNIT_PX, SvgUnit::In => ffi::SVG_UNIT_IN, SvgUnit::Cm => ffi::SVG_UNIT_CM, SvgUnit::Mm => ffi::SVG_UNIT_MM, SvgUnit::Pt => ffi::SVG_UNIT_PT, SvgUnit::Pc => ffi::SVG_UNIT_PC, SvgUnit::Percent => ffi::SVG_UNIT_PERCENT, SvgUnit::__Unknown(value) => value, } } } #[doc(hidden)] #[cfg(any(all(feature = "svg", feature = "v1_16"), feature = "dox"))] impl From for SvgUnit { fn from(value: ffi::cairo_svg_unit_t) -> Self { match value { ffi::SVG_UNIT_USER => Self::User, ffi::SVG_UNIT_EM => Self::Em, ffi::SVG_UNIT_EX => Self::Ex, ffi::SVG_UNIT_PX => Self::Px, ffi::SVG_UNIT_IN => Self::In, ffi::SVG_UNIT_CM => Self::Cm, ffi::SVG_UNIT_MM => Self::Mm, ffi::SVG_UNIT_PT => Self::Pt, ffi::SVG_UNIT_PC => Self::Pc, ffi::SVG_UNIT_PERCENT => Self::Percent, value => Self::__Unknown(value), } } } #[cfg(any(all(feature = "svg", feature = "v1_16"), feature = "dox"))] impl fmt::Display for SvgUnit { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::User => "User", Self::Em => "Em", Self::Ex => "Ex", Self::Px => "Px", Self::In => "In", Self::Cm => "Cm", Self::Mm => "Mm", Self::Pt => "Pt", Self::Pc => "Pc", Self::Percent => "Percent", _ => "Unknown", } ) } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[non_exhaustive] #[doc(alias = "cairo_format_t")] pub enum Format { #[doc(alias = "FORMAT_INVALID")] Invalid, #[doc(alias = "FORMAT_A_RGB32")] ARgb32, #[doc(alias = "FORMAT_RGB24")] Rgb24, #[doc(alias = "FORMAT_A8")] A8, #[doc(alias = "FORMAT_A1")] A1, #[doc(alias = "FORMAT_RGB16_565")] Rgb16_565, #[doc(alias = "FORMAT_RGB30")] Rgb30, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_format_t { fn from(val: Format) -> ffi::cairo_format_t { match val { Format::Invalid => ffi::FORMAT_INVALID, Format::ARgb32 => ffi::FORMAT_A_RGB32, Format::Rgb24 => ffi::FORMAT_RGB24, Format::A8 => ffi::FORMAT_A8, Format::A1 => ffi::FORMAT_A1, Format::Rgb16_565 => ffi::FORMAT_RGB16_565, Format::Rgb30 => ffi::FORMAT_RGB30, Format::__Unknown(value) => value, } } } #[doc(hidden)] impl From for Format { fn from(value: ffi::cairo_format_t) -> Self { match value { ffi::FORMAT_INVALID => Self::Invalid, ffi::FORMAT_A_RGB32 => Self::ARgb32, ffi::FORMAT_RGB24 => Self::Rgb24, ffi::FORMAT_A8 => Self::A8, ffi::FORMAT_A1 => Self::A1, ffi::FORMAT_RGB16_565 => Self::Rgb16_565, ffi::FORMAT_RGB30 => Self::Rgb30, value => Self::__Unknown(value), } } } impl fmt::Display for Format { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Invalid => "Invalid", Self::ARgb32 => "ARgb32", Self::Rgb24 => "Rgb24", Self::A8 => "A8", Self::A1 => "A1", Self::Rgb16_565 => "Rgb16_565", Self::Rgb30 => "Rgb30", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(Format, ffi::gobject::cairo_gobject_format_get_type); impl Format { #[doc(alias = "cairo_format_stride_for_width")] pub fn stride_for_width(self, width: u32) -> Result { assert!(width <= i32::MAX as u32); let width = width as i32; let stride = unsafe { ffi::cairo_format_stride_for_width(self.into(), width) }; if stride == -1 { Err(Error::InvalidFormat) } else { Ok(stride) } } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[non_exhaustive] #[doc(alias = "cairo_region_overlap_t")] pub enum RegionOverlap { #[doc(alias = "REGION_OVERLAP_IN")] In, #[doc(alias = "REGION_OVERLAP_OUT")] Out, #[doc(alias = "REGION_OVERLAP_PART")] Part, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_region_overlap_t { fn from(val: RegionOverlap) -> ffi::cairo_region_overlap_t { match val { RegionOverlap::In => ffi::REGION_OVERLAP_IN, RegionOverlap::Out => ffi::REGION_OVERLAP_OUT, RegionOverlap::Part => ffi::REGION_OVERLAP_PART, RegionOverlap::__Unknown(value) => value, } } } #[doc(hidden)] impl From for RegionOverlap { fn from(value: ffi::cairo_region_overlap_t) -> Self { match value { ffi::REGION_OVERLAP_IN => Self::In, ffi::REGION_OVERLAP_OUT => Self::Out, ffi::REGION_OVERLAP_PART => Self::Part, value => Self::__Unknown(value), } } } impl fmt::Display for RegionOverlap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::In => "In", Self::Out => "Out", Self::Part => "Part", _ => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!( RegionOverlap, ffi::gobject::cairo_gobject_region_overlap_get_type ); bitflags::bitflags! { pub struct PdfOutline: i32 { #[doc(alias = "PDF_OUTLINE_FLAG_OPEN")] const OPEN = ffi::PDF_OUTLINE_FLAG_OPEN; #[doc(alias = "PDF_OUTLINE_FLAG_BOLD")] const BOLD = ffi::PDF_OUTLINE_FLAG_BOLD; #[doc(alias = "PDF_OUTLINE_FLAG_ITALIC")] const ITALIC = ffi::PDF_OUTLINE_FLAG_ITALIC; } } #[cfg(any(feature = "pdf", feature = "dox"))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[non_exhaustive] #[doc(alias = "cairo_pdf_metadata_t")] pub enum PdfMetadata { #[doc(alias = "PDF_METADATA_TITLE")] Title, #[doc(alias = "PDF_METADATA_AUTHOR")] Author, #[doc(alias = "PDF_METADATA_SUBJECT")] Subject, #[doc(alias = "PDF_METADATA_KEYWORDS")] Keywords, #[doc(alias = "PDF_METADATA_CREATOR")] Creator, #[doc(alias = "PDF_METADATA_CREATE_DATE")] CreateDate, #[doc(alias = "PDF_METADATA_MOD_DATE")] ModDate, #[doc(hidden)] __Unknown(i32), } #[cfg(any(all(feature = "pdf", feature = "v1_16"), feature = "dox"))] #[doc(hidden)] impl From for ffi::cairo_pdf_metadata_t { fn from(val: PdfMetadata) -> ffi::cairo_pdf_metadata_t { match val { PdfMetadata::Title => ffi::PDF_METADATA_TITLE, PdfMetadata::Author => ffi::PDF_METADATA_AUTHOR, PdfMetadata::Subject => ffi::PDF_METADATA_SUBJECT, PdfMetadata::Keywords => ffi::PDF_METADATA_KEYWORDS, PdfMetadata::Creator => ffi::PDF_METADATA_CREATOR, PdfMetadata::CreateDate => ffi::PDF_METADATA_CREATE_DATE, PdfMetadata::ModDate => ffi::PDF_METADATA_MOD_DATE, PdfMetadata::__Unknown(value) => value, } } } #[cfg(any(all(feature = "pdf", feature = "v1_16"), feature = "dox"))] #[doc(hidden)] impl From for PdfMetadata { fn from(value: ffi::cairo_pdf_metadata_t) -> Self { match value { ffi::PDF_METADATA_TITLE => Self::Title, ffi::PDF_METADATA_AUTHOR => Self::Author, ffi::PDF_METADATA_SUBJECT => Self::Subject, ffi::PDF_METADATA_KEYWORDS => Self::Keywords, ffi::PDF_METADATA_CREATOR => Self::Creator, ffi::PDF_METADATA_CREATE_DATE => Self::CreateDate, ffi::PDF_METADATA_MOD_DATE => Self::ModDate, value => Self::__Unknown(value), } } } #[cfg(any(all(feature = "pdf", feature = "v1_16"), feature = "dox"))] impl fmt::Display for PdfMetadata { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Title => "Title", Self::Author => "Author", Self::Subject => "Subject", Self::Keywords => "Keywords", Self::Creator => "Creator", Self::CreateDate => "CreateDate", Self::ModDate => "ModDate", _ => "Unknown", } ) } } #[cfg(any(feature = "pdf", feature = "dox"))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[non_exhaustive] #[doc(alias = "cairo_pdf_version_t")] pub enum PdfVersion { #[doc(alias = "PDF_VERSION__1_4")] _1_4, #[doc(alias = "PDF_VERSION__1_5")] _1_5, #[doc(hidden)] __Unknown(i32), } #[cfg(any(feature = "pdf", feature = "dox"))] #[doc(hidden)] impl From for ffi::cairo_pdf_version_t { fn from(val: PdfVersion) -> ffi::cairo_pdf_version_t { match val { PdfVersion::_1_4 => ffi::PDF_VERSION__1_4, PdfVersion::_1_5 => ffi::PDF_VERSION__1_5, PdfVersion::__Unknown(value) => value, } } } #[cfg(any(feature = "pdf", feature = "dox"))] #[doc(hidden)] impl From for PdfVersion { fn from(value: ffi::cairo_pdf_version_t) -> Self { match value { ffi::PDF_VERSION__1_4 => Self::_1_4, ffi::PDF_VERSION__1_5 => Self::_1_5, value => Self::__Unknown(value), } } } #[cfg(any(feature = "pdf", feature = "dox"))] impl fmt::Display for PdfVersion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::_1_4 => "1_4", Self::_1_5 => "1_5", _ => "Unknown", } ) } } #[cfg(any(feature = "svg", feature = "dox"))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[non_exhaustive] #[doc(alias = "cairo_svg_version_t")] pub enum SvgVersion { #[doc(alias = "SVG_VERSION__1_1")] _1_1, #[doc(alias = "SVG_VERSION__1_2")] _1_2, #[doc(hidden)] __Unknown(i32), } #[cfg(any(feature = "svg", feature = "dox"))] #[doc(hidden)] impl From for ffi::cairo_svg_version_t { fn from(val: SvgVersion) -> ffi::cairo_svg_version_t { match val { SvgVersion::_1_1 => ffi::SVG_VERSION__1_1, SvgVersion::_1_2 => ffi::SVG_VERSION__1_2, SvgVersion::__Unknown(value) => value, } } } #[cfg(any(feature = "svg", feature = "dox"))] #[doc(hidden)] impl From for SvgVersion { fn from(value: ffi::cairo_svg_version_t) -> Self { match value { ffi::SVG_VERSION__1_1 => Self::_1_1, ffi::SVG_VERSION__1_2 => Self::_1_2, value => Self::__Unknown(value), } } } #[cfg(any(feature = "svg", feature = "dox"))] impl fmt::Display for SvgVersion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::_1_1 => "1_1", Self::_1_2 => "1_2", _ => "Unknown", } ) } } #[cfg(any(feature = "ps", feature = "dox"))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[non_exhaustive] #[doc(alias = "cairo_ps_level_t")] pub enum PsLevel { #[doc(alias = "PS_LEVEL__2")] _2, #[doc(alias = "PS_LEVEL__3")] _3, #[doc(hidden)] __Unknown(i32), } #[cfg(any(feature = "ps", feature = "dox"))] #[doc(hidden)] impl From for ffi::cairo_ps_level_t { fn from(val: PsLevel) -> ffi::cairo_ps_level_t { match val { PsLevel::_2 => ffi::PS_LEVEL__2, PsLevel::_3 => ffi::PS_LEVEL__3, PsLevel::__Unknown(value) => value, } } } #[cfg(any(feature = "ps", feature = "dox"))] #[doc(hidden)] impl From for PsLevel { fn from(value: ffi::cairo_ps_level_t) -> Self { match value { ffi::PS_LEVEL__2 => Self::_2, ffi::PS_LEVEL__3 => Self::_3, value => Self::__Unknown(value), } } } #[cfg(any(feature = "ps", feature = "dox"))] impl fmt::Display for PsLevel { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::_2 => "_2", Self::_3 => "_3", _ => "Unknown", } ) } } #[derive(Clone, PartialEq, PartialOrd, Copy, Debug)] #[non_exhaustive] #[doc(alias = "cairo_mesh_corner_t")] pub enum MeshCorner { #[doc(alias = "MESH_CORNER_MESH_CORNER0")] MeshCorner0, #[doc(alias = "MESH_CORNER_MESH_CORNER1")] MeshCorner1, #[doc(alias = "MESH_CORNER_MESH_CORNER2")] MeshCorner2, #[doc(alias = "MESH_CORNER_MESH_CORNER3")] MeshCorner3, #[doc(hidden)] __Unknown(u32), } #[doc(hidden)] impl From for ffi::cairo_mesh_corner_t { fn from(val: MeshCorner) -> ffi::cairo_mesh_corner_t { match val { MeshCorner::MeshCorner0 => ffi::MESH_CORNER_MESH_CORNER0, MeshCorner::MeshCorner1 => ffi::MESH_CORNER_MESH_CORNER1, MeshCorner::MeshCorner2 => ffi::MESH_CORNER_MESH_CORNER2, MeshCorner::MeshCorner3 => ffi::MESH_CORNER_MESH_CORNER3, MeshCorner::__Unknown(value) => value, } } } #[doc(hidden)] impl From for MeshCorner { fn from(value: ffi::cairo_mesh_corner_t) -> Self { match value { ffi::MESH_CORNER_MESH_CORNER0 => Self::MeshCorner0, ffi::MESH_CORNER_MESH_CORNER1 => Self::MeshCorner1, ffi::MESH_CORNER_MESH_CORNER2 => Self::MeshCorner2, ffi::MESH_CORNER_MESH_CORNER3 => Self::MeshCorner3, value => Self::__Unknown(value), } } } impl fmt::Display for MeshCorner { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::MeshCorner0 => "MeshCorner0", Self::MeshCorner1 => "MeshCorner1", Self::MeshCorner2 => "MeshCorner2", Self::MeshCorner3 => "MeshCorner3", _ => "Unknown", } ) } } #[cfg(any(feature = "freetype", feature = "dox"))] #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_ft_synthesize_t")] pub enum FtSynthesize { #[doc(alias = "CAIRO_FT_SYNTHESIZE_BOLD")] Bold, #[doc(alias = "CAIRO_FT_SYNTHESIZE_OBLIQUE")] Oblique, #[doc(hidden)] __Unknown(u32), } #[cfg(any(feature = "freetype", feature = "dox"))] #[doc(hidden)] impl From for ffi::cairo_ft_synthesize_t { fn from(val: FtSynthesize) -> ffi::cairo_ft_synthesize_t { match val { FtSynthesize::Bold => ffi::CAIRO_FT_SYNTHESIZE_BOLD, FtSynthesize::Oblique => ffi::CAIRO_FT_SYNTHESIZE_OBLIQUE, FtSynthesize::__Unknown(value) => value, } } } #[cfg(any(feature = "freetype", feature = "dox"))] #[doc(hidden)] impl From for FtSynthesize { fn from(value: ffi::cairo_ft_synthesize_t) -> Self { match value { ffi::CAIRO_FT_SYNTHESIZE_BOLD => Self::Bold, ffi::CAIRO_FT_SYNTHESIZE_OBLIQUE => Self::Oblique, value => Self::__Unknown(value), } } } #[cfg(any(feature = "freetype", feature = "dox"))] impl fmt::Display for FtSynthesize { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Bold => "Bold", Self::Oblique => "Oblique", Self::__Unknown(_) => "Unknown", } ) } } #[cfg(any(feature = "script", feature = "dox"))] #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_script_mode_t")] pub enum ScriptMode { #[doc(alias = "CAIRO_SCRIPT_MODE_ASCII")] Ascii, #[doc(alias = "CAIRO_SCRIPT_MODE_BINARY")] Binary, #[doc(hidden)] __Unknown(i32), } #[cfg(any(feature = "script", feature = "dox"))] #[doc(hidden)] impl From for ffi::cairo_script_mode_t { fn from(val: ScriptMode) -> ffi::cairo_script_mode_t { match val { ScriptMode::Ascii => ffi::CAIRO_SCRIPT_MODE_ASCII, ScriptMode::Binary => ffi::CAIRO_SCRIPT_MODE_BINARY, ScriptMode::__Unknown(value) => value, } } } #[cfg(any(feature = "script", feature = "dox"))] #[doc(hidden)] impl From for ScriptMode { fn from(value: ffi::cairo_script_mode_t) -> Self { match value { ffi::CAIRO_SCRIPT_MODE_ASCII => Self::Ascii, ffi::CAIRO_SCRIPT_MODE_BINARY => Self::Binary, value => Self::__Unknown(value), } } } #[cfg(any(feature = "script", feature = "dox"))] impl fmt::Display for ScriptMode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Ascii => "Ascii", Self::Binary => "Binary", Self::__Unknown(_) => "Unknown", } ) } } #[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] #[non_exhaustive] #[doc(alias = "cairo_device_type_t")] pub enum DeviceType { #[doc(alias = "CAIRO_DEVICE_TYPE_DRM")] Ascii, #[doc(alias = "CAIRO_DEVICE_TYPE_GL")] Binary, #[doc(alias = "CAIRO_DEVICE_TYPE_SCRIPT")] Script, #[doc(alias = "CAIRO_DEVICE_TYPE_XCB")] Xcb, #[doc(alias = "CAIRO_DEVICE_TYPE_XLIB")] Xlib, #[doc(alias = "CAIRO_DEVICE_TYPE_XML")] Xml, #[doc(alias = "CAIRO_DEVICE_TYPE_COGL")] Cogl, #[doc(alias = "CAIRO_DEVICE_TYPE_WIN32")] Win32, #[doc(alias = "CAIRO_DEVICE_TYPE_INVALID")] Invalid, #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_device_type_t { fn from(val: DeviceType) -> ffi::cairo_device_type_t { match val { DeviceType::Ascii => ffi::CAIRO_DEVICE_TYPE_DRM, DeviceType::Binary => ffi::CAIRO_DEVICE_TYPE_GL, DeviceType::Script => ffi::CAIRO_DEVICE_TYPE_SCRIPT, DeviceType::Xcb => ffi::CAIRO_DEVICE_TYPE_XCB, DeviceType::Xlib => ffi::CAIRO_DEVICE_TYPE_XLIB, DeviceType::Xml => ffi::CAIRO_DEVICE_TYPE_XML, DeviceType::Cogl => ffi::CAIRO_DEVICE_TYPE_COGL, DeviceType::Win32 => ffi::CAIRO_DEVICE_TYPE_WIN32, DeviceType::Invalid => ffi::CAIRO_DEVICE_TYPE_INVALID, DeviceType::__Unknown(value) => value, } } } #[doc(hidden)] impl From for DeviceType { fn from(value: ffi::cairo_device_type_t) -> Self { match value { ffi::CAIRO_DEVICE_TYPE_DRM => Self::Ascii, ffi::CAIRO_DEVICE_TYPE_GL => Self::Binary, ffi::CAIRO_DEVICE_TYPE_SCRIPT => Self::Script, ffi::CAIRO_DEVICE_TYPE_XCB => Self::Xcb, ffi::CAIRO_DEVICE_TYPE_XLIB => Self::Xlib, ffi::CAIRO_DEVICE_TYPE_XML => Self::Xml, ffi::CAIRO_DEVICE_TYPE_COGL => Self::Cogl, ffi::CAIRO_DEVICE_TYPE_WIN32 => Self::Win32, ffi::CAIRO_DEVICE_TYPE_INVALID => Self::Invalid, value => Self::__Unknown(value), } } } impl fmt::Display for DeviceType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::Ascii => "Ascii", Self::Binary => "Binary", Self::Script => "Script", Self::Xcb => "Xcb", Self::Xlib => "Xlib", Self::Xml => "Xml", Self::Cogl => "Cogl", Self::Win32 => "Win32", Self::Invalid => "Invalid", Self::__Unknown(_) => "Unknown", } ) } } #[cfg(feature = "use_glib")] gvalue_impl!(DeviceType, ffi::gobject::cairo_gobject_device_type_get_type); #[cfg(test)] mod tests { use super::*; #[test] #[should_panic] fn stride_panics_on_bad_value() { let _ = Format::Rgb24.stride_for_width(u32::MAX); } #[test] fn stride_errors_on_large_width() { assert!(Format::Rgb24.stride_for_width(i32::MAX as u32).is_err()); } #[test] fn stride_works() { assert_eq!(Format::Rgb24.stride_for_width(1).unwrap(), 4); } } cairo-rs-0.14.9/src/error.rs000064400000000000000000000250210072674642500137540ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use std::fmt::Debug; use std::io; use thiserror::Error; #[derive(Error, Debug, Clone, PartialEq, Copy, Eq)] #[non_exhaustive] #[doc(alias = "cairo_status_t")] pub enum Error { #[error("No Memory")] #[doc(alias = "STATUS_NO_MEMORY")] NoMemory, #[error("Invalid Restore")] #[doc(alias = "STATUS_INVALID_RESTORE")] InvalidRestore, #[error("Invalid Pop Group")] #[doc(alias = "STATUS_INVALID_POP_GROUP")] InvalidPopGroup, #[error("No Current Point")] #[doc(alias = "STATUS_NO_CURRENT_POINT")] NoCurrentPoint, #[error("Invalid Matrix")] #[doc(alias = "STATUS_INVALID_MATRIX")] InvalidMatrix, #[error("Invalid Status")] #[doc(alias = "STATUS_INVALID_STATUS")] InvalidStatus, #[error("Null Pointer")] #[doc(alias = "STATUS_NULL_POINTER")] NullPointer, #[error("Invalid String")] #[doc(alias = "STATUS_INVALID_STRING")] InvalidString, #[error("Invalid Path Data")] #[doc(alias = "STATUS_INVALID_PATH_DATA")] InvalidPathData, #[error("Cairo : Read Error")] #[doc(alias = "STATUS_READ_ERROR")] ReadError, #[error("Write Error")] #[doc(alias = "STATUS_WRITE_ERROR")] WriteError, #[error("Surface Finished")] #[doc(alias = "STATUS_SURFACE_FINISHED")] SurfaceFinished, #[error("Surface Type Mismatch")] #[doc(alias = "STATUS_SURFACE_TYPE_MISMATCH")] SurfaceTypeMismatch, #[error("Pattern Type Mismatch")] #[doc(alias = "STATUS_PATTERN_TYPE_MISMATCH")] PatternTypeMismatch, #[error("Invalid Content")] #[doc(alias = "STATUS_INVALID_CONTENT")] InvalidContent, #[error("Invalid Format")] #[doc(alias = "STATUS_INVALID_FORMAT")] InvalidFormat, #[error("Invalid Visual")] #[doc(alias = "STATUS_INVALID_VISUAL")] InvalidVisual, #[error("File Not Found")] #[doc(alias = "STATUS_FILE_NOT_FOUND")] FileNotFound, #[error("Invalid Dash")] #[doc(alias = "STATUS_INVALID_DASH")] InvalidDash, #[error("Invalid Dash Comment")] #[doc(alias = "STATUS_INVALID_DSC_COMMENT")] InvalidDscComment, #[error("Invalid Index")] #[doc(alias = "STATUS_INVALID_INDEX")] InvalidIndex, #[error("Clip Not Representable")] #[doc(alias = "STATUS_CLIP_NOT_REPRESENTABLE")] ClipNotRepresentable, #[error("Temp File Error")] #[doc(alias = "STATUS_TEMP_FILE_ERROR")] TempFileError, #[error("Invalid Stride")] #[doc(alias = "STATUS_INVALID_STRIDE")] InvalidStride, #[error("Font Type Mismatch")] #[doc(alias = "STATUS_FONT_TYPE_MISMATCH")] FontTypeMismatch, #[error("User Font Immutable")] #[doc(alias = "STATUS_USER_FONT_IMMUTABLE")] UserFontImmutable, #[error("User Font Error")] #[doc(alias = "STATUS_USER_FONT_ERROR")] UserFontError, #[error("Negative Count")] #[doc(alias = "STATUS_NEGATIVE_COUNT")] NegativeCount, #[error("Invalid Clusters")] #[doc(alias = "STATUS_INVALID_CLUSTERS")] InvalidClusters, #[error("Invalid Slant")] #[doc(alias = "STATUS_INVALID_SLANT")] InvalidSlant, #[error("Invalid Weight")] #[doc(alias = "STATUS_INVALID_WEIGHT")] InvalidWeight, #[error("Invalid Size")] #[doc(alias = "STATUS_INVALID_SIZE")] InvalidSize, #[error("User Font Not Implemented")] #[doc(alias = "STATUS_USER_FONT_NOT_IMPLEMENTED")] UserFontNotImplemented, #[error("Device Type Mismatch")] #[doc(alias = "STATUS_DEVICE_TYPE_MISMATCH")] DeviceTypeMismatch, #[error("Device Error")] #[doc(alias = "STATUS_DEVICE_ERROR")] DeviceError, #[error("Invalid Mesh Construction")] #[doc(alias = "STATUS_INVALID_MESH_CONSTRUCTION")] InvalidMeshConstruction, #[error("Device Finished")] #[doc(alias = "STATUS_DEVICE_FINISHED")] DeviceFinished, #[error("JBig2Global Missing")] #[doc(alias = "STATUS_J_BIG2_GLOBAL_MISSING")] JBig2GlobalMissing, #[error("PNG Error")] #[doc(alias = "STATUS_PNG_ERROR")] PngError, #[error("Freetype Error")] #[doc(alias = "STATUS_FREETYPE_ERROR")] FreetypeError, #[error("Win32Gdi Error")] #[doc(alias = "STATUS_WIN32_GDI_ERROR")] Win32GdiError, #[error("LastStatus")] #[doc(alias = "STATUS_LAST_STATUS")] LastStatus, #[error("Unknown {0}")] #[doc(hidden)] __Unknown(i32), } #[doc(hidden)] impl From for ffi::cairo_status_t { fn from(err: Error) -> ffi::cairo_status_t { match err { Error::NoMemory => ffi::STATUS_NO_MEMORY, Error::InvalidRestore => ffi::STATUS_INVALID_RESTORE, Error::InvalidPopGroup => ffi::STATUS_INVALID_POP_GROUP, Error::NoCurrentPoint => ffi::STATUS_NO_CURRENT_POINT, Error::InvalidMatrix => ffi::STATUS_INVALID_MATRIX, Error::InvalidStatus => ffi::STATUS_INVALID_STATUS, Error::NullPointer => ffi::STATUS_NULL_POINTER, Error::InvalidString => ffi::STATUS_INVALID_STRING, Error::InvalidPathData => ffi::STATUS_INVALID_PATH_DATA, Error::ReadError => ffi::STATUS_READ_ERROR, Error::WriteError => ffi::STATUS_WRITE_ERROR, Error::SurfaceFinished => ffi::STATUS_SURFACE_FINISHED, Error::SurfaceTypeMismatch => ffi::STATUS_SURFACE_TYPE_MISMATCH, Error::PatternTypeMismatch => ffi::STATUS_PATTERN_TYPE_MISMATCH, Error::InvalidContent => ffi::STATUS_INVALID_CONTENT, Error::InvalidFormat => ffi::STATUS_INVALID_FORMAT, Error::InvalidVisual => ffi::STATUS_INVALID_VISUAL, Error::FileNotFound => ffi::STATUS_FILE_NOT_FOUND, Error::InvalidDash => ffi::STATUS_INVALID_DASH, Error::InvalidDscComment => ffi::STATUS_INVALID_DSC_COMMENT, Error::InvalidIndex => ffi::STATUS_INVALID_INDEX, Error::ClipNotRepresentable => ffi::STATUS_CLIP_NOT_REPRESENTABLE, Error::TempFileError => ffi::STATUS_TEMP_FILE_ERROR, Error::InvalidStride => ffi::STATUS_INVALID_STRIDE, Error::FontTypeMismatch => ffi::STATUS_FONT_TYPE_MISMATCH, Error::UserFontImmutable => ffi::STATUS_USER_FONT_IMMUTABLE, Error::UserFontError => ffi::STATUS_USER_FONT_ERROR, Error::NegativeCount => ffi::STATUS_NEGATIVE_COUNT, Error::InvalidClusters => ffi::STATUS_INVALID_CLUSTERS, Error::InvalidSlant => ffi::STATUS_INVALID_SLANT, Error::InvalidWeight => ffi::STATUS_INVALID_WEIGHT, Error::InvalidSize => ffi::STATUS_INVALID_SIZE, Error::UserFontNotImplemented => ffi::STATUS_USER_FONT_NOT_IMPLEMENTED, Error::DeviceTypeMismatch => ffi::STATUS_DEVICE_TYPE_MISMATCH, Error::DeviceError => ffi::STATUS_DEVICE_ERROR, Error::InvalidMeshConstruction => ffi::STATUS_INVALID_MESH_CONSTRUCTION, Error::DeviceFinished => ffi::STATUS_DEVICE_FINISHED, Error::JBig2GlobalMissing => ffi::STATUS_J_BIG2_GLOBAL_MISSING, Error::PngError => ffi::STATUS_PNG_ERROR, Error::FreetypeError => ffi::STATUS_FREETYPE_ERROR, Error::Win32GdiError => ffi::STATUS_WIN32_GDI_ERROR, Error::LastStatus => ffi::STATUS_LAST_STATUS, Error::__Unknown(value) => value, } } } #[doc(hidden)] impl From for Error { fn from(value: ffi::cairo_status_t) -> Self { match value { ffi::STATUS_NO_MEMORY => Self::NoMemory, ffi::STATUS_INVALID_RESTORE => Self::InvalidRestore, ffi::STATUS_INVALID_POP_GROUP => Self::InvalidPopGroup, ffi::STATUS_NO_CURRENT_POINT => Self::NoCurrentPoint, ffi::STATUS_INVALID_MATRIX => Self::InvalidMatrix, ffi::STATUS_INVALID_STATUS => Self::InvalidStatus, ffi::STATUS_NULL_POINTER => Self::NullPointer, ffi::STATUS_INVALID_STRING => Self::InvalidString, ffi::STATUS_INVALID_PATH_DATA => Self::InvalidPathData, ffi::STATUS_READ_ERROR => Self::ReadError, ffi::STATUS_WRITE_ERROR => Self::WriteError, ffi::STATUS_SURFACE_FINISHED => Self::SurfaceFinished, ffi::STATUS_SURFACE_TYPE_MISMATCH => Self::SurfaceTypeMismatch, ffi::STATUS_PATTERN_TYPE_MISMATCH => Self::PatternTypeMismatch, ffi::STATUS_INVALID_CONTENT => Self::InvalidContent, ffi::STATUS_INVALID_FORMAT => Self::InvalidFormat, ffi::STATUS_INVALID_VISUAL => Self::InvalidVisual, ffi::STATUS_FILE_NOT_FOUND => Self::FileNotFound, ffi::STATUS_INVALID_DASH => Self::InvalidDash, ffi::STATUS_INVALID_DSC_COMMENT => Self::InvalidDscComment, ffi::STATUS_INVALID_INDEX => Self::InvalidIndex, ffi::STATUS_CLIP_NOT_REPRESENTABLE => Self::ClipNotRepresentable, ffi::STATUS_TEMP_FILE_ERROR => Self::TempFileError, ffi::STATUS_INVALID_STRIDE => Self::InvalidStride, ffi::STATUS_FONT_TYPE_MISMATCH => Self::FontTypeMismatch, ffi::STATUS_USER_FONT_IMMUTABLE => Self::UserFontImmutable, ffi::STATUS_USER_FONT_ERROR => Self::UserFontError, ffi::STATUS_NEGATIVE_COUNT => Self::NegativeCount, ffi::STATUS_INVALID_CLUSTERS => Self::InvalidClusters, ffi::STATUS_INVALID_SLANT => Self::InvalidSlant, ffi::STATUS_INVALID_WEIGHT => Self::InvalidWeight, ffi::STATUS_INVALID_SIZE => Self::InvalidSize, ffi::STATUS_USER_FONT_NOT_IMPLEMENTED => Self::UserFontNotImplemented, ffi::STATUS_DEVICE_TYPE_MISMATCH => Self::DeviceTypeMismatch, ffi::STATUS_DEVICE_ERROR => Self::DeviceError, ffi::STATUS_INVALID_MESH_CONSTRUCTION => Self::InvalidMeshConstruction, ffi::STATUS_DEVICE_FINISHED => Self::DeviceFinished, ffi::STATUS_J_BIG2_GLOBAL_MISSING => Self::JBig2GlobalMissing, ffi::STATUS_PNG_ERROR => Self::PngError, ffi::STATUS_FREETYPE_ERROR => Self::FreetypeError, ffi::STATUS_WIN32_GDI_ERROR => Self::Win32GdiError, ffi::STATUS_LAST_STATUS => Self::LastStatus, value => Self::__Unknown(value), } } } #[derive(Error, Debug)] pub enum IoError { #[error("Cairo error: {0}")] Cairo(#[from] Error), #[error("IO error: {0}")] Io(#[from] io::Error), } #[derive(Error, Debug)] pub enum BorrowError { #[error("Failed to borrow with Cairo error: {0}")] Cairo(#[from] crate::Error), #[error("Can't get exclusive access")] NonExclusive, } pub type Result = std::result::Result; cairo-rs-0.14.9/src/font/font_face.rs000064400000000000000000000147730072674642500155310ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. #[cfg(feature = "use_glib")] use glib::translate::*; use std::ffi::{CStr, CString}; #[cfg(not(feature = "use_glib"))] use std::ptr; use crate::{ enums::{FontSlant, FontType, FontWeight}, Error, }; #[cfg(any(feature = "freetype", feature = "dox"))] use crate::enums::FtSynthesize; use crate::utils::status_to_result; #[cfg(feature = "use_glib")] glib::wrapper! { #[derive(Debug)] #[doc(alias = "cairo_font_face_t")] pub struct FontFace(Shared); match fn { ref => |ptr| ffi::cairo_font_face_reference(ptr), unref => |ptr| ffi::cairo_font_face_destroy(ptr), type_ => || ffi::gobject::cairo_gobject_font_face_get_type(), } } #[cfg(not(feature = "use_glib"))] #[derive(Debug)] #[doc(alias = "cairo_font_face_t")] pub struct FontFace(ptr::NonNull); impl FontFace { #[doc(alias = "cairo_toy_font_face_create")] pub fn toy_create( family: &str, slant: FontSlant, weight: FontWeight, ) -> Result { let font_face: FontFace = unsafe { let family = CString::new(family).unwrap(); FontFace::from_raw_full(ffi::cairo_toy_font_face_create( family.as_ptr(), slant.into(), weight.into(), )) }; let status = unsafe { ffi::cairo_font_face_status(font_face.to_raw_none()) }; status_to_result(status)?; Ok(font_face) } // Safety: the FT_Face must be valid and not be freed until the `FontFace` is dropped. #[cfg(any(feature = "freetype", feature = "dox"))] #[doc(alias = "cairo_ft_font_face_create_for_ft_face")] pub unsafe fn create_from_ft( face: freetype_crate::freetype::FT_Face, ) -> Result { let font_face = FontFace::from_raw_full(ffi::cairo_ft_font_face_create_for_ft_face( face as *mut _, 0, )); let status = ffi::cairo_font_face_status(font_face.to_raw_none()); status_to_result(status)?; Ok(font_face) } // Safety: the FT_Face must be valid and not be freed until the `FontFace` is dropped. #[cfg(any(feature = "freetype", feature = "dox"))] #[doc(alias = "cairo_ft_font_face_create_for_ft_face")] pub unsafe fn create_from_ft_with_flags( face: freetype_crate::freetype::FT_Face, load_flags: libc::c_int, ) -> Result { let font_face = FontFace::from_raw_full(ffi::cairo_ft_font_face_create_for_ft_face( face as *mut _, load_flags, )); let status = ffi::cairo_font_face_status(font_face.to_raw_none()); status_to_result(status)?; Ok(font_face) } #[cfg(feature = "use_glib")] pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_font_face_t) -> FontFace { from_glib_full(ptr) } #[cfg(not(feature = "use_glib"))] pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_font_face_t) -> FontFace { assert!(!ptr.is_null()); FontFace(ptr::NonNull::new_unchecked(ptr)) } #[cfg(feature = "use_glib")] pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_font_face_t) -> FontFace { from_glib_none(ptr) } #[cfg(not(feature = "use_glib"))] pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_font_face_t) -> FontFace { assert!(!ptr.is_null()); FontFace(ptr::NonNull::new_unchecked(ptr)) } #[cfg(feature = "use_glib")] pub fn to_raw_none(&self) -> *mut ffi::cairo_font_face_t { self.to_glib_none().0 } #[cfg(not(feature = "use_glib"))] pub fn to_raw_none(&self) -> *mut ffi::cairo_font_face_t { self.0.as_ptr() } #[doc(alias = "cairo_toy_font_face_get_family")] pub fn toy_get_family(&self) -> Option { unsafe { to_optional_string(ffi::cairo_toy_font_face_get_family(self.to_raw_none())) } } #[doc(alias = "cairo_toy_font_face_get_slant")] pub fn toy_get_slant(&self) -> FontSlant { unsafe { FontSlant::from(ffi::cairo_toy_font_face_get_slant(self.to_raw_none())) } } #[doc(alias = "cairo_toy_font_face_get_weight")] pub fn toy_get_weight(&self) -> FontWeight { unsafe { FontWeight::from(ffi::cairo_toy_font_face_get_weight(self.to_raw_none())) } } #[doc(alias = "cairo_font_face_get_type")] #[doc(alias = "get_type")] pub fn type_(&self) -> FontType { unsafe { FontType::from(ffi::cairo_font_face_get_type(self.to_raw_none())) } } #[doc(alias = "cairo_font_face_get_reference_count")] #[doc(alias = "get_reference_count")] pub fn reference_count(&self) -> usize { unsafe { ffi::cairo_font_face_get_reference_count(self.to_raw_none()) as usize } } #[doc(alias = "cairo_ft_font_face_get_synthesize")] #[cfg(any(feature = "freetype", feature = "dox"))] #[doc(alias = "get_synthesize")] pub fn synthesize(&self) -> FtSynthesize { unsafe { FtSynthesize::from(ffi::cairo_ft_font_face_get_synthesize(self.to_raw_none())) } } #[cfg(any(feature = "freetype", feature = "dox"))] #[doc(alias = "cairo_ft_font_face_set_synthesize")] pub fn set_synthesize(&self, synth_flags: FtSynthesize) { unsafe { ffi::cairo_ft_font_face_set_synthesize(self.to_raw_none(), synth_flags.into()) } } #[cfg(any(feature = "freetype", feature = "dox"))] #[doc(alias = "cairo_ft_font_face_unset_synthesize")] pub fn unset_synthesize(&self, synth_flags: FtSynthesize) { unsafe { ffi::cairo_ft_font_face_unset_synthesize(self.to_raw_none(), synth_flags.into()) } } #[doc(alias = "cairo_font_face_status")] pub fn status(&self) -> Result<(), Error> { let status = unsafe { ffi::cairo_font_face_status(self.to_raw_none()) }; status_to_result(status) } user_data_methods! { ffi::cairo_font_face_get_user_data, ffi::cairo_font_face_set_user_data, } } #[cfg(not(feature = "use_glib"))] impl Drop for FontFace { fn drop(&mut self) { unsafe { ffi::cairo_font_face_destroy(self.to_raw_none()); } } } #[cfg(not(feature = "use_glib"))] impl Clone for FontFace { fn clone(&self) -> FontFace { unsafe { FontFace::from_raw_none(self.to_raw_none()) } } } pub(crate) unsafe fn to_optional_string(str: *const libc::c_char) -> Option { if str.is_null() { None } else { Some(String::from_utf8_lossy(CStr::from_ptr(str).to_bytes()).into_owned()) } } cairo-rs-0.14.9/src/font/font_options.rs000064400000000000000000000145710072674642500163220ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. #[cfg(feature = "use_glib")] use glib::translate::*; use std::cmp::PartialEq; use std::hash; #[cfg(any(feature = "v1_16", feature = "dox"))] use crate::font::font_face::to_optional_string; #[cfg(any(feature = "v1_16", feature = "dox"))] use std::ffi::CString; #[cfg(not(feature = "use_glib"))] use std::ptr; use crate::utils::status_to_result; use crate::{ enums::{Antialias, HintMetrics, HintStyle, SubpixelOrder}, Error, }; #[cfg(feature = "use_glib")] glib::wrapper! { #[derive(Debug)] #[doc(alias = "cairo_font_options_t")] pub struct FontOptions(Boxed); match fn { copy => |ptr| { let ptr = ffi::cairo_font_options_copy(ptr); let status = ffi::cairo_font_options_status(ptr); status_to_result(status).expect("Failed to create a copy of FontOptions"); ptr }, free => |ptr| ffi::cairo_font_options_destroy(ptr), type_ => || ffi::gobject::cairo_gobject_font_options_get_type(), } } #[cfg(not(feature = "use_glib"))] #[derive(Debug)] #[doc(alias = "cairo_font_options_t")] pub struct FontOptions(ptr::NonNull); impl FontOptions { #[doc(alias = "cairo_font_options_create")] pub fn new() -> Result { let font_options: FontOptions = unsafe { FontOptions::from_raw_full(ffi::cairo_font_options_create()) }; let status = unsafe { ffi::cairo_font_options_status(font_options.to_raw_none()) }; status_to_result(status)?; Ok(font_options) } #[cfg(feature = "use_glib")] pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_font_options_t) -> Self { from_glib_full(ptr) } #[cfg(not(feature = "use_glib"))] pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_font_options_t) -> Self { assert!(!ptr.is_null()); Self(ptr::NonNull::new_unchecked(ptr)) } #[cfg(feature = "use_glib")] pub fn to_raw_none(&self) -> *mut ffi::cairo_font_options_t { mut_override(self.to_glib_none().0) } #[cfg(not(feature = "use_glib"))] pub fn to_raw_none(&self) -> *mut ffi::cairo_font_options_t { self.0.as_ptr() } #[doc(alias = "cairo_font_options_merge")] pub fn merge(&mut self, other: &FontOptions) { unsafe { ffi::cairo_font_options_merge(self.to_raw_none(), other.to_raw_none()) } } #[doc(alias = "cairo_font_options_set_antialias")] pub fn set_antialias(&mut self, antialias: Antialias) { unsafe { ffi::cairo_font_options_set_antialias(self.to_raw_none(), antialias.into()) } } #[doc(alias = "cairo_font_options_get_antialias")] #[doc(alias = "get_antialias")] pub fn antialias(&self) -> Antialias { unsafe { Antialias::from(ffi::cairo_font_options_get_antialias(self.to_raw_none())) } } #[doc(alias = "cairo_font_options_set_subpixel_order")] pub fn set_subpixel_order(&mut self, order: SubpixelOrder) { unsafe { ffi::cairo_font_options_set_subpixel_order(self.to_raw_none(), order.into()) } } #[doc(alias = "cairo_font_options_get_subpixel_order")] #[doc(alias = "get_subpixel_order")] pub fn subpixel_order(&self) -> SubpixelOrder { unsafe { SubpixelOrder::from(ffi::cairo_font_options_get_subpixel_order( self.to_raw_none(), )) } } #[doc(alias = "cairo_font_options_set_hint_style")] pub fn set_hint_style(&mut self, hint_style: HintStyle) { unsafe { ffi::cairo_font_options_set_hint_style(self.to_raw_none(), hint_style.into()) } } #[doc(alias = "cairo_font_options_get_hint_style")] #[doc(alias = "get_hint_style")] pub fn hint_style(&self) -> HintStyle { unsafe { HintStyle::from(ffi::cairo_font_options_get_hint_style(self.to_raw_none())) } } #[doc(alias = "cairo_font_options_set_hint_metrics")] pub fn set_hint_metrics(&mut self, hint_metrics: HintMetrics) { unsafe { ffi::cairo_font_options_set_hint_metrics(self.to_raw_none(), hint_metrics.into()) } } #[doc(alias = "cairo_font_options_get_hint_metrics")] #[doc(alias = "get_hint_metrics")] pub fn hint_metrics(&self) -> HintMetrics { unsafe { HintMetrics::from(ffi::cairo_font_options_get_hint_metrics(self.to_raw_none())) } } #[cfg(any(feature = "v1_16", feature = "dox"))] #[doc(alias = "cairo_font_options_get_variations")] #[doc(alias = "get_variations")] pub fn variations(&self) -> Option { unsafe { to_optional_string(ffi::cairo_font_options_get_variations(self.to_raw_none())) } } #[cfg(any(feature = "v1_16", feature = "dox"))] #[doc(alias = "cairo_font_options_set_variations")] pub fn set_variations<'a, T: Into>>(&self, variations: T) { unsafe { let variations = variations.into(); match variations { Some(v) => { let v = CString::new(v).unwrap(); ffi::cairo_font_options_set_variations(self.to_raw_none(), v.as_ptr()) } None => { ffi::cairo_font_options_set_variations(self.to_raw_none(), std::ptr::null()) } } } } #[doc(alias = "cairo_font_options_status")] pub fn status(&self) -> Result<(), Error> { let status = unsafe { ffi::cairo_font_options_status(self.to_raw_none()) }; status_to_result(status) } } impl PartialEq for FontOptions { #[doc(alias = "cairo_font_options_equal")] fn eq(&self, other: &FontOptions) -> bool { unsafe { ffi::cairo_font_options_equal(self.to_raw_none(), other.to_raw_none()).as_bool() } } } impl Eq for FontOptions {} impl hash::Hash for FontOptions { #[doc(alias = "cairo_font_options_hash")] fn hash(&self, state: &mut H) where H: hash::Hasher, { unsafe { hash::Hash::hash(&ffi::cairo_font_options_hash(self.to_raw_none()), state) } } } #[cfg(not(feature = "use_glib"))] impl Drop for FontOptions { fn drop(&mut self) { unsafe { ffi::cairo_font_options_destroy(self.to_raw_none()); } } } #[cfg(not(feature = "use_glib"))] impl Clone for FontOptions { fn clone(&self) -> FontOptions { unsafe { FontOptions::from_raw_full(ffi::cairo_font_options_copy(self.to_raw_none())) } } } cairo-rs-0.14.9/src/font/mod.rs000064400000000000000000000024640072674642500143560ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. mod font_face; mod font_options; mod scaled_font; pub use crate::enums::{ Antialias, FontSlant, FontType, FontWeight, HintMetrics, HintStyle, SubpixelOrder, TextClusterFlags, }; pub use crate::ffi::{FontExtents, Glyph, TextCluster, TextExtents}; /* TODO Allocates an array of cairo_glyph_t's. This function is only useful in implementations of cairo_user_scaled_font_text_to_glyphs_func_t where the user needs to allocate an array of glyphs that cairo will free. For all other uses, user can use their own allocation method for glyphs. impl Glyph { //pub fn cairo_glyph_allocate(num_glyphs: c_int) -> *Glyph; //pub fn cairo_glyph_free(glyphs: *Glyph); } Allocates an array of cairo_glyph_t's. This function is only useful in implementations of cairo_user_scaled_font_text_to_glyphs_func_t where the user needs to allocate an array of glyphs that cairo will free. For all other uses, user can use their own allocation method for glyphs. impl TextCluster { //pub fn cairo_text_cluster_allocate(num_clusters: c_int) -> *TextCluster; //pub fn cairo_text_cluster_free(clusters: *TextCluster); } */ pub use self::font_face::FontFace; pub use self::font_options::FontOptions; pub use self::scaled_font::ScaledFont; cairo-rs-0.14.9/src/font/scaled_font.rs000064400000000000000000000212010072674642500160460ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. #[cfg(feature = "use_glib")] use glib::translate::*; use std::ffi::CString; use std::ptr; use crate::ffi::{FontExtents, Glyph, TextCluster, TextExtents}; use crate::matrices::Matrix; use crate::utils::status_to_result; use crate::{enums::FontType, Error}; use super::{FontFace, FontOptions}; #[cfg(feature = "use_glib")] glib::wrapper! { #[derive(Debug)] #[doc(alias = "cairo_scaled_font_t")] pub struct ScaledFont(Shared); match fn { ref => |ptr| ffi::cairo_scaled_font_reference(ptr), unref => |ptr| ffi::cairo_scaled_font_destroy(ptr), type_ => || ffi::gobject::cairo_gobject_scaled_font_get_type(), } } #[cfg(not(feature = "use_glib"))] #[derive(Debug)] #[doc(alias = "cairo_scaled_font_t")] pub struct ScaledFont(ptr::NonNull); impl ScaledFont { #[doc(alias = "cairo_scaled_font_create")] pub fn new( font_face: &FontFace, font_matrix: &Matrix, ctm: &Matrix, options: &FontOptions, ) -> Result { let scaled_font: ScaledFont = unsafe { ScaledFont::from_raw_full(ffi::cairo_scaled_font_create( font_face.to_raw_none(), font_matrix.ptr(), ctm.ptr(), options.to_raw_none(), )) }; let status = unsafe { ffi::cairo_scaled_font_status(scaled_font.to_raw_none()) }; status_to_result(status)?; Ok(scaled_font) } #[cfg(feature = "use_glib")] pub fn to_raw_none(&self) -> *mut ffi::cairo_scaled_font_t { self.to_glib_none().0 } #[cfg(not(feature = "use_glib"))] pub fn to_raw_none(&self) -> *mut ffi::cairo_scaled_font_t { self.0.as_ptr() } #[cfg(not(feature = "use_glib"))] pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont { assert!(!ptr.is_null()); ScaledFont(ptr::NonNull::new_unchecked(ptr)) } #[cfg(feature = "use_glib")] pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont { from_glib_full(ptr) } #[cfg(feature = "use_glib")] pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont { from_glib_none(ptr) } #[cfg(not(feature = "use_glib"))] pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont { assert!(!ptr.is_null()); ffi::cairo_scaled_font_reference(ptr); ScaledFont(ptr::NonNull::new_unchecked(ptr)) } #[doc(alias = "cairo_scaled_font_get_type")] #[doc(alias = "get_type")] pub fn type_(&self) -> FontType { unsafe { FontType::from(ffi::cairo_scaled_font_get_type(self.to_raw_none())) } } #[doc(alias = "cairo_scaled_font_get_reference_count")] #[doc(alias = "get_reference_count")] pub fn reference_count(&self) -> usize { unsafe { ffi::cairo_scaled_font_get_reference_count(self.to_raw_none()) as usize } } #[doc(alias = "cairo_scaled_font_extents")] pub fn extents(&self) -> FontExtents { let mut extents = FontExtents { ascent: 0.0, descent: 0.0, height: 0.0, max_x_advance: 0.0, max_y_advance: 0.0, }; unsafe { ffi::cairo_scaled_font_extents(self.to_raw_none(), &mut extents) } extents } #[doc(alias = "cairo_scaled_font_text_extents")] pub fn text_extents(&self, text: &str) -> TextExtents { let mut extents = TextExtents { x_bearing: 0.0, y_bearing: 0.0, width: 0.0, height: 0.0, x_advance: 0.0, y_advance: 0.0, }; let text = CString::new(text).unwrap(); unsafe { ffi::cairo_scaled_font_text_extents(self.to_raw_none(), text.as_ptr(), &mut extents) } extents } #[doc(alias = "cairo_scaled_font_glyph_extents")] pub fn glyph_extents(&self, glyphs: &[Glyph]) -> TextExtents { let mut extents = TextExtents { x_bearing: 0.0, y_bearing: 0.0, width: 0.0, height: 0.0, x_advance: 0.0, y_advance: 0.0, }; unsafe { ffi::cairo_scaled_font_glyph_extents( self.to_raw_none(), glyphs.as_ptr(), glyphs.len() as i32, &mut extents, ) } extents } #[doc(alias = "cairo_scaled_font_text_to_glyphs")] pub fn text_to_glyphs( &self, x: f64, y: f64, text: &str, ) -> Result<(Vec, Vec), Error> { // This large unsafe block is due to the FFI function returning two specially allocated // (cairo_{glyph,text_cluster}_allocate) pointers that need to be copied into Vec // types before they're of any use to Rust code. unsafe { let mut glyphs_ptr: *mut Glyph = ptr::null_mut(); let mut glyph_count = 0i32; let mut clusters_ptr: *mut TextCluster = ptr::null_mut(); let mut cluster_count = 0i32; let mut cluster_flags = 0i32; let text_length = text.len() as i32; let text = CString::new(text).unwrap(); let status = ffi::cairo_scaled_font_text_to_glyphs( self.to_raw_none(), x, y, text.as_ptr(), text_length, &mut glyphs_ptr, &mut glyph_count, &mut clusters_ptr, &mut cluster_count, &mut cluster_flags, ); status_to_result(status)?; let glyph_count = glyph_count as usize; let glyphs: Vec = { let mut glyphs: Vec = Vec::with_capacity(glyph_count); glyphs.set_len(glyph_count); ptr::copy(glyphs_ptr, glyphs.as_mut_ptr(), glyph_count); glyphs }; let cluster_count = cluster_count as usize; let clusters: Vec = { let mut clusters = Vec::with_capacity(cluster_count); clusters.set_len(cluster_count); ptr::copy(clusters_ptr, clusters.as_mut_ptr(), cluster_count); clusters }; ffi::cairo_glyph_free(glyphs_ptr); ffi::cairo_text_cluster_free(clusters_ptr); Ok((glyphs, clusters)) } } #[doc(alias = "cairo_scaled_font_get_font_face")] #[doc(alias = "get_font_face")] pub fn font_face(&self) -> FontFace { unsafe { FontFace::from_raw_none(ffi::cairo_scaled_font_get_font_face(self.to_raw_none())) } } #[doc(alias = "cairo_scaled_font_get_font_options")] #[doc(alias = "get_font_options")] pub fn font_options(&self) -> Result { let options = FontOptions::new()?; unsafe { ffi::cairo_scaled_font_get_font_options(self.to_raw_none(), options.to_raw_none()) } Ok(options) } #[doc(alias = "cairo_scaled_font_get_font_matrix")] #[doc(alias = "get_font_matrix")] pub fn font_matrix(&self) -> Matrix { let mut matrix = Matrix::null(); unsafe { ffi::cairo_scaled_font_get_font_matrix(self.to_raw_none(), matrix.mut_ptr()) } matrix } #[doc(alias = "cairo_scaled_font_get_ctm")] #[doc(alias = "get_ctm")] pub fn ctm(&self) -> Matrix { let mut matrix = Matrix::null(); unsafe { ffi::cairo_scaled_font_get_ctm(self.to_raw_none(), matrix.mut_ptr()) } matrix } #[doc(alias = "cairo_scaled_font_get_scale_matrix")] #[doc(alias = "get_scale_matrix")] pub fn scale_matrix(&self) -> Matrix { let mut matrix = Matrix::null(); unsafe { ffi::cairo_scaled_font_get_scale_matrix(self.to_raw_none(), matrix.mut_ptr()) } matrix } #[doc(alias = "cairo_scaled_font_status")] pub fn status(&self) -> Result<(), Error> { let status = unsafe { ffi::cairo_scaled_font_status(self.to_raw_none()) }; status_to_result(status) } user_data_methods! { ffi::cairo_scaled_font_get_user_data, ffi::cairo_scaled_font_set_user_data, } } #[cfg(not(feature = "use_glib"))] impl Drop for ScaledFont { fn drop(&mut self) { unsafe { ffi::cairo_scaled_font_destroy(self.to_raw_none()); } } } #[cfg(not(feature = "use_glib"))] impl Clone for ScaledFont { fn clone(&self) -> ScaledFont { unsafe { ScaledFont::from_raw_none(self.to_raw_none()) } } } cairo-rs-0.14.9/src/image_surface.rs000064400000000000000000000226040072674642500154210ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use std::convert::TryFrom; use std::ops::{Deref, DerefMut}; use std::rc::Rc; use std::slice; use crate::enums::{Format, SurfaceType}; use crate::error::Error; #[cfg(feature = "use_glib")] use glib::translate::*; use crate::surface::Surface; use crate::utils::status_to_result; use crate::BorrowError; use std::fmt; declare_surface!(ImageSurface, SurfaceType::Image); impl ImageSurface { #[doc(alias = "cairo_image_surface_create")] pub fn create(format: Format, width: i32, height: i32) -> Result { unsafe { Self::from_raw_full(ffi::cairo_image_surface_create( format.into(), width, height, )) } } // rustdoc-stripper-ignore-next /// Creates an image surface for the provided pixel data. /// - The pointer `data` is the beginning of the underlying slice, /// and at least `width * stride` succeeding bytes should be allocated. /// - `data` must live longer than any reference to the returned surface. /// - You have to free `data` by yourself. #[doc(alias = "cairo_image_surface_create_for_data")] pub unsafe fn create_for_data_unsafe( data: *mut u8, format: Format, width: i32, height: i32, stride: i32, ) -> Result { ImageSurface::from_raw_full(ffi::cairo_image_surface_create_for_data( data, format.into(), width, height, stride, )) } #[doc(alias = "cairo_image_surface_create_for_data")] pub fn create_for_data + 'static>( data: D, format: Format, width: i32, height: i32, stride: i32, ) -> Result { let mut data: Box> = Box::new(data); let (ptr, len) = { let data: &mut [u8] = (*data).as_mut(); (data.as_mut_ptr(), data.len()) }; assert!(len >= (height * stride) as usize); let result = unsafe { ImageSurface::from_raw_full(ffi::cairo_image_surface_create_for_data( ptr, format.into(), width, height, stride, )) }; if let Ok(surface) = &result { static IMAGE_SURFACE_DATA: crate::UserDataKey>> = crate::UserDataKey::new(); surface.set_user_data(&IMAGE_SURFACE_DATA, Rc::new(data))?; } result } #[doc(alias = "cairo_image_surface_get_data")] #[doc(alias = "get_data")] pub fn data(&mut self) -> Result { unsafe { if ffi::cairo_surface_get_reference_count(self.to_raw_none()) > 1 { return Err(BorrowError::NonExclusive); } self.flush(); let status = ffi::cairo_surface_status(self.to_raw_none()); if let Some(err) = status_to_result(status).err() { return Err(BorrowError::from(err)); } if ffi::cairo_image_surface_get_data(self.to_raw_none()).is_null() || is_finished(self) { return Err(BorrowError::from(Error::SurfaceFinished)); } Ok(ImageSurfaceData::new(self)) } } pub fn take_data(self) -> Result { unsafe { if ffi::cairo_surface_get_reference_count(self.to_raw_none()) > 1 { return Err(BorrowError::NonExclusive); } self.flush(); let status = ffi::cairo_surface_status(self.to_raw_none()); if let Some(err) = status_to_result(status).err() { return Err(BorrowError::from(err)); } if ffi::cairo_image_surface_get_data(self.to_raw_none()).is_null() || is_finished(&self) { return Err(BorrowError::from(Error::SurfaceFinished)); } Ok(ImageSurfaceDataOwned { surface: self }) } } pub fn with_data(&self, f: F) -> Result<(), BorrowError> { self.flush(); unsafe { let status = ffi::cairo_surface_status(self.to_raw_none()); if let Some(err) = status_to_result(status).err() { return Err(BorrowError::from(err)); } let ptr = ffi::cairo_image_surface_get_data(self.to_raw_none()); if ptr.is_null() || is_finished(self) { return Err(BorrowError::from(Error::SurfaceFinished)); } let len = self.height() as usize * self.stride() as usize; f(slice::from_raw_parts(ptr, len)); } Ok(()) } #[doc(alias = "cairo_image_surface_get_format")] #[doc(alias = "get_format")] pub fn format(&self) -> Format { unsafe { Format::from(ffi::cairo_image_surface_get_format(self.to_raw_none())) } } #[doc(alias = "cairo_image_surface_get_height")] #[doc(alias = "get_height")] pub fn height(&self) -> i32 { unsafe { ffi::cairo_image_surface_get_height(self.to_raw_none()) } } #[doc(alias = "cairo_image_surface_get_stride")] #[doc(alias = "get_stride")] pub fn stride(&self) -> i32 { unsafe { ffi::cairo_image_surface_get_stride(self.to_raw_none()) } } #[doc(alias = "cairo_image_surface_get_width")] #[doc(alias = "get_width")] pub fn width(&self) -> i32 { unsafe { ffi::cairo_image_surface_get_width(self.to_raw_none()) } } } pub struct ImageSurfaceDataOwned { surface: ImageSurface, } impl AsRef<[u8]> for ImageSurfaceDataOwned { fn as_ref(&self) -> &[u8] { let len = (self.surface.stride() as usize) * (self.surface.height() as usize); unsafe { let ptr = ffi::cairo_image_surface_get_data(self.surface.to_raw_none()); debug_assert!(!ptr.is_null()); slice::from_raw_parts(ptr, len) } } } impl AsMut<[u8]> for ImageSurfaceDataOwned { fn as_mut(&mut self) -> &mut [u8] { let len = (self.surface.stride() as usize) * (self.surface.height() as usize); unsafe { let ptr = ffi::cairo_image_surface_get_data(self.surface.to_raw_none()); debug_assert!(!ptr.is_null()); slice::from_raw_parts_mut(ptr, len) } } } impl Deref for ImageSurfaceDataOwned { type Target = [u8]; fn deref(&self) -> &Self::Target { self.as_ref() } } impl DerefMut for ImageSurfaceDataOwned { fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut() } } #[derive(Debug)] pub struct ImageSurfaceData<'a> { surface: &'a mut ImageSurface, slice: &'a mut [u8], dirty: bool, } impl<'a> ImageSurfaceData<'a> { fn new(surface: &'a mut ImageSurface) -> ImageSurfaceData<'a> { unsafe { let ptr = ffi::cairo_image_surface_get_data(surface.to_raw_none()); debug_assert!(!ptr.is_null()); let len = (surface.stride() as usize) * (surface.height() as usize); ImageSurfaceData { surface, slice: slice::from_raw_parts_mut(ptr, len), dirty: false, } } } } impl<'a> Drop for ImageSurfaceData<'a> { fn drop(&mut self) { if self.dirty { self.surface.mark_dirty() } } } impl<'a> Deref for ImageSurfaceData<'a> { type Target = [u8]; fn deref(&self) -> &[u8] { self.slice } } impl<'a> DerefMut for ImageSurfaceData<'a> { fn deref_mut(&mut self) -> &mut [u8] { self.dirty = true; self.slice } } impl<'a> fmt::Display for ImageSurfaceData<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ImageSurfaceData") } } // Workaround for cairo not having a direct way to check if the surface is finished. // See: https://gitlab.freedesktop.org/cairo/cairo/-/issues/406 fn is_finished(surface: &ImageSurface) -> bool { use super::Context; Context::new(surface).is_err() } #[cfg(test)] mod tests { use super::*; #[test] fn create_with_invalid_size_yields_error() { let result = ImageSurface::create(Format::ARgb32, 50000, 50000); assert!(result.is_err()); } #[test] fn create_for_data_with_invalid_stride_yields_error() { let result = ImageSurface::create_for_data(vec![0u8; 10], Format::ARgb32, 1, 2, 5); // unaligned stride assert!(result.is_err()); } #[test] fn create_with_valid_size() { let result = ImageSurface::create(Format::ARgb32, 10, 10); assert!(result.is_ok()); let result = ImageSurface::create_for_data(vec![0u8; 40 * 10], Format::ARgb32, 10, 10, 40); assert!(result.is_ok()); } #[test] fn no_crash_after_finish() { let mut surf = ImageSurface::create(Format::ARgb32, 1024, 1024).unwrap(); surf.finish(); assert!(surf.data().is_err()); } #[test] fn create_from_owned() { let result = ImageSurface::create(Format::ARgb32, 10, 10); assert!(result.is_ok()); let image_surface = result.unwrap(); let stride = image_surface.stride(); let data = image_surface.take_data().unwrap(); let second = ImageSurface::create_for_data(data, Format::ARgb32, 10, 10, stride); assert!(second.is_ok()) } } cairo-rs-0.14.9/src/image_surface_png.rs000064400000000000000000000151310072674642500162620ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use crate::utils::status_to_result; use std::any::Any; use std::io::{self, Read, Write}; use std::panic::AssertUnwindSafe; use std::slice; use libc::{c_uint, c_void}; use crate::error::{Error, IoError}; use crate::ImageSurface; use ffi::cairo_status_t; struct ReadEnv<'a, R: 'a + Read> { reader: &'a mut R, io_error: Option, unwind_payload: Option>, } unsafe extern "C" fn read_func( closure: *mut c_void, data: *mut u8, len: c_uint, ) -> cairo_status_t { let read_env: &mut ReadEnv = &mut *(closure as *mut ReadEnv); // Don’t attempt another read, if a previous one errored or panicked: if read_env.io_error.is_some() || read_env.unwind_payload.is_some() { return Error::ReadError.into(); } let buffer = slice::from_raw_parts_mut(data, len as usize); let result = std::panic::catch_unwind(AssertUnwindSafe(|| read_env.reader.read_exact(buffer))); match result { Ok(Ok(())) => ffi::STATUS_SUCCESS, Ok(Err(error)) => { read_env.io_error = Some(error); Error::ReadError.into() } Err(payload) => { read_env.unwind_payload = Some(payload); Error::ReadError.into() } } } struct WriteEnv<'a, W: 'a + Write> { writer: &'a mut W, io_error: Option, unwind_payload: Option>, } unsafe extern "C" fn write_func( closure: *mut c_void, data: *mut u8, len: c_uint, ) -> cairo_status_t { let write_env: &mut WriteEnv = &mut *(closure as *mut WriteEnv); // Don’t attempt another write, if a previous one errored or panicked: if write_env.io_error.is_some() || write_env.unwind_payload.is_some() { return Error::WriteError.into(); } let buffer = slice::from_raw_parts(data, len as usize); let result = std::panic::catch_unwind(AssertUnwindSafe(|| write_env.writer.write_all(buffer))); match result { Ok(Ok(())) => ffi::STATUS_SUCCESS, Ok(Err(error)) => { write_env.io_error = Some(error); Error::WriteError.into() } Err(payload) => { write_env.unwind_payload = Some(payload); Error::WriteError.into() } } } impl ImageSurface { #[doc(alias = "cairo_image_surface_create_from_png_stream")] pub fn create_from_png(stream: &mut R) -> Result { let mut env = ReadEnv { reader: stream, io_error: None, unwind_payload: None, }; unsafe { let raw_surface = ffi::cairo_image_surface_create_from_png_stream( Some(read_func::), &mut env as *mut ReadEnv as *mut c_void, ); let surface = ImageSurface::from_raw_full(raw_surface)?; if let Some(payload) = env.unwind_payload { std::panic::resume_unwind(payload) } match env.io_error { None => Ok(surface), Some(err) => Err(IoError::Io(err)), } } } #[doc(alias = "cairo_surface_write_to_png_stream")] pub fn write_to_png(&self, stream: &mut W) -> Result<(), IoError> { let mut env = WriteEnv { writer: stream, io_error: None, unwind_payload: None, }; let status = unsafe { ffi::cairo_surface_write_to_png_stream( self.to_raw_none(), Some(write_func::), &mut env as *mut WriteEnv as *mut c_void, ) }; if let Some(payload) = env.unwind_payload { std::panic::resume_unwind(payload) } match env.io_error { None => match status_to_result(status) { Err(err) => Err(IoError::Cairo(err)), Ok(_) => Ok(()), }, Some(err) => Err(IoError::Io(err)), } } } #[cfg(test)] mod tests { use super::*; use crate::enums::Format; use std::io::ErrorKind; struct IoErrorReader; // A reader that always returns an error impl Read for IoErrorReader { fn read(&mut self, _: &mut [u8]) -> Result { Err(io::Error::new(ErrorKind::Other, "yikes!")) } } #[test] fn valid_png_reads_correctly() { // A 1x1 PNG, RGB, no alpha, with a single pixel with (42, 42, 42) values let png_data: Vec = vec![ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, 0xde, 0x00, 0x00, 0x00, 0x0c, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xd0, 0xd2, 0xd2, 0x02, 0x00, 0x01, 0x00, 0x00, 0x7f, 0x09, 0xa9, 0x5a, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, ]; let r = ImageSurface::create_from_png(&mut &png_data[..]); assert!(r.is_ok()); let mut surface = r.unwrap(); assert_eq!(surface.width(), 1); assert_eq!(surface.height(), 1); assert_eq!(surface.format(), Format::Rgb24); let data = surface.data().unwrap(); assert!(data.len() >= 3); let slice = &data[0..3]; assert_eq!(slice[0], 42); assert_eq!(slice[1], 42); assert_eq!(slice[2], 42); } #[cfg(not(target_os = "macos"))] #[test] fn invalid_png_yields_error() { let png_data: Vec = vec![ // v--- this byte is modified 0x89, 0x40, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, 0xde, 0x00, 0x00, 0x00, 0x0c, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xd0, 0xd2, 0xd2, 0x02, 0x00, 0x01, 0x00, 0x00, 0x7f, 0x09, 0xa9, 0x5a, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, ]; match ImageSurface::create_from_png(&mut &png_data[..]) { Err(IoError::Cairo(_)) => (), _ => unreachable!(), } } #[cfg(not(target_os = "macos"))] #[test] fn io_error_yields_cairo_read_error() { let mut r = IoErrorReader; match ImageSurface::create_from_png(&mut r) { Err(IoError::Cairo(Error::ReadError)) => (), _ => unreachable!(), } } } cairo-rs-0.14.9/src/lib.rs000064400000000000000000000164550072674642500134040ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. //! # Cairo bindings //! //! This library contains safe Rust bindings for [Cairo](https://www.cairographics.org/). //! It is a part of [gtk-rs](https://gtk-rs.org/). //! //! Cairo 1.14 is the lowest supported version for the underlying library. //! //! # Crate features //! //! ## Default-on features //! //! * **use_glib** - Use with [glib](mod@glib) //! //! ## Fileformat features //! //! * **png** - Reading and writing PNG images //! * **pdf** - Rendering PDF documents //! * **svg** - Rendering SVG documents //! * **ps** - Rendering PostScript documents //! //! ## Cairo API version features //! //! * **v1_16** - Use Cairo 1.16 APIs //! //! ## Documentation features //! //! * **dox** - Used to keep system dependent items in documentation //! //! ## X Window features //! //! * **xcb** - X Window System rendering using the XCB library //! * **xlib** - X Window System rendering using XLib //! //! ## Windows API features //! //! * **win32-surface** - Microsoft Windows surface support #![cfg_attr(feature = "dox", feature(doc_cfg))] #![allow(clippy::missing_safety_doc)] #![allow(clippy::wrong_self_convention)] pub use ffi; #[cfg(feature = "freetype")] pub use freetype_crate as freetype; #[cfg(feature = "use_glib")] pub use glib; // Helper macro for our GValue related trait impls #[cfg(feature = "use_glib")] macro_rules! gvalue_impl { ($name:ty, $ffi_name:ty, $get_type:expr) => { #[allow(unused_imports)] use glib::translate::*; impl glib::types::StaticType for $name { fn static_type() -> glib::types::Type { unsafe { from_glib($get_type()) } } } impl glib::value::ValueType for $name { type Type = Self; } unsafe impl<'a> glib::value::FromValue<'a> for $name { type Checker = glib::value::GenericValueTypeOrNoneChecker; unsafe fn from_value(value: &'a glib::Value) -> Self { let ptr = glib::gobject_ffi::g_value_get_boxed( glib::translate::ToGlibPtr::to_glib_none(value).0, ); assert!(!ptr.is_null()); <$name as glib::translate::FromGlibPtrNone<*mut $ffi_name>>::from_glib_none( ptr as *mut $ffi_name, ) } } impl glib::value::ToValue for $name { fn to_value(&self) -> glib::Value { unsafe { let mut value = glib::Value::from_type(<$name as glib::StaticType>::static_type()); glib::gobject_ffi::g_value_set_boxed( value.to_glib_none_mut().0, self.to_glib_none().0 as *mut _, ); value } } fn value_type(&self) -> glib::Type { <$name as glib::StaticType>::static_type() } } impl glib::value::ToValueOptional for $name { fn to_value_optional(s: Option<&Self>) -> glib::Value { let mut value = glib::Value::for_value_type::(); unsafe { glib::gobject_ffi::g_value_take_boxed( value.to_glib_none_mut().0, glib::translate::ToGlibPtr::to_glib_full(&s) as *mut _, ); } value } } }; } pub use crate::user_data::UserDataKey; pub use crate::context::{Context, RectangleList}; pub use crate::paths::{Path, PathSegment, PathSegments}; pub use crate::device::Device; pub use crate::enums::*; pub use crate::error::{BorrowError, Error, IoError, Result}; pub use crate::patterns::{ Gradient, LinearGradient, Mesh, Pattern, RadialGradient, SolidPattern, SurfacePattern, }; pub use crate::font::{ FontExtents, FontFace, FontOptions, FontSlant, FontType, FontWeight, Glyph, ScaledFont, TextCluster, TextExtents, }; pub use crate::matrices::Matrix; pub use crate::recording_surface::RecordingSurface; pub use crate::rectangle::Rectangle; pub use crate::rectangle_int::RectangleInt; pub use crate::region::Region; pub use crate::surface::{MappedImageSurface, Surface}; pub use crate::image_surface::{ImageSurface, ImageSurfaceData, ImageSurfaceDataOwned}; #[cfg(any(feature = "pdf", feature = "svg", feature = "ps", feature = "dox"))] pub use stream::StreamWithError; #[cfg(any(feature = "pdf", feature = "dox"))] pub use pdf::PdfSurface; #[cfg(any(feature = "ps", feature = "dox"))] pub use ps::PsSurface; #[cfg(any(feature = "svg", feature = "dox"))] pub use svg::SvgSurface; #[cfg(any(feature = "xcb", feature = "dox"))] pub use xcb::{ XCBConnection, XCBDrawable, XCBPixmap, XCBRenderPictFormInfo, XCBScreen, XCBSurface, XCBVisualType, }; #[macro_use] mod surface_macros; #[macro_use] mod user_data; mod constants; pub use crate::constants::*; mod utils; pub use crate::utils::{debug_reset_static_data, version_string, Version}; mod context; mod device; mod enums; mod error; mod font; mod image_surface; #[cfg(any(feature = "png", feature = "dox"))] mod image_surface_png; mod matrices; mod paths; mod patterns; mod recording_surface; mod rectangle; mod rectangle_int; mod region; mod surface; #[cfg(any(feature = "xcb", feature = "dox"))] mod xcb; #[cfg(any(feature = "pdf", feature = "svg", feature = "ps", feature = "dox"))] #[macro_use] mod stream; #[cfg(any(feature = "pdf", feature = "dox"))] mod pdf; #[cfg(any(feature = "ps", feature = "dox"))] mod ps; #[cfg(any(feature = "svg", feature = "dox"))] mod svg; #[cfg(any(target_os = "macos", feature = "dox"))] mod quartz_surface; #[cfg(any(target_os = "macos", feature = "dox"))] pub use quartz_surface::QuartzSurface; #[cfg(any(all(windows, feature = "win32-surface"), feature = "dox"))] mod win32_surface; #[cfg(any(all(windows, feature = "win32-surface"), feature = "dox"))] pub use win32_surface::Win32Surface; #[cfg(not(feature = "use_glib"))] mod borrowed { use std::mem; /// Wrapper around values representing borrowed C memory. /// /// This is returned by `from_glib_borrow()` and ensures that the wrapped value /// is never dropped when going out of scope. /// /// Borrowed values must never be passed by value or mutable reference to safe Rust code and must /// not leave the C scope in which they are valid. #[derive(Debug)] pub struct Borrowed(mem::ManuallyDrop); impl Borrowed { /// Creates a new borrowed value. pub fn new(val: T) -> Self { Self(mem::ManuallyDrop::new(val)) } /// Extracts the contained value. /// /// The returned value must never be dropped and instead has to be passed to `mem::forget()` or /// be directly wrapped in `mem::ManuallyDrop` or another `Borrowed` wrapper. pub unsafe fn into_inner(self) -> T { mem::ManuallyDrop::into_inner(self.0) } } impl AsRef for Borrowed { fn as_ref(&self) -> &T { &*self.0 } } impl std::ops::Deref for Borrowed { type Target = T; fn deref(&self) -> &T { &*self.0 } } } #[cfg(not(feature = "use_glib"))] pub use borrowed::Borrowed; #[cfg(feature = "use_glib")] pub(crate) use glib::translate::Borrowed; cairo-rs-0.14.9/src/matrices.rs000064400000000000000000000104170072674642500144350ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use crate::error::Error; use crate::utils::status_to_result; use libc::c_double; #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq)] pub struct Matrix { pub xx: c_double, pub yx: c_double, pub xy: c_double, pub yy: c_double, pub x0: c_double, pub y0: c_double, } impl Default for Matrix { fn default() -> Self { Self::identity() } } impl Matrix { pub(crate) fn ptr(&self) -> *const ffi::Matrix { self as *const Matrix as _ } pub(crate) fn mut_ptr(&mut self) -> *mut ffi::Matrix { self as *mut Matrix as _ } pub(crate) fn null() -> Self { Self { xx: 0.0, yx: 0.0, xy: 0.0, yy: 0.0, x0: 0.0, y0: 0.0, } } pub fn identity() -> Self { Self { xx: 1.0, yx: 0.0, xy: 0.0, yy: 1.0, x0: 0.0, y0: 0.0, } } pub fn new(xx: f64, yx: f64, xy: f64, yy: f64, x0: f64, y0: f64) -> Self { Self { xx, yx, xy, yy, x0, y0, } } #[doc(alias = "cairo_matrix_multiply")] pub fn multiply(left: &Matrix, right: &Matrix) -> Matrix { let mut matrix = Self::null(); unsafe { ffi::cairo_matrix_multiply(matrix.mut_ptr(), left.ptr(), right.ptr()); } matrix } #[doc(alias = "cairo_matrix_translate")] pub fn translate(&mut self, tx: f64, ty: f64) { unsafe { ffi::cairo_matrix_translate(self.mut_ptr(), tx, ty) } } #[doc(alias = "cairo_matrix_scale")] pub fn scale(&mut self, sx: f64, sy: f64) { unsafe { ffi::cairo_matrix_scale(self.mut_ptr(), sx, sy) } } #[doc(alias = "cairo_matrix_rotate")] pub fn rotate(&mut self, angle: f64) { unsafe { ffi::cairo_matrix_rotate(self.mut_ptr(), angle) } } #[doc(alias = "cairo_matrix_invert")] pub fn invert(&mut self) { let status = unsafe { ffi::cairo_matrix_invert(self.mut_ptr()) }; status_to_result(status).expect("Failed to invert the matrix") } #[doc(alias = "cairo_matrix_invert")] pub fn try_invert(&self) -> Result { let mut matrix = *self; let status = unsafe { ffi::cairo_matrix_invert(matrix.mut_ptr()) }; status_to_result(status)?; Ok(matrix) } #[doc(alias = "cairo_matrix_transform_distance")] pub fn transform_distance(&self, _dx: f64, _dy: f64) -> (f64, f64) { let mut dx = _dx; let mut dy = _dy; unsafe { ffi::cairo_matrix_transform_distance(self.ptr(), &mut dx, &mut dy); } (dx, dy) } #[doc(alias = "cairo_matrix_transform_point")] pub fn transform_point(&self, _x: f64, _y: f64) -> (f64, f64) { let mut x = _x; let mut y = _y; unsafe { ffi::cairo_matrix_transform_point(self.ptr(), &mut x, &mut y); } (x, y) } } #[cfg(test)] mod tests { use super::*; #[test] fn memory_layout_is_ffi_equivalent() { macro_rules! dummy_values { ($Matrix: ident) => { $Matrix { xx: 1.0, yx: 2.0, xy: 3.0, yy: 4.0, x0: 5.0, y0: 6.0, } }; } use crate::ffi::Matrix as FfiMatrix; let transmuted: Matrix = unsafe { std::mem::transmute(dummy_values!(FfiMatrix)) }; assert_eq!(transmuted, dummy_values!(Matrix)); } #[test] fn invalid_matrix_does_not_invert() { let matrix = Matrix::null(); assert!(matrix.try_invert().is_err()); } #[test] #[should_panic] fn inverting_invalid_matrix_panics() { let mut matrix = Matrix::null(); matrix.invert(); } #[test] fn valid_matrix_try_invert() { let matrix = Matrix::identity(); assert_eq!(matrix.try_invert().unwrap(), Matrix::identity()); } #[test] fn valid_matrix_invert() { let mut matrix = Matrix::identity(); matrix.invert(); assert_eq!(matrix, Matrix::identity()); } } cairo-rs-0.14.9/src/paths.rs000064400000000000000000000141600072674642500137440ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use crate::enums::PathDataType; use crate::ffi::cairo_path_t; use std::fmt; use std::iter::Iterator; use std::ptr; #[derive(Debug)] pub struct Path(ptr::NonNull); impl Path { pub fn as_ptr(&self) -> *mut cairo_path_t { self.0.as_ptr() } pub unsafe fn from_raw_full(pointer: *mut cairo_path_t) -> Path { assert!(!pointer.is_null()); Path(ptr::NonNull::new_unchecked(pointer)) } pub fn iter(&self) -> PathSegments { use std::slice; unsafe { let ptr: *mut cairo_path_t = self.as_ptr(); let length = (*ptr).num_data as usize; let data_ptr = (*ptr).data; let data_vec = if length != 0 && !data_ptr.is_null() { slice::from_raw_parts(data_ptr, length) } else { &[] }; PathSegments { data: data_vec, i: 0, num_data: length, } } } } impl Drop for Path { fn drop(&mut self) { unsafe { ffi::cairo_path_destroy(self.as_ptr()); } } } impl fmt::Display for Path { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Path") } } #[derive(Debug, Clone, Copy, PartialEq)] pub enum PathSegment { MoveTo((f64, f64)), LineTo((f64, f64)), CurveTo((f64, f64), (f64, f64), (f64, f64)), ClosePath, } impl fmt::Display for PathSegment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Self::{}", match *self { Self::MoveTo(_) => "MoveTo", Self::LineTo(_) => "LineTo", Self::CurveTo(_, _, _) => "CurveTo", Self::ClosePath => "ClosePath", } ) } } pub struct PathSegments<'a> { data: &'a [ffi::cairo_path_data], i: usize, num_data: usize, } impl<'a> Iterator for PathSegments<'a> { type Item = PathSegment; fn next(&mut self) -> Option { if self.i >= self.num_data { return None; } unsafe { let res = match PathDataType::from(self.data[self.i].header.data_type) { PathDataType::MoveTo => PathSegment::MoveTo(to_tuple(&self.data[self.i + 1].point)), PathDataType::LineTo => PathSegment::LineTo(to_tuple(&self.data[self.i + 1].point)), PathDataType::CurveTo => PathSegment::CurveTo( to_tuple(&self.data[self.i + 1].point), to_tuple(&self.data[self.i + 2].point), to_tuple(&self.data[self.i + 3].point), ), PathDataType::ClosePath => PathSegment::ClosePath, PathDataType::__Unknown(x) => panic!("Unknown value: {}", x), }; self.i += self.data[self.i].header.length as usize; Some(res) } } } impl<'a> fmt::Display for PathSegments<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "PathSegments") } } fn to_tuple(pair: &[f64; 2]) -> (f64, f64) { (pair[0], pair[1]) } #[cfg(test)] mod tests { use super::*; use crate::context::*; use crate::enums::Format; use crate::image_surface::*; fn make_cr() -> Context { let surface = ImageSurface::create(Format::Rgb24, 1, 1).unwrap(); Context::new(&surface).expect("Can't create a Cairo context") } fn assert_path_equals_segments(expected: &Path, actual: &[PathSegment]) { // First ensure the lengths are equal let expected_iter = expected.iter(); let actual_iter = actual.iter(); assert_eq!(expected_iter.count(), actual_iter.count()); // Then actually compare the contents let expected_iter = expected.iter(); let actual_iter = actual.iter(); let iter = expected_iter.zip(actual_iter); for (e, a) in iter { assert_eq!(e, *a); } } #[test] fn empty_path_doesnt_iter() { let cr = make_cr(); let path = cr.copy_path().expect("Invalid context"); assert!(path.iter().next().is_none()); } #[test] fn moveto() { let cr = make_cr(); cr.move_to(1.0, 2.0); let path = cr.copy_path().expect("Invalid path"); assert_path_equals_segments(&path, &[PathSegment::MoveTo((1.0, 2.0))]); } #[test] fn moveto_lineto_moveto() { let cr = make_cr(); cr.move_to(1.0, 2.0); cr.line_to(3.0, 4.0); cr.move_to(5.0, 6.0); let path = cr.copy_path().expect("Invalid path"); assert_path_equals_segments( &path, &[ PathSegment::MoveTo((1.0, 2.0)), PathSegment::LineTo((3.0, 4.0)), PathSegment::MoveTo((5.0, 6.0)), ], ); } #[test] fn moveto_closepath() { let cr = make_cr(); cr.move_to(1.0, 2.0); cr.close_path(); let path = cr.copy_path().expect("Invalid path"); // Note that Cairo represents a close_path as closepath+moveto, // so that the next subpath will have a starting point, // from the extra moveto. assert_path_equals_segments( &path, &[ PathSegment::MoveTo((1.0, 2.0)), PathSegment::ClosePath, PathSegment::MoveTo((1.0, 2.0)), ], ); } #[test] fn curveto_closed_subpath_lineto() { let cr = make_cr(); cr.move_to(1.0, 2.0); cr.curve_to(3.0, 4.0, 5.0, 6.0, 7.0, 8.0); cr.close_path(); cr.line_to(9.0, 10.0); let path = cr.copy_path().expect("Invalid path"); assert_path_equals_segments( &path, &[ PathSegment::MoveTo((1.0, 2.0)), PathSegment::CurveTo((3.0, 4.0), (5.0, 6.0), (7.0, 8.0)), PathSegment::ClosePath, PathSegment::MoveTo((1.0, 2.0)), PathSegment::LineTo((9.0, 10.0)), ], ); } } cairo-rs-0.14.9/src/patterns.rs000064400000000000000000000370650072674642500144760ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use crate::enums::MeshCorner; use crate::enums::{Extend, Filter, PatternType}; use crate::error::Error; use crate::ffi::{cairo_pattern_t, cairo_surface_t}; use crate::utils::status_to_result; use crate::{Matrix, Path, Surface}; use libc::{c_double, c_int, c_uint}; use std::convert::TryFrom; use std::fmt; use std::ops::Deref; use std::ptr; // See https://cairographics.org/manual/bindings-patterns.html for more info #[derive(Debug)] pub struct Pattern { pointer: *mut cairo_pattern_t, } impl fmt::Display for Pattern { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Pattern") } } impl Pattern { user_data_methods! { ffi::cairo_pattern_get_user_data, ffi::cairo_pattern_set_user_data, } pub fn to_raw_none(&self) -> *mut cairo_pattern_t { self.pointer } pub unsafe fn from_raw_none(pointer: *mut cairo_pattern_t) -> Pattern { ffi::cairo_pattern_reference(pointer); Self::from_raw_full(pointer) } pub unsafe fn from_raw_full(pointer: *mut cairo_pattern_t) -> Pattern { Self { pointer } } #[doc(alias = "cairo_pattern_get_type")] #[doc(alias = "get_type")] pub fn type_(&self) -> PatternType { unsafe { ffi::cairo_pattern_get_type(self.pointer).into() } } #[doc(alias = "cairo_pattern_get_reference_count")] #[doc(alias = "get_reference_count")] pub fn reference_count(&self) -> isize { unsafe { ffi::cairo_pattern_get_reference_count(self.pointer) as isize } } #[doc(alias = "cairo_pattern_set_extend")] pub fn set_extend(&self, extend: Extend) { unsafe { ffi::cairo_pattern_set_extend(self.pointer, extend.into()) } } #[doc(alias = "cairo_pattern_get_extend")] #[doc(alias = "get_extend")] pub fn extend(&self) -> Extend { unsafe { Extend::from(ffi::cairo_pattern_get_extend(self.pointer)) } } #[doc(alias = "cairo_pattern_set_filter")] pub fn set_filter(&self, filter: Filter) { unsafe { ffi::cairo_pattern_set_filter(self.pointer, filter.into()) } } #[doc(alias = "cairo_pattern_get_filter")] #[doc(alias = "get_filter")] pub fn filter(&self) -> Filter { unsafe { Filter::from(ffi::cairo_pattern_get_filter(self.pointer)) } } #[doc(alias = "cairo_pattern_set_matrix")] pub fn set_matrix(&self, matrix: Matrix) { unsafe { ffi::cairo_pattern_set_matrix(self.pointer, matrix.ptr()) } } #[doc(alias = "cairo_pattern_get_matrix")] #[doc(alias = "get_matrix")] pub fn matrix(&self) -> Matrix { let mut matrix = Matrix::null(); unsafe { ffi::cairo_pattern_get_matrix(self.pointer, matrix.mut_ptr()); } matrix } #[doc(alias = "cairo_pattern_status")] pub fn status(&self) -> Result<(), Error> { let status = unsafe { ffi::cairo_pattern_status(self.pointer) }; status_to_result(status) } } impl Clone for Pattern { fn clone(&self) -> Self { Self { pointer: unsafe { ffi::cairo_pattern_reference(self.pointer) }, } } } impl Drop for Pattern { fn drop(&mut self) { unsafe { ffi::cairo_pattern_destroy(self.pointer) } } } macro_rules! convert { ($source: ident => $dest: ident = $( $variant: ident )|+ $( ($intermediate: ident) )*) => { impl TryFrom<$source> for $dest { type Error = $source; fn try_from(pattern: $source) -> Result { if $( pattern.type_() == PatternType::$variant )||+ { $( let pattern = $intermediate(pattern); )* Ok($dest(pattern)) } else { Err(pattern) } } } }; } macro_rules! pattern_type( //Signals without arguments ($pattern_type:ident $( = $variant: ident)*) => ( #[derive(Debug, Clone)] pub struct $pattern_type(Pattern); impl Deref for $pattern_type { type Target = Pattern; fn deref(&self) -> &Pattern { &self.0 } } impl fmt::Display for $pattern_type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, stringify!($pattern_type)) } } $( convert!(Pattern => $pattern_type = $variant); )* ); ); pattern_type!(SolidPattern = Solid); impl SolidPattern { #[doc(alias = "cairo_pattern_create_rgb")] pub fn from_rgb(red: f64, green: f64, blue: f64) -> Self { unsafe { Self(Pattern::from_raw_full(ffi::cairo_pattern_create_rgb( red, green, blue, ))) } } #[doc(alias = "cairo_pattern_create_rgba")] pub fn from_rgba(red: f64, green: f64, blue: f64, alpha: f64) -> Self { unsafe { Self(Pattern::from_raw_full(ffi::cairo_pattern_create_rgba( red, green, blue, alpha, ))) } } #[doc(alias = "cairo_pattern_get_rgba")] #[doc(alias = "get_rgba")] pub fn rgba(&self) -> Result<(f64, f64, f64, f64), Error> { unsafe { let mut red = 0.0; let mut green = 0.0; let mut blue = 0.0; let mut alpha = 0.0; let status = ffi::cairo_pattern_get_rgba( self.pointer, &mut red, &mut green, &mut blue, &mut alpha, ); status_to_result(status)?; Ok((red, green, blue, alpha)) } } } pattern_type!(Gradient); convert!(Pattern => Gradient = LinearGradient | RadialGradient); impl Gradient { #[doc(alias = "cairo_pattern_add_color_stop_rgb")] pub fn add_color_stop_rgb(&self, offset: f64, red: f64, green: f64, blue: f64) { unsafe { ffi::cairo_pattern_add_color_stop_rgb(self.pointer, offset, red, green, blue) } } #[doc(alias = "cairo_pattern_add_color_stop_rgba")] pub fn add_color_stop_rgba(&self, offset: f64, red: f64, green: f64, blue: f64, alpha: f64) { unsafe { ffi::cairo_pattern_add_color_stop_rgba(self.pointer, offset, red, green, blue, alpha) } } #[doc(alias = "cairo_pattern_get_color_stop_count")] #[doc(alias = "get_color_stop_count")] pub fn color_stop_count(&self) -> Result { unsafe { let mut count = 0; let status = ffi::cairo_pattern_get_color_stop_count(self.pointer, &mut count); status_to_result(status)?; Ok(count as isize) } } #[doc(alias = "cairo_pattern_get_color_stop_rgba")] #[doc(alias = "get_color_stop_rgba")] pub fn color_stop_rgba(&self, index: isize) -> Result<(f64, f64, f64, f64, f64), Error> { unsafe { let mut offset = 0.0; let mut red = 0.0; let mut green = 0.0; let mut blue = 0.0; let mut alpha = 0.0; let status = ffi::cairo_pattern_get_color_stop_rgba( self.pointer, index as c_int, &mut offset, &mut red, &mut green, &mut blue, &mut alpha, ); status_to_result(status)?; Ok((offset, red, green, blue, alpha)) } } } macro_rules! gradient_type { ($gradient_type: ident) => { #[derive(Debug, Clone)] pub struct $gradient_type(Gradient); impl Deref for $gradient_type { type Target = Gradient; fn deref(&self) -> &Gradient { &self.0 } } impl fmt::Display for $gradient_type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, stringify!($gradient_type)) } } convert!(Pattern => $gradient_type = $gradient_type (Gradient)); convert!(Gradient => $gradient_type = $gradient_type); } } gradient_type!(LinearGradient); impl LinearGradient { #[doc(alias = "cairo_pattern_create_linear")] pub fn new(x0: f64, y0: f64, x1: f64, y1: f64) -> Self { unsafe { Self(Gradient(Pattern::from_raw_full( ffi::cairo_pattern_create_linear(x0, y0, x1, y1), ))) } } #[doc(alias = "cairo_pattern_get_linear_points")] #[doc(alias = "get_linear_points")] pub fn linear_points(&self) -> Result<(f64, f64, f64, f64), Error> { unsafe { let mut x0 = 0.0; let mut y0 = 0.0; let mut x1 = 0.0; let mut y1 = 0.0; let status = ffi::cairo_pattern_get_linear_points( self.pointer, &mut x0, &mut y0, &mut x1, &mut y1, ); status_to_result(status)?; Ok((x0, y0, x1, y1)) } } } gradient_type!(RadialGradient); impl RadialGradient { #[doc(alias = "cairo_pattern_create_radial")] pub fn new(x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64) -> Self { unsafe { Self(Gradient(Pattern::from_raw_full( ffi::cairo_pattern_create_radial(x0, y0, r0, x1, y1, r1), ))) } } #[doc(alias = "cairo_pattern_get_radial_circles")] #[doc(alias = "get_radial_circles")] pub fn radial_circles(&self) -> Result<(f64, f64, f64, f64, f64, f64), Error> { unsafe { let mut x0 = 0.0; let mut y0 = 0.0; let mut r0 = 0.0; let mut x1 = 0.0; let mut y1 = 0.0; let mut r1 = 0.0; let status = ffi::cairo_pattern_get_radial_circles( self.pointer, &mut x0, &mut y0, &mut r0, &mut x1, &mut y1, &mut r1, ); status_to_result(status)?; Ok((x0, y0, r0, x1, y1, r1)) } } } pattern_type!(SurfacePattern = Surface); impl SurfacePattern { #[doc(alias = "cairo_pattern_create_for_surface")] pub fn create(surface: &Surface) -> Self { unsafe { Self(Pattern::from_raw_full( ffi::cairo_pattern_create_for_surface(surface.to_raw_none()), )) } } #[doc(alias = "cairo_pattern_get_surface")] #[doc(alias = "get_surface")] pub fn surface(&self) -> Result { unsafe { let mut surface_ptr: *mut cairo_surface_t = ptr::null_mut(); let status = ffi::cairo_pattern_get_surface(self.pointer, &mut surface_ptr); status_to_result(status)?; Ok(Surface::from_raw_none(surface_ptr)) } } } pattern_type!(Mesh = Mesh); impl Mesh { #[doc(alias = "cairo_pattern_create_mesh")] pub fn new() -> Self { unsafe { Self(Pattern::from_raw_full(ffi::cairo_pattern_create_mesh())) } } #[doc(alias = "cairo_mesh_pattern_begin_patch")] pub fn begin_patch(&self) { unsafe { ffi::cairo_mesh_pattern_begin_patch(self.pointer) } } #[doc(alias = "cairo_mesh_pattern_end_patch")] pub fn end_patch(&self) { unsafe { ffi::cairo_mesh_pattern_end_patch(self.pointer) } } #[doc(alias = "cairo_mesh_pattern_move_to")] pub fn move_to(&self, x: f64, y: f64) { unsafe { ffi::cairo_mesh_pattern_move_to(self.pointer, x, y) } } #[doc(alias = "cairo_mesh_pattern_line_to")] pub fn line_to(&self, x: f64, y: f64) { unsafe { ffi::cairo_mesh_pattern_line_to(self.pointer, x, y) } } #[doc(alias = "cairo_mesh_pattern_curve_to")] pub fn curve_to(&self, x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) { unsafe { ffi::cairo_mesh_pattern_curve_to(self.pointer, x1, y1, x2, y2, x3, y3) } } #[doc(alias = "cairo_mesh_pattern_set_control_point")] pub fn set_control_point(&self, corner: MeshCorner, x: f64, y: f64) { unsafe { ffi::cairo_mesh_pattern_set_control_point(self.pointer, corner.into(), x, y) } } #[doc(alias = "cairo_mesh_pattern_get_control_point")] #[doc(alias = "get_control_point")] pub fn control_point(&self, patch_num: usize, corner: MeshCorner) -> Result<(f64, f64), Error> { let mut x: c_double = 0.0; let mut y: c_double = 0.0; let status = unsafe { ffi::cairo_mesh_pattern_get_control_point( self.pointer, patch_num as c_uint, corner.into(), &mut x, &mut y, ) }; status_to_result(status)?; Ok((x, y)) } #[doc(alias = "cairo_mesh_pattern_set_corner_color_rgb")] pub fn set_corner_color_rgb(&self, corner: MeshCorner, red: f64, green: f64, blue: f64) { unsafe { ffi::cairo_mesh_pattern_set_corner_color_rgb( self.pointer, corner.into(), red, green, blue, ) } } #[doc(alias = "cairo_mesh_pattern_set_corner_color_rgba")] pub fn set_corner_color_rgba( &self, corner: MeshCorner, red: f64, green: f64, blue: f64, alpha: f64, ) { unsafe { ffi::cairo_mesh_pattern_set_corner_color_rgba( self.pointer, corner.into(), red, green, blue, alpha, ) } } #[doc(alias = "cairo_mesh_pattern_get_corner_color_rgba")] #[doc(alias = "get_corner_color_rgba")] pub fn corner_color_rgba( &self, patch_num: usize, corner: MeshCorner, ) -> Result<(f64, f64, f64, f64), Error> { let mut red: c_double = 0.0; let mut green: c_double = 0.0; let mut blue: c_double = 0.0; let mut alpha: c_double = 0.0; let status = unsafe { ffi::cairo_mesh_pattern_get_corner_color_rgba( self.pointer, patch_num as c_uint, corner.into(), &mut red, &mut green, &mut blue, &mut alpha, ) }; status_to_result(status)?; Ok((red, green, blue, alpha)) } #[doc(alias = "cairo_mesh_pattern_get_patch_count")] #[doc(alias = "get_patch_count")] pub fn patch_count(&self) -> Result { let mut count: c_uint = 0; unsafe { let status = ffi::cairo_mesh_pattern_get_patch_count(self.pointer, &mut count); status_to_result(status)?; } Ok(count as usize) } #[doc(alias = "cairo_mesh_pattern_get_path")] #[doc(alias = "get_path")] pub fn path(&self, patch_num: usize) -> Result { let path: Path = unsafe { Path::from_raw_full(ffi::cairo_mesh_pattern_get_path( self.pointer, patch_num as c_uint, )) }; let status = unsafe { let ptr: *mut ffi::cairo_path_t = path.as_ptr(); (*ptr).status }; status_to_result(status)?; Ok(path) } } impl Default for Mesh { fn default() -> Self { Self::new() } } #[test] fn try_from() { let linear = LinearGradient::new(0., 0., 1., 1.); let gradient = Gradient::clone(&linear); let pattern = Pattern::clone(&linear); assert!(Gradient::try_from(pattern.clone()).is_ok()); assert!(LinearGradient::try_from(gradient).is_ok()); assert!(LinearGradient::try_from(pattern).is_ok()); } cairo-rs-0.14.9/src/pdf.rs000064400000000000000000000174450072674642500134070ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use std::convert::TryFrom; use std::ffi::{CStr, CString}; use std::fmt; use std::io; use std::mem; use std::ops::Deref; use std::path::Path; use std::ptr; #[cfg(any(all(feature = "pdf", feature = "v1_16"), feature = "dox"))] use crate::enums::{PdfMetadata, PdfOutline}; use crate::enums::{PdfVersion, SurfaceType}; use crate::error::Error; use crate::surface::Surface; #[cfg(feature = "use_glib")] use glib::translate::*; impl PdfVersion { pub fn as_str(self) -> Option<&'static str> { unsafe { let res = ffi::cairo_pdf_version_to_string(self.into()); res.as_ref() .and_then(|cstr| CStr::from_ptr(cstr as _).to_str().ok()) } } } declare_surface!(PdfSurface, SurfaceType::Pdf); impl PdfSurface { #[doc(alias = "cairo_pdf_surface_create")] pub fn new>(width: f64, height: f64, path: P) -> Result { let path = path.as_ref().to_string_lossy().into_owned(); let path = CString::new(path).unwrap(); unsafe { Self::from_raw_full(ffi::cairo_pdf_surface_create(path.as_ptr(), width, height)) } } for_stream_constructors!(cairo_pdf_surface_create_for_stream); #[doc(alias = "cairo_pdf_get_versions")] #[doc(alias = "get_versions")] pub fn versions() -> impl Iterator { let vers_slice = unsafe { let mut vers_ptr = ptr::null_mut(); let mut num_vers = mem::MaybeUninit::uninit(); ffi::cairo_pdf_get_versions(&mut vers_ptr, num_vers.as_mut_ptr()); std::slice::from_raw_parts(vers_ptr, num_vers.assume_init() as _) }; vers_slice.iter().map(|v| PdfVersion::from(*v)) } #[doc(alias = "cairo_pdf_surface_restrict_to_version")] pub fn restrict(&self, version: PdfVersion) -> Result<(), Error> { unsafe { ffi::cairo_pdf_surface_restrict_to_version(self.0.to_raw_none(), version.into()); } self.status() } #[doc(alias = "cairo_pdf_surface_set_size")] pub fn set_size(&self, width: f64, height: f64) -> Result<(), Error> { unsafe { ffi::cairo_pdf_surface_set_size(self.0.to_raw_none(), width, height); } self.status() } #[cfg(any(all(feature = "pdf", feature = "v1_16"), feature = "dox"))] #[doc(alias = "cairo_pdf_surface_set_metadata")] pub fn set_metadata(&self, metadata: PdfMetadata, value: &str) -> Result<(), Error> { let value = CString::new(value).unwrap(); unsafe { ffi::cairo_pdf_surface_set_metadata( self.0.to_raw_none(), metadata.into(), value.as_ptr(), ); } self.status() } #[cfg(any(all(feature = "pdf", feature = "v1_16"), feature = "dox"))] #[doc(alias = "cairo_pdf_surface_set_page_label")] pub fn set_page_label(&self, label: &str) -> Result<(), Error> { let label = CString::new(label).unwrap(); unsafe { ffi::cairo_pdf_surface_set_page_label(self.0.to_raw_none(), label.as_ptr()); } self.status() } #[cfg(any(all(feature = "pdf", feature = "v1_16"), feature = "dox"))] #[doc(alias = "cairo_pdf_surface_set_thumbnail_size")] pub fn set_thumbnail_size(&self, width: i32, height: i32) -> Result<(), Error> { unsafe { ffi::cairo_pdf_surface_set_thumbnail_size( self.0.to_raw_none(), width as _, height as _, ); } self.status() } #[cfg(any(all(feature = "pdf", feature = "v1_16"), feature = "dox"))] #[doc(alias = "cairo_pdf_surface_add_outline")] pub fn add_outline( &self, parent_id: i32, name: &str, link_attribs: &str, flags: PdfOutline, ) -> Result { let name = CString::new(name).unwrap(); let link_attribs = CString::new(link_attribs).unwrap(); let res = unsafe { ffi::cairo_pdf_surface_add_outline( self.0.to_raw_none(), parent_id, name.as_ptr(), link_attribs.as_ptr(), flags.bits() as _, ) as _ }; self.status()?; Ok(res) } } #[cfg(test)] mod test { use super::*; use crate::context::*; use tempfile::tempfile; fn draw(surface: &Surface) { let cr = Context::new(surface).expect("Can't create a Cairo context"); cr.set_line_width(25.0); cr.set_source_rgba(1.0, 0.0, 0.0, 0.5); cr.line_to(0., 0.); cr.line_to(100., 100.); cr.stroke().expect("Surface on an invalid state"); cr.set_source_rgba(0.0, 0.0, 1.0, 0.5); cr.line_to(0., 100.); cr.line_to(100., 0.); cr.stroke().expect("Surface on an invalid state"); } fn draw_in_buffer() -> Vec { let buffer: Vec = vec![]; let surface = PdfSurface::for_stream(100., 100., buffer).unwrap(); draw(&surface); *surface.finish_output_stream().unwrap().downcast().unwrap() } #[test] fn versions() { assert!(PdfSurface::versions().any(|v| v == PdfVersion::_1_4)); } #[test] fn version_string() { let ver_str = PdfVersion::_1_4.as_str().unwrap(); assert_eq!(ver_str, "PDF 1.4"); } #[test] #[cfg(unix)] fn file() { let surface = PdfSurface::new(100., 100., "/dev/null").unwrap(); draw(&surface); surface.finish(); } #[test] fn writer() { let file = tempfile().expect("tempfile failed"); let surface = PdfSurface::for_stream(100., 100., file).unwrap(); draw(&surface); let stream = surface.finish_output_stream().unwrap(); let file = stream.downcast::().unwrap(); let buffer = draw_in_buffer(); let file_size = file.metadata().unwrap().len(); assert_eq!(file_size, buffer.len() as u64); } #[test] fn ref_writer() { let mut file = tempfile().expect("tempfile failed"); let surface = unsafe { PdfSurface::for_raw_stream(100., 100., &mut file).unwrap() }; draw(&surface); surface.finish_output_stream().unwrap(); drop(file); } #[test] fn buffer() { let buffer = draw_in_buffer(); let header = b"%PDF-1.5"; assert_eq!(&buffer[..header.len()], header); } #[test] fn custom_writer() { struct CustomWriter(usize); impl io::Write for CustomWriter { fn write(&mut self, buf: &[u8]) -> io::Result { self.0 += buf.len(); Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } let custom_writer = CustomWriter(0); let surface = PdfSurface::for_stream(20., 20., custom_writer).unwrap(); surface.set_size(100., 100.).unwrap(); draw(&surface); let stream = surface.finish_output_stream().unwrap(); let custom_writer = stream.downcast::().unwrap(); let buffer = draw_in_buffer(); assert_eq!(custom_writer.0, buffer.len()); } fn with_panicky_stream() -> PdfSurface { struct PanicWriter; impl io::Write for PanicWriter { fn write(&mut self, _buf: &[u8]) -> io::Result { panic!("panic in writer"); } fn flush(&mut self) -> io::Result<()> { Ok(()) } } let surface = PdfSurface::for_stream(20., 20., PanicWriter).unwrap(); surface.finish(); surface } #[test] #[should_panic] fn finish_stream_propagates_panic() { let _ = with_panicky_stream().finish_output_stream(); } } cairo-rs-0.14.9/src/ps.rs000064400000000000000000000156160072674642500132560ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use std::convert::TryFrom; use std::ffi::{CStr, CString}; use std::fmt; use std::io; use std::mem; use std::ops::Deref; use std::path::Path; use std::ptr; use crate::enums::{PsLevel, SurfaceType}; use crate::error::Error; use crate::surface::Surface; #[cfg(feature = "use_glib")] use glib::translate::*; impl PsLevel { pub fn as_str(self) -> Option<&'static str> { unsafe { let res = ffi::cairo_ps_level_to_string(self.into()); res.as_ref() .and_then(|cstr| CStr::from_ptr(cstr as _).to_str().ok()) } } } declare_surface!(PsSurface, SurfaceType::Ps); impl PsSurface { #[doc(alias = "cairo_ps_surface_create")] pub fn new>(width: f64, height: f64, path: P) -> Result { let path = path.as_ref().to_string_lossy().into_owned(); let path = CString::new(path).unwrap(); unsafe { Self::from_raw_full(ffi::cairo_ps_surface_create(path.as_ptr(), width, height)) } } for_stream_constructors!(cairo_ps_surface_create_for_stream); #[doc(alias = "cairo_ps_get_levels")] #[doc(alias = "get_levels")] pub fn levels() -> impl Iterator { let lvls_slice = unsafe { let mut vers_ptr = ptr::null_mut(); let mut num_vers = mem::MaybeUninit::uninit(); ffi::cairo_ps_get_levels(&mut vers_ptr, num_vers.as_mut_ptr()); std::slice::from_raw_parts(vers_ptr, num_vers.assume_init() as _) }; lvls_slice.iter().map(|v| PsLevel::from(*v)) } #[doc(alias = "cairo_ps_surface_restrict_to_level")] pub fn restrict(&self, level: PsLevel) { unsafe { ffi::cairo_ps_surface_restrict_to_level(self.0.to_raw_none(), level.into()); } } #[doc(alias = "cairo_ps_surface_get_eps")] #[doc(alias = "get_eps")] pub fn is_eps(&self) -> bool { unsafe { ffi::cairo_ps_surface_get_eps(self.0.to_raw_none()).as_bool() } } #[doc(alias = "cairo_ps_surface_set_eps")] pub fn set_eps(&self, eps: bool) { unsafe { ffi::cairo_ps_surface_set_eps(self.0.to_raw_none(), eps.into()); } } #[doc(alias = "cairo_ps_surface_set_size")] pub fn set_size(&self, width: f64, height: f64) { unsafe { ffi::cairo_ps_surface_set_size(self.0.to_raw_none(), width, height); } } #[doc(alias = "cairo_ps_surface_dsc_begin_setup")] pub fn dsc_begin_setup(&self) { unsafe { ffi::cairo_ps_surface_dsc_begin_setup(self.0.to_raw_none()); } } #[doc(alias = "cairo_ps_surface_dsc_begin_page_setup")] pub fn begin_page_setup(&self) { unsafe { ffi::cairo_ps_surface_dsc_begin_page_setup(self.0.to_raw_none()); } } #[doc(alias = "cairo_ps_surface_dsc_comment")] pub fn dsc_comment(&self, comment: &str) { let comment = CString::new(comment).unwrap(); unsafe { ffi::cairo_ps_surface_dsc_comment(self.0.to_raw_none(), comment.as_ptr()); } } } #[cfg(test)] mod test { use super::*; use crate::context::*; use tempfile::tempfile; fn draw(surface: &Surface) { let cr = Context::new(surface).expect("Can't create a Cairo context"); // Note: Not using RGBA here as PS doesn't natively support // semi-transparency and Cairo would then embed a rasterized bitmap cr.set_line_width(25.0); cr.set_source_rgb(1.0, 0.0, 0.0); cr.line_to(0., 0.); cr.line_to(100., 100.); cr.stroke().expect("Surface on an invalid state"); cr.set_source_rgb(0.0, 0.0, 1.0); cr.line_to(0., 100.); cr.line_to(100., 0.); cr.stroke().expect("Surface on an invalid state"); } fn draw_in_buffer() -> Vec { let buffer: Vec = vec![]; let surface = PsSurface::for_stream(100., 100., buffer).unwrap(); draw(&surface); *surface.finish_output_stream().unwrap().downcast().unwrap() } #[test] fn levels() { assert!(PsSurface::levels().any(|v| v == PsLevel::_2)); } #[test] fn level_string() { let ver_str = PsLevel::_2.as_str().unwrap(); assert_eq!(ver_str, "PS Level 2"); } #[test] fn eps() { let buffer: Vec = vec![]; let surface = PsSurface::for_stream(100., 100., buffer).unwrap(); surface.set_eps(true); assert!(surface.is_eps()); } #[test] #[cfg(unix)] fn file() { let surface = PsSurface::new(100., 100., "/dev/null").unwrap(); draw(&surface); surface.finish(); } #[test] fn writer() { let file = tempfile().expect("tempfile failed"); let surface = PsSurface::for_stream(100., 100., file).unwrap(); draw(&surface); let stream = surface.finish_output_stream().unwrap(); let file = stream.downcast::().unwrap(); let buffer = draw_in_buffer(); let file_size = file.metadata().unwrap().len(); assert_eq!(file_size, buffer.len() as u64); } #[test] fn ref_writer() { let mut file = tempfile().expect("tempfile failed"); let surface = unsafe { PsSurface::for_raw_stream(100., 100., &mut file).unwrap() }; draw(&surface); surface.finish_output_stream().unwrap(); } #[test] fn buffer() { let buffer = draw_in_buffer(); let header = b"%!PS-Adobe"; assert_eq!(&buffer[..header.len()], header); } #[test] fn custom_writer() { struct CustomWriter(usize); impl io::Write for CustomWriter { fn write(&mut self, buf: &[u8]) -> io::Result { self.0 += buf.len(); Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } let custom_writer = CustomWriter(0); let surface = PsSurface::for_stream(20., 20., custom_writer).unwrap(); surface.set_size(100., 100.); draw(&surface); let stream = surface.finish_output_stream().unwrap(); let custom_writer = stream.downcast::().unwrap(); let buffer = draw_in_buffer(); assert_eq!(custom_writer.0, buffer.len()); } fn with_panicky_stream() -> PsSurface { struct PanicWriter; impl io::Write for PanicWriter { fn write(&mut self, _buf: &[u8]) -> io::Result { panic!("panic in writer"); } fn flush(&mut self) -> io::Result<()> { Ok(()) } } let surface = PsSurface::for_stream(20., 20., PanicWriter).unwrap(); surface.finish(); surface } #[test] #[should_panic] fn finish_stream_propagates_panic() { let _ = with_panicky_stream().finish_output_stream(); } } cairo-rs-0.14.9/src/quartz_surface.rs000064400000000000000000000025020072674642500156600ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use std::convert::TryFrom; use std::fmt; use std::ops::Deref; use crate::enums::{Format, SurfaceType}; use crate::error::Error; use crate::surface::Surface; #[cfg(feature = "use_glib")] use glib::translate::*; use ffi::CGContextRef; declare_surface!(QuartzSurface, SurfaceType::Quartz); impl QuartzSurface { #[doc(alias = "cairo_quartz_surface_create")] pub fn create(format: Format, width: u32, height: u32) -> Result { unsafe { Self::from_raw_full(ffi::cairo_quartz_surface_create( format.into(), width, height, )) } } #[doc(alias = "cairo_quartz_surface_create_for_cg_context")] pub fn create_for_cg_context( cg_context: CGContextRef, width: u32, height: u32, ) -> Result { unsafe { Self::from_raw_full(ffi::cairo_quartz_surface_create_for_cg_context( cg_context, width, height, )) } } #[doc(alias = "cairo_quartz_surface_get_cg_context")] #[doc(alias = "get_cg_context")] pub fn cg_context(&self) -> CGContextRef { unsafe { ffi::cairo_quartz_surface_get_cg_context(self.to_raw_none()) } } } cairo-rs-0.14.9/src/recording_surface.rs000064400000000000000000000035340072674642500163140ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use std::convert::TryFrom; use std::fmt; use std::ops::Deref; use crate::enums::{Content, SurfaceType}; use crate::error::Error; use crate::rectangle::Rectangle; #[cfg(feature = "use_glib")] use glib::translate::*; use crate::surface::Surface; declare_surface!(RecordingSurface, SurfaceType::Recording); impl RecordingSurface { #[doc(alias = "cairo_recording_surface_create")] pub fn create>>( content: Content, extends: T, ) -> Result { unsafe { let extends = extends.into(); let extends = match extends { Some(c) => c.to_raw_none(), None => ::std::ptr::null(), }; Self::from_raw_full(ffi::cairo_recording_surface_create(content.into(), extends)) } } #[doc(alias = "cairo_recording_surface_get_extents")] #[doc(alias = "get_extents")] pub fn extents(&self) -> Option { unsafe { let rectangle: Rectangle = ::std::mem::zeroed(); if ffi::cairo_recording_surface_get_extents(self.to_raw_none(), rectangle.to_raw_none()) .as_bool() { Some(rectangle) } else { None } } } #[doc(alias = "cairo_recording_surface_ink_extents")] pub fn ink_extents(&self) -> (f64, f64, f64, f64) { let mut x0 = 0.; let mut y0 = 0.; let mut width = 0.; let mut height = 0.; unsafe { ffi::cairo_recording_surface_ink_extents( self.to_raw_none(), &mut x0, &mut y0, &mut width, &mut height, ); } (x0, y0, width, height) } } cairo-rs-0.14.9/src/rectangle.rs000064400000000000000000000046160072674642500145760ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. #[cfg(feature = "use_glib")] use glib::translate::*; use std::fmt; #[cfg(feature = "use_glib")] use std::mem; #[derive(Clone, Copy, Debug, PartialEq)] #[repr(C)] #[doc(alias = "cairo_rectangle_t")] pub struct Rectangle { pub x: f64, pub y: f64, pub width: f64, pub height: f64, } #[cfg(feature = "use_glib")] #[doc(hidden)] impl Uninitialized for Rectangle { #[inline] unsafe fn uninitialized() -> Self { mem::zeroed() } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl<'a> ToGlibPtr<'a, *const ffi::cairo_rectangle_t> for Rectangle { type Storage = &'a Self; #[inline] fn to_glib_none(&'a self) -> Stash<'a, *const ffi::cairo_rectangle_t, Self> { let ptr: *const Rectangle = &*self; Stash(ptr as *const ffi::cairo_rectangle_t, self) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl<'a> ToGlibPtrMut<'a, *mut ffi::cairo_rectangle_t> for Rectangle { type Storage = &'a mut Self; #[inline] fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::cairo_rectangle_t, Self> { let ptr: *mut Rectangle = &mut *self; StashMut(ptr as *mut ffi::cairo_rectangle_t, self) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl FromGlibPtrNone<*const ffi::cairo_rectangle_t> for Rectangle { unsafe fn from_glib_none(ptr: *const ffi::cairo_rectangle_t) -> Self { *(ptr as *const Rectangle) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl FromGlibPtrBorrow<*mut ffi::cairo_rectangle_t> for Rectangle { unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_rectangle_t) -> crate::Borrowed { crate::Borrowed::new(*(ptr as *mut Rectangle)) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl FromGlibPtrNone<*mut ffi::cairo_rectangle_t> for Rectangle { unsafe fn from_glib_none(ptr: *mut ffi::cairo_rectangle_t) -> Self { *(ptr as *mut Rectangle) } } #[cfg(feature = "use_glib")] gvalue_impl!( Rectangle, ffi::cairo_rectangle_t, ffi::gobject::cairo_gobject_rectangle_get_type ); impl Rectangle { pub fn to_raw_none(&self) -> *mut ffi::cairo_rectangle_t { let ptr = &*self as *const Rectangle as usize; ptr as *mut ffi::cairo_rectangle_t } } impl fmt::Display for Rectangle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Rectangle") } } cairo-rs-0.14.9/src/rectangle_int.rs000064400000000000000000000050170072674642500154440ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. #[cfg(feature = "use_glib")] use glib::translate::*; use std::fmt; #[cfg(feature = "use_glib")] use std::mem; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[repr(C)] #[doc(alias = "cairo_rectangle_int_t")] pub struct RectangleInt { pub x: i32, pub y: i32, pub width: i32, pub height: i32, } #[cfg(feature = "use_glib")] #[doc(hidden)] impl Uninitialized for RectangleInt { #[inline] unsafe fn uninitialized() -> Self { mem::zeroed() } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl<'a> ToGlibPtr<'a, *const ffi::cairo_rectangle_int_t> for RectangleInt { type Storage = &'a Self; #[inline] fn to_glib_none(&'a self) -> Stash<'a, *const ffi::cairo_rectangle_int_t, Self> { let ptr: *const RectangleInt = &*self; Stash(ptr as *const ffi::cairo_rectangle_int_t, self) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl<'a> ToGlibPtrMut<'a, *mut ffi::cairo_rectangle_int_t> for RectangleInt { type Storage = &'a mut Self; #[inline] fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::cairo_rectangle_int_t, Self> { let ptr: *mut RectangleInt = &mut *self; StashMut(ptr as *mut ffi::cairo_rectangle_int_t, self) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl FromGlibPtrNone<*const ffi::cairo_rectangle_int_t> for RectangleInt { unsafe fn from_glib_none(ptr: *const ffi::cairo_rectangle_int_t) -> Self { *(ptr as *const RectangleInt) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl FromGlibPtrBorrow<*mut ffi::cairo_rectangle_int_t> for RectangleInt { unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_rectangle_int_t) -> crate::Borrowed { crate::Borrowed::new(*(ptr as *mut RectangleInt)) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl FromGlibPtrNone<*mut ffi::cairo_rectangle_int_t> for RectangleInt { unsafe fn from_glib_none(ptr: *mut ffi::cairo_rectangle_int_t) -> Self { *(ptr as *mut RectangleInt) } } #[cfg(feature = "use_glib")] gvalue_impl!( RectangleInt, ffi::cairo_rectangle_int_t, ffi::gobject::cairo_gobject_rectangle_int_get_type ); impl RectangleInt { pub fn to_raw_none(&self) -> *mut ffi::cairo_rectangle_int_t { let ptr = &*self as *const RectangleInt as usize; ptr as *mut ffi::cairo_rectangle_int_t } } impl fmt::Display for RectangleInt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "RectangleInt") } } cairo-rs-0.14.9/src/region.rs000064400000000000000000000204340072674642500141110ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use crate::enums::RegionOverlap; use crate::error::Error; use crate::utils::status_to_result; use crate::RectangleInt; #[cfg(feature = "use_glib")] use glib::translate::*; use std::fmt; use std::ptr; use crate::ffi::cairo_region_t; #[derive(Debug)] pub struct Region(ptr::NonNull); #[cfg(feature = "use_glib")] #[doc(hidden)] impl<'a> ToGlibPtr<'a, *mut ffi::cairo_region_t> for &'a Region { type Storage = &'a Region; #[inline] fn to_glib_none(&self) -> Stash<'a, *mut ffi::cairo_region_t, &'a Region> { Stash(self.0.as_ptr(), *self) } #[inline] fn to_glib_full(&self) -> *mut ffi::cairo_region_t { unsafe { ffi::cairo_region_reference(self.0.as_ptr()) } } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl<'a> ToGlibPtrMut<'a, *mut ffi::cairo_region_t> for Region { type Storage = &'a mut Self; // FIXME: This is unsafe: regions are reference counted, so we could get multiple mutable // references here #[inline] fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::cairo_region_t, Self> { StashMut(self.0.as_ptr(), self) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl FromGlibPtrNone<*mut ffi::cairo_region_t> for Region { #[inline] unsafe fn from_glib_none(ptr: *mut ffi::cairo_region_t) -> Region { Self::from_raw_none(ptr) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl FromGlibPtrBorrow<*mut ffi::cairo_region_t> for Region { #[inline] unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_region_t) -> crate::Borrowed { Self::from_raw_borrow(ptr) } } #[cfg(feature = "use_glib")] #[doc(hidden)] impl FromGlibPtrFull<*mut ffi::cairo_region_t> for Region { #[inline] unsafe fn from_glib_full(ptr: *mut ffi::cairo_region_t) -> Region { Self::from_raw_full(ptr) } } #[cfg(feature = "use_glib")] gvalue_impl!( Region, ffi::cairo_region_t, ffi::gobject::cairo_gobject_region_get_type ); impl Clone for Region { fn clone(&self) -> Region { unsafe { Self::from_raw_none(self.to_raw_none()) } } } impl Drop for Region { fn drop(&mut self) { unsafe { ffi::cairo_region_destroy(self.0.as_ptr()); } } } impl PartialEq for Region { #[doc(alias = "cairo_region_equal")] fn eq(&self, other: &Region) -> bool { unsafe { ffi::cairo_region_equal(self.0.as_ptr(), other.0.as_ptr()).as_bool() } } } impl Eq for Region {} impl Region { #[inline] pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_region_t) -> Region { assert!(!ptr.is_null()); ffi::cairo_region_reference(ptr); Region(ptr::NonNull::new_unchecked(ptr)) } #[inline] pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_region_t) -> crate::Borrowed { assert!(!ptr.is_null()); crate::Borrowed::new(Region(ptr::NonNull::new_unchecked(ptr))) } #[inline] pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_region_t) -> Region { assert!(!ptr.is_null()); Region(ptr::NonNull::new_unchecked(ptr)) } pub fn to_raw_none(&self) -> *mut ffi::cairo_region_t { self.0.as_ptr() } #[doc(alias = "cairo_region_create")] pub fn create() -> Region { unsafe { Self::from_raw_full(ffi::cairo_region_create()) } } #[doc(alias = "cairo_region_create_rectangle")] pub fn create_rectangle(rectangle: &RectangleInt) -> Region { unsafe { Self::from_raw_full(ffi::cairo_region_create_rectangle(rectangle.to_raw_none())) } } #[doc(alias = "cairo_region_create_rectangles")] pub fn create_rectangles(rectangles: &[RectangleInt]) -> Region { unsafe { Self::from_raw_full(ffi::cairo_region_create_rectangles( rectangles.as_ptr() as *mut ffi::cairo_rectangle_int_t, rectangles.len() as i32, )) } } #[doc(alias = "cairo_region_copy")] pub fn copy(&self) -> Region { unsafe { Self::from_raw_full(ffi::cairo_region_copy(self.0.as_ptr())) } } #[doc(alias = "get_extents")] #[doc(alias = "cairo_region_get_extents")] pub fn extents(&self, rectangle: &mut RectangleInt) { unsafe { ffi::cairo_region_get_extents(self.0.as_ptr(), rectangle.to_raw_none()) } } #[doc(alias = "cairo_region_num_rectangles")] pub fn num_rectangles(&self) -> i32 { unsafe { ffi::cairo_region_num_rectangles(self.0.as_ptr()) } } #[doc(alias = "get_rectangle")] #[doc(alias = "cairo_region_get_rectangle")] pub fn rectangle(&self, nth: i32) -> RectangleInt { unsafe { let rectangle: RectangleInt = ::std::mem::zeroed(); ffi::cairo_region_get_rectangle(self.0.as_ptr(), nth, rectangle.to_raw_none()); rectangle } } #[doc(alias = "cairo_region_is_empty")] pub fn is_empty(&self) -> bool { unsafe { ffi::cairo_region_is_empty(self.0.as_ptr()).as_bool() } } #[doc(alias = "cairo_region_contains_point")] pub fn contains_point(&self, x: i32, y: i32) -> bool { unsafe { ffi::cairo_region_contains_point(self.0.as_ptr(), x, y).as_bool() } } #[doc(alias = "cairo_region_contains_rectangle")] pub fn contains_rectangle(&self, rectangle: &RectangleInt) -> RegionOverlap { unsafe { RegionOverlap::from(ffi::cairo_region_contains_rectangle( self.0.as_ptr(), rectangle.to_raw_none(), )) } } #[doc(alias = "cairo_region_translate")] pub fn translate(&self, dx: i32, dy: i32) { unsafe { ffi::cairo_region_translate(self.0.as_ptr(), dx, dy) } } #[doc(alias = "cairo_region_intersect")] pub fn intersect(&self, other: &Region) -> Result<(), Error> { unsafe { let status = ffi::cairo_region_intersect(self.0.as_ptr(), other.0.as_ptr()); status_to_result(status) } } #[doc(alias = "cairo_region_intersect_rectangle")] pub fn intersect_rectangle(&self, rectangle: &RectangleInt) -> Result<(), Error> { unsafe { let status = ffi::cairo_region_intersect_rectangle(self.0.as_ptr(), rectangle.to_raw_none()); status_to_result(status) } } #[doc(alias = "cairo_region_subtract")] pub fn subtract(&self, other: &Region) -> Result<(), Error> { unsafe { let status = ffi::cairo_region_subtract(self.0.as_ptr(), other.0.as_ptr()); status_to_result(status) } } #[doc(alias = "cairo_region_subtract_rectangle")] pub fn subtract_rectangle(&self, rectangle: &RectangleInt) -> Result<(), Error> { unsafe { let status = ffi::cairo_region_subtract_rectangle(self.0.as_ptr(), rectangle.to_raw_none()); status_to_result(status) } } #[doc(alias = "cairo_region_union")] pub fn union(&self, other: &Region) -> Result<(), Error> { unsafe { let status = ffi::cairo_region_union(self.0.as_ptr(), other.0.as_ptr()); status_to_result(status) } } #[doc(alias = "cairo_region_union_rectangle")] pub fn union_rectangle(&self, rectangle: &RectangleInt) -> Result<(), Error> { unsafe { let status = ffi::cairo_region_union_rectangle(self.0.as_ptr(), rectangle.to_raw_none()); status_to_result(status) } } #[doc(alias = "cairo_region_xor")] pub fn xor(&self, other: &Region) -> Result<(), Error> { unsafe { let status = ffi::cairo_region_xor(self.0.as_ptr(), other.0.as_ptr()); status_to_result(status) } } #[doc(alias = "cairo_region_xor_rectangle")] pub fn xor_rectangle(&self, rectangle: &RectangleInt) -> Result<(), Error> { unsafe { let status = ffi::cairo_region_xor_rectangle(self.0.as_ptr(), rectangle.to_raw_none()); status_to_result(status) } } #[doc(alias = "cairo_region_status")] pub fn status(&self) -> Result<(), Error> { let status = unsafe { ffi::cairo_region_status(self.0.as_ptr()) }; status_to_result(status) } } impl fmt::Display for Region { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Region") } } cairo-rs-0.14.9/src/stream.rs000064400000000000000000000223160072674642500141220ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use crate::error::Error; use crate::{Surface, UserDataKey}; use ffi::cairo_status_t; use libc::{c_double, c_uchar, c_uint, c_void}; use std::any::Any; use std::cell::{Cell, RefCell}; use std::io; use std::panic::AssertUnwindSafe; use std::ptr; use std::rc::Rc; macro_rules! for_stream_constructors { ($constructor_ffi: ident) => { /// Takes full ownership of the output stream, /// which is not allowed to borrow any lifetime shorter than `'static`. /// /// Because the underlying `cairo_surface_t` is reference-counted, /// a lifetime parameter in a Rust wrapper type would not be enough to track /// how long it can keep writing to the stream. pub fn for_stream( width: f64, height: f64, stream: W, ) -> Result { Ok(Self(Surface::_for_stream( ffi::$constructor_ffi, width, height, stream, )?)) } /// Allows writing to a borrowed stream. The lifetime of the borrow is not tracked. /// /// # Safety /// /// The value that `stream` points to must live at least until the underlying `cairo_surface_t` /// (which maybe be longer then the Rust `PdfSurface` wrapper, because of reference-counting), /// or until the output stream is removed from the surface with [`Surface::finish_output_stream`]. /// /// Since the former is hard to track for sure, the latter is strongly recommended. /// The concrete type behind the `Box` value returned by `finish_output_stream` /// is private, so you won’t be able to downcast it. /// But removing it anyway ensures that later writes do not go through a dangling pointer. pub unsafe fn for_raw_stream( width: f64, height: f64, stream: *mut W, ) -> Result { Ok(Self(Surface::_for_raw_stream( ffi::$constructor_ffi, width, height, stream, )?)) } }; } impl Surface { pub(crate) fn _for_stream( constructor: Constructor, width: f64, height: f64, stream: W, ) -> Result { let env_rc = Rc::new(CallbackEnvironment { mutable: RefCell::new(MutableCallbackEnvironment { stream: Some((Box::new(stream), None)), unwind_payload: None, }), saw_already_borrowed: Cell::new(false), }); let env: *const CallbackEnvironment = &*env_rc; unsafe { let ptr = constructor(Some(write_callback::), env as *mut c_void, width, height); let surface = Surface::from_raw_full(ptr)?; surface.set_user_data(&STREAM_CALLBACK_ENVIRONMENT, env_rc)?; Ok(surface) } } pub(crate) unsafe fn _for_raw_stream( constructor: Constructor, width: f64, height: f64, stream: *mut W, ) -> Result { Self::_for_stream( constructor, width, height, RawStream(ptr::NonNull::new(stream).expect("NULL stream passed")), ) } /// Finish the surface, then remove and return the output stream if any. /// /// This calls [`Surface::finish`], to make sure pending writes are done. /// /// This is relevant for surfaces created for example with [`PdfSurface::for_stream`]. /// /// Use [`Box::downcast`] to recover the concrete stream type. /// /// # Panics /// /// This method panics if: /// /// * This method was already called for this surface, or /// * This surface was not created with an output stream in the first place, or /// * A previous write to this surface panicked, or /// * A previous write happened while another write was ongoing, or /// * A write is ongoing now. /// /// The latter two cases can only occur with a pathological output stream type /// that accesses the same surface again from `Write::write_all`. pub fn finish_output_stream(&self) -> Result, StreamWithError> { self.finish(); let env = self .user_data_ptr(&STREAM_CALLBACK_ENVIRONMENT) .expect("surface without an output stream"); // Safety: since `STREAM_CALLBACK_ENVIRONMENT` is private and we never // call `set_user_data` again or `remove_user_data` with it, // the contract of `get_user_data_ptr` says that the user data entry // lives as long as the underlying `cairo_surface_t` // which is at least as long as `self`. let env = unsafe { &*env.as_ptr() }; if env.saw_already_borrowed.get() { panic!("The output stream’s RefCell was already borrowed when cairo attempted a write") } let mut mutable = env.mutable.borrow_mut(); if let Some(payload) = mutable.unwind_payload.take() { std::panic::resume_unwind(payload) } let (stream, io_error) = mutable .stream .take() .expect("output stream was already taken"); if let Some(error) = io_error { Err(StreamWithError { stream, error }) } else { Ok(stream) } } } pub struct StreamWithError { pub stream: Box, pub error: io::Error, } impl std::fmt::Debug for StreamWithError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { self.error.fmt(f) } } impl std::fmt::Display for StreamWithError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { self.error.fmt(f) } } impl From for io::Error { fn from(e: StreamWithError) -> Self { e.error } } pub(crate) type Constructor = unsafe extern "C" fn( ffi::cairo_write_func_t, *mut c_void, c_double, c_double, ) -> *mut ffi::cairo_surface_t; static STREAM_CALLBACK_ENVIRONMENT: UserDataKey = UserDataKey::new(); struct CallbackEnvironment { mutable: RefCell, saw_already_borrowed: Cell, } struct MutableCallbackEnvironment { stream: Option<(Box, Option)>, unwind_payload: Option>, } // Safety: unwinding into C is undefined behavior (https://github.com/rust-lang/rust/issues/58794) // so code outside of the `catch_unwind` call must never panic. extern "C" fn write_callback( env: *mut c_void, data: *mut c_uchar, length: c_uint, ) -> cairo_status_t { // This is consistent with the type of `env` in `Surface::_for_stream`. let env: *const CallbackEnvironment = env as _; // Safety: the user data entry keeps `Rc` alive // until the surface is destroyed. // If this is called by cairo, the surface is still alive. let env: &CallbackEnvironment = unsafe { &*env }; if let Ok(mut mutable) = env.mutable.try_borrow_mut() { if let MutableCallbackEnvironment { stream: Some(( stream, // Don’t attempt another write, if a previous one errored or panicked: io_error @ None, )), unwind_payload: unwind_payload @ None, } = &mut *mutable { // Safety: `write_callback` was instantiated in `Surface::_for_stream` // with a W parameter consistent with the box that was unsized to `Box`. let stream = unsafe { stream.downcast_mut_unchecked::() }; // Safety: this is the callback contract from cairo’s API let data = unsafe { std::slice::from_raw_parts(data, length as usize) }; // Because `::write_all` is a generic, // we must conservatively assume that it can panic. let result = std::panic::catch_unwind(AssertUnwindSafe(|| stream.write_all(data))); match result { Ok(Ok(())) => return ffi::STATUS_SUCCESS, Ok(Err(error)) => { *io_error = Some(error); } Err(payload) => { *unwind_payload = Some(payload); } } } } else { env.saw_already_borrowed.set(true) } Error::WriteError.into() } struct RawStream(ptr::NonNull); impl io::Write for RawStream { fn write(&mut self, buf: &[u8]) -> io::Result { unsafe { (*self.0.as_ptr()).write(buf) } } fn flush(&mut self) -> io::Result<()> { unsafe { (*self.0.as_ptr()).flush() } } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { unsafe { (*self.0.as_ptr()).write_all(buf) } } } trait AnyExt { /// Any::downcast_mut, but YOLO unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { let ptr = self as *mut Self as *mut T; &mut *ptr } } impl AnyExt for dyn Any {} cairo-rs-0.14.9/src/surface.rs000064400000000000000000000303750072674642500142630ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use libc::{c_ulong, c_void}; use std::ffi::CString; use std::fmt; use std::ops::Deref; use std::ptr; use std::slice; use crate::enums::{Content, Format, SurfaceType}; use crate::error::Error; use crate::utils::status_to_result; #[cfg(feature = "use_glib")] use glib::translate::*; use crate::device::Device; use crate::image_surface::ImageSurface; use crate::rectangle::Rectangle; use crate::rectangle_int::RectangleInt; #[derive(Debug)] #[doc(alias = "cairo_surface_t")] pub struct Surface(ptr::NonNull); impl Surface { pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_surface_t) -> Surface { assert!(!ptr.is_null()); ffi::cairo_surface_reference(ptr); Surface(ptr::NonNull::new_unchecked(ptr)) } pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_surface_t) -> crate::Borrowed { assert!(!ptr.is_null()); crate::Borrowed::new(Surface(ptr::NonNull::new_unchecked(ptr))) } pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_surface_t) -> Result { assert!(!ptr.is_null()); let status = ffi::cairo_surface_status(ptr); status_to_result(status)?; Ok(Surface(ptr::NonNull::new_unchecked(ptr))) } pub fn to_raw_none(&self) -> *mut ffi::cairo_surface_t { self.0.as_ptr() } #[doc(alias = "cairo_surface_create_similar")] pub fn create_similar( &self, content: Content, width: i32, height: i32, ) -> Result { unsafe { Self::from_raw_full(ffi::cairo_surface_create_similar( self.0.as_ptr(), content.into(), width, height, )) } } #[doc(alias = "cairo_surface_create_for_rectangle")] pub fn create_for_rectangle(&self, bounds: Rectangle) -> Result { unsafe { Self::from_raw_full(ffi::cairo_surface_create_for_rectangle( self.0.as_ptr(), bounds.x, bounds.y, bounds.width, bounds.height, )) } } #[doc(alias = "cairo_surface_get_mime_data")] #[doc(alias = "get_mime_data")] pub fn mime_data(&self, mime_type: &str) -> Option> { let data_ptr: *mut u8 = ptr::null_mut(); let mut length: c_ulong = 0; unsafe { let mime_type = CString::new(mime_type).unwrap(); ffi::cairo_surface_get_mime_data( self.to_raw_none(), mime_type.as_ptr(), &data_ptr, &mut length, ); if !data_ptr.is_null() && length != 0 { Some(slice::from_raw_parts(data_ptr as *const u8, length as usize).to_vec()) } else { None } } } #[doc(alias = "cairo_surface_get_mime_data")] #[doc(alias = "get_mime_data_raw")] pub unsafe fn mime_data_raw(&self, mime_type: &str) -> Option<&[u8]> { let data_ptr: *mut u8 = ptr::null_mut(); let mut length: c_ulong = 0; let mime_type = CString::new(mime_type).unwrap(); ffi::cairo_surface_get_mime_data( self.to_raw_none(), mime_type.as_ptr(), &data_ptr, &mut length, ); if !data_ptr.is_null() && length != 0 { Some(slice::from_raw_parts( data_ptr as *const u8, length as usize, )) } else { None } } #[doc(alias = "cairo_surface_set_mime_data")] pub fn set_mime_data + 'static>( &self, mime_type: &str, slice: T, ) -> Result<(), Error> { let b = Box::new(slice); let (size, data) = { let slice = (*b).as_ref(); (slice.len(), slice.as_ptr()) }; let user_data = Box::into_raw(b); unsafe extern "C" fn unbox(data: *mut c_void) { let data: Box = Box::from_raw(data as *mut T); drop(data); } let status = unsafe { let mime_type = CString::new(mime_type).unwrap(); ffi::cairo_surface_set_mime_data( self.to_raw_none(), mime_type.as_ptr(), data, size as c_ulong, Some(unbox::), user_data as *mut _, ) }; status_to_result(status) } #[doc(alias = "cairo_surface_supports_mime_type")] pub fn supports_mime_type(&self, mime_type: &str) -> bool { unsafe { let mime_type = CString::new(mime_type).unwrap(); ffi::cairo_surface_supports_mime_type(self.0.as_ptr(), mime_type.as_ptr()).as_bool() } } #[doc(alias = "cairo_surface_get_device")] #[doc(alias = "get_device")] pub fn device(&self) -> Option { unsafe { let device = ffi::cairo_surface_get_device(self.to_raw_none()); if device.is_null() { None } else { Some(Device::from_raw_none(device)) } } } #[doc(alias = "cairo_surface_set_device_offset")] pub fn set_device_offset(&self, x_offset: f64, y_offset: f64) { unsafe { ffi::cairo_surface_set_device_offset(self.to_raw_none(), x_offset, y_offset) } } #[doc(alias = "cairo_surface_get_device_offset")] #[doc(alias = "get_device_offset")] pub fn device_offset(&self) -> (f64, f64) { let mut x_offset = 0.0f64; let mut y_offset = 0.0f64; unsafe { ffi::cairo_surface_get_device_offset(self.to_raw_none(), &mut x_offset, &mut y_offset); } (x_offset, y_offset) } #[doc(alias = "cairo_surface_set_device_scale")] pub fn set_device_scale(&self, x_scale: f64, y_scale: f64) { unsafe { ffi::cairo_surface_set_device_scale(self.to_raw_none(), x_scale, y_scale) } } #[doc(alias = "cairo_surface_get_device_scale")] #[doc(alias = "get_device_scale")] pub fn device_scale(&self) -> (f64, f64) { let mut x_scale = 0.0f64; let mut y_scale = 0.0f64; unsafe { ffi::cairo_surface_get_device_scale(self.to_raw_none(), &mut x_scale, &mut y_scale); } (x_scale, y_scale) } #[doc(alias = "cairo_surface_set_fallback_resolution")] pub fn set_fallback_resolution(&self, x_pixels_per_inch: f64, y_pixels_per_inch: f64) { unsafe { ffi::cairo_surface_set_fallback_resolution( self.to_raw_none(), x_pixels_per_inch, y_pixels_per_inch, ) } } #[doc(alias = "cairo_surface_get_fallback_resolution")] #[doc(alias = "get_fallback_resolution")] pub fn fallback_resolution(&self) -> (f64, f64) { let mut x_pixels_per_inch = 0.0f64; let mut y_pixels_per_inch = 0.0f64; unsafe { ffi::cairo_surface_get_fallback_resolution( self.to_raw_none(), &mut x_pixels_per_inch, &mut y_pixels_per_inch, ); } (x_pixels_per_inch, y_pixels_per_inch) } #[doc(alias = "cairo_surface_create_similar_image")] pub fn create_similar_image( &self, format: Format, width: i32, height: i32, ) -> Result { unsafe { Self::from_raw_full(ffi::cairo_surface_create_similar_image( self.to_raw_none(), format.into(), width, height, )) } } #[doc(alias = "cairo_surface_map_to_image")] pub fn map_to_image(&self, extents: Option) -> Result { unsafe { ImageSurface::from_raw_none(match extents { Some(ref e) => ffi::cairo_surface_map_to_image(self.to_raw_none(), e.to_raw_none()), None => ffi::cairo_surface_map_to_image(self.to_raw_none(), std::ptr::null()), }) .map(|s| MappedImageSurface { original_surface: self.clone(), image_surface: s, }) } } #[doc(alias = "cairo_surface_mark_dirty")] pub fn mark_dirty(&self) { unsafe { ffi::cairo_surface_mark_dirty(self.to_raw_none()) } } #[doc(alias = "cairo_surface_mark_dirty_rectangle")] pub fn mark_dirty_rectangle(&self, x: i32, y: i32, width: i32, height: i32) { unsafe { ffi::cairo_surface_mark_dirty_rectangle(self.to_raw_none(), x, y, width, height) } } #[doc(alias = "cairo_surface_status")] pub fn status(&self) -> Result<(), Error> { let status = unsafe { ffi::cairo_surface_status(self.to_raw_none()) }; status_to_result(status) } user_data_methods! { ffi::cairo_surface_get_user_data, ffi::cairo_surface_set_user_data, } } #[cfg(feature = "use_glib")] impl<'a> ToGlibPtr<'a, *mut ffi::cairo_surface_t> for Surface { type Storage = &'a Surface; #[inline] fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_surface_t, Self> { Stash(self.to_raw_none(), self) } #[inline] fn to_glib_full(&self) -> *mut ffi::cairo_surface_t { unsafe { ffi::cairo_surface_reference(self.to_raw_none()) } } } #[cfg(feature = "use_glib")] impl FromGlibPtrNone<*mut ffi::cairo_surface_t> for Surface { #[inline] unsafe fn from_glib_none(ptr: *mut ffi::cairo_surface_t) -> Surface { Self::from_raw_none(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrBorrow<*mut ffi::cairo_surface_t> for Surface { #[inline] unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_surface_t) -> crate::Borrowed { Self::from_raw_borrow(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrFull<*mut ffi::cairo_surface_t> for Surface { #[inline] unsafe fn from_glib_full(ptr: *mut ffi::cairo_surface_t) -> Surface { Self::from_raw_full(ptr).unwrap() } } #[cfg(feature = "use_glib")] gvalue_impl!( Surface, ffi::cairo_surface_t, ffi::gobject::cairo_gobject_surface_get_type ); impl Clone for Surface { fn clone(&self) -> Surface { unsafe { Self::from_raw_none(self.0.as_ptr()) } } } impl Drop for Surface { fn drop(&mut self) { unsafe { ffi::cairo_surface_destroy(self.0.as_ptr()); } } } impl fmt::Display for Surface { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Surface") } } impl Surface { #[doc(alias = "cairo_surface_flush")] pub fn flush(&self) { unsafe { ffi::cairo_surface_flush(self.0.as_ptr()); } } #[doc(alias = "cairo_surface_finish")] pub fn finish(&self) { unsafe { ffi::cairo_surface_finish(self.0.as_ptr()); } } #[doc(alias = "cairo_surface_get_type")] #[doc(alias = "get_type")] pub fn type_(&self) -> SurfaceType { unsafe { SurfaceType::from(ffi::cairo_surface_get_type(self.0.as_ptr())) } } } #[derive(Debug)] pub struct MappedImageSurface { original_surface: Surface, image_surface: ImageSurface, } impl Deref for MappedImageSurface { type Target = ImageSurface; fn deref(&self) -> &ImageSurface { &self.image_surface } } impl Drop for MappedImageSurface { fn drop(&mut self) { unsafe { ffi::cairo_surface_unmap_image( self.original_surface.to_raw_none(), self.image_surface.to_raw_none(), ); } } } impl fmt::Display for MappedImageSurface { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "MappedImageSurface") } } #[cfg(test)] mod tests { use crate::constants::MIME_TYPE_PNG; use crate::Format; use crate::ImageSurface; #[test] fn mime_data() { let surface = ImageSurface::create(Format::ARgb32, 500, 500).unwrap(); let data = surface.mime_data(MIME_TYPE_PNG); /* Initially the data for any mime type has to be none */ assert!(data.is_none()); assert!(surface.set_mime_data(MIME_TYPE_PNG, &[1u8, 10u8]).is_ok()); let data = surface.mime_data(MIME_TYPE_PNG).unwrap(); assert_eq!(data, &[1u8, 10u8]); } } cairo-rs-0.14.9/src/surface_macros.rs000064400000000000000000000072030072674642500156210ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. // e.g. declare_surface(ImageSurface, SurfaceType::Image) macro_rules! declare_surface { ($surf_name:ident, $surf_type:expr) => { #[derive(Debug)] pub struct $surf_name(Surface); impl TryFrom for $surf_name { type Error = Surface; fn try_from(surface: Surface) -> Result<$surf_name, Surface> { if surface.type_() == $surf_type { Ok($surf_name(surface)) } else { Err(surface) } } } impl $surf_name { pub unsafe fn from_raw_full( ptr: *mut ffi::cairo_surface_t, ) -> Result<$surf_name, crate::error::Error> { let surface = Surface::from_raw_full(ptr)?; Self::try_from(surface).map_err(|_| crate::error::Error::SurfaceTypeMismatch) } pub unsafe fn from_raw_none( ptr: *mut ffi::cairo_surface_t, ) -> Result<$surf_name, crate::error::Error> { let surface = Surface::from_raw_none(ptr); Self::try_from(surface).map_err(|_| crate::error::Error::SurfaceTypeMismatch) } } #[cfg(feature = "use_glib")] impl<'a> ToGlibPtr<'a, *mut ffi::cairo_surface_t> for $surf_name { type Storage = &'a Surface; #[inline] fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_surface_t, Self> { let stash = self.0.to_glib_none(); Stash(stash.0, stash.1) } #[inline] fn to_glib_full(&self) -> *mut ffi::cairo_surface_t { unsafe { ffi::cairo_surface_reference(self.to_glib_none().0) } } } #[cfg(feature = "use_glib")] impl FromGlibPtrNone<*mut ffi::cairo_surface_t> for $surf_name { #[inline] unsafe fn from_glib_none(ptr: *mut ffi::cairo_surface_t) -> $surf_name { Self::try_from(from_glib_none::<_, Surface>(ptr)).unwrap() } } #[cfg(feature = "use_glib")] impl FromGlibPtrBorrow<*mut ffi::cairo_surface_t> for $surf_name { #[inline] unsafe fn from_glib_borrow( ptr: *mut ffi::cairo_surface_t, ) -> crate::Borrowed<$surf_name> { let surface = from_glib_borrow::<_, Surface>(ptr); let surface = Self::try_from(surface.into_inner()) .map_err(std::mem::forget) .unwrap(); crate::Borrowed::new(surface) } } #[cfg(feature = "use_glib")] impl FromGlibPtrFull<*mut ffi::cairo_surface_t> for $surf_name { #[inline] unsafe fn from_glib_full(ptr: *mut ffi::cairo_surface_t) -> $surf_name { Self::from_raw_full(ptr).unwrap() } } #[cfg(feature = "use_glib")] gvalue_impl!( $surf_name, ffi::cairo_surface_t, ffi::gobject::cairo_gobject_surface_get_type ); impl Deref for $surf_name { type Target = Surface; fn deref(&self) -> &Surface { &self.0 } } impl Clone for $surf_name { fn clone(&self) -> $surf_name { $surf_name(self.0.clone()) } } impl fmt::Display for $surf_name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(stringify!($surf_name)) } } }; } cairo-rs-0.14.9/src/svg.rs000064400000000000000000000171710072674642500134310ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. #[cfg(any(all(feature = "svg", feature = "v1_16"), feature = "dox"))] use crate::enums::SvgUnit; use crate::enums::{SurfaceType, SvgVersion}; use crate::error::Error; use std::convert::TryFrom; use std::ffi::{CStr, CString}; use std::fmt; use std::io; use std::mem; use std::ops::Deref; #[cfg(not(windows))] use std::os::unix::prelude::*; use std::path::Path; use std::ptr; use crate::surface::Surface; #[cfg(feature = "use_glib")] use glib::translate::*; impl SvgVersion { pub fn as_str(self) -> Option<&'static str> { unsafe { let res = ffi::cairo_svg_version_to_string(self.into()); res.as_ref() .and_then(|cstr| CStr::from_ptr(cstr as _).to_str().ok()) } } } declare_surface!(SvgSurface, SurfaceType::Svg); impl SvgSurface { #[doc(alias = "cairo_svg_surface_create")] pub fn new>( width: f64, height: f64, path: Option

, ) -> Result { #[cfg(not(windows))] let path = path.map(|p| { CString::new(p.as_ref().as_os_str().as_bytes()).expect("Invalid path with NULL bytes") }); #[cfg(windows)] let path = path.map(|p| { let path_str = p .as_ref() .to_str() .expect("Path can't be represented as UTF-8") .to_owned(); if path_str.starts_with("\\\\?\\") { CString::new(path_str[4..].as_bytes()) } else { CString::new(path_str.as_bytes()) } .expect("Invalid path with NUL bytes") }); unsafe { Ok(Self(Surface::from_raw_full( ffi::cairo_svg_surface_create( path.as_ref().map(|p| p.as_ptr()).unwrap_or(ptr::null()), width, height, ), )?)) } } for_stream_constructors!(cairo_svg_surface_create_for_stream); #[doc(alias = "cairo_svg_get_versions")] #[doc(alias = "get_versions")] pub fn versions() -> impl Iterator { let vers_slice = unsafe { let mut vers_ptr = ptr::null_mut(); let mut num_vers = mem::MaybeUninit::uninit(); ffi::cairo_svg_get_versions(&mut vers_ptr, num_vers.as_mut_ptr()); std::slice::from_raw_parts(vers_ptr, num_vers.assume_init() as _) }; vers_slice.iter().map(|v| SvgVersion::from(*v)) } #[doc(alias = "cairo_svg_surface_restrict_to_version")] pub fn restrict(&self, version: SvgVersion) { unsafe { ffi::cairo_svg_surface_restrict_to_version(self.0.to_raw_none(), version.into()); } } #[cfg(any(all(feature = "svg", feature = "v1_16"), feature = "dox"))] #[doc(alias = "cairo_svg_surface_set_document_unit")] pub fn set_document_unit(&mut self, unit: SvgUnit) { unsafe { ffi::cairo_svg_surface_set_document_unit(self.0.to_raw_none(), unit.into()); } } #[cfg(any(all(feature = "svg", feature = "v1_16"), feature = "dox"))] #[doc(alias = "cairo_svg_surface_get_document_unit")] #[doc(alias = "get_document_unit")] pub fn document_unit(&self) -> SvgUnit { unsafe { SvgUnit::from(ffi::cairo_svg_surface_get_document_unit( self.0.to_raw_none(), )) } } } #[cfg(test)] mod test { use super::*; use crate::context::*; use tempfile::{tempfile, NamedTempFile}; fn draw(surface: &Surface) { let cr = Context::new(surface).expect("Can't create a Cairo context"); cr.set_line_width(25.0); cr.set_source_rgba(1.0, 0.0, 0.0, 0.5); cr.line_to(0., 0.); cr.line_to(100., 100.); cr.stroke().expect("Surface on an invalid state"); cr.set_source_rgba(0.0, 0.0, 1.0, 0.5); cr.line_to(0., 100.); cr.line_to(100., 0.); cr.stroke().expect("Surface on an invalid state"); } fn draw_in_buffer() -> Vec { let buffer: Vec = vec![]; let surface = SvgSurface::for_stream(100., 100., buffer).unwrap(); draw(&surface); *surface.finish_output_stream().unwrap().downcast().unwrap() } fn assert_len_close_enough(len_a: usize, len_b: usize) { // It seems cairo randomizes some element IDs which might make one svg slightly // larger than the other. Here we make sure the difference is within ~10%. let len_diff = (len_a as isize - len_b as isize).abs() as usize; assert!(len_diff < len_b / 10); } #[test] fn versions() { assert!(SvgSurface::versions().any(|v| v == SvgVersion::_1_1)); } #[test] fn version_string() { let ver_str = SvgVersion::_1_1.as_str().unwrap(); assert_eq!(ver_str, "SVG 1.1"); } #[test] fn without_file() { let surface = SvgSurface::new(100., 100., None::<&Path>).unwrap(); draw(&surface); surface.finish(); } #[test] fn file() { let file = NamedTempFile::new().expect("tempfile failed"); let surface = SvgSurface::new(100., 100., Some(&file.path())).unwrap(); draw(&surface); surface.finish(); } #[test] fn writer() { let file = tempfile().expect("tempfile failed"); let surface = SvgSurface::for_stream(100., 100., file).unwrap(); draw(&surface); let stream = surface.finish_output_stream().unwrap(); let file = stream.downcast::().unwrap(); let buffer = draw_in_buffer(); let file_size = file.metadata().unwrap().len(); assert_len_close_enough(file_size as usize, buffer.len()); } #[test] fn ref_writer() { let mut file = tempfile().expect("tempfile failed"); let surface = unsafe { SvgSurface::for_raw_stream(100., 100., &mut file).unwrap() }; draw(&surface); surface.finish_output_stream().unwrap(); } #[test] fn buffer() { let buffer = draw_in_buffer(); let header = b" io::Result { self.1.write_all(buf)?; self.0 += buf.len(); Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } let file = tempfile().expect("tempfile failed"); let custom_writer = CustomWriter(0, file); let surface = SvgSurface::for_stream(100., 100., custom_writer).unwrap(); draw(&surface); let stream = surface.finish_output_stream().unwrap(); let custom_writer = stream.downcast::().unwrap(); let buffer = draw_in_buffer(); assert_len_close_enough(custom_writer.0, buffer.len()); } fn with_panicky_stream() -> SvgSurface { struct PanicWriter; impl io::Write for PanicWriter { fn write(&mut self, _buf: &[u8]) -> io::Result { panic!("panic in writer"); } fn flush(&mut self) -> io::Result<()> { Ok(()) } } let surface = SvgSurface::for_stream(20., 20., PanicWriter).unwrap(); surface.finish(); surface } #[test] #[should_panic] fn finish_stream_propagates_panic() { let _ = with_panicky_stream().finish_output_stream(); } } cairo-rs-0.14.9/src/user_data.rs000064400000000000000000000133700072674642500145760ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use std::marker::PhantomData; use crate::ffi::cairo_user_data_key_t; pub struct UserDataKey { pub(crate) ffi: cairo_user_data_key_t, marker: PhantomData<*const T>, } unsafe impl Sync for UserDataKey {} impl UserDataKey { pub const fn new() -> Self { Self { ffi: cairo_user_data_key_t { unused: 0 }, marker: PhantomData, } } } // In a safe API for user data we can’t make `get_user_data` // transfer full ownership of the value to the caller (e.g. by returning `Box`) // because `self` still has a pointer to that value // and `get_user_data` could be called again with the same key. // // We also can’t return a `&T` reference that borrows from `self` // because the value could be removed with `remove_user_data` or replaced with `set_user_data` // while the borrow still needs to be valid. // (Borrowing with `&mut self` would not help as `Self` can be itself reference-counted.) // // Therefore, the value must be reference-counted. // // We use `Rc` over `Arc` because the types implementing these methods are `!Send` and `!Sync`. // See macro_rules! user_data_methods { ($ffi_get_user_data: path, $ffi_set_user_data: path,) => { /// Attach user data to `self` for the given `key`. pub fn set_user_data( &self, key: &'static crate::UserDataKey, value: std::rc::Rc, ) -> Result<(), crate::Error> { unsafe extern "C" fn destructor(ptr: *mut libc::c_void) { let ptr: *const T = ptr as _; drop(std::rc::Rc::from_raw(ptr)) } // Safety: // // The destructor’s cast and `from_raw` are symmetric // with the `into_raw` and cast below. // They both transfer ownership of one strong reference: // neither of them touches the reference count. let ptr: *const T = std::rc::Rc::into_raw(value); let ptr = ptr as *mut T as *mut libc::c_void; let status = unsafe { $ffi_set_user_data(self.to_raw_none(), &key.ffi, ptr, Some(destructor::)) }; crate::utils::status_to_result(status) } /// Return the user data previously attached to `self` with the given `key`, if any. pub fn user_data( &self, key: &'static crate::UserDataKey, ) -> Option> { let ptr = self.user_data_ptr(key)?.as_ptr(); // Safety: // // `Rc::from_raw` would normally take ownership of a strong reference for this pointer. // But `self` still has a copy of that pointer and `get_user_data` can be called again // with the same key. // We use `ManuallyDrop` to avoid running the destructor of that first `Rc`, // and return a cloned one (which increments the reference count). unsafe { let rc = std::mem::ManuallyDrop::new(std::rc::Rc::from_raw(ptr)); Some(std::rc::Rc::clone(&rc)) } } /// Return the user data previously attached to `self` with the given `key`, if any, /// without incrementing the reference count. /// /// The pointer is valid when it is returned from this method, /// until the cairo object that `self` represents is destroyed /// or `remove_user_data` or `set_user_data` is called with the same key. pub fn user_data_ptr( &self, key: &'static crate::UserDataKey, ) -> Option> { // Safety: // // If `ffi_get_user_data` returns a non-null pointer, // there was a previous call to `ffi_set_user_data` with a key with the same address. // Either: // // * This was a call to a Rust `Self::set_user_data` method. // Because that method takes a `&'static` reference, // the key used then must live at that address until the end of the process. // Because `UserDataKey` has a non-zero size regardless of `T`, // no other `UserDataKey` value can have the same address. // Therefore, the `T` type was the same then at it is now and `cast` is type-safe. // // * Or, it is technically possible that the `set` call was to the C function directly, // with a `cairo_user_data_key_t` in heap-allocated memory that was then freed, // then `Box::new(UserDataKey::new()).leak()` was used to create a `&'static` // that happens to have the same address because the allocator for `Box` // reused that memory region. // Since this involves a C (or FFI) call *and* is so far out of “typical” use // of the user data functionality, we consider this a misuse of an unsafe API. unsafe { let ptr = $ffi_get_user_data(self.to_raw_none(), &key.ffi); Some(std::ptr::NonNull::new(ptr)?.cast()) } } /// Unattached from `self` the user data associated with `key`, if any. /// If there is no other `Rc` strong reference, the data is destroyed. pub fn remove_user_data( &self, key: &'static crate::UserDataKey, ) -> Result<(), crate::Error> { let status = unsafe { $ffi_set_user_data(self.to_raw_none(), &key.ffi, std::ptr::null_mut(), None) }; crate::utils::status_to_result(status) } }; } cairo-rs-0.14.9/src/utils.rs000064400000000000000000000030750072674642500137700ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use crate::error::Error; use std::ffi::CStr; use std::fmt; #[doc(alias = "cairo_debug_reset_static_data")] pub unsafe fn debug_reset_static_data() { ffi::cairo_debug_reset_static_data() } pub fn status_to_result(status: ffi::cairo_status_t) -> Result<(), Error> { match status { ffi::STATUS_SUCCESS => Ok(()), err => Err(err.into()), } } #[doc(alias = "cairo_version_string")] #[doc(alias = "get_version_string")] pub fn version_string() -> &'static str { unsafe { let ptr = ffi::cairo_version_string(); CStr::from_ptr(ptr) .to_str() .expect("invalid version string") } } #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] pub struct Version { pub major: u8, pub minor: u8, pub micro: u8, } impl Version { #[allow(clippy::self_named_constructors)] #[doc(alias = "cairo_version")] #[doc(alias = "get_version")] pub fn version() -> Version { let version = unsafe { ffi::cairo_version() }; Version { major: (version / 10_000 % 100) as _, minor: (version / 100 % 100) as _, micro: (version % 100) as _, } } } impl fmt::Display for Version { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}.{}.{}", self.major, self.minor, self.micro) } } #[cfg(test)] mod tests { use super::*; #[test] fn check_versions() { assert_eq!(version_string(), Version::version().to_string()); } } cairo-rs-0.14.9/src/win32_surface.rs000064400000000000000000000036520072674642500153030ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. pub use ffi::winapi; use std::convert::TryFrom; use std::fmt; use std::ops::Deref; use crate::enums::{Format, SurfaceType}; use crate::error::Error; use crate::surface::Surface; #[cfg(feature = "use_glib")] use glib::translate::*; declare_surface!(Win32Surface, SurfaceType::Win32); impl Win32Surface { #[doc(alias = "cairo_win32_surface_create")] pub fn create(hdc: winapi::HDC) -> Result { unsafe { Self::from_raw_full(ffi::cairo_win32_surface_create(hdc)) } } #[doc(alias = "cairo_win32_surface_create_with_format")] pub fn create_with_format(hdc: winapi::HDC, format: Format) -> Result { unsafe { Self::from_raw_full(ffi::cairo_win32_surface_create_with_format( hdc, format.into(), )) } } #[doc(alias = "cairo_win32_surface_create_with_dib")] pub fn create_with_dib(format: Format, width: i32, height: i32) -> Result { unsafe { Self::from_raw_full(ffi::cairo_win32_surface_create_with_dib( format.into(), width, height, )) } } #[doc(alias = "cairo_win32_surface_create_with_ddb")] pub fn create_with_ddb( hdc: winapi::HDC, format: Format, width: i32, height: i32, ) -> Result { unsafe { Self::from_raw_full(ffi::cairo_win32_surface_create_with_ddb( hdc, format.into(), width, height, )) } } #[doc(alias = "cairo_win32_printing_surface_create")] pub fn printing_surface_create(hdc: winapi::HDC) -> Result { unsafe { Self::from_raw_full(ffi::cairo_win32_printing_surface_create(hdc)) } } } cairo-rs-0.14.9/src/xcb.rs000064400000000000000000000305600072674642500134030ustar 00000000000000// Take a look at the license at the top of the repository in the LICENSE file. use crate::enums::SurfaceType; #[cfg(feature = "use_glib")] use glib::translate::*; use std::convert::TryFrom; use std::fmt; use std::ops::Deref; use std::ptr; use crate::error::Error; use crate::surface::Surface; #[derive(Debug)] pub struct XCBDrawable(pub u32); impl XCBDrawable { fn to_raw_none(&self) -> u32 { self.0 } } impl fmt::Display for XCBDrawable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "XCBDrawable") } } #[derive(Debug)] pub struct XCBPixmap(pub u32); impl XCBPixmap { fn to_raw_none(&self) -> u32 { self.0 } } impl fmt::Display for XCBPixmap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "XCBPixmap") } } #[derive(Debug)] #[doc(alias = "xcb_connection_t")] pub struct XCBConnection(pub ptr::NonNull); impl XCBConnection { pub fn to_raw_none(&self) -> *mut ffi::xcb_connection_t { self.0.as_ptr() } pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_connection_t) -> XCBConnection { assert!(!ptr.is_null()); XCBConnection(ptr::NonNull::new_unchecked(ptr)) } pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_connection_t) -> Borrowed { assert!(!ptr.is_null()); Borrowed::new(XCBConnection(ptr::NonNull::new_unchecked(ptr))) } pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_connection_t) -> XCBConnection { assert!(!ptr.is_null()); XCBConnection(ptr::NonNull::new_unchecked(ptr)) } } #[cfg(feature = "use_glib")] impl<'a> ToGlibPtr<'a, *mut ffi::xcb_connection_t> for &'a XCBConnection { type Storage = &'a XCBConnection; #[inline] fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_connection_t, &'a XCBConnection> { Stash(self.to_raw_none(), *self) } } #[cfg(feature = "use_glib")] impl FromGlibPtrNone<*mut ffi::xcb_connection_t> for XCBConnection { #[inline] unsafe fn from_glib_none(ptr: *mut ffi::xcb_connection_t) -> XCBConnection { Self::from_raw_none(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrBorrow<*mut ffi::xcb_connection_t> for XCBConnection { #[inline] unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_connection_t) -> Borrowed { Self::from_raw_borrow(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrFull<*mut ffi::xcb_connection_t> for XCBConnection { #[inline] unsafe fn from_glib_full(ptr: *mut ffi::xcb_connection_t) -> XCBConnection { Self::from_raw_full(ptr) } } impl Clone for XCBConnection { fn clone(&self) -> XCBConnection { unsafe { Self::from_raw_none(self.to_raw_none()) } } } impl fmt::Display for XCBConnection { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "XCBConnection") } } #[derive(Debug)] #[doc(alias = "xcb_render_pictforminfo_t")] pub struct XCBRenderPictFormInfo(pub ptr::NonNull); impl XCBRenderPictFormInfo { pub fn to_raw_none(&self) -> *mut ffi::xcb_render_pictforminfo_t { self.0.as_ptr() } pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo { assert!(!ptr.is_null()); XCBRenderPictFormInfo(ptr::NonNull::new_unchecked(ptr)) } pub unsafe fn from_raw_borrow( ptr: *mut ffi::xcb_render_pictforminfo_t, ) -> Borrowed { assert!(!ptr.is_null()); Borrowed::new(XCBRenderPictFormInfo(ptr::NonNull::new_unchecked(ptr))) } pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo { assert!(!ptr.is_null()); XCBRenderPictFormInfo(ptr::NonNull::new_unchecked(ptr)) } } #[cfg(feature = "use_glib")] impl<'a> ToGlibPtr<'a, *mut ffi::xcb_render_pictforminfo_t> for &'a XCBRenderPictFormInfo { type Storage = &'a XCBRenderPictFormInfo; #[inline] fn to_glib_none( &self, ) -> Stash<'a, *mut ffi::xcb_render_pictforminfo_t, &'a XCBRenderPictFormInfo> { Stash(self.to_raw_none(), *self) } } #[cfg(feature = "use_glib")] impl FromGlibPtrNone<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo { #[inline] unsafe fn from_glib_none(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo { Self::from_raw_none(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrBorrow<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo { #[inline] unsafe fn from_glib_borrow( ptr: *mut ffi::xcb_render_pictforminfo_t, ) -> Borrowed { Self::from_raw_borrow(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrFull<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo { #[inline] unsafe fn from_glib_full(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo { Self::from_raw_full(ptr) } } impl Clone for XCBRenderPictFormInfo { fn clone(&self) -> XCBRenderPictFormInfo { unsafe { Self::from_raw_none(self.to_raw_none()) } } } impl fmt::Display for XCBRenderPictFormInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "XCBRenderPictFormInfo") } } #[derive(Debug)] #[doc(alias = "xcb_screen_t")] pub struct XCBScreen(pub ptr::NonNull); impl XCBScreen { pub fn to_raw_none(&self) -> *mut ffi::xcb_screen_t { self.0.as_ptr() } pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_screen_t) -> XCBScreen { assert!(!ptr.is_null()); XCBScreen(ptr::NonNull::new_unchecked(ptr)) } pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_screen_t) -> Borrowed { assert!(!ptr.is_null()); Borrowed::new(XCBScreen(ptr::NonNull::new_unchecked(ptr))) } pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_screen_t) -> XCBScreen { assert!(!ptr.is_null()); XCBScreen(ptr::NonNull::new_unchecked(ptr)) } } #[cfg(feature = "use_glib")] impl<'a> ToGlibPtr<'a, *mut ffi::xcb_screen_t> for &'a XCBScreen { type Storage = &'a XCBScreen; #[inline] fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_screen_t, &'a XCBScreen> { Stash(self.to_raw_none(), *self) } } #[cfg(feature = "use_glib")] impl FromGlibPtrNone<*mut ffi::xcb_screen_t> for XCBScreen { #[inline] unsafe fn from_glib_none(ptr: *mut ffi::xcb_screen_t) -> XCBScreen { Self::from_raw_none(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrBorrow<*mut ffi::xcb_screen_t> for XCBScreen { #[inline] unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_screen_t) -> Borrowed { Self::from_raw_borrow(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrFull<*mut ffi::xcb_screen_t> for XCBScreen { #[inline] unsafe fn from_glib_full(ptr: *mut ffi::xcb_screen_t) -> XCBScreen { Self::from_raw_full(ptr) } } impl Clone for XCBScreen { fn clone(&self) -> XCBScreen { unsafe { Self::from_raw_none(self.to_raw_none()) } } } impl fmt::Display for XCBScreen { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "XCBScreen") } } declare_surface!(XCBSurface, SurfaceType::Xcb); impl XCBSurface { #[doc(alias = "cairo_xcb_surface_create")] pub fn create( connection: &XCBConnection, drawable: &XCBDrawable, visual: &XCBVisualType, width: i32, height: i32, ) -> Result { unsafe { Self::from_raw_full(ffi::cairo_xcb_surface_create( connection.to_raw_none(), drawable.to_raw_none(), visual.to_raw_none(), width, height, )) } } #[doc(alias = "cairo_xcb_surface_create_for_bitmap")] pub fn create_for_bitmap( connection: &XCBConnection, screen: &XCBScreen, bitmap: &XCBPixmap, width: i32, height: i32, ) -> Result { unsafe { Ok(Self(Surface::from_raw_full( ffi::cairo_xcb_surface_create_for_bitmap( connection.to_raw_none(), screen.to_raw_none(), bitmap.to_raw_none(), width, height, ), )?)) } } #[doc(alias = "cairo_xcb_surface_create_with_xrender_format")] pub fn create_with_xrender_format( connection: &XCBConnection, screen: &XCBScreen, bitmap: &XCBPixmap, format: &XCBRenderPictFormInfo, width: i32, height: i32, ) -> Result { unsafe { Ok(Self(Surface::from_raw_full( ffi::cairo_xcb_surface_create_with_xrender_format( connection.to_raw_none(), screen.to_raw_none(), bitmap.to_raw_none(), format.to_raw_none(), width, height, ), )?)) } } #[doc(alias = "cairo_xcb_surface_set_size")] pub fn set_size(&self, width: i32, height: i32) -> Result<(), Error> { unsafe { ffi::cairo_xcb_surface_set_size(self.to_raw_none(), width, height) } self.status() } #[doc(alias = "cairo_xcb_surface_set_drawable")] pub fn set_drawable( &self, drawable: &XCBDrawable, width: i32, height: i32, ) -> Result<(), Error> { unsafe { ffi::cairo_xcb_surface_set_drawable( self.to_raw_none(), drawable.to_raw_none(), width, height, ) } self.status() } } #[derive(Debug)] #[doc(alias = "xcb_visualtype_t")] pub struct XCBVisualType(pub ptr::NonNull); impl XCBVisualType { pub fn to_raw_none(&self) -> *mut ffi::xcb_visualtype_t { self.0.as_ptr() } pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType { assert!(!ptr.is_null()); XCBVisualType(ptr::NonNull::new_unchecked(ptr)) } pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_visualtype_t) -> Borrowed { assert!(!ptr.is_null()); Borrowed::new(XCBVisualType(ptr::NonNull::new_unchecked(ptr))) } pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType { assert!(!ptr.is_null()); XCBVisualType(ptr::NonNull::new_unchecked(ptr)) } } #[cfg(feature = "use_glib")] impl<'a> ToGlibPtr<'a, *mut ffi::xcb_visualtype_t> for &'a XCBVisualType { type Storage = &'a XCBVisualType; #[inline] fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_visualtype_t, &'a XCBVisualType> { Stash(self.to_raw_none(), *self) } } #[cfg(feature = "use_glib")] impl FromGlibPtrNone<*mut ffi::xcb_visualtype_t> for XCBVisualType { #[inline] unsafe fn from_glib_none(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType { Self::from_raw_none(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrBorrow<*mut ffi::xcb_visualtype_t> for XCBVisualType { #[inline] unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_visualtype_t) -> Borrowed { Self::from_raw_borrow(ptr) } } #[cfg(feature = "use_glib")] impl FromGlibPtrFull<*mut ffi::xcb_visualtype_t> for XCBVisualType { #[inline] unsafe fn from_glib_full(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType { Self::from_raw_full(ptr) } } impl Clone for XCBVisualType { fn clone(&self) -> XCBVisualType { unsafe { Self::from_raw_none(self.to_raw_none()) } } } impl fmt::Display for XCBVisualType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "XCBVisualType") } } impl crate::device::Device { #[doc(alias = "cairo_xcb_device_get_connection")] #[doc(alias = "get_connection")] pub fn connection(&self) -> XCBConnection { unsafe { XCBConnection::from_raw_full(ffi::cairo_xcb_device_get_connection(self.to_raw_none())) } } #[doc(alias = "cairo_xcb_device_debug_cap_xshm_version")] pub fn debug_cap_xshm_version(&self, major_version: i32, minor_version: i32) { unsafe { ffi::cairo_xcb_device_debug_cap_xshm_version( self.to_raw_none(), major_version, minor_version, ) } } }