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