summaryrefslogtreecommitdiffstats
path: root/third_party/rust/dwrote/src/font_collection.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/dwrote/src/font_collection.rs')
-rw-r--r--third_party/rust/dwrote/src/font_collection.rs171
1 files changed, 171 insertions, 0 deletions
diff --git a/third_party/rust/dwrote/src/font_collection.rs b/third_party/rust/dwrote/src/font_collection.rs
new file mode 100644
index 0000000000..b1c99dbe50
--- /dev/null
+++ b/third_party/rust/dwrote/src/font_collection.rs
@@ -0,0 +1,171 @@
+/* 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 std::sync::atomic::{AtomicUsize, Ordering};
+use winapi::shared::minwindef::{BOOL, FALSE, TRUE};
+use winapi::shared::winerror::S_OK;
+use winapi::um::dwrite::IDWriteFontCollectionLoader;
+use winapi::um::dwrite::{IDWriteFont, IDWriteFontCollection, IDWriteFontFamily};
+use wio::com::ComPtr;
+
+use crate::helpers::*;
+use super::{DWriteFactory, Font, FontDescriptor, FontFace, FontFamily};
+
+static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
+
+pub struct FontCollectionFamilyIterator {
+ collection: ComPtr<IDWriteFontCollection>,
+ curr: u32,
+ count: u32,
+}
+
+impl Iterator for FontCollectionFamilyIterator {
+ type Item = FontFamily;
+ fn next(&mut self) -> Option<FontFamily> {
+ if self.curr == self.count {
+ return None;
+ }
+
+ unsafe {
+ let mut family: *mut IDWriteFontFamily = ptr::null_mut();
+ let hr = self.collection.GetFontFamily(self.curr, &mut family);
+ assert!(hr == 0);
+ self.curr += 1;
+ Some(FontFamily::take(ComPtr::from_raw(family)))
+ }
+ }
+}
+
+pub struct FontCollection {
+ native: UnsafeCell<ComPtr<IDWriteFontCollection>>,
+}
+
+impl FontCollection {
+ pub fn get_system(update: bool) -> FontCollection {
+ unsafe {
+ let mut native: *mut IDWriteFontCollection = ptr::null_mut();
+ let hr = (*DWriteFactory()).GetSystemFontCollection(
+ &mut native,
+ if update { TRUE } else { FALSE },
+ );
+ assert!(hr == 0);
+
+ FontCollection {
+ native: UnsafeCell::new(ComPtr::from_raw(native)),
+ }
+ }
+ }
+
+ pub fn system() -> FontCollection {
+ FontCollection::get_system(false)
+ }
+
+ pub fn take(native: ComPtr<IDWriteFontCollection>) -> FontCollection {
+ FontCollection {
+ native: UnsafeCell::new(native),
+ }
+ }
+
+ pub fn from_loader(collection_loader: ComPtr<IDWriteFontCollectionLoader>) -> FontCollection {
+ unsafe {
+ let factory = DWriteFactory();
+ assert_eq!(
+ (*factory).RegisterFontCollectionLoader(collection_loader.clone().into_raw()),
+ S_OK
+ );
+ let mut collection: *mut IDWriteFontCollection = ptr::null_mut();
+ let id = NEXT_ID.fetch_add(1, Ordering::SeqCst);
+ assert_eq!(
+ (*factory).CreateCustomFontCollection(
+ collection_loader.clone().into_raw(),
+ &id as *const usize as *const _,
+ mem::size_of::<AtomicUsize>() as u32,
+ &mut collection
+ ),
+ S_OK
+ );
+ FontCollection::take(ComPtr::from_raw(collection))
+ }
+ }
+
+ pub unsafe fn as_ptr(&self) -> *mut IDWriteFontCollection {
+ (*self.native.get()).as_raw()
+ }
+
+ pub fn families_iter(&self) -> FontCollectionFamilyIterator {
+ unsafe {
+ FontCollectionFamilyIterator {
+ collection: (*self.native.get()).clone(),
+ curr: 0,
+ count: (*self.native.get()).GetFontFamilyCount(),
+ }
+ }
+ }
+
+ pub fn get_font_family_count(&self) -> u32 {
+ unsafe { (*self.native.get()).GetFontFamilyCount() }
+ }
+
+ pub fn get_font_family(&self, index: u32) -> FontFamily {
+ unsafe {
+ let mut family: *mut IDWriteFontFamily = ptr::null_mut();
+ let hr = (*self.native.get()).GetFontFamily(index, &mut family);
+ assert!(hr == 0);
+ FontFamily::take(ComPtr::from_raw(family))
+ }
+ }
+
+ // Find a font matching the given font descriptor in this
+ // font collection.
+ pub fn get_font_from_descriptor(&self, desc: &FontDescriptor) -> Option<Font> {
+ if let Some(family) = self.get_font_family_by_name(&desc.family_name) {
+ let font = family.get_first_matching_font(desc.weight, desc.stretch, desc.style);
+ // Exact matches only here
+ if font.weight() == desc.weight
+ && font.stretch() == desc.stretch
+ && font.style() == desc.style
+ {
+ return Some(font);
+ }
+ }
+
+ None
+ }
+
+ pub fn get_font_from_face(&self, face: &FontFace) -> Option<Font> {
+ unsafe {
+ let mut font: *mut IDWriteFont = ptr::null_mut();
+ let hr = (*self.native.get()).GetFontFromFontFace(face.as_ptr(), &mut font);
+ if hr != 0 {
+ return None;
+ }
+ Some(Font::take(ComPtr::from_raw(font)))
+ }
+ }
+
+ pub fn get_font_family_by_name(&self, family_name: &str) -> Option<FontFamily> {
+ unsafe {
+ let mut index: u32 = 0;
+ let mut exists: BOOL = FALSE;
+ let hr = (*self.native.get()).FindFamilyName(
+ family_name.to_wide_null().as_ptr(),
+ &mut index,
+ &mut exists,
+ );
+ assert!(hr == 0);
+ if exists == FALSE {
+ return None;
+ }
+
+ let mut family: *mut IDWriteFontFamily = ptr::null_mut();
+ let hr = (*self.native.get()).GetFontFamily(index, &mut family);
+ assert!(hr == 0);
+
+ Some(FontFamily::take(ComPtr::from_raw(family)))
+ }
+ }
+}