font_kit/sources/
directwrite.rs

1// font-kit/src/sources/directwrite.rs
2//
3// Copyright © 2018 The Pathfinder Project Developers.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! A source that contains the installed fonts on Windows.
12
13use dwrote::Font as DWriteFont;
14use dwrote::FontCollection as DWriteFontCollection;
15use std::any::Any;
16
17use crate::error::SelectionError;
18use crate::family_handle::FamilyHandle;
19use crate::family_name::FamilyName;
20use crate::handle::Handle;
21use crate::properties::Properties;
22use crate::source::Source;
23
24/// A source that contains the installed fonts on Windows.
25#[allow(missing_debug_implementations)]
26pub struct DirectWriteSource {
27    system_font_collection: DWriteFontCollection,
28}
29
30impl DirectWriteSource {
31    /// Opens the system font collection.
32    pub fn new() -> DirectWriteSource {
33        DirectWriteSource {
34            system_font_collection: DWriteFontCollection::system(),
35        }
36    }
37
38    /// Returns paths of all fonts installed on the system.
39    pub fn all_fonts(&self) -> Result<Vec<Handle>, SelectionError> {
40        let mut handles = Vec::new();
41
42        for dwrite_family in self.system_font_collection.families_iter() {
43            for font_index in 0..dwrite_family.get_font_count() {
44                let dwrite_font = dwrite_family.get_font(font_index);
45                handles.push(self.create_handle_from_dwrite_font(dwrite_font))
46            }
47        }
48
49        Ok(handles)
50    }
51
52    /// Returns the names of all families installed on the system.
53    pub fn all_families(&self) -> Result<Vec<String>, SelectionError> {
54        Ok(self
55            .system_font_collection
56            .families_iter()
57            .map(|dwrite_family| dwrite_family.name())
58            .collect())
59    }
60
61    /// Looks up a font family by name and returns the handles of all the fonts in that family.
62    ///
63    /// TODO(pcwalton): Case-insensitivity.
64    pub fn select_family_by_name(&self, family_name: &str) -> Result<FamilyHandle, SelectionError> {
65        let mut family = FamilyHandle::new();
66        let dwrite_family = match self
67            .system_font_collection
68            .get_font_family_by_name(family_name)
69        {
70            Some(dwrite_family) => dwrite_family,
71            None => return Err(SelectionError::NotFound),
72        };
73        for font_index in 0..dwrite_family.get_font_count() {
74            let dwrite_font = dwrite_family.get_font(font_index);
75            family.push(self.create_handle_from_dwrite_font(dwrite_font))
76        }
77        Ok(family)
78    }
79
80    /// Selects a font by PostScript name, which should be a unique identifier.
81    ///
82    /// On the DirectWrite backend, this does a brute-force search of installed fonts to find the
83    /// one that matches.
84    pub fn select_by_postscript_name(
85        &self,
86        postscript_name: &str,
87    ) -> Result<Handle, SelectionError> {
88        <Self as Source>::select_by_postscript_name(self, postscript_name)
89    }
90
91    /// Performs font matching according to the CSS Fonts Level 3 specification and returns the
92    /// handle.
93    #[inline]
94    pub fn select_best_match(
95        &self,
96        family_names: &[FamilyName],
97        properties: &Properties,
98    ) -> Result<Handle, SelectionError> {
99        <Self as Source>::select_best_match(self, family_names, properties)
100    }
101
102    fn create_handle_from_dwrite_font(&self, dwrite_font: DWriteFont) -> Handle {
103        let dwrite_font_face = dwrite_font.create_font_face();
104        let dwrite_font_files = dwrite_font_face.get_files();
105        Handle::Path {
106            path: dwrite_font_files[0].get_font_file_path().unwrap(),
107            font_index: dwrite_font_face.get_index(),
108        }
109    }
110}
111
112impl Source for DirectWriteSource {
113    #[inline]
114    fn all_fonts(&self) -> Result<Vec<Handle>, SelectionError> {
115        self.all_fonts()
116    }
117
118    #[inline]
119    fn all_families(&self) -> Result<Vec<String>, SelectionError> {
120        self.all_families()
121    }
122
123    #[inline]
124    fn select_family_by_name(&self, family_name: &str) -> Result<FamilyHandle, SelectionError> {
125        self.select_family_by_name(family_name)
126    }
127
128    #[inline]
129    fn as_any(&self) -> &dyn Any {
130        self
131    }
132
133    #[inline]
134    fn as_mut_any(&mut self) -> &mut dyn Any {
135        self
136    }
137}