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