Skip to main content

fonts/
font_store.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::collections::HashMap;
6use std::ops::Deref;
7use std::sync::Arc;
8
9use fonts_traits::{
10    FontDescriptor, FontIdentifier, FontTemplate, FontTemplateRef, FontTemplateRefMethods,
11    IsOblique, LowercaseFontFamilyName,
12};
13use log::warn;
14use malloc_size_of_derive::MallocSizeOf;
15use parking_lot::RwLock;
16use style::properties::generated::font_face::Descriptors as FontFaceRuleDescriptors;
17use style::values::computed::{FontStyle, FontWeight};
18
19#[derive(Default, MallocSizeOf)]
20pub(crate) struct FontStore {
21    pub(crate) families: HashMap<LowercaseFontFamilyName, FontTemplates>,
22}
23
24#[derive(Default, MallocSizeOf)]
25pub(crate) struct CrossThreadFontStore(#[conditional_malloc_size_of] Arc<RwLock<FontStore>>);
26
27impl Deref for CrossThreadFontStore {
28    type Target = Arc<RwLock<FontStore>>;
29    fn deref(&self) -> &Self::Target {
30        &self.0
31    }
32}
33
34impl FontStore {
35    pub(crate) fn clear(&mut self) {
36        self.families.clear();
37    }
38
39    pub(crate) fn add_new_template(
40        &mut self,
41        family_name: LowercaseFontFamilyName,
42        new_template: FontTemplate,
43    ) {
44        self.families
45            .entry(family_name)
46            .or_default()
47            .add_template(new_template);
48    }
49}
50
51/// A struct that represents the available templates in a "simple family." A simple family
52/// is one that contains <= 4 available faces: regular, bold, italic, and bold italic. Having
53/// this simple family abstraction makes font matching much faster for families that don't
54/// have a complex set of fonts.
55///
56/// This optimization is taken from:
57/// <https://searchfox.org/mozilla-central/source/gfx/thebes/gfxFontEntry.cpp>.
58#[derive(Clone, Debug, Default, MallocSizeOf)]
59struct SimpleFamily {
60    regular: Option<FontTemplateRef>,
61    bold: Option<FontTemplateRef>,
62    italic: Option<FontTemplateRef>,
63    bold_italic: Option<FontTemplateRef>,
64}
65
66impl SimpleFamily {
67    /// Find a font in this family that matches a given descriptor.
68    fn find_for_descriptor(&self, descriptor_to_match: &FontDescriptor) -> Option<FontTemplateRef> {
69        let want_bold = descriptor_to_match.weight > FontWeight::PREFER_BOLD_THRESHOLD;
70        let want_italic = descriptor_to_match.style != FontStyle::NORMAL;
71
72        // This represents the preference of which font to return from the [`SimpleFamily`],
73        // given what kind of font we are requesting.
74        let preference = match (want_bold, want_italic) {
75            (true, true) => [&self.bold_italic, &self.italic, &self.bold, &self.regular],
76            (true, false) => [&self.bold, &self.regular, &self.bold_italic, &self.italic],
77            (false, true) => [&self.italic, &self.bold_italic, &self.regular, &self.bold],
78            (false, false) => [&self.regular, &self.bold, &self.italic, &self.bold_italic],
79        };
80        preference.iter().find_map(|template| (*template).clone())
81    }
82
83    fn remove_templates_for_font_face_rule(&mut self, font_face_rule: &FontFaceRuleDescriptors) {
84        let remove_if_template_matches = |template: &mut Option<FontTemplateRef>| {
85            if template.as_ref().is_some_and(|template| {
86                template
87                    .borrow()
88                    .is_defined_by_font_face_rule(font_face_rule)
89            }) {
90                *template = None;
91            }
92        };
93        remove_if_template_matches(&mut self.regular);
94        remove_if_template_matches(&mut self.bold);
95        remove_if_template_matches(&mut self.italic);
96        remove_if_template_matches(&mut self.bold_italic);
97    }
98
99    pub(crate) fn for_all_identifiers(&self, mut callback: impl FnMut(&FontIdentifier)) {
100        let mut call_if_not_none = |template: &Option<FontTemplateRef>| {
101            if let Some(template) = template {
102                callback(&template.identifier())
103            }
104        };
105        call_if_not_none(&self.regular);
106        call_if_not_none(&self.bold);
107        call_if_not_none(&self.italic);
108        call_if_not_none(&self.bold_italic);
109    }
110}
111/// A list of font templates that make up a given font family.
112#[derive(Clone, Debug, MallocSizeOf)]
113pub struct FontTemplates {
114    pub(crate) templates: Vec<FontTemplateRef>,
115    simple_family: Option<SimpleFamily>,
116}
117
118impl Default for FontTemplates {
119    fn default() -> Self {
120        Self {
121            templates: Default::default(),
122            simple_family: Some(SimpleFamily::default()),
123        }
124    }
125}
126
127impl FontTemplates {
128    /// Find a font in this family that matches a given descriptor.
129    pub fn find_for_descriptor(
130        &self,
131        descriptor_to_match: Option<&FontDescriptor>,
132    ) -> Vec<FontTemplateRef> {
133        let Some(descriptor_to_match) = descriptor_to_match else {
134            return self.templates.clone();
135        };
136
137        if self.templates.len() == 1 {
138            return vec![self.templates[0].clone()];
139        }
140
141        if let Some(template) = self
142            .simple_family
143            .as_ref()
144            .and_then(|simple_family| simple_family.find_for_descriptor(descriptor_to_match))
145        {
146            return vec![template];
147        }
148
149        let mut best_templates = Vec::new();
150        let mut best_distance = f32::MAX;
151        for template in self.templates.iter() {
152            let distance = template.descriptor_distance(descriptor_to_match);
153            if distance < best_distance {
154                best_templates = vec![template.clone()];
155                best_distance = distance
156            } else if distance == best_distance {
157                best_templates.push(template.clone());
158            }
159        }
160
161        if !best_templates.is_empty() {
162            return best_templates;
163        }
164
165        // If a request is made for a font family that exists,
166        // pick the first valid font in the family if we failed
167        // to find an exact match for the descriptor.
168        if let Some(template) = self.templates.first() {
169            return vec![template.clone()];
170        }
171
172        Vec::new()
173    }
174
175    pub fn add_template(&mut self, new_template: FontTemplate) {
176        for existing_template in &self.templates {
177            let existing_template = existing_template.borrow();
178            if *existing_template.identifier() == new_template.identifier &&
179                existing_template.descriptor == new_template.descriptor
180            {
181                return;
182            }
183        }
184
185        let new_template = FontTemplateRef::new(new_template);
186        self.templates.push(new_template.clone());
187        self.update_simple_family(new_template);
188    }
189
190    fn update_simple_family(&mut self, added_template: FontTemplateRef) {
191        // If this was detected to not be a simple family before, it cannot ever be one
192        // in the future.
193        let Some(simple_family) = self.simple_family.as_mut() else {
194            return;
195        };
196
197        if self.templates.len() > 4 {
198            self.simple_family = None;
199            return;
200        }
201
202        // Variation fonts are never simple families.
203        if added_template.descriptor().is_variation_font() {
204            self.simple_family = None;
205            return;
206        }
207
208        let Some(first) = self.templates.first() else {
209            warn!("Called before adding any templates.");
210            return;
211        };
212
213        // If the stretch between any of these fonts differ, it cannot be a simple family nor if this
214        // font is oblique.
215        let stretch = added_template.descriptor().stretch.0;
216        let style = added_template.descriptor().style.0;
217        if first.descriptor().stretch.0 != stretch || style.is_oblique() {
218            self.simple_family = None;
219            return;
220        }
221
222        let weight = added_template.descriptor().weight.0;
223        let supports_bold = weight >= FontWeight::BOLD_THRESHOLD;
224        let is_italic = style == FontStyle::ITALIC;
225        let slot = match (supports_bold, is_italic) {
226            (true, true) => &mut simple_family.bold_italic,
227            (true, false) => &mut simple_family.bold,
228            (false, true) => &mut simple_family.italic,
229            (false, false) => &mut simple_family.regular,
230        };
231
232        // If the slot was already filled there are two fonts with the same simple properties
233        // and this isn't a simple family.
234        if slot.is_some() {
235            self.simple_family = None;
236            return;
237        }
238
239        slot.replace(added_template);
240    }
241
242    /// Returns true if any templates were removed.
243    pub(crate) fn remove_template_for_font_face_rule(
244        &mut self,
245        removed_rule: &FontFaceRuleDescriptors,
246    ) -> bool {
247        let old_length = self.templates.len();
248        self.templates
249            .retain(|template| !template.borrow().is_defined_by_font_face_rule(removed_rule));
250
251        if let Some(simple_family) = self.simple_family.as_mut() {
252            simple_family.remove_templates_for_font_face_rule(removed_rule);
253        }
254
255        self.templates.len() != old_length
256    }
257
258    pub(crate) fn for_all_identifiers(&self, mut callback: impl FnMut(&FontIdentifier)) {
259        for template in self.templates.iter() {
260            callback(&template.borrow().identifier);
261        }
262        if let Some(ref simple_family) = self.simple_family {
263            simple_family.for_all_identifiers(callback)
264        }
265    }
266}