font_kit/sources/
multi.rs

1// font-kit/src/sources/multi.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 encapsulates multiple sources and allows them to be queried as a group.
12//!
13//! This is useful when an application wants a library of fonts consisting of the installed system
14//! fonts plus some other application-supplied fonts.
15
16use crate::error::SelectionError;
17use crate::family_handle::FamilyHandle;
18use crate::family_name::FamilyName;
19use crate::handle::Handle;
20use crate::properties::Properties;
21use crate::source::Source;
22use std::{
23    any::Any,
24    fmt,
25    ops::{Index, IndexMut},
26    slice,
27};
28
29/// A source that encapsulates multiple sources and allows them to be queried as a group.
30///
31/// This is useful when an application wants a library of fonts consisting of the installed system
32/// fonts plus some other application-supplied fonts.
33#[allow(missing_debug_implementations)]
34pub struct MultiSource {
35    subsources: Vec<Box<dyn Source>>,
36}
37
38impl MultiSource {
39    /// Creates a new source that contains all the fonts in the supplied sources.
40    pub fn from_sources(subsources: Vec<Box<dyn Source>>) -> MultiSource {
41        MultiSource { subsources }
42    }
43
44    /// Returns paths of all fonts installed on the system.
45    pub fn all_fonts(&self) -> Result<Vec<Handle>, SelectionError> {
46        let mut handles = vec![];
47        for subsource in &self.subsources {
48            handles.extend(subsource.all_fonts()?.into_iter())
49        }
50        Ok(handles)
51    }
52
53    /// Returns the names of all families installed on the system.
54    pub fn all_families(&self) -> Result<Vec<String>, SelectionError> {
55        let mut families = vec![];
56        for subsource in &self.subsources {
57            families.extend(subsource.all_families()?.into_iter())
58        }
59        Ok(families)
60    }
61
62    /// Looks up a font family by name and returns the handles of all the fonts in that family.
63    pub fn select_family_by_name(&self, family_name: &str) -> Result<FamilyHandle, SelectionError> {
64        for subsource in &self.subsources {
65            match subsource.select_family_by_name(family_name) {
66                Ok(family) => return Ok(family),
67                Err(SelectionError::NotFound) => {}
68                Err(err) => return Err(err),
69            }
70        }
71        Err(SelectionError::NotFound)
72    }
73
74    /// Selects a font by PostScript name, which should be a unique identifier.
75    pub fn select_by_postscript_name(
76        &self,
77        postscript_name: &str,
78    ) -> Result<Handle, SelectionError> {
79        for subsource in &self.subsources {
80            match subsource.select_by_postscript_name(postscript_name) {
81                Ok(font) => return Ok(font),
82                Err(SelectionError::NotFound) => {}
83                Err(err) => return Err(err),
84            }
85        }
86        Err(SelectionError::NotFound)
87    }
88
89    /// Performs font matching according to the CSS Fonts Level 3 specification and returns the
90    /// handle.
91    #[inline]
92    pub fn select_best_match(
93        &self,
94        family_names: &[FamilyName],
95        properties: &Properties,
96    ) -> Result<Handle, SelectionError> {
97        <Self as Source>::select_best_match(self, family_names, properties)
98    }
99
100    /// Returns an iterator over the contained sources.
101    #[inline]
102    pub fn iter(&self) -> MultiIter<'_> {
103        MultiIter(self.subsources.iter())
104    }
105
106    /// Returns an iterator over the contained sources with mutable access.
107    #[inline]
108    pub fn iter_mut(&mut self) -> MultiIterMut<'_> {
109        MultiIterMut(self.subsources.iter_mut())
110    }
111
112    /// A convenience method to get the first source with the given type.
113    ///
114    /// Returns `None` if no source of the given type was found.
115    pub fn find_source<T: Source + 'static>(&self) -> Option<&T> {
116        self.iter().find_map(|v| v.as_any().downcast_ref())
117    }
118
119    /// A convenience method to get the first source with the given type.
120    ///
121    /// Returns `None` if no source of the given type was found.
122    pub fn find_source_mut<T: Source + 'static>(&mut self) -> Option<&mut T> {
123        self.iter_mut().find_map(|v| v.as_mut_any().downcast_mut())
124    }
125}
126
127impl Source for MultiSource {
128    #[inline]
129    fn all_fonts(&self) -> Result<Vec<Handle>, SelectionError> {
130        self.all_fonts()
131    }
132
133    #[inline]
134    fn all_families(&self) -> Result<Vec<String>, SelectionError> {
135        self.all_families()
136    }
137
138    #[inline]
139    fn select_family_by_name(&self, family_name: &str) -> Result<FamilyHandle, SelectionError> {
140        self.select_family_by_name(family_name)
141    }
142
143    #[inline]
144    fn select_by_postscript_name(&self, postscript_name: &str) -> Result<Handle, SelectionError> {
145        self.select_by_postscript_name(postscript_name)
146    }
147
148    fn as_any(&self) -> &dyn Any {
149        self
150    }
151
152    fn as_mut_any(&mut self) -> &mut dyn Any {
153        self
154    }
155}
156
157impl Index<usize> for MultiSource {
158    type Output = dyn Source;
159
160    fn index(&self, idx: usize) -> &Self::Output {
161        &*self.subsources[idx]
162    }
163}
164
165impl IndexMut<usize> for MultiSource {
166    fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
167        &mut *self.subsources[idx]
168    }
169}
170
171/// An iterator over the sources in a [`MultiSource`].
172pub struct MultiIter<'a>(slice::Iter<'a, Box<dyn Source>>);
173
174impl<'a> Iterator for MultiIter<'a> {
175    type Item = &'a dyn Source;
176
177    fn next(&mut self) -> Option<Self::Item> {
178        self.0.next().map(|v| &**v)
179    }
180}
181
182impl fmt::Debug for MultiIter<'_> {
183    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
184        f.debug_struct("MultiIter").finish()
185    }
186}
187
188/// An iterator over the mutable sources in a [`MultiSource`].
189pub struct MultiIterMut<'a>(slice::IterMut<'a, Box<dyn Source>>);
190
191impl<'a> Iterator for MultiIterMut<'a> {
192    type Item = &'a mut dyn Source;
193
194    fn next(&mut self) -> Option<Self::Item> {
195        self.0.next().map(|v| &mut **v)
196    }
197}
198
199impl fmt::Debug for MultiIterMut<'_> {
200    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
201        f.debug_struct("MultiIterMut").finish()
202    }
203}