diff options
Diffstat (limited to 'third_party/rust/dwrote/src/font.rs')
-rw-r--r-- | third_party/rust/dwrote/src/font.rs | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/third_party/rust/dwrote/src/font.rs b/third_party/rust/dwrote/src/font.rs new file mode 100644 index 0000000000..eacad1c3bf --- /dev/null +++ b/third_party/rust/dwrote/src/font.rs @@ -0,0 +1,182 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::cell::UnsafeCell; +use std::mem; +use std::ptr; +use winapi::shared::minwindef::{FALSE, TRUE}; +use winapi::shared::winerror::S_OK; +use winapi::um::dwrite::IDWriteFont; +use winapi::um::dwrite::IDWriteFontFace; +use winapi::um::dwrite::IDWriteFontFamily; +use winapi::um::dwrite::IDWriteLocalizedStrings; +use winapi::um::dwrite::DWRITE_FONT_METRICS; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_FULL_NAME; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_ID; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME; +use winapi::um::dwrite::DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME; +use winapi::um::dwrite_1::{IDWriteFont1, DWRITE_FONT_METRICS1}; +use wio::com::ComPtr; + +use super::*; +use helpers::*; + +pub struct Font { + native: UnsafeCell<ComPtr<IDWriteFont>>, +} + +impl Font { + pub fn take(native: ComPtr<IDWriteFont>) -> Font { + Font { + native: UnsafeCell::new(native), + } + } + + pub unsafe fn as_ptr(&self) -> *mut IDWriteFont { + (*self.native.get()).as_raw() + } + + pub fn to_descriptor(&self) -> FontDescriptor { + FontDescriptor { + family_name: self.family_name(), + stretch: self.stretch(), + style: self.style(), + weight: self.weight(), + } + } + + pub fn stretch(&self) -> FontStretch { + unsafe { mem::transmute::<u32, FontStretch>((*self.native.get()).GetStretch()) } + } + + pub fn style(&self) -> FontStyle { + unsafe { mem::transmute::<u32, FontStyle>((*self.native.get()).GetStyle()) } + } + + pub fn weight(&self) -> FontWeight { + unsafe { FontWeight::from_u32((*self.native.get()).GetWeight()) } + } + + pub fn is_monospace(&self) -> Option<bool> { + unsafe { + let font1: Option<ComPtr<IDWriteFont1>> = (*self.native.get()).cast().ok(); + font1.map(|font| font.IsMonospacedFont() == TRUE) + } + } + + pub fn simulations(&self) -> FontSimulations { + unsafe { mem::transmute::<u32, FontSimulations>((*self.native.get()).GetSimulations()) } + } + + pub fn family_name(&self) -> String { + unsafe { + let mut family: *mut IDWriteFontFamily = ptr::null_mut(); + let hr = (*self.native.get()).GetFontFamily(&mut family); + assert!(hr == 0); + + FontFamily::take(ComPtr::from_raw(family)).name() + } + } + + pub fn face_name(&self) -> String { + unsafe { + let mut names: *mut IDWriteLocalizedStrings = ptr::null_mut(); + let hr = (*self.native.get()).GetFaceNames(&mut names); + assert!(hr == 0); + + get_locale_string(&mut ComPtr::from_raw(names)) + } + } + + pub fn informational_string(&self, id: InformationalStringId) -> Option<String> { + unsafe { + let mut names: *mut IDWriteLocalizedStrings = ptr::null_mut(); + let mut exists = FALSE; + let id = id as DWRITE_INFORMATIONAL_STRING_ID; + let hr = (*self.native.get()).GetInformationalStrings(id, &mut names, &mut exists); + assert!(hr == S_OK); + if exists == TRUE { + Some(get_locale_string(&mut ComPtr::from_raw(names))) + } else { + None + } + } + } + + pub fn create_font_face(&self) -> FontFace { + // FIXME create_font_face should cache the FontFace and return it, + // there's a 1:1 relationship + unsafe { + let mut face: *mut IDWriteFontFace = ptr::null_mut(); + let hr = (*self.native.get()).CreateFontFace(&mut face); + assert!(hr == 0); + FontFace::take(ComPtr::from_raw(face)) + } + } + + pub fn metrics(&self) -> FontMetrics { + unsafe { + let font_1: Option<ComPtr<IDWriteFont1>> = (*self.native.get()).cast().ok(); + match font_1 { + None => { + let mut metrics = mem::zeroed(); + (*self.native.get()).GetMetrics(&mut metrics); + FontMetrics::Metrics0(metrics) + } + Some(font_1) => { + let mut metrics_1 = mem::zeroed(); + font_1.GetMetrics(&mut metrics_1); + FontMetrics::Metrics1(metrics_1) + } + } + } + } +} + +impl Clone for Font { + fn clone(&self) -> Font { + unsafe { + Font { + native: UnsafeCell::new((*self.native.get()).clone()), + } + } + } +} + +#[repr(u32)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum InformationalStringId { + FullName = DWRITE_INFORMATIONAL_STRING_FULL_NAME, + PostscriptName = DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, + PostscriptCidName = DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME, +} + +/// A wrapper around the `DWRITE_FONT_METRICS` and `DWRITE_FONT_METRICS1` types. +pub enum FontMetrics { + /// Windows 7. + Metrics0(DWRITE_FONT_METRICS), + /// Windows 8 and up. + Metrics1(DWRITE_FONT_METRICS1), +} + +impl FontMetrics { + /// Convert self to the Metrics0 arm (throwing away additional information) + pub fn metrics0(self) -> DWRITE_FONT_METRICS { + match self { + FontMetrics::Metrics0(metrics) => metrics, + FontMetrics::Metrics1(metrics) => DWRITE_FONT_METRICS { + designUnitsPerEm: metrics.designUnitsPerEm, + ascent: metrics.ascent, + descent: metrics.descent, + lineGap: metrics.lineGap, + capHeight: metrics.capHeight, + xHeight: metrics.xHeight, + underlinePosition: metrics.underlinePosition, + underlineThickness: metrics.underlineThickness, + strikethroughPosition: metrics.strikethroughPosition, + strikethroughThickness: metrics.strikethroughThickness, + } + } + } +} |