1 // Take a look at the license at the top of the repository in the LICENSE file. 2 3 #[cfg(feature = "use_glib")] 4 use glib::translate::*; 5 use std::ffi::CString; 6 use std::ptr; 7 8 use crate::ffi::{FontExtents, Glyph, TextCluster, TextExtents}; 9 use crate::matrices::Matrix; 10 use crate::utils::status_to_result; 11 use crate::{enums::FontType, Error}; 12 13 use super::{FontFace, FontOptions}; 14 15 #[cfg(feature = "use_glib")] 16 glib::wrapper! { 17 #[derive(Debug)] 18 #[doc(alias = "cairo_scaled_font_t")] 19 pub struct ScaledFont(Shared<ffi::cairo_scaled_font_t>); 20 21 match fn { 22 ref => |ptr| ffi::cairo_scaled_font_reference(ptr), 23 unref => |ptr| ffi::cairo_scaled_font_destroy(ptr), 24 type_ => || ffi::gobject::cairo_gobject_scaled_font_get_type(), 25 } 26 } 27 28 #[cfg(not(feature = "use_glib"))] 29 #[derive(Debug)] 30 #[doc(alias = "cairo_scaled_font_t")] 31 pub struct ScaledFont(ptr::NonNull<ffi::cairo_scaled_font_t>); 32 33 impl ScaledFont { 34 #[doc(alias = "cairo_scaled_font_create")] new( font_face: &FontFace, font_matrix: &Matrix, ctm: &Matrix, options: &FontOptions, ) -> Result<ScaledFont, Error>35 pub fn new( 36 font_face: &FontFace, 37 font_matrix: &Matrix, 38 ctm: &Matrix, 39 options: &FontOptions, 40 ) -> Result<ScaledFont, Error> { 41 let scaled_font: ScaledFont = unsafe { 42 ScaledFont::from_raw_full(ffi::cairo_scaled_font_create( 43 font_face.to_raw_none(), 44 font_matrix.ptr(), 45 ctm.ptr(), 46 options.to_raw_none(), 47 )) 48 }; 49 let status = unsafe { ffi::cairo_scaled_font_status(scaled_font.to_raw_none()) }; 50 status_to_result(status)?; 51 52 Ok(scaled_font) 53 } 54 55 #[cfg(feature = "use_glib")] to_raw_none(&self) -> *mut ffi::cairo_scaled_font_t56 pub fn to_raw_none(&self) -> *mut ffi::cairo_scaled_font_t { 57 self.to_glib_none().0 58 } 59 60 #[cfg(not(feature = "use_glib"))] to_raw_none(&self) -> *mut ffi::cairo_scaled_font_t61 pub fn to_raw_none(&self) -> *mut ffi::cairo_scaled_font_t { 62 self.0.as_ptr() 63 } 64 65 #[cfg(not(feature = "use_glib"))] from_raw_full(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont66 pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont { 67 assert!(!ptr.is_null()); 68 ScaledFont(ptr::NonNull::new_unchecked(ptr)) 69 } 70 71 #[cfg(feature = "use_glib")] from_raw_full(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont72 pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont { 73 from_glib_full(ptr) 74 } 75 76 #[cfg(feature = "use_glib")] from_raw_none(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont77 pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont { 78 from_glib_none(ptr) 79 } 80 81 #[cfg(not(feature = "use_glib"))] from_raw_none(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont82 pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont { 83 assert!(!ptr.is_null()); 84 ffi::cairo_scaled_font_reference(ptr); 85 ScaledFont(ptr::NonNull::new_unchecked(ptr)) 86 } 87 88 #[doc(alias = "cairo_scaled_font_get_type")] 89 #[doc(alias = "get_type")] type_(&self) -> FontType90 pub fn type_(&self) -> FontType { 91 unsafe { FontType::from(ffi::cairo_scaled_font_get_type(self.to_raw_none())) } 92 } 93 94 #[doc(alias = "cairo_scaled_font_get_reference_count")] 95 #[doc(alias = "get_reference_count")] reference_count(&self) -> usize96 pub fn reference_count(&self) -> usize { 97 unsafe { ffi::cairo_scaled_font_get_reference_count(self.to_raw_none()) as usize } 98 } 99 100 #[doc(alias = "cairo_scaled_font_extents")] extents(&self) -> FontExtents101 pub fn extents(&self) -> FontExtents { 102 let mut extents = FontExtents { 103 ascent: 0.0, 104 descent: 0.0, 105 height: 0.0, 106 max_x_advance: 0.0, 107 max_y_advance: 0.0, 108 }; 109 110 unsafe { ffi::cairo_scaled_font_extents(self.to_raw_none(), &mut extents) } 111 112 extents 113 } 114 115 #[doc(alias = "cairo_scaled_font_text_extents")] text_extents(&self, text: &str) -> TextExtents116 pub fn text_extents(&self, text: &str) -> TextExtents { 117 let mut extents = TextExtents { 118 x_bearing: 0.0, 119 y_bearing: 0.0, 120 width: 0.0, 121 height: 0.0, 122 x_advance: 0.0, 123 y_advance: 0.0, 124 }; 125 126 let text = CString::new(text).unwrap(); 127 unsafe { 128 ffi::cairo_scaled_font_text_extents(self.to_raw_none(), text.as_ptr(), &mut extents) 129 } 130 131 extents 132 } 133 134 #[doc(alias = "cairo_scaled_font_glyph_extents")] glyph_extents(&self, glyphs: &[Glyph]) -> TextExtents135 pub fn glyph_extents(&self, glyphs: &[Glyph]) -> TextExtents { 136 let mut extents = TextExtents { 137 x_bearing: 0.0, 138 y_bearing: 0.0, 139 width: 0.0, 140 height: 0.0, 141 x_advance: 0.0, 142 y_advance: 0.0, 143 }; 144 145 unsafe { 146 ffi::cairo_scaled_font_glyph_extents( 147 self.to_raw_none(), 148 glyphs.as_ptr(), 149 glyphs.len() as i32, 150 &mut extents, 151 ) 152 } 153 154 extents 155 } 156 157 #[doc(alias = "cairo_scaled_font_text_to_glyphs")] text_to_glyphs( &self, x: f64, y: f64, text: &str, ) -> Result<(Vec<Glyph>, Vec<TextCluster>), Error>158 pub fn text_to_glyphs( 159 &self, 160 x: f64, 161 y: f64, 162 text: &str, 163 ) -> Result<(Vec<Glyph>, Vec<TextCluster>), Error> { 164 // This large unsafe block is due to the FFI function returning two specially allocated 165 // (cairo_{glyph,text_cluster}_allocate) pointers that need to be copied into Vec<T> 166 // types before they're of any use to Rust code. 167 168 unsafe { 169 let mut glyphs_ptr: *mut Glyph = ptr::null_mut(); 170 let mut glyph_count = 0i32; 171 let mut clusters_ptr: *mut TextCluster = ptr::null_mut(); 172 let mut cluster_count = 0i32; 173 let mut cluster_flags = 0i32; 174 let text_length = text.len() as i32; 175 let text = CString::new(text).unwrap(); 176 177 let status = ffi::cairo_scaled_font_text_to_glyphs( 178 self.to_raw_none(), 179 x, 180 y, 181 text.as_ptr(), 182 text_length, 183 &mut glyphs_ptr, 184 &mut glyph_count, 185 &mut clusters_ptr, 186 &mut cluster_count, 187 &mut cluster_flags, 188 ); 189 status_to_result(status)?; 190 191 let glyph_count = glyph_count as usize; 192 let glyphs: Vec<Glyph> = { 193 let mut glyphs: Vec<Glyph> = Vec::with_capacity(glyph_count); 194 195 glyphs.set_len(glyph_count); 196 ptr::copy(glyphs_ptr, glyphs.as_mut_ptr(), glyph_count); 197 198 glyphs 199 }; 200 201 let cluster_count = cluster_count as usize; 202 let clusters: Vec<TextCluster> = { 203 let mut clusters = Vec::with_capacity(cluster_count); 204 205 clusters.set_len(cluster_count); 206 ptr::copy(clusters_ptr, clusters.as_mut_ptr(), cluster_count); 207 208 clusters 209 }; 210 211 ffi::cairo_glyph_free(glyphs_ptr); 212 ffi::cairo_text_cluster_free(clusters_ptr); 213 214 Ok((glyphs, clusters)) 215 } 216 } 217 218 #[doc(alias = "cairo_scaled_font_get_font_face")] 219 #[doc(alias = "get_font_face")] font_face(&self) -> FontFace220 pub fn font_face(&self) -> FontFace { 221 unsafe { FontFace::from_raw_none(ffi::cairo_scaled_font_get_font_face(self.to_raw_none())) } 222 } 223 224 #[doc(alias = "cairo_scaled_font_get_font_options")] 225 #[doc(alias = "get_font_options")] font_options(&self) -> Result<FontOptions, Error>226 pub fn font_options(&self) -> Result<FontOptions, Error> { 227 let options = FontOptions::new()?; 228 229 unsafe { 230 ffi::cairo_scaled_font_get_font_options(self.to_raw_none(), options.to_raw_none()) 231 } 232 233 Ok(options) 234 } 235 236 #[doc(alias = "cairo_scaled_font_get_font_matrix")] 237 #[doc(alias = "get_font_matrix")] font_matrix(&self) -> Matrix238 pub fn font_matrix(&self) -> Matrix { 239 let mut matrix = Matrix::null(); 240 241 unsafe { ffi::cairo_scaled_font_get_font_matrix(self.to_raw_none(), matrix.mut_ptr()) } 242 243 matrix 244 } 245 246 #[doc(alias = "cairo_scaled_font_get_ctm")] 247 #[doc(alias = "get_ctm")] ctm(&self) -> Matrix248 pub fn ctm(&self) -> Matrix { 249 let mut matrix = Matrix::null(); 250 251 unsafe { ffi::cairo_scaled_font_get_ctm(self.to_raw_none(), matrix.mut_ptr()) } 252 253 matrix 254 } 255 256 #[doc(alias = "cairo_scaled_font_get_scale_matrix")] 257 #[doc(alias = "get_scale_matrix")] scale_matrix(&self) -> Matrix258 pub fn scale_matrix(&self) -> Matrix { 259 let mut matrix = Matrix::null(); 260 261 unsafe { ffi::cairo_scaled_font_get_scale_matrix(self.to_raw_none(), matrix.mut_ptr()) } 262 263 matrix 264 } 265 266 #[doc(alias = "cairo_scaled_font_status")] status(&self) -> Result<(), Error>267 pub fn status(&self) -> Result<(), Error> { 268 let status = unsafe { ffi::cairo_scaled_font_status(self.to_raw_none()) }; 269 status_to_result(status) 270 } 271 272 user_data_methods! { 273 ffi::cairo_scaled_font_get_user_data, 274 ffi::cairo_scaled_font_set_user_data, 275 } 276 } 277 278 #[cfg(not(feature = "use_glib"))] 279 impl Drop for ScaledFont { drop(&mut self)280 fn drop(&mut self) { 281 unsafe { 282 ffi::cairo_scaled_font_destroy(self.to_raw_none()); 283 } 284 } 285 } 286 287 #[cfg(not(feature = "use_glib"))] 288 impl Clone for ScaledFont { clone(&self) -> ScaledFont289 fn clone(&self) -> ScaledFont { 290 unsafe { ScaledFont::from_raw_none(self.to_raw_none()) } 291 } 292 } 293