summaryrefslogtreecommitdiffstats
path: root/third_party/rust/dwrote/src/font.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/dwrote/src/font.rs')
-rw-r--r--third_party/rust/dwrote/src/font.rs182
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,
+ }
+ }
+ }
+}