fonts: Add more types to fonts_traits (#38898)

This is necessary so that `constellation_traits` can get these types via
a
dependency on `fonts_traits`. This will allow sending IPC channels to
shared
workers so that they can have access to a shared `FontContext` from
`script`.

Testing: This just moves code between crates, so is covered by existing
tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-08-24 12:36:59 -07:00 committed by GitHub
parent 0b5bcfbf17
commit 3a97d4eed2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 495 additions and 446 deletions

View file

@ -13,12 +13,12 @@ use core_foundation::string::{CFString, CFStringRef};
use core_foundation::url::{CFURL, kCFURLPOSIXPathStyle};
use core_graphics::display::CFDictionary;
use core_text::font_descriptor::{kCTFontURLAttribute, kCTFontVariationAttribute};
use fonts_traits::FontIdentifier;
use parking_lot::RwLock;
use webrender_api::FontVariation;
use crate::FontData;
use crate::platform::font::PlatformFont;
use crate::system_font_service::FontIdentifier;
/// A cache of `CTFont` to avoid having to create `CTFont` instances over and over. It is
/// always possible to create a `CTFont` using a `FontTemplate` even if it isn't in this

View file

@ -17,16 +17,16 @@ use core_text::font_descriptor::{
CTFontTraits, SymbolicTraitAccessors, TraitAccessors, kCTFontDefaultOrientation,
};
use euclid::default::{Point2D, Rect, Size2D};
use fonts_traits::{FontIdentifier, LocalFontIdentifier};
use log::debug;
use skrifa::Tag;
use style::values::computed::font::{FontStretch, FontStyle, FontWeight};
use webrender_api::{FontInstanceFlags, FontVariation};
use super::core_text_font_cache::CoreTextFontCache;
use super::font_list::LocalFontIdentifier;
use crate::{
CBDT, COLR, FontData, FontIdentifier, FontMetrics, FontTableMethods, FontTemplateDescriptor,
FractionalPixel, GlyphId, KERN, PlatformFontMethods, SBIX, map_platform_values_to_style_values,
CBDT, COLR, FontData, FontMetrics, FontTableMethods, FontTemplateDescriptor, FractionalPixel,
GlyphId, KERN, PlatformFontMethods, SBIX, map_platform_values_to_style_values,
};
const KERN_PAIR_LEN: usize = 6;

View file

@ -2,107 +2,20 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::fs::File;
use std::path::Path;
use base::text::{UnicodeBlock, UnicodeBlockMethod, unicode_plane};
use log::{debug, warn};
use malloc_size_of_derive::MallocSizeOf;
use memmap2::Mmap;
use read_fonts::types::NameId;
use read_fonts::{FileRef, TableProvider as _};
use serde::{Deserialize, Serialize};
use fonts_traits::LocalFontIdentifier;
use log::debug;
use style::Atom;
use style::values::computed::font::GenericFontFamily;
use unicode_script::Script;
use webrender_api::NativeFontHandle;
use crate::platform::add_noto_fallback_families;
use crate::platform::font::CoreTextFontTraitsMapping;
use crate::{
EmojiPresentationPreference, FallbackFontSelectionOptions, FontData, FontDataAndIndex,
FontIdentifier, FontTemplate, FontTemplateDescriptor, LowercaseFontFamilyName,
EmojiPresentationPreference, FallbackFontSelectionOptions, FontIdentifier, FontTemplate,
FontTemplateDescriptor, LowercaseFontFamilyName,
};
/// An identifier for a local font on a MacOS system. These values comes from the CoreText
/// CTFontCollection. Note that `path` here is required. We do not load fonts that do not
/// have paths.
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub struct LocalFontIdentifier {
pub postscript_name: Atom,
pub path: Atom,
}
impl LocalFontIdentifier {
pub(crate) fn native_font_handle(&self) -> NativeFontHandle {
NativeFontHandle {
name: self.postscript_name.to_string(),
path: self.path.to_string(),
}
}
pub(crate) fn index(&self) -> u32 {
0
}
pub(crate) fn font_data_and_index(&self) -> Option<FontDataAndIndex> {
let file = File::open(Path::new(&*self.path)).ok()?;
let mmap = unsafe { Mmap::map(&file).ok()? };
// Determine index
let file_ref = FileRef::new(mmap.as_ref()).ok()?;
let index = ttc_index_from_postscript_name(file_ref, &self.postscript_name);
Some(FontDataAndIndex {
data: FontData::from_bytes(&mmap),
index,
})
}
}
/// CoreText font enumeration gives us a Postscript name rather than an index.
/// This functions maps from a Postscript name to an index.
///
/// This mapping works for single-font files and for simple TTC files, but may not work in all cases.
/// We are not 100% sure which cases (if any) will not work. But we suspect that variable fonts may cause
/// issues due to the Postscript names corresponding to instances not being straightforward, and the possibility
/// that CoreText may return a non-standard in that scenerio.
fn ttc_index_from_postscript_name(font_file: FileRef<'_>, postscript_name: &str) -> u32 {
match font_file {
// File only contains one font: simply return 0
FileRef::Font(_) => 0,
// File is a collection: iterate through each font in the collection and check
// whether the name matches
FileRef::Collection(collection) => {
for i in 0..collection.len() {
let font = collection.get(i).unwrap();
let name_table = font.name().unwrap();
if name_table
.name_record()
.iter()
.filter(|record| record.name_id() == NameId::POSTSCRIPT_NAME)
.any(|record| {
record
.string(name_table.string_data())
.unwrap()
.chars()
.eq(postscript_name.chars())
})
{
return i;
}
}
// If we fail to find a font, just use the first font in the file.
warn!(
"Font with postscript_name {} not found in collection",
postscript_name
);
0
},
}
}
pub fn for_each_available_family<F>(mut callback: F)
where
F: FnMut(String),