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::zeroed;
9 
10 use comptr::ComPtr;
11 use super::{FontMetrics, FontFile, DefaultDWriteRenderParams, DWriteFactory};
12 
13 use winapi;
14 
15 #[derive(Debug)]
16 pub struct FontFace {
17     native: UnsafeCell<ComPtr<winapi::IDWriteFontFace>>,
18     metrics: FontMetrics,
19 }
20 
21 impl FontFace {
take(native: ComPtr<winapi::IDWriteFontFace>) -> FontFace22     pub fn take(native: ComPtr<winapi::IDWriteFontFace>) -> FontFace {
23         unsafe {
24             let mut metrics: FontMetrics = zeroed();
25             let cell = UnsafeCell::new(native);
26             (*cell.get()).GetMetrics(&mut metrics);
27             FontFace {
28                 native: cell,
29                 metrics: metrics,
30             }
31         }
32     }
33 
as_ptr(&self) -> *mut winapi::IDWriteFontFace34     pub unsafe fn as_ptr(&self) -> *mut winapi::IDWriteFontFace {
35         (*self.native.get()).as_ptr()
36     }
37 
get_raw_files(&self) -> Vec<*mut winapi::IDWriteFontFile>38     unsafe fn get_raw_files(&self) -> Vec<*mut winapi::IDWriteFontFile> {
39         let mut number_of_files: u32 = 0;
40         let hr = (*self.native.get()).GetFiles(&mut number_of_files, ptr::null_mut());
41         assert!(hr == 0);
42 
43         let mut file_ptrs: Vec<*mut winapi::IDWriteFontFile> =
44             vec![ptr::null_mut(); number_of_files as usize];
45         let hr = (*self.native.get()).GetFiles(&mut number_of_files, file_ptrs.as_mut_ptr());
46         assert!(hr == 0);
47         file_ptrs
48     }
49 
get_files(&self) -> Vec<FontFile>50     pub fn get_files(&self) -> Vec<FontFile> {
51         unsafe {
52             let file_ptrs = self.get_raw_files();
53             file_ptrs.iter().map(|p| FontFile::take(ComPtr::already_addrefed(*p))).collect()
54         }
55     }
56 
create_font_face_with_simulations(&self, simulations: winapi::DWRITE_FONT_SIMULATIONS) -> FontFace57     pub fn create_font_face_with_simulations(&self, simulations: winapi::DWRITE_FONT_SIMULATIONS) -> FontFace {
58         unsafe {
59             let file_ptrs = self.get_raw_files();
60             let face_type = (*self.native.get()).GetType();
61             let face_index = (*self.native.get()).GetIndex();
62             let mut face: ComPtr<winapi::IDWriteFontFace> = ComPtr::new();
63             let hr = (*DWriteFactory()).CreateFontFace(
64                 face_type,
65                 file_ptrs.len() as u32,
66                 file_ptrs.as_ptr(),
67                 face_index,
68                 simulations,
69                 face.getter_addrefs()
70             );
71             for p in file_ptrs {
72                 let _ = ComPtr::<winapi::IDWriteFontFile>::already_addrefed(p);
73             }
74             assert!(hr == 0);
75             FontFace::take(face)
76         }
77     }
78 
get_glyph_count(&self) -> u1679     pub fn get_glyph_count(&self) -> u16 {
80         unsafe {
81             (*self.native.get()).GetGlyphCount()
82         }
83     }
84 
metrics(&self) -> &FontMetrics85     pub fn metrics(&self) -> &FontMetrics {
86         &self.metrics
87     }
88 
get_metrics(&self) -> FontMetrics89     pub fn get_metrics(&self) -> FontMetrics {
90         unsafe {
91             let mut metrics: winapi::DWRITE_FONT_METRICS = zeroed();
92             (*self.native.get()).GetMetrics(&mut metrics);
93             metrics
94         }
95     }
96 
get_glyph_indices(&self, code_points: &[u32]) -> Vec<u16>97     pub fn get_glyph_indices(&self, code_points: &[u32]) -> Vec<u16> {
98         unsafe {
99             let mut glyph_indices: Vec<u16> = vec![0; code_points.len()];
100             let hr = (*self.native.get()).GetGlyphIndices(code_points.as_ptr(),
101                                                           code_points.len() as u32,
102                                                           glyph_indices.as_mut_ptr());
103             assert!(hr == 0);
104             glyph_indices
105         }
106     }
107 
get_design_glyph_metrics(&self, glyph_indices: &[u16], is_sideways: bool) -> Vec<winapi::DWRITE_GLYPH_METRICS>108     pub fn get_design_glyph_metrics(&self, glyph_indices: &[u16], is_sideways: bool) -> Vec<winapi::DWRITE_GLYPH_METRICS> {
109         unsafe {
110             let mut metrics: Vec<winapi::DWRITE_GLYPH_METRICS> = vec![zeroed(); glyph_indices.len()];
111             let hr = (*self.native.get()).GetDesignGlyphMetrics(glyph_indices.as_ptr(),
112                                                                 glyph_indices.len() as u32,
113                                                                 metrics.as_mut_ptr(),
114                                                                 is_sideways as winapi::BOOL);
115             assert!(hr == 0);
116             metrics
117         }
118     }
119 
get_gdi_compatible_glyph_metrics(&self, em_size: f32, pixels_per_dip: f32, transform: *const winapi::DWRITE_MATRIX, use_gdi_natural: bool, glyph_indices: &[u16], is_sideways: bool) -> Vec<winapi::DWRITE_GLYPH_METRICS>120     pub fn get_gdi_compatible_glyph_metrics(&self, em_size: f32, pixels_per_dip: f32, transform: *const winapi::DWRITE_MATRIX,
121                                             use_gdi_natural: bool, glyph_indices: &[u16], is_sideways: bool)
122                                             -> Vec<winapi::DWRITE_GLYPH_METRICS>
123     {
124         unsafe {
125             let mut metrics: Vec<winapi::DWRITE_GLYPH_METRICS> = vec![zeroed(); glyph_indices.len()];
126             let hr = (*self.native.get()).GetGdiCompatibleGlyphMetrics(em_size, pixels_per_dip,
127                                                                        transform,
128                                                                        use_gdi_natural as winapi::BOOL,
129                                                                        glyph_indices.as_ptr(),
130                                                                        glyph_indices.len() as u32,
131                                                                        metrics.as_mut_ptr(),
132                                                                        is_sideways as winapi::BOOL);
133             assert!(hr == 0);
134             metrics
135         }
136     }
137 
get_font_table(&self, opentype_table_tag: u32) -> Option<Vec<u8>>138     pub fn get_font_table(&self, opentype_table_tag: u32) -> Option<Vec<u8>> {
139         unsafe {
140             let mut table_data_ptr: *const u8 = ptr::null_mut();
141             let mut table_size: u32 = 0;
142             let mut table_context: *mut winapi::c_void = ptr::null_mut();
143             let mut exists: winapi::BOOL = winapi::FALSE;
144 
145             let hr = (*self.native.get()).TryGetFontTable(opentype_table_tag,
146                                                           &mut table_data_ptr as *mut *const _ as *mut *const winapi::c_void,
147                                                           &mut table_size,
148                                                           &mut table_context,
149                                                           &mut exists);
150             assert!(hr == 0);
151 
152             if exists == winapi::FALSE {
153                 return None;
154             }
155 
156             let table_bytes = slice::from_raw_parts(table_data_ptr, table_size as usize).to_vec();
157 
158             (*self.native.get()).ReleaseFontTable(table_context);
159 
160             Some(table_bytes)
161         }
162     }
163 
get_recommended_rendering_mode(&self, em_size: f32, pixels_per_dip: f32, measure_mode: winapi::DWRITE_MEASURING_MODE, rendering_params: *mut winapi::IDWriteRenderingParams) -> winapi::DWRITE_RENDERING_MODE164     pub fn get_recommended_rendering_mode(&self,
165                                           em_size: f32,
166                                           pixels_per_dip: f32,
167                                           measure_mode: winapi::DWRITE_MEASURING_MODE,
168                                           rendering_params: *mut winapi::IDWriteRenderingParams) ->
169                                           winapi::DWRITE_RENDERING_MODE {
170       unsafe {
171         let mut render_mode : winapi::DWRITE_RENDERING_MODE = winapi::DWRITE_RENDERING_MODE_DEFAULT;
172         let hr = (*self.native.get()).GetRecommendedRenderingMode(em_size,
173                                                                   pixels_per_dip,
174                                                                   measure_mode,
175                                                                   rendering_params,
176                                                                   &mut render_mode);
177 
178         if !(hr != 0) {
179           return winapi::DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
180         }
181 
182         render_mode
183       }
184     }
185 
get_recommended_rendering_mode_default_params(&self, em_size: f32, pixels_per_dip: f32, measure_mode: winapi::DWRITE_MEASURING_MODE) -> winapi::DWRITE_RENDERING_MODE186     pub fn get_recommended_rendering_mode_default_params(&self,
187                                                         em_size: f32,
188                                                         pixels_per_dip: f32,
189                                                         measure_mode: winapi::DWRITE_MEASURING_MODE) ->
190                                                         winapi::DWRITE_RENDERING_MODE {
191       self.get_recommended_rendering_mode(em_size,
192                                           pixels_per_dip,
193                                           measure_mode,
194                                           DefaultDWriteRenderParams())
195     }
196 }
197