fonts: Add FontIdentifier and LocalFontIdentifier (#31658)

Instead of using a simple `Atom` to identify a local font, use a data
structure. This allows us to carry more information necessary to
identify a local font (such as a path on MacOS). We need this for the
new version of WebRender, as fonts on MacOS now require a path.

This has a lot of benefits:
 1. We can avoid loading fonts without paths on MacOS, which should
    avoid a lot of problems with flakiness and ensure we always load the
    same font for a given identifier.
 2. This clarifies the difference between web fonts and local fonts,
    though there is more work to do here.
 3. This avoid a *lot* of font shenanigans, such as trying to work
    backwards from the name of the font to the path of the font we
    actually matched. In general, we can remove a lot of code trying to
    accomplish these shenanigans.
 4. Getting the font bytes always returns an `Arc` now avoiding an extra
    full font copy in the case of Canvas.
This commit is contained in:
Martin Robinson 2024-03-14 12:31:00 +01:00 committed by GitHub
parent b1debf2068
commit e5fbb3d487
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 365 additions and 320 deletions

View file

@ -13,7 +13,6 @@ use std::sync::Arc;
use app_units::Au;
use dwrote::{Font, FontFace, FontFile, FontStretch, FontStyle};
use log::debug;
use servo_atoms::Atom;
use style::computed_values::font_stretch::T as StyleFontStretch;
use style::computed_values::font_weight::T as StyleFontWeight;
use style::values::computed::font::FontStyle as StyleFontStyle;
@ -22,9 +21,9 @@ use style::values::specified::font::FontStretchKeyword;
use crate::font::{
FontHandleMethods, FontMetrics, FontTableMethods, FontTableTag, FractionalPixel,
};
use crate::font_cache_thread::FontIdentifier;
use crate::platform::font_template::FontTemplateData;
use crate::platform::windows::font_context::FontContextHandle;
use crate::platform::windows::font_list::font_from_atom;
use crate::text::glyph::GlyphId;
// 1em = 12pt = 16px, assuming 72 points per inch and 96 px per inch
@ -208,7 +207,6 @@ pub struct FontHandle {
face: Nondebug<FontFace>,
info: FontInfo,
em_size: f32,
du_per_em: f32,
du_to_px: f32,
scaled_du_to_px: f32,
}
@ -236,24 +234,17 @@ impl FontHandleMethods for FontHandle {
template: Arc<FontTemplateData>,
pt_size: Option<Au>,
) -> Result<Self, ()> {
let (info, face) = if let Some(ref raw_font) = template.bytes {
let font_file = FontFile::new_from_data(Arc::new(raw_font.clone()));
if font_file.is_none() {
// failed to load raw font
return Err(());
}
let face = font_file
.unwrap()
.create_face(0, dwrote::DWRITE_FONT_SIMULATIONS_NONE)
.map_err(|_| ())?;
let info = FontInfo::new_from_face(&face)?;
(info, face)
} else {
let font = font_from_atom(&template.identifier);
let face = font.create_font_face();
let info = FontInfo::new_from_font(&font)?;
(info, face)
let (face, info) = match template.get_font() {
Some(font) => (font.create_font_face(), FontInfo::new_from_font(&font)?),
None => {
let bytes = template.bytes();
let font_file = FontFile::new_from_data(bytes).ok_or(())?;
let face = font_file
.create_face(0, dwrote::DWRITE_FONT_SIMULATIONS_NONE)
.map_err(|_| ())?;
let info = FontInfo::new_from_face(&face)?;
(face, info)
},
};
let pt_size = pt_size.unwrap_or(au_from_pt(12.));
@ -268,9 +259,8 @@ impl FontHandleMethods for FontHandle {
Ok(FontHandle {
font_data: template.clone(),
face: Nondebug(face),
info: info,
em_size: em_size,
du_per_em: du_per_em,
info,
em_size,
du_to_px: design_units_to_pixels,
scaled_du_to_px: scaled_design_units_to_pixels,
})
@ -366,7 +356,7 @@ impl FontHandleMethods for FontHandle {
.map(|bytes| FontTable { data: bytes })
}
fn identifier(&self) -> Atom {
self.font_data.identifier.clone()
fn identifier(&self) -> &FontIdentifier {
&self.font_data.identifier
}
}