Bug 1866105 - Add the font file path to the font descriptor sent to webrender on macOS. r=gfx-reviewers,lsalzman

This allows us to skip additional font registration in content processes,
as it ensures consistent resolution of the font descriptor even when there
are multiple font resources with the same psname present.

Differential Revision: https://phabricator.services.mozilla.com/D195418
This commit is contained in:
Jonathan Kew 2023-12-05 10:59:06 +00:00
Родитель c619ad7090
Коммит 5ce9bfb3a4
6 изменённых файлов: 84 добавлений и 25 удалений

Просмотреть файл

@ -374,7 +374,7 @@ bool UnscaledFontMac::GetFontDescriptor(FontDescriptorOutput aCb,
return false;
}
char buf[256];
char buf[1024];
const char* cstr = CFStringGetCStringPtr(psname, kCFStringEncodingUTF8);
if (!cstr) {
if (!CFStringGetCString(psname, buf, sizeof(buf), kCFStringEncodingUTF8)) {
@ -383,7 +383,28 @@ bool UnscaledFontMac::GetFontDescriptor(FontDescriptorOutput aCb,
cstr = buf;
}
aCb(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr), 0, aBaton);
nsAutoCString descriptor(cstr);
uint32_t psNameLen = descriptor.Length();
AutoRelease<CTFontRef> ctFont(
CTFontCreateWithGraphicsFont(mFont, 0, nullptr, nullptr));
AutoRelease<CFURLRef> fontUrl(
(CFURLRef)CTFontCopyAttribute(ctFont, kCTFontURLAttribute));
if (fontUrl) {
CFStringRef urlStr(CFURLCopyFileSystemPath(fontUrl, kCFURLPOSIXPathStyle));
cstr = CFStringGetCStringPtr(urlStr, kCFStringEncodingUTF8);
if (!cstr) {
if (!CFStringGetCString(urlStr, buf, sizeof(buf),
kCFStringEncodingUTF8)) {
return false;
}
cstr = buf;
}
descriptor.Append(cstr);
}
aCb(reinterpret_cast<const uint8_t*>(descriptor.get()), descriptor.Length(),
psNameLen, aBaton);
return true;
}
@ -763,17 +784,39 @@ already_AddRefed<UnscaledFont> UnscaledFontMac::CreateFromFontDescriptor(
gfxWarning() << "Mac font descriptor is truncated.";
return nullptr;
}
CFStringRef name =
CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)aData,
aDataLength, kCFStringEncodingUTF8, false);
AutoRelease<CFStringRef> name(
CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)aData, aIndex,
kCFStringEncodingUTF8, false));
if (!name) {
return nullptr;
}
CGFontRef font = CGFontCreateWithFontName(name);
CFRelease(name);
if (!font) {
return nullptr;
}
// If the descriptor included a font file path, apply that attribute and
// refresh the font in case it changed.
if (aIndex < aDataLength) {
AutoRelease<CFStringRef> path(CFStringCreateWithBytes(
kCFAllocatorDefault, (const UInt8*)aData + aIndex, aDataLength - aIndex,
kCFStringEncodingUTF8, false));
AutoRelease<CFURLRef> url(CFURLCreateWithFileSystemPath(
kCFAllocatorDefault, path, kCFURLPOSIXPathStyle, false));
AutoRelease<CFDictionaryRef> attrs(CFDictionaryCreate(
nullptr, (const void**)&kCTFontURLAttribute, (const void**)&url, 1,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
AutoRelease<CTFontRef> ctFont(
CTFontCreateWithGraphicsFont(font, 0.0, nullptr, nullptr));
AutoRelease<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(ctFont));
AutoRelease<CTFontDescriptorRef> newDesc(
CTFontDescriptorCreateCopyWithAttributes(desc, attrs));
AutoRelease<CTFontRef> newFont(
CTFontCreateWithFontDescriptor(newDesc, 0.0, nullptr));
CFRelease(font);
font = CTFontCopyGraphicsFont(newFont, nullptr);
}
RefPtr<UnscaledFont> unscaledFont = new UnscaledFontMac(font);
CFRelease(font);
return unscaledFont.forget();

Просмотреть файл

@ -72,6 +72,10 @@ class UnscaledFontMac final : public UnscaledFont {
uint32_t aVariationCount,
const FontVariation* aVariations);
// Generate a font descriptor to send to WebRender. The descriptor consists
// of a string that concatenates the PostScript name of the font and the path
// to the font file, and an "index" that indicates the length of the psname
// part of the string (= starting offset of the path).
bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override;
CFArrayRef& CGAxesCache() { return mCGAxesCache; }

Просмотреть файл

@ -74,21 +74,12 @@ PRThread* gfxPlatformMac::sFontRegistrationThread = nullptr;
our font list. */
/* static */
void gfxPlatformMac::RegisterSupplementalFonts() {
switch (XRE_GetProcessType()) {
case GeckoProcessType_Default:
case GeckoProcessType_Content:
// TODO: figure out if this matters to any other processes (e.g. GPU?)
//
// We activate the fonts on a separate thread, to minimize the startup-
// time cost.
sFontRegistrationThread = PR_CreateThread(
PR_USER_THREAD, FontRegistrationCallback, nullptr, PR_PRIORITY_NORMAL,
PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
break;
default:
// Assume other process types don't actually need the full font list.
break;
if (XRE_GetProcessType() == GeckoProcessType_Default) {
// We activate the fonts on a separate thread, to minimize the startup-
// time cost.
sFontRegistrationThread = PR_CreateThread(
PR_USER_THREAD, FontRegistrationCallback, nullptr, PR_PRIORITY_NORMAL,
PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
}
}

Просмотреть файл

@ -2303,10 +2303,16 @@ fn read_font_descriptor(bytes: &mut WrVecU8, index: u32) -> NativeFontHandle {
}
#[cfg(target_os = "macos")]
fn read_font_descriptor(bytes: &mut WrVecU8, _index: u32) -> NativeFontHandle {
fn read_font_descriptor(bytes: &mut WrVecU8, index: u32) -> NativeFontHandle {
// On macOS, the descriptor string is a concatenation of the PostScript name
// and the font file path (to disambiguate cases where there are multiple
// faces with the same psname present). The index is the length of the psname
// portion of the descriptor (= starting offset of the path).
// Here, we split the descriptor into its two components for further use.
let chars = bytes.flush_into_vec();
NativeFontHandle {
name: String::from_utf8(chars).unwrap(),
name: String::from_utf8(chars[..index as usize].to_vec()).unwrap_or("".to_string()),
path: String::from_utf8(chars[index as usize..].to_vec()).unwrap_or("".to_string()),
}
}

Просмотреть файл

@ -63,6 +63,7 @@ pub struct NativeFontHandle {
#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct NativeFontHandle {
pub name: String,
pub path: String,
}
#[repr(C)]

Просмотреть файл

@ -9,6 +9,7 @@ use core_foundation::base::TCFType;
use core_foundation::dictionary::CFDictionary;
use core_foundation::number::{CFNumber};
use core_foundation::string::CFString;
use core_foundation::url::{CFURL, kCFURLPOSIXPathStyle};
use core_graphics::base::{kCGImageAlphaNoneSkipFirst, kCGImageAlphaPremultipliedFirst};
use core_graphics::base::{kCGBitmapByteOrder32Little};
use core_graphics::color_space::CGColorSpace;
@ -19,7 +20,7 @@ use core_graphics::geometry::{CGAffineTransform, CGPoint, CGSize};
use core_graphics::geometry::{CG_AFFINE_TRANSFORM_IDENTITY, CGRect};
use core_text;
use core_text::font::CTFont;
use core_text::font_descriptor::{CTFontDescriptor, kCTFontDefaultOrientation, kCTFontVariationAttribute};
use core_text::font_descriptor::{CTFontDescriptor, kCTFontDefaultOrientation, kCTFontURLAttribute, kCTFontVariationAttribute};
use core_text::font_manager;
use euclid::default::Size2D;
use crate::gamma_lut::{ColorLut, GammaLut};
@ -282,7 +283,7 @@ impl FontContext {
// we can't instantiate CTFonts via a descriptor. We're really
// supposed to use CTFontCreateUIFontForLanguage, but for now
// we just use the CGFont.
let desc = if native_font_handle.name.starts_with('.') {
let mut desc = if native_font_handle.name.starts_with('.') {
let cg_font = match CGFont::from_name(&cf_name) {
Ok(cg_font) => cg_font,
Err(_) => {
@ -300,6 +301,19 @@ impl FontContext {
core_text::font_descriptor::new_from_postscript_name(&cf_name)
};
// If the NativeFontHandle includes a file path, add this to the descriptor
// to disambiguate cases where multiple installed fonts have the same psname.
if native_font_handle.path.len() > 0 {
let cf_path = CFString::new(&native_font_handle.path);
let url_attribute = unsafe { CFString::wrap_under_get_rule(kCTFontURLAttribute) };
let attrs = CFDictionary::from_CFType_pairs(&[
(url_attribute, CFURL::from_file_system_path(cf_path, kCFURLPOSIXPathStyle, false)),
]);
if let Ok(desc_with_path) = desc.create_copy_with_attributes(attrs.to_untyped()) {
desc = desc_with_path;
}
}
self.ct_font_descs
.insert(*font_key, desc);
}