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::cell::UnsafeCell; 6 use std::mem; 7 use std::ptr; 8 use winapi::shared::minwindef::{FALSE, TRUE}; 9 use winapi::shared::winerror::S_OK; 10 use winapi::um::dwrite::IDWriteFont; 11 use winapi::um::dwrite::IDWriteFontFace; 12 use winapi::um::dwrite::IDWriteFontFamily; 13 use winapi::um::dwrite::IDWriteLocalizedStrings; 14 use winapi::um::dwrite::DWRITE_FONT_METRICS; 15 use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_FULL_NAME; 16 use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_ID; 17 use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME; 18 use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME; 19 use winapi::um::dwrite_1::{IDWriteFont1, DWRITE_FONT_METRICS1}; 20 use wio::com::ComPtr; 21 22 use super::*; 23 use helpers::*; 24 25 pub struct Font { 26 native: UnsafeCell<ComPtr<IDWriteFont>>, 27 } 28 29 impl Font { take(native: ComPtr<IDWriteFont>) -> Font30 pub fn take(native: ComPtr<IDWriteFont>) -> Font { 31 Font { 32 native: UnsafeCell::new(native), 33 } 34 } 35 as_ptr(&self) -> *mut IDWriteFont36 pub unsafe fn as_ptr(&self) -> *mut IDWriteFont { 37 (*self.native.get()).as_raw() 38 } 39 to_descriptor(&self) -> FontDescriptor40 pub fn to_descriptor(&self) -> FontDescriptor { 41 FontDescriptor { 42 family_name: self.family_name(), 43 stretch: self.stretch(), 44 style: self.style(), 45 weight: self.weight(), 46 } 47 } 48 stretch(&self) -> FontStretch49 pub fn stretch(&self) -> FontStretch { 50 unsafe { mem::transmute::<u32, FontStretch>((*self.native.get()).GetStretch()) } 51 } 52 style(&self) -> FontStyle53 pub fn style(&self) -> FontStyle { 54 unsafe { mem::transmute::<u32, FontStyle>((*self.native.get()).GetStyle()) } 55 } 56 weight(&self) -> FontWeight57 pub fn weight(&self) -> FontWeight { 58 unsafe { FontWeight::from_u32((*self.native.get()).GetWeight()) } 59 } 60 is_monospace(&self) -> Option<bool>61 pub fn is_monospace(&self) -> Option<bool> { 62 unsafe { 63 let font1: Option<ComPtr<IDWriteFont1>> = (*self.native.get()).cast().ok(); 64 font1.map(|font| font.IsMonospacedFont() == TRUE) 65 } 66 } 67 simulations(&self) -> FontSimulations68 pub fn simulations(&self) -> FontSimulations { 69 unsafe { mem::transmute::<u32, FontSimulations>((*self.native.get()).GetSimulations()) } 70 } 71 family_name(&self) -> String72 pub fn family_name(&self) -> String { 73 unsafe { 74 let mut family: *mut IDWriteFontFamily = ptr::null_mut(); 75 let hr = (*self.native.get()).GetFontFamily(&mut family); 76 assert!(hr == 0); 77 78 FontFamily::take(ComPtr::from_raw(family)).name() 79 } 80 } 81 face_name(&self) -> String82 pub fn face_name(&self) -> String { 83 unsafe { 84 let mut names: *mut IDWriteLocalizedStrings = ptr::null_mut(); 85 let hr = (*self.native.get()).GetFaceNames(&mut names); 86 assert!(hr == 0); 87 88 get_locale_string(&mut ComPtr::from_raw(names)) 89 } 90 } 91 informational_string(&self, id: InformationalStringId) -> Option<String>92 pub fn informational_string(&self, id: InformationalStringId) -> Option<String> { 93 unsafe { 94 let mut names: *mut IDWriteLocalizedStrings = ptr::null_mut(); 95 let mut exists = FALSE; 96 let id = id as DWRITE_INFORMATIONAL_STRING_ID; 97 let hr = (*self.native.get()).GetInformationalStrings(id, &mut names, &mut exists); 98 assert!(hr == S_OK); 99 if exists == TRUE { 100 Some(get_locale_string(&mut ComPtr::from_raw(names))) 101 } else { 102 None 103 } 104 } 105 } 106 create_font_face(&self) -> FontFace107 pub fn create_font_face(&self) -> FontFace { 108 // FIXME create_font_face should cache the FontFace and return it, 109 // there's a 1:1 relationship 110 unsafe { 111 let mut face: *mut IDWriteFontFace = ptr::null_mut(); 112 let hr = (*self.native.get()).CreateFontFace(&mut face); 113 assert!(hr == 0); 114 FontFace::take(ComPtr::from_raw(face)) 115 } 116 } 117 metrics(&self) -> FontMetrics118 pub fn metrics(&self) -> FontMetrics { 119 unsafe { 120 let font_1: Option<ComPtr<IDWriteFont1>> = (*self.native.get()).cast().ok(); 121 match font_1 { 122 None => { 123 let mut metrics = mem::zeroed(); 124 (*self.native.get()).GetMetrics(&mut metrics); 125 FontMetrics::Metrics0(metrics) 126 } 127 Some(font_1) => { 128 let mut metrics_1 = mem::zeroed(); 129 font_1.GetMetrics(&mut metrics_1); 130 FontMetrics::Metrics1(metrics_1) 131 } 132 } 133 } 134 } 135 } 136 137 impl Clone for Font { clone(&self) -> Font138 fn clone(&self) -> Font { 139 unsafe { 140 Font { 141 native: UnsafeCell::new((*self.native.get()).clone()), 142 } 143 } 144 } 145 } 146 147 #[repr(u32)] 148 #[derive(Clone, Copy, Debug, PartialEq)] 149 pub enum InformationalStringId { 150 FullName = DWRITE_INFORMATIONAL_STRING_FULL_NAME, 151 PostscriptName = DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, 152 PostscriptCidName = DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME, 153 } 154 155 /// A wrapper around the `DWRITE_FONT_METRICS` and `DWRITE_FONT_METRICS1` types. 156 pub enum FontMetrics { 157 /// Windows 7. 158 Metrics0(DWRITE_FONT_METRICS), 159 /// Windows 8 and up. 160 Metrics1(DWRITE_FONT_METRICS1), 161 } 162 163 impl FontMetrics { 164 /// Convert self to the Metrics0 arm (throwing away additional information) metrics0(self) -> DWRITE_FONT_METRICS165 pub fn metrics0(self) -> DWRITE_FONT_METRICS { 166 match self { 167 FontMetrics::Metrics0(metrics) => metrics, 168 FontMetrics::Metrics1(metrics) => DWRITE_FONT_METRICS { 169 designUnitsPerEm: metrics.designUnitsPerEm, 170 ascent: metrics.ascent, 171 descent: metrics.descent, 172 lineGap: metrics.lineGap, 173 capHeight: metrics.capHeight, 174 xHeight: metrics.xHeight, 175 underlinePosition: metrics.underlinePosition, 176 underlineThickness: metrics.underlineThickness, 177 strikethroughPosition: metrics.strikethroughPosition, 178 strikethroughThickness: metrics.strikethroughThickness, 179 } 180 } 181 } 182 } 183