Files
servo/components/gfx/platform/macos/font_list.rs
Martin Robinson e5fbb3d487 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.
2024-03-14 11:31:00 +00:00

217 lines
8.4 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* 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 log::debug;
use serde::{Deserialize, Serialize};
use style::Atom;
use ucd::{Codepoint, UnicodeBlock};
use crate::text::util::unicode_plane;
/// 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, PartialEq, Serialize)]
pub struct LocalFontIdentifier {
pub postscript_name: Atom,
pub path: Atom,
}
pub fn for_each_available_family<F>(mut callback: F)
where
F: FnMut(String),
{
let family_names = core_text::font_collection::get_family_names();
for family_name in family_names.iter() {
callback(family_name.to_string());
}
}
pub fn for_each_variation<F>(family_name: &str, mut callback: F)
where
F: FnMut(LocalFontIdentifier),
{
debug!("Looking for faces of family: {}", family_name);
let family_collection = core_text::font_collection::create_for_family(family_name);
if let Some(family_collection) = family_collection {
if let Some(family_descriptors) = family_collection.get_descriptors() {
for family_descriptor in family_descriptors.iter() {
let path = family_descriptor.font_path();
let path = match path.as_ref().and_then(|path| path.to_str()) {
Some(path) => path,
None => continue,
};
callback(LocalFontIdentifier {
postscript_name: Atom::from(family_descriptor.font_name()),
path: Atom::from(path),
})
}
}
}
}
pub fn system_default_family(_generic_name: &str) -> Option<String> {
None
}
// Based on gfxPlatformMac::GetCommonFallbackFonts() in Gecko
pub fn fallback_font_families(codepoint: Option<char>) -> Vec<&'static str> {
let mut families = vec!["Lucida Grande"];
if let Some(codepoint) = codepoint {
match unicode_plane(codepoint) {
// https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
0 => {
if let Some(block) = codepoint.block() {
match block {
UnicodeBlock::Arabic |
UnicodeBlock::Syriac |
UnicodeBlock::ArabicSupplement |
UnicodeBlock::Thaana |
UnicodeBlock::NKo => {
families.push("Geeza Pro");
},
UnicodeBlock::Devanagari => {
families.push("Devanagari Sangam MN");
},
UnicodeBlock::Gurmukhi => {
families.push("Gurmukhi MN");
},
UnicodeBlock::Gujarati => {
families.push("Gujarati Sangam MN");
},
UnicodeBlock::Tamil => {
families.push("Tamil MN");
},
UnicodeBlock::Lao => {
families.push("Lao MN");
},
UnicodeBlock::Tibetan => {
families.push("Songti SC");
},
UnicodeBlock::Myanmar => {
families.push("Myanmar MN");
},
UnicodeBlock::Ethiopic |
UnicodeBlock::EthiopicSupplement |
UnicodeBlock::EthiopicExtended |
UnicodeBlock::EthiopicExtendedA => {
families.push("Kefa");
},
UnicodeBlock::Cherokee => {
families.push("Plantagenet Cherokee");
},
UnicodeBlock::UnifiedCanadianAboriginalSyllabics |
UnicodeBlock::UnifiedCanadianAboriginalSyllabicsExtended => {
families.push("Euphemia UCAS");
},
UnicodeBlock::Mongolian |
UnicodeBlock::YiSyllables |
UnicodeBlock::YiRadicals => {
families.push("STHeiti");
},
UnicodeBlock::Khmer | UnicodeBlock::KhmerSymbols => {
families.push("Khmer MN");
},
UnicodeBlock::TaiLe => {
families.push("Microsoft Tai Le");
},
UnicodeBlock::GeneralPunctuation |
UnicodeBlock::SuperscriptsandSubscripts |
UnicodeBlock::CurrencySymbols |
UnicodeBlock::CombiningDiacriticalMarksforSymbols |
UnicodeBlock::LetterlikeSymbols |
UnicodeBlock::NumberForms |
UnicodeBlock::Arrows |
UnicodeBlock::MathematicalOperators |
UnicodeBlock::MiscellaneousTechnical |
UnicodeBlock::ControlPictures |
UnicodeBlock::OpticalCharacterRecognition |
UnicodeBlock::EnclosedAlphanumerics |
UnicodeBlock::BoxDrawing |
UnicodeBlock::BlockElements |
UnicodeBlock::GeometricShapes |
UnicodeBlock::MiscellaneousSymbols |
UnicodeBlock::Dingbats |
UnicodeBlock::MiscellaneousMathematicalSymbolsA |
UnicodeBlock::SupplementalArrowsA |
UnicodeBlock::SupplementalArrowsB |
UnicodeBlock::MiscellaneousMathematicalSymbolsB |
UnicodeBlock::SupplementalMathematicalOperators |
UnicodeBlock::MiscellaneousSymbolsandArrows |
UnicodeBlock::SupplementalPunctuation => {
families.push("Hiragino Kaku Gothic ProN");
families.push("Apple Symbols");
families.push("Menlo");
families.push("STIXGeneral");
},
UnicodeBlock::BraillePatterns => {
families.push("Apple Braille");
},
UnicodeBlock::Bopomofo |
UnicodeBlock::HangulCompatibilityJamo |
UnicodeBlock::Kanbun |
UnicodeBlock::BopomofoExtended |
UnicodeBlock::CJKStrokes |
UnicodeBlock::KatakanaPhoneticExtensions => {
families.push("Hiragino Sans GB");
},
UnicodeBlock::YijingHexagramSymbols |
UnicodeBlock::CyrillicExtendedB |
UnicodeBlock::Bamum |
UnicodeBlock::ModifierToneLetters |
UnicodeBlock::LatinExtendedD |
UnicodeBlock::ArabicPresentationFormsA |
UnicodeBlock::HalfwidthandFullwidthForms |
UnicodeBlock::Specials => {
families.push("Apple Symbols");
},
_ => {},
}
}
},
// https://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Multilingual_Plane
1 => {
families.push("Apple Symbols");
families.push("STIXGeneral");
},
// https://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Ideographic_Plane
2 => {
// Systems with MS Office may have these fonts
families.push("MingLiU-ExtB");
families.push("SimSun-ExtB");
},
_ => {},
}
}
families.push("Geneva");
families.push("Arial Unicode MS");
families
}
pub static SANS_SERIF_FONT_FAMILY: &'static str = "Helvetica";