1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use std::slice;
6 use std::ptr;
7 use std::cell::UnsafeCell;
8 use std::mem::{self, zeroed};
9 
10 use com_helpers::Com;
11 use comptr::ComPtr;
12 use font::Font;
13 use geometry_sink_impl::GeometrySinkImpl;
14 use outline_builder::OutlineBuilder;
15 use super::{FontMetrics, FontFile, DefaultDWriteRenderParams, DWriteFactory};
16 
17 use winapi::Interface;
18 use winapi::ctypes::c_void;
19 use winapi::shared::minwindef::{BOOL, FALSE, TRUE};
20 use winapi::shared::winerror::S_OK;
21 use winapi::um::dcommon::DWRITE_MEASURING_MODE;
22 use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_BITMAP, DWRITE_FONT_FACE_TYPE_CFF};
23 use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_RAW_CFF, DWRITE_FONT_FACE_TYPE_TYPE1};
24 use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_TRUETYPE};
25 use winapi::um::dwrite::{DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION, DWRITE_FONT_FACE_TYPE_VECTOR};
26 use winapi::um::dwrite::{DWRITE_FONT_METRICS, DWRITE_FONT_SIMULATIONS, DWRITE_GLYPH_METRICS};
27 use winapi::um::dwrite::{DWRITE_GLYPH_OFFSET, DWRITE_MATRIX, DWRITE_RENDERING_MODE};
28 use winapi::um::dwrite::{DWRITE_RENDERING_MODE_DEFAULT, DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC};
29 use winapi::um::dwrite::{IDWriteFontCollection, IDWriteFont, IDWriteFontFace, IDWriteFontFile};
30 use winapi::um::dwrite::{IDWriteRenderingParams};
31 use winapi::um::dwrite_3::{IDWriteFontFace5, IDWriteFontResource, DWRITE_FONT_AXIS_VALUE};
32 
33 pub struct FontFace {
34     native: UnsafeCell<ComPtr<IDWriteFontFace>>,
35     face5: UnsafeCell<Option<ComPtr<IDWriteFontFace5>>>,
36     metrics: FontMetrics,
37 }
38 
39 impl FontFace {
take(native: ComPtr<IDWriteFontFace>) -> FontFace40     pub fn take(native: ComPtr<IDWriteFontFace>) -> FontFace {
41         unsafe {
42             let mut metrics: FontMetrics = zeroed();
43             let cell = UnsafeCell::new(native);
44             (*cell.get()).GetMetrics(&mut metrics);
45             FontFace {
46                 native: cell,
47                 face5: UnsafeCell::new(None),
48                 metrics: metrics,
49             }
50         }
51     }
52 
as_ptr(&self) -> *mut IDWriteFontFace53     pub unsafe fn as_ptr(&self) -> *mut IDWriteFontFace {
54         (*self.native.get()).as_ptr()
55     }
56 
get_raw_files(&self) -> Vec<*mut IDWriteFontFile>57     unsafe fn get_raw_files(&self) -> Vec<*mut IDWriteFontFile> {
58         let mut number_of_files: u32 = 0;
59         let hr = (*self.native.get()).GetFiles(&mut number_of_files, ptr::null_mut());
60         assert!(hr == 0);
61 
62         let mut file_ptrs: Vec<*mut IDWriteFontFile> =
63             vec![ptr::null_mut(); number_of_files as usize];
64         let hr = (*self.native.get()).GetFiles(&mut number_of_files, file_ptrs.as_mut_ptr());
65         assert!(hr == 0);
66         file_ptrs
67     }
68 
get_files(&self) -> Vec<FontFile>69     pub fn get_files(&self) -> Vec<FontFile> {
70         unsafe {
71             let file_ptrs = self.get_raw_files();
72             file_ptrs.iter().map(|p| FontFile::take(ComPtr::from_ptr(*p))).collect()
73         }
74     }
75 
create_font_face_with_simulations(&self, simulations: DWRITE_FONT_SIMULATIONS) -> FontFace76     pub fn create_font_face_with_simulations(&self, simulations: DWRITE_FONT_SIMULATIONS) -> FontFace {
77         unsafe {
78             let file_ptrs = self.get_raw_files();
79             let face_type = (*self.native.get()).GetType();
80             let face_index = (*self.native.get()).GetIndex();
81             let mut face: ComPtr<IDWriteFontFace> = ComPtr::new();
82             let hr = (*DWriteFactory()).CreateFontFace(
83                 face_type,
84                 file_ptrs.len() as u32,
85                 file_ptrs.as_ptr(),
86                 face_index,
87                 simulations,
88                 face.getter_addrefs()
89             );
90             for p in file_ptrs {
91                 let _ = ComPtr::<IDWriteFontFile>::already_addrefed(p);
92             }
93             assert!(hr == 0);
94             FontFace::take(face)
95         }
96     }
97 
get_glyph_count(&self) -> u1698     pub fn get_glyph_count(&self) -> u16 {
99         unsafe {
100             (*self.native.get()).GetGlyphCount()
101         }
102     }
103 
metrics(&self) -> &FontMetrics104     pub fn metrics(&self) -> &FontMetrics {
105         &self.metrics
106     }
107 
get_metrics(&self) -> FontMetrics108     pub fn get_metrics(&self) -> FontMetrics {
109         unsafe {
110             let mut metrics: DWRITE_FONT_METRICS = zeroed();
111             (*self.native.get()).GetMetrics(&mut metrics);
112             metrics
113         }
114     }
115 
get_glyph_indices(&self, code_points: &[u32]) -> Vec<u16>116     pub fn get_glyph_indices(&self, code_points: &[u32]) -> Vec<u16> {
117         unsafe {
118             let mut glyph_indices: Vec<u16> = vec![0; code_points.len()];
119             let hr = (*self.native.get()).GetGlyphIndices(code_points.as_ptr(),
120                                                           code_points.len() as u32,
121                                                           glyph_indices.as_mut_ptr());
122             assert!(hr == 0);
123             glyph_indices
124         }
125     }
126 
get_design_glyph_metrics(&self, glyph_indices: &[u16], is_sideways: bool) -> Vec<DWRITE_GLYPH_METRICS>127     pub fn get_design_glyph_metrics(&self, glyph_indices: &[u16], is_sideways: bool) -> Vec<DWRITE_GLYPH_METRICS> {
128         unsafe {
129             let mut metrics: Vec<DWRITE_GLYPH_METRICS> = vec![zeroed(); glyph_indices.len()];
130             let hr = (*self.native.get()).GetDesignGlyphMetrics(glyph_indices.as_ptr(),
131                                                                 glyph_indices.len() as u32,
132                                                                 metrics.as_mut_ptr(),
133                                                                 is_sideways as BOOL);
134             assert!(hr == 0);
135             metrics
136         }
137     }
138 
get_gdi_compatible_glyph_metrics(&self, em_size: f32, pixels_per_dip: f32, transform: *const DWRITE_MATRIX, use_gdi_natural: bool, glyph_indices: &[u16], is_sideways: bool) -> Vec<DWRITE_GLYPH_METRICS>139     pub fn get_gdi_compatible_glyph_metrics(&self, em_size: f32, pixels_per_dip: f32, transform: *const DWRITE_MATRIX,
140                                             use_gdi_natural: bool, glyph_indices: &[u16], is_sideways: bool)
141                                             -> Vec<DWRITE_GLYPH_METRICS>
142     {
143         unsafe {
144             let mut metrics: Vec<DWRITE_GLYPH_METRICS> = vec![zeroed(); glyph_indices.len()];
145             let hr = (*self.native.get()).GetGdiCompatibleGlyphMetrics(em_size, pixels_per_dip,
146                                                                        transform,
147                                                                        use_gdi_natural as BOOL,
148                                                                        glyph_indices.as_ptr(),
149                                                                        glyph_indices.len() as u32,
150                                                                        metrics.as_mut_ptr(),
151                                                                        is_sideways as BOOL);
152             assert!(hr == 0);
153             metrics
154         }
155     }
156 
get_font_table(&self, opentype_table_tag: u32) -> Option<Vec<u8>>157     pub fn get_font_table(&self, opentype_table_tag: u32) -> Option<Vec<u8>> {
158         unsafe {
159             let mut table_data_ptr: *const u8 = ptr::null_mut();
160             let mut table_size: u32 = 0;
161             let mut table_context: *mut c_void = ptr::null_mut();
162             let mut exists: BOOL = FALSE;
163 
164             let hr = (*self.native.get()).TryGetFontTable(opentype_table_tag,
165                                                           &mut table_data_ptr as *mut *const _ as *mut *const c_void,
166                                                           &mut table_size,
167                                                           &mut table_context,
168                                                           &mut exists);
169             assert!(hr == 0);
170 
171             if exists == FALSE {
172                 return None;
173             }
174 
175             let table_bytes = slice::from_raw_parts(table_data_ptr, table_size as usize).to_vec();
176 
177             (*self.native.get()).ReleaseFontTable(table_context);
178 
179             Some(table_bytes)
180         }
181     }
182 
get_recommended_rendering_mode(&self, em_size: f32, pixels_per_dip: f32, measure_mode: DWRITE_MEASURING_MODE, rendering_params: *mut IDWriteRenderingParams) -> DWRITE_RENDERING_MODE183     pub fn get_recommended_rendering_mode(&self,
184                                           em_size: f32,
185                                           pixels_per_dip: f32,
186                                           measure_mode: DWRITE_MEASURING_MODE,
187                                           rendering_params: *mut IDWriteRenderingParams) ->
188                                           DWRITE_RENDERING_MODE {
189       unsafe {
190         let mut render_mode : DWRITE_RENDERING_MODE = DWRITE_RENDERING_MODE_DEFAULT;
191         let hr = (*self.native.get()).GetRecommendedRenderingMode(em_size,
192                                                                   pixels_per_dip,
193                                                                   measure_mode,
194                                                                   rendering_params,
195                                                                   &mut render_mode);
196 
197         if hr != 0 {
198           return DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
199         }
200 
201         render_mode
202       }
203     }
204 
get_recommended_rendering_mode_default_params(&self, em_size: f32, pixels_per_dip: f32, measure_mode: DWRITE_MEASURING_MODE) -> DWRITE_RENDERING_MODE205     pub fn get_recommended_rendering_mode_default_params(&self,
206                                                         em_size: f32,
207                                                         pixels_per_dip: f32,
208                                                         measure_mode: DWRITE_MEASURING_MODE) ->
209                                                         DWRITE_RENDERING_MODE {
210       self.get_recommended_rendering_mode(em_size,
211                                           pixels_per_dip,
212                                           measure_mode,
213                                           DefaultDWriteRenderParams())
214     }
215 
get_glyph_run_outline(&self, em_size: f32, glyph_indices: &[u16], glyph_advances: Option<&[f32]>, glyph_offsets: Option<&[DWRITE_GLYPH_OFFSET]>, is_sideways: bool, is_right_to_left: bool, outline_builder: Box<OutlineBuilder>)216     pub fn get_glyph_run_outline(&self,
217                                  em_size: f32,
218                                  glyph_indices: &[u16],
219                                  glyph_advances: Option<&[f32]>,
220                                  glyph_offsets: Option<&[DWRITE_GLYPH_OFFSET]>,
221                                  is_sideways: bool,
222                                  is_right_to_left: bool,
223                                  outline_builder: Box<OutlineBuilder>) {
224         unsafe {
225             let glyph_advances = match glyph_advances {
226                 None => ptr::null(),
227                 Some(glyph_advances) => {
228                     assert_eq!(glyph_advances.len(), glyph_indices.len());
229                     glyph_advances.as_ptr()
230                 }
231             };
232             let glyph_offsets = match glyph_offsets {
233                 None => ptr::null(),
234                 Some(glyph_offsets) => {
235                     assert_eq!(glyph_offsets.len(), glyph_indices.len());
236                     glyph_offsets.as_ptr()
237                 }
238             };
239             let is_sideways = if is_sideways { TRUE } else { FALSE };
240             let is_right_to_left = if is_right_to_left { TRUE } else { FALSE };
241             let geometry_sink = GeometrySinkImpl::new(outline_builder);
242             let geometry_sink = geometry_sink.into_interface();
243             let hr = (*self.native.get()).GetGlyphRunOutline(em_size,
244                                                             glyph_indices.as_ptr(),
245                                                             glyph_advances,
246                                                             glyph_offsets,
247                                                             glyph_indices.len() as u32,
248                                                             is_sideways,
249                                                             is_right_to_left,
250                                                             geometry_sink);
251             assert_eq!(hr, S_OK);
252         }
253     }
254 
255     #[inline]
get_type(&self) -> FontFaceType256     pub fn get_type(&self) -> FontFaceType {
257         unsafe {
258             match (*self.native.get()).GetType() {
259                 DWRITE_FONT_FACE_TYPE_CFF => FontFaceType::Cff,
260                 DWRITE_FONT_FACE_TYPE_RAW_CFF => FontFaceType::RawCff,
261                 DWRITE_FONT_FACE_TYPE_TRUETYPE => FontFaceType::TrueType,
262                 DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION => FontFaceType::TrueTypeCollection,
263                 DWRITE_FONT_FACE_TYPE_TYPE1 => FontFaceType::Type1,
264                 DWRITE_FONT_FACE_TYPE_VECTOR => FontFaceType::Vector,
265                 DWRITE_FONT_FACE_TYPE_BITMAP => FontFaceType::Bitmap,
266                 _ => FontFaceType::Unknown,
267             }
268         }
269     }
270 
271     #[inline]
get_index(&self) -> u32272     pub fn get_index(&self) -> u32 {
273         unsafe {
274             (*self.native.get()).GetIndex()
275         }
276     }
277 
278     #[inline]
get_face5(&self) -> &mut ComPtr<IDWriteFontFace5>279     unsafe fn get_face5(&self) -> &mut ComPtr<IDWriteFontFace5> {
280         (*self.face5.get()).get_or_insert_with(|| {
281             (*self.native.get())
282                 .query_interface(&IDWriteFontFace5::uuidof())
283                 .unwrap_or(ComPtr::new())
284         })
285     }
286 
has_variations(&self) -> bool287     pub fn has_variations(&self) -> bool {
288         unsafe {
289             let face5 = self.get_face5();
290             if !face5.is_null() {
291                 face5.HasVariations() == TRUE
292             } else {
293                 false
294             }
295         }
296     }
297 
create_font_face_with_variations( &self, simulations: DWRITE_FONT_SIMULATIONS, axis_values: &[DWRITE_FONT_AXIS_VALUE], ) -> Option<FontFace>298     pub fn create_font_face_with_variations(
299         &self,
300         simulations: DWRITE_FONT_SIMULATIONS,
301         axis_values: &[DWRITE_FONT_AXIS_VALUE],
302     ) -> Option<FontFace> {
303         unsafe {
304             let face5 = self.get_face5();
305             if !face5.is_null() {
306                 let mut resource: ComPtr<IDWriteFontResource> = ComPtr::new();
307                 let hr = face5.GetFontResource(resource.getter_addrefs());
308                 if hr == S_OK && !resource.is_null() {
309                     let mut var_face: ComPtr<IDWriteFontFace> = ComPtr::new();
310                     let hr = resource.CreateFontFace(
311                         simulations,
312                         axis_values.as_ptr(),
313                         axis_values.len() as u32,
314                         var_face.getter_addrefs(),
315                     );
316                     if hr == S_OK && !var_face.is_null() {
317                         return Some(FontFace::take(var_face));
318                     }
319                 }
320             }
321             None
322         }
323     }
324 }
325 
326 impl Clone for FontFace {
clone(&self) -> FontFace327     fn clone(&self) -> FontFace {
328         unsafe {
329             FontFace {
330                 native: UnsafeCell::new((*self.native.get()).clone()),
331                 face5: UnsafeCell::new(None),
332                 metrics: self.metrics,
333             }
334         }
335     }
336 }
337 
338 #[derive(Clone, Copy, Debug, PartialEq)]
339 pub enum FontFaceType {
340     Unknown,
341     Cff,
342     RawCff,
343     TrueType,
344     TrueTypeCollection,
345     Type1,
346     Vector,
347     Bitmap,
348 }
349