cairo/font/
scaled_font.rs1use ffi;
2#[cfg(feature = "use_glib")]
3use glib::translate::*;
4use std::ffi::CString;
5use std::ptr;
6
7use enums::{FontType, Status};
8use ffi::{FontExtents, Glyph, TextCluster, TextExtents};
9use matrices::Matrix;
10
11use super::{FontFace, FontOptions};
12
13#[cfg(feature = "use_glib")]
14glib_wrapper! {
15 #[derive(Debug)]
16 pub struct ScaledFont(Shared<ffi::cairo_scaled_font_t>);
17
18 match fn {
19 ref => |ptr| ffi::cairo_scaled_font_reference(ptr),
20 unref => |ptr| ffi::cairo_scaled_font_destroy(ptr),
21 get_type => || ffi::gobject::cairo_gobject_scaled_font_get_type(),
22 }
23}
24
25#[cfg(not(feature = "use_glib"))]
26#[derive(Debug)]
27pub struct ScaledFont(*mut ffi::cairo_scaled_font_t);
28
29impl ScaledFont {
30 pub fn new(
31 font_face: &FontFace,
32 font_matrix: &Matrix,
33 ctm: &Matrix,
34 options: &FontOptions,
35 ) -> ScaledFont {
36 let scaled_font: ScaledFont = unsafe {
37 ScaledFont::from_raw_full(ffi::cairo_scaled_font_create(
38 font_face.to_raw_none(),
39 font_matrix.ptr(),
40 ctm.ptr(),
41 options.to_raw_none(),
42 ))
43 };
44 scaled_font.ensure_status();
45 scaled_font
46 }
47
48 #[cfg(feature = "use_glib")]
49 pub fn to_raw_none(&self) -> *mut ffi::cairo_scaled_font_t {
50 self.to_glib_none().0
51 }
52
53 #[cfg(not(feature = "use_glib"))]
54 pub fn to_raw_none(&self) -> *mut ffi::cairo_scaled_font_t {
55 self.0
56 }
57
58 #[cfg(not(feature = "use_glib"))]
59 pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont {
60 assert!(!ptr.is_null());
61 ScaledFont(ptr)
62 }
63
64 #[cfg(feature = "use_glib")]
65 pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont {
66 from_glib_full(ptr)
67 }
68
69 #[cfg(feature = "use_glib")]
70 pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont {
71 from_glib_none(ptr)
72 }
73
74 #[cfg(not(feature = "use_glib"))]
75 pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_scaled_font_t) -> ScaledFont {
76 assert!(!ptr.is_null());
77 ffi::cairo_scaled_font_reference(ptr);
78 ScaledFont(ptr)
79 }
80
81 pub fn ensure_status(&self) {
82 let status = unsafe { ffi::cairo_scaled_font_status(self.to_raw_none()) };
83 Status::from(status).ensure_valid()
84 }
85
86 pub fn get_type(&self) -> FontType {
87 unsafe { FontType::from(ffi::cairo_scaled_font_get_type(self.to_raw_none())) }
88 }
89
90 pub fn get_reference_count(&self) -> usize {
91 unsafe { ffi::cairo_scaled_font_get_reference_count(self.to_raw_none()) as usize }
92 }
93
94 pub fn extents(&self) -> FontExtents {
95 let mut extents = FontExtents {
96 ascent: 0.0,
97 descent: 0.0,
98 height: 0.0,
99 max_x_advance: 0.0,
100 max_y_advance: 0.0,
101 };
102
103 unsafe { ffi::cairo_scaled_font_extents(self.to_raw_none(), &mut extents) }
104
105 extents
106 }
107
108 pub fn text_extents(&self, text: &str) -> TextExtents {
109 let mut extents = TextExtents {
110 x_bearing: 0.0,
111 y_bearing: 0.0,
112 width: 0.0,
113 height: 0.0,
114 x_advance: 0.0,
115 y_advance: 0.0,
116 };
117
118 let text = CString::new(text).unwrap();
119 unsafe {
120 ffi::cairo_scaled_font_text_extents(self.to_raw_none(), text.as_ptr(), &mut extents)
121 }
122
123 extents
124 }
125
126 pub fn glyph_extents(&self, glyphs: &[Glyph]) -> TextExtents {
127 let mut extents = TextExtents {
128 x_bearing: 0.0,
129 y_bearing: 0.0,
130 width: 0.0,
131 height: 0.0,
132 x_advance: 0.0,
133 y_advance: 0.0,
134 };
135
136 unsafe {
137 ffi::cairo_scaled_font_glyph_extents(
138 self.to_raw_none(),
139 glyphs.as_ptr(),
140 glyphs.len() as i32,
141 &mut extents,
142 )
143 }
144
145 extents
146 }
147
148 pub fn text_to_glyphs(&self, x: f64, y: f64, text: &str) -> (Vec<Glyph>, Vec<TextCluster>) {
149 unsafe {
154 let mut glyphs_ptr: *mut Glyph = ptr::null_mut();
155 let mut glyph_count = 0i32;
156 let mut clusters_ptr: *mut TextCluster = ptr::null_mut();
157 let mut cluster_count = 0i32;
158 let mut cluster_flags = 0i32;
159 let text_length = text.len() as i32;
160 let text = CString::new(text).unwrap();
161
162 let status = ffi::cairo_scaled_font_text_to_glyphs(
163 self.to_raw_none(),
164 x,
165 y,
166 text.as_ptr(),
167 text_length,
168 &mut glyphs_ptr,
169 &mut glyph_count,
170 &mut clusters_ptr,
171 &mut cluster_count,
172 &mut cluster_flags,
173 );
174
175 Status::from(status).ensure_valid();
176
177 let glyph_count = glyph_count as usize;
178 let glyphs: Vec<Glyph> = {
179 let mut glyphs: Vec<Glyph> = Vec::with_capacity(glyph_count);
180
181 glyphs.set_len(glyph_count);
182 ptr::copy(glyphs_ptr, glyphs.as_mut_ptr(), glyph_count);
183
184 glyphs
185 };
186
187 let cluster_count = cluster_count as usize;
188 let clusters: Vec<TextCluster> = {
189 let mut clusters = Vec::with_capacity(cluster_count);
190
191 clusters.set_len(cluster_count);
192 ptr::copy(clusters_ptr, clusters.as_mut_ptr(), cluster_count);
193
194 clusters
195 };
196
197 ffi::cairo_glyph_free(glyphs_ptr);
198 ffi::cairo_text_cluster_free(clusters_ptr);
199
200 (glyphs, clusters)
201 }
202 }
203
204 pub fn get_font_face(&self) -> FontFace {
205 unsafe { FontFace::from_raw_none(ffi::cairo_scaled_font_get_font_face(self.to_raw_none())) }
206 }
207
208 pub fn get_font_options(&self) -> FontOptions {
209 let options = FontOptions::new();
210
211 unsafe {
212 ffi::cairo_scaled_font_get_font_options(self.to_raw_none(), options.to_raw_none())
213 }
214
215 options
216 }
217
218 pub fn get_font_matrix(&self) -> Matrix {
219 let mut matrix = Matrix::null();
220
221 unsafe { ffi::cairo_scaled_font_get_font_matrix(self.to_raw_none(), matrix.mut_ptr()) }
222
223 matrix
224 }
225
226 pub fn get_ctm(&self) -> Matrix {
227 let mut matrix = Matrix::null();
228
229 unsafe { ffi::cairo_scaled_font_get_ctm(self.to_raw_none(), matrix.mut_ptr()) }
230
231 matrix
232 }
233
234 pub fn get_scale_matrix(&self) -> Matrix {
235 let mut matrix = Matrix::null();
236
237 unsafe { ffi::cairo_scaled_font_get_scale_matrix(self.to_raw_none(), matrix.mut_ptr()) }
238
239 matrix
240 }
241
242 user_data_methods! {
243 ffi::cairo_scaled_font_get_user_data,
244 ffi::cairo_scaled_font_set_user_data,
245 }
246}
247
248#[cfg(not(feature = "use_glib"))]
249impl Drop for ScaledFont {
250 fn drop(&mut self) {
251 unsafe {
252 ffi::cairo_scaled_font_destroy(self.to_raw_none());
253 }
254 }
255}
256
257#[cfg(not(feature = "use_glib"))]
258impl Clone for ScaledFont {
259 fn clone(&self) -> ScaledFont {
260 unsafe { ScaledFont::from_raw_none(self.to_raw_none()) }
261 }
262}