1 /* -*- Mode: ObjC; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * ***** BEGIN LICENSE BLOCK *****
5 * Copyright (C) 2006-2009 Mozilla Corporation. All rights reserved.
8 * Vladimir Vukicevic <vladimir@pobox.com>
9 * Masayuki Nakano <masayuki@d-toybox.com>
10 * John Daggett <jdaggett@mozilla.com>
11 * Jonathan Kew <jfkthame@gmail.com>
13 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
25 * its contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
29 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * ***** END LICENSE BLOCK ***** */
41 #include "mozilla/Logging.h"
45 #import <AppKit/AppKit.h>
47 #include "gfxFontConstants.h"
48 #include "gfxPlatformMac.h"
49 #include "gfxMacPlatformFontList.h"
50 #include "gfxMacFont.h"
51 #include "gfxUserFontSet.h"
52 #include "SharedFontList-impl.h"
54 #include "harfbuzz/hb.h"
56 #include "AppleUtils.h"
57 #include "MainThreadUtils.h"
58 #include "nsDirectoryServiceUtils.h"
59 #include "nsDirectoryServiceDefs.h"
60 #include "nsAppDirectoryServiceDefs.h"
61 #include "nsIDirectoryEnumerator.h"
62 #include "nsCharTraits.h"
63 #include "nsCocoaFeatures.h"
64 #include "nsCocoaUtils.h"
65 #include "nsComponentManagerUtils.h"
66 #include "nsServiceManagerUtils.h"
69 #include "mozilla/dom/ContentChild.h"
70 #include "mozilla/dom/ContentParent.h"
71 #include "mozilla/FontPropertyTypes.h"
72 #include "mozilla/MemoryReporting.h"
73 #include "mozilla/Preferences.h"
74 #include "mozilla/ProfilerLabels.h"
75 #include "mozilla/Sprintf.h"
76 #include "mozilla/StaticPrefs_gfx.h"
77 #include "mozilla/Telemetry.h"
78 #include "mozilla/gfx/2D.h"
84 #include "StandardFonts-macos.inc"
86 using namespace mozilla;
87 using namespace mozilla::gfx;
89 // indexes into the NSArray objects that the Cocoa font manager returns
90 // as the available members of a family
91 #define INDEX_FONT_POSTSCRIPT_NAME 0
92 #define INDEX_FONT_FACE_NAME 1
93 #define INDEX_FONT_WEIGHT 2
94 #define INDEX_FONT_TRAITS 3
96 static const int kAppleMaxWeight = 14;
97 static const int kAppleExtraLightWeight = 3;
98 static const int kAppleUltraLightWeight = 2;
100 static const int gAppleWeightToCSSWeight[] = {
103 1, // 2. W1, ultralight
104 2, // 3. W2, extralight
106 4, // 5. W4, semilight
109 6, // 8. W6, semibold
111 8, // 10. W8, extrabold
113 9, // 12. W9, ultrabold
118 // cache Cocoa's "shared font manager" for performance
119 static NSFontManager* sFontManager;
121 static void GetStringForNSString(const NSString* aSrc, nsAString& aDest) {
122 aDest.SetLength([aSrc length]);
123 [aSrc getCharacters:reinterpret_cast<unichar*>(aDest.BeginWriting())
124 range:NSMakeRange(0, [aSrc length])];
127 static NSString* GetNSStringForString(const nsAString& aSrc) {
128 return [NSString stringWithCharacters:reinterpret_cast<const unichar*>(aSrc.BeginReading())
129 length:aSrc.Length()];
132 #define LOG_FONTLIST(args) \
133 MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), mozilla::LogLevel::Debug, args)
134 #define LOG_FONTLIST_ENABLED() \
135 MOZ_LOG_TEST(gfxPlatform::GetLog(eGfxLog_fontlist), mozilla::LogLevel::Debug)
136 #define LOG_CMAPDATA_ENABLED() \
137 MOZ_LOG_TEST(gfxPlatform::GetLog(eGfxLog_cmapdata), mozilla::LogLevel::Debug)
141 // Complex scripts will not render correctly unless appropriate AAT or OT
142 // layout tables are present.
143 // For OpenType, we also check that the GSUB table supports the relevant
144 // script tag, to avoid using things like Arial Unicode MS for Lao (it has
145 // the characters, but lacks OpenType support).
147 // TODO: consider whether we should move this to gfxFontEntry and do similar
148 // cmap-masking on other platforms to avoid using fonts that won't shape
151 nsresult MacOSFontEntry::ReadCMAP(FontInfoData* aFontInfoData) {
152 // attempt this once, if errors occur leave a blank cmap
153 if (mCharacterMap || mShmemCharacterMap) {
157 RefPtr<gfxCharacterMap> charmap;
160 if (aFontInfoData && (charmap = GetCMAPFromFontInfo(aFontInfoData, mUVSOffset))) {
163 uint32_t kCMAP = TRUETYPE_TAG('c', 'm', 'a', 'p');
164 charmap = new gfxCharacterMap();
165 AutoTable cmapTable(this, kCMAP);
169 const uint8_t* cmapData =
170 reinterpret_cast<const uint8_t*>(hb_blob_get_data(cmapTable, &cmapLen));
171 rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen, *charmap, mUVSOffset);
173 rv = NS_ERROR_NOT_AVAILABLE;
177 if (NS_SUCCEEDED(rv) && !mIsDataUserFont && !HasGraphiteTables()) {
178 // For downloadable fonts, trust the author and don't
179 // try to munge the cmap based on script shaping support.
181 // We also assume a Graphite font knows what it's doing,
182 // and provides whatever shaping is needed for the
183 // characters it supports, so only check/clear the
184 // complex-script ranges for non-Graphite fonts
186 // for layout support, check for the presence of mort/morx/kerx and/or
187 // opentype layout tables
188 bool hasAATLayout = HasFontTable(TRUETYPE_TAG('m', 'o', 'r', 'x')) ||
189 HasFontTable(TRUETYPE_TAG('m', 'o', 'r', 't'));
190 bool hasAppleKerning = HasFontTable(TRUETYPE_TAG('k', 'e', 'r', 'x'));
191 bool hasGSUB = HasFontTable(TRUETYPE_TAG('G', 'S', 'U', 'B'));
192 bool hasGPOS = HasFontTable(TRUETYPE_TAG('G', 'P', 'O', 'S'));
193 if ((hasAATLayout && !(hasGSUB || hasGPOS)) || hasAppleKerning) {
194 mRequiresAAT = true; // prefer CoreText if font has no OTL tables,
195 // or if it uses the Apple-specific 'kerx'
196 // variant of kerning table
199 for (const ScriptRange* sr = gfxPlatformFontList::sComplexScriptRanges; sr->rangeStart; sr++) {
200 // check to see if the cmap includes complex script codepoints
201 if (charmap->TestRange(sr->rangeStart, sr->rangeEnd)) {
203 // prefer CoreText for Apple's complex-script fonts,
204 // even if they also have some OpenType tables
205 // (e.g. Geeza Pro Bold on 10.6; see bug 614903)
207 // and don't mask off complex-script ranges, we assume
208 // the AAT tables will provide the necessary shaping
212 // We check for GSUB here, as GPOS alone would not be ok.
213 if (hasGSUB && SupportsScriptInGSUB(sr->tags, sr->numTags)) {
217 charmap->ClearRange(sr->rangeStart, sr->rangeEnd);
221 // Bug 1360309, 1393624: several of Apple's Chinese fonts have spurious
222 // blank glyphs for obscure Tibetan and Arabic-script codepoints.
223 // Blocklist these so that font fallback will not use them.
225 (FamilyName().EqualsLiteral("Songti SC") || FamilyName().EqualsLiteral("Songti TC") ||
226 FamilyName().EqualsLiteral("STSong") ||
227 // Bug 1390980: on 10.11, the Kaiti fonts are also affected.
228 FamilyName().EqualsLiteral("Kaiti SC") || FamilyName().EqualsLiteral("Kaiti TC") ||
229 FamilyName().EqualsLiteral("STKaiti"))) {
230 charmap->ClearRange(0x0f6b, 0x0f70);
231 charmap->ClearRange(0x0f8c, 0x0f8f);
232 charmap->clear(0x0f98);
233 charmap->clear(0x0fbd);
234 charmap->ClearRange(0x0fcd, 0x0fff);
235 charmap->clear(0x0620);
236 charmap->clear(0x065f);
237 charmap->ClearRange(0x06ee, 0x06ef);
238 charmap->clear(0x06ff);
242 mHasCmapTable = NS_SUCCEEDED(rv);
244 gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
245 fontlist::FontList* sharedFontList = pfl->SharedFontList();
246 if (!IsUserFont() && mShmemFace) {
247 mShmemFace->SetCharacterMap(sharedFontList, charmap); // async
248 if (!TrySetShmemCharacterMap()) {
249 // Temporarily retain charmap, until the shared version is
251 mCharacterMap = charmap;
254 mCharacterMap = pfl->FindCharMap(charmap);
257 // if error occurred, initialize to null cmap
258 mCharacterMap = new gfxCharacterMap();
261 LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %zu hash: %8.8x%s\n", mName.get(),
262 charmap->SizeOfIncludingThis(moz_malloc_size_of), charmap->mHash,
263 mCharacterMap == charmap ? " new" : ""));
264 if (LOG_CMAPDATA_ENABLED()) {
266 SprintfLiteral(prefix, "(cmapdata) name: %.220s", mName.get());
267 charmap->Dump(prefix, eGfxLog_cmapdata);
273 gfxFont* MacOSFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle) {
274 RefPtr<UnscaledFontMac> unscaledFont(mUnscaledFont);
276 CGFontRef baseFont = GetFontRef();
280 unscaledFont = new UnscaledFontMac(baseFont, mIsDataUserFont);
281 mUnscaledFont = unscaledFont;
284 return new gfxMacFont(unscaledFont, this, aFontStyle);
287 bool MacOSFontEntry::HasVariations() {
288 if (!mHasVariationsInitialized) {
289 mHasVariationsInitialized = true;
290 mHasVariations = gfxPlatform::GetPlatform()->HasVariationFontSupport() &&
291 HasFontTable(TRUETYPE_TAG('f', 'v', 'a', 'r'));
294 return mHasVariations;
297 void MacOSFontEntry::GetVariationAxes(nsTArray<gfxFontVariationAxis>& aVariationAxes) {
298 // We could do this by creating a CTFont and calling CTFontCopyVariationAxes,
299 // but it is expensive to instantiate a CTFont for every face just to set up
300 // the axis information.
301 // Instead we use gfxFontUtils to read the font tables directly.
302 gfxFontUtils::GetVariationData(this, &aVariationAxes, nullptr);
305 void MacOSFontEntry::GetVariationInstances(nsTArray<gfxFontVariationInstance>& aInstances) {
306 // Core Text doesn't offer API for this, so we use gfxFontUtils to read the
307 // font tables directly.
308 gfxFontUtils::GetVariationData(this, nullptr, &aInstances);
311 bool MacOSFontEntry::IsCFF() {
312 if (!mIsCFFInitialized) {
313 mIsCFFInitialized = true;
314 mIsCFF = HasFontTable(TRUETYPE_TAG('C', 'F', 'F', ' '));
320 MacOSFontEntry::MacOSFontEntry(const nsACString& aPostscriptName, WeightRange aWeight,
321 bool aIsStandardFace, double aSizeHint)
322 : gfxFontEntry(aPostscriptName, aIsStandardFace),
324 mSizeHint(aSizeHint),
325 mFontRefInitialized(false),
328 mIsCFFInitialized(false),
329 mHasVariations(false),
330 mHasVariationsInitialized(false),
331 mHasAATSmallCaps(false),
332 mHasAATSmallCapsInitialized(false) {
333 mWeightRange = aWeight;
337 MacOSFontEntry::MacOSFontEntry(const nsACString& aPostscriptName, CGFontRef aFontRef,
338 WeightRange aWeight, StretchRange aStretch, SlantStyleRange aStyle,
339 bool aIsDataUserFont, bool aIsLocalUserFont)
340 : gfxFontEntry(aPostscriptName, false),
343 mFontRefInitialized(false),
346 mIsCFFInitialized(false),
347 mHasVariations(false),
348 mHasVariationsInitialized(false),
349 mHasAATSmallCaps(false),
350 mHasAATSmallCapsInitialized(false) {
352 mFontRefInitialized = true;
353 ::CFRetain(mFontRef);
355 mWeightRange = aWeight;
356 mStretchRange = aStretch;
357 mFixedPitch = false; // xxx - do we need this for downloaded fonts?
358 mStyleRange = aStyle;
361 NS_ASSERTION(!(aIsDataUserFont && aIsLocalUserFont),
362 "userfont is either a data font or a local font");
363 mIsDataUserFont = aIsDataUserFont;
364 mIsLocalUserFont = aIsLocalUserFont;
367 gfxFontEntry* MacOSFontEntry::Clone() const {
368 MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!");
369 MacOSFontEntry* fe = new MacOSFontEntry(Name(), Weight(), mStandardFace, mSizeHint);
370 fe->mStyleRange = mStyleRange;
371 fe->mStretchRange = mStretchRange;
372 fe->mFixedPitch = mFixedPitch;
376 CGFontRef MacOSFontEntry::GetFontRef() {
377 if (!mFontRefInitialized) {
378 // Cache the CGFontRef, to be released by our destructor.
379 mFontRef = CreateOrCopyFontRef();
380 mFontRefInitialized = true;
382 // Return a non-retained reference; caller does not need to release.
386 CGFontRef MacOSFontEntry::CreateOrCopyFontRef() {
388 // We have a cached CGFont, just add a reference. Caller must
389 // release, but we'll still own our reference.
390 ::CGFontRetain(mFontRef);
393 // Create a new CGFont; caller will own the only reference to it.
394 NSString* psname = GetNSStringForString(NS_ConvertUTF8toUTF16(mName));
395 CGFontRef ref = CGFontCreateWithFontName(CFStringRef(psname));
397 CrashReporter::AutoAnnotateCrashReport autoFontName(CrashReporter::Annotation::FontName,
400 // This happens on macOS 10.12 for font entry names that start with
401 // .AppleSystemUIFont. For those fonts, we need to go through NSFont
402 // to get the correct CGFontRef.
403 // Both the Text and the Display variant of the display font use
404 // .AppleSystemUIFontSomethingSomething as their member names.
405 // That's why we're carrying along mSizeHint to this place so that
406 // we get the variant that we want for this family.
407 NSFont* font = [NSFont fontWithName:psname size:mSizeHint];
409 ref = CTFontCopyGraphicsFont((CTFontRef)font, nullptr);
412 return ref; // Not saved in mFontRef; caller will own the reference
415 // For a logging build, we wrap the CFDataRef in a FontTableRec so that we can
416 // use the MOZ_COUNT_[CD]TOR macros in it. A release build without logging
417 // does not get this overhead.
420 explicit FontTableRec(CFDataRef aDataRef) : mDataRef(aDataRef) { MOZ_COUNT_CTOR(FontTableRec); }
423 MOZ_COUNT_DTOR(FontTableRec);
424 ::CFRelease(mDataRef);
431 /*static*/ void MacOSFontEntry::DestroyBlobFunc(void* aUserData) {
432 #ifdef NS_BUILD_REFCNT_LOGGING
433 FontTableRec* ftr = static_cast<FontTableRec*>(aUserData);
436 ::CFRelease((CFDataRef)aUserData);
440 hb_blob_t* MacOSFontEntry::GetFontTable(uint32_t aTag) {
441 AutoCFRelease<CGFontRef> fontRef = CreateOrCopyFontRef();
446 CFDataRef dataRef = ::CGFontCopyTableForTag(fontRef, aTag);
448 return hb_blob_create((const char*)::CFDataGetBytePtr(dataRef), ::CFDataGetLength(dataRef),
449 HB_MEMORY_MODE_READONLY,
450 #ifdef NS_BUILD_REFCNT_LOGGING
451 new FontTableRec(dataRef),
461 bool MacOSFontEntry::HasFontTable(uint32_t aTableTag) {
462 if (mAvailableTables.Count() == 0) {
463 nsAutoreleasePool localPool;
465 AutoCFRelease<CGFontRef> fontRef = CreateOrCopyFontRef();
469 AutoCFRelease<CFArrayRef> tags = ::CGFontCopyTableTags(fontRef);
473 int numTags = (int)::CFArrayGetCount(tags);
474 for (int t = 0; t < numTags; t++) {
475 uint32_t tag = (uint32_t)(uintptr_t)::CFArrayGetValueAtIndex(tags, t);
476 mAvailableTables.PutEntry(tag);
480 return mAvailableTables.GetEntry(aTableTag);
483 static bool CheckForAATSmallCaps(CFArrayRef aFeatures) {
484 // Walk the array of feature descriptors from the font, and see whether
485 // a small-caps feature setting is available.
486 // Just bail out (returning false) if at any point we fail to find the
487 // expected dictionary keys, etc; if the font has bad data, we don't even
488 // try to search the rest of it.
489 auto numFeatures = CFArrayGetCount(aFeatures);
490 for (auto f = 0; f < numFeatures; ++f) {
491 auto featureDict = (CFDictionaryRef)CFArrayGetValueAtIndex(aFeatures, f);
496 (CFNumberRef)CFDictionaryGetValue(featureDict, CFSTR("CTFeatureTypeIdentifier"));
501 if (!CFNumberGetValue(featureNum, kCFNumberSInt16Type, &featureType)) {
504 if (featureType == kLetterCaseType || featureType == kLowerCaseType) {
505 // Which selector to look for, depending whether we've found the
506 // legacy LetterCase feature or the new LowerCase one.
507 const uint16_t smallCaps =
508 (featureType == kLetterCaseType) ? kSmallCapsSelector : kLowerCaseSmallCapsSelector;
510 (CFArrayRef)CFDictionaryGetValue(featureDict, CFSTR("CTFeatureTypeSelectors"));
514 auto numSelectors = CFArrayGetCount(selectors);
515 for (auto s = 0; s < numSelectors; s++) {
516 auto selectorDict = (CFDictionaryRef)CFArrayGetValueAtIndex(selectors, s);
521 (CFNumberRef)CFDictionaryGetValue(selectorDict, CFSTR("CTFeatureSelectorIdentifier"));
525 int16_t selectorValue;
526 if (!CFNumberGetValue(selectorNum, kCFNumberSInt16Type, &selectorValue)) {
529 if (selectorValue == smallCaps) {
538 bool MacOSFontEntry::SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag) {
539 // If we're going to shape with Core Text, we don't support added
540 // OpenType features (aside from any CT applies by default), except
541 // for 'smcp' which we map to an AAT feature selector.
542 if (RequiresAATLayout()) {
543 if (aFeatureTag != HB_TAG('s', 'm', 'c', 'p')) {
546 if (mHasAATSmallCapsInitialized) {
547 return mHasAATSmallCaps;
549 mHasAATSmallCapsInitialized = true;
550 CGFontRef cgFont = GetFontRef();
552 return mHasAATSmallCaps;
554 AutoCFRelease<CTFontRef> ctFont = CTFontCreateWithGraphicsFont(cgFont, 0.0, nullptr, nullptr);
556 AutoCFRelease<CFArrayRef> features = CTFontCopyFeatures(ctFont);
558 mHasAATSmallCaps = CheckForAATSmallCaps(features);
561 return mHasAATSmallCaps;
563 return gfxFontEntry::SupportsOpenTypeFeature(aScript, aFeatureTag);
566 void MacOSFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
567 FontListSizes* aSizes) const {
568 aSizes->mFontListSize += aMallocSizeOf(this);
569 AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
572 /* gfxMacFontFamily */
575 class gfxMacFontFamily final : public gfxFontFamily {
577 gfxMacFontFamily(const nsACString& aName, FontVisibility aVisibility, double aSizeHint)
578 : gfxFontFamily(aName, aVisibility), mSizeHint(aSizeHint) {}
580 virtual ~gfxMacFontFamily() = default;
582 virtual void LocalizedName(nsACString& aLocalizedName);
584 virtual void FindStyleVariations(FontInfoData* aFontInfoData = nullptr);
590 void gfxMacFontFamily::LocalizedName(nsACString& aLocalizedName) {
591 nsAutoreleasePool localPool;
593 // It's unsafe to call HasOtherFamilyNames off the main thread because
594 // it entrains FindStyleVariations, which calls GetWeightOverride, which
595 // retrieves prefs. And the pref names can change (via user overrides),
596 // so we can't use StaticPrefs to access them.
597 if (NS_IsMainThread() && !HasOtherFamilyNames()) {
598 aLocalizedName = mName;
602 NSString* family = GetNSStringForString(NS_ConvertUTF8toUTF16(mName));
603 NSString* localized = [sFontManager localizedNameForFamily:family face:nil];
606 nsAutoString locName;
607 GetStringForNSString(localized, locName);
608 CopyUTF16toUTF8(locName, aLocalizedName);
612 // failed to get localized name, just use the canonical one
613 aLocalizedName = mName;
616 // Return the CSS weight value to use for the given face, overriding what
617 // AppKit gives us (used to adjust families with bad weight values, see
619 // A return value of 0 indicates no override - use the existing weight.
620 static inline int GetWeightOverride(const nsAString& aPSName) {
621 nsAutoCString prefName("font.weight-override.");
622 // The PostScript name is required to be ASCII; if it's not, the font is
623 // broken anyway, so we really don't care that this is lossy.
624 LossyAppendUTF16toASCII(aPSName, prefName);
625 return Preferences::GetInt(prefName.get(), 0);
628 void gfxMacFontFamily::FindStyleVariations(FontInfoData* aFontInfoData) {
633 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("gfxMacFontFamily::FindStyleVariations", LAYOUT, mName);
635 nsAutoreleasePool localPool;
637 NSString* family = GetNSStringForString(NS_ConvertUTF8toUTF16(mName));
639 // create a font entry for each face
640 NSArray* fontfaces = [sFontManager
641 availableMembersOfFontFamily:family]; // returns an array of [psname, style name, weight,
642 // traits] elements, goofy api
643 int faceCount = [fontfaces count];
646 for (faceIndex = 0; faceIndex < faceCount; faceIndex++) {
647 NSArray* face = [fontfaces objectAtIndex:faceIndex];
648 NSString* psname = [face objectAtIndex:INDEX_FONT_POSTSCRIPT_NAME];
649 int32_t appKitWeight = [[face objectAtIndex:INDEX_FONT_WEIGHT] unsignedIntValue];
650 uint32_t macTraits = [[face objectAtIndex:INDEX_FONT_TRAITS] unsignedIntValue];
651 NSString* facename = [face objectAtIndex:INDEX_FONT_FACE_NAME];
652 bool isStandardFace = false;
654 if (appKitWeight == kAppleExtraLightWeight) {
655 // if the facename contains UltraLight, set the weight to the ultralight weight value
656 NSRange range = [facename rangeOfString:@"ultralight" options:NSCaseInsensitiveSearch];
657 if (range.location != NSNotFound) {
658 appKitWeight = kAppleUltraLightWeight;
663 nsAutoString postscriptFontName;
664 GetStringForNSString(psname, postscriptFontName);
666 int32_t cssWeight = gfxMacPlatformFontList::AppleWeightToCSSWeight(appKitWeight);
667 // If we are on the startup-time InitFontList thread, we skip this as it
668 // wants to retrieve faces for the default font family, but cannot safely
669 // call the Preferences APIs. Fortunately, the default font doesn't actually
670 // depend on a weight override pref.
671 if (!gfxPlatformFontList::IsInitFontListThread()) {
672 int32_t weightOverride = GetWeightOverride(postscriptFontName);
673 if (weightOverride) {
674 // scale down and clamp, to get a value from 1..9
675 cssWeight = ((weightOverride + 50) / 100);
676 cssWeight = std::max(1, std::min(cssWeight, 9));
679 cssWeight *= 100; // scale up to CSS values
681 if ([facename isEqualToString:@"Regular"] || [facename isEqualToString:@"Bold"] ||
682 [facename isEqualToString:@"Italic"] || [facename isEqualToString:@"Oblique"] ||
683 [facename isEqualToString:@"Bold Italic"] || [facename isEqualToString:@"Bold Oblique"]) {
684 isStandardFace = true;
687 // create a font entry
688 MacOSFontEntry* fontEntry =
689 new MacOSFontEntry(NS_ConvertUTF16toUTF8(postscriptFontName),
690 WeightRange(FontWeight(cssWeight)), isStandardFace, mSizeHint);
695 // set additional properties based on the traits reported by Cocoa
696 if (macTraits & (NSCondensedFontMask | NSNarrowFontMask | NSCompressedFontMask)) {
697 fontEntry->mStretchRange = StretchRange(FontStretch::Condensed());
698 } else if (macTraits & NSExpandedFontMask) {
699 fontEntry->mStretchRange = StretchRange(FontStretch::Expanded());
701 // Cocoa fails to set the Italic traits bit for HelveticaLightItalic,
702 // at least (see bug 611855), so check for style name endings as well
703 if ((macTraits & NSItalicFontMask) || [facename hasSuffix:@"Italic"] ||
704 [facename hasSuffix:@"Oblique"]) {
705 fontEntry->mStyleRange = SlantStyleRange(FontSlantStyle::Italic());
707 if (macTraits & NSFixedPitchFontMask) {
708 fontEntry->mFixedPitch = true;
711 if (gfxPlatform::GetPlatform()->HasVariationFontSupport()) {
712 fontEntry->SetupVariationRanges();
715 if (LOG_FONTLIST_ENABLED()) {
716 nsAutoCString weightString;
717 fontEntry->Weight().ToString(weightString);
718 nsAutoCString stretchString;
719 fontEntry->Stretch().ToString(stretchString);
720 LOG_FONTLIST(("(fontlist) added (%s) to family (%s)"
721 " with style: %s weight: %s stretch: %s"
722 " (apple-weight: %d macTraits: %8.8x)",
723 fontEntry->Name().get(), Name().get(),
724 fontEntry->IsItalic() ? "italic" : "normal", weightString.get(),
725 stretchString.get(), appKitWeight, macTraits));
728 // insert into font entry array of family
729 AddFontEntry(fontEntry);
732 SortAvailableFonts();
735 if (mIsBadUnderlineFamily) {
736 SetBadUnderlineFonts();
739 CheckForSimpleFamily();
742 /* gfxSingleFaceMacFontFamily */
745 class gfxSingleFaceMacFontFamily final : public gfxFontFamily {
747 gfxSingleFaceMacFontFamily(const nsACString& aName, FontVisibility aVisibility)
748 : gfxFontFamily(aName, aVisibility) {
749 mFaceNamesInitialized = true; // omit from face name lists
752 virtual ~gfxSingleFaceMacFontFamily() = default;
754 virtual void LocalizedName(nsACString& aLocalizedName);
756 virtual void ReadOtherFamilyNames(gfxPlatformFontList* aPlatformFontList);
758 virtual bool IsSingleFaceFamily() const { return true; }
761 void gfxSingleFaceMacFontFamily::LocalizedName(nsACString& aLocalizedName) {
762 nsAutoreleasePool localPool;
764 if (!HasOtherFamilyNames()) {
765 aLocalizedName = mName;
769 gfxFontEntry* fe = mAvailableFonts[0];
770 NSFont* font = [NSFont fontWithName:GetNSStringForString(NS_ConvertUTF8toUTF16(fe->Name()))
773 NSString* localized = [font displayName];
775 nsAutoString locName;
776 GetStringForNSString(localized, locName);
777 CopyUTF16toUTF8(locName, aLocalizedName);
782 // failed to get localized name, just use the canonical one
783 aLocalizedName = mName;
786 void gfxSingleFaceMacFontFamily::ReadOtherFamilyNames(gfxPlatformFontList* aPlatformFontList) {
787 if (mOtherFamilyNamesInitialized) {
791 gfxFontEntry* fe = mAvailableFonts[0];
796 const uint32_t kNAME = TRUETYPE_TAG('n', 'a', 'm', 'e');
798 gfxFontEntry::AutoTable nameTable(fe, kNAME);
803 mHasOtherFamilyNames = ReadOtherFamilyNamesForFace(aPlatformFontList, nameTable, true);
805 mOtherFamilyNamesInitialized = true;
808 /* gfxMacPlatformFontList */
811 gfxMacPlatformFontList::gfxMacPlatformFontList()
812 : gfxPlatformFontList(false), mDefaultFont(nullptr), mUseSizeSensitiveSystemFont(false) {
813 CheckFamilyList(kBaseFonts);
815 // cache this in a static variable so that MacOSFontFamily objects
816 // don't have to repeatedly look it up
817 sFontManager = [NSFontManager sharedFontManager];
819 // Load the font-list preferences now, so that we don't have to do it from
820 // Init[Shared]FontListForPlatform, which may be called off-main-thread.
821 gfxFontUtils::GetPrefsFontList("font.single-face-list", mSingleFaceFonts);
822 gfxFontUtils::GetPrefsFontList("font.preload-names-list", mPreloadFonts);
825 gfxMacPlatformFontList::~gfxMacPlatformFontList() {
826 if (XRE_IsParentProcess()) {
827 ::CFNotificationCenterRemoveObserver(::CFNotificationCenterGetLocalCenter(), this,
828 kCTFontManagerRegisteredFontsChangedNotification, 0);
832 ::CFRelease(mDefaultFont);
836 void gfxMacPlatformFontList::AddFamily(const nsACString& aFamilyName, FontVisibility aVisibility) {
837 double sizeHint = 0.0;
838 if (aVisibility == FontVisibility::Hidden && mUseSizeSensitiveSystemFont &&
839 mSystemDisplayFontFamilyName.Equals(aFamilyName)) {
844 ToLowerCase(aFamilyName, key);
846 RefPtr<gfxFontFamily> familyEntry = new gfxMacFontFamily(aFamilyName, aVisibility, sizeHint);
847 mFontFamilies.InsertOrUpdate(key, RefPtr{familyEntry});
849 // check the bad underline blocklist
850 if (mBadUnderlineFamilyNames.ContainsSorted(key)) {
851 familyEntry->SetBadUnderlineFamily();
855 FontVisibility gfxMacPlatformFontList::GetVisibilityForFamily(const nsACString& aName) const {
856 if (aName[0] == '.' || aName.LowerCaseEqualsLiteral("lastresort")) {
857 return FontVisibility::Hidden;
859 if (FamilyInList(aName, kBaseFonts)) {
860 return FontVisibility::Base;
862 return FontVisibility::User;
865 void gfxMacPlatformFontList::AddFamily(CFStringRef aFamily) {
866 NSString* family = (NSString*)aFamily;
868 // CTFontManager includes weird internal family names and
869 // LastResort, skip over those
870 if (!family || [family caseInsensitiveCompare:@"LastResort"] == NSOrderedSame ||
871 [family caseInsensitiveCompare:@".LastResort"] == NSOrderedSame) {
875 nsAutoString familyName;
876 nsCocoaUtils::GetStringForNSString(family, familyName);
878 NS_ConvertUTF16toUTF8 nameUtf8(familyName);
879 AddFamily(nameUtf8, GetVisibilityForFamily(nameUtf8));
882 void gfxMacPlatformFontList::ReadSystemFontList(dom::SystemFontList* aList) {
883 // Note: We rely on the records for mSystemTextFontFamilyName and
884 // mSystemDisplayFontFamilyName (if present) being *before* the main
885 // font list, so that those names are known in the content process
886 // by the time we add the actual family records to the font list.
887 aList->entries().AppendElement(FontFamilyListEntry(
888 mSystemTextFontFamilyName, FontVisibility::Unknown, kTextSizeSystemFontFamily));
889 if (mUseSizeSensitiveSystemFont) {
890 aList->entries().AppendElement(FontFamilyListEntry(
891 mSystemDisplayFontFamilyName, FontVisibility::Unknown, kDisplaySizeSystemFontFamily));
893 // Now collect the list of available families, with visibility attributes.
894 for (auto f = mFontFamilies.Iter(); !f.Done(); f.Next()) {
895 auto macFamily = f.Data().get();
896 if (macFamily->IsSingleFaceFamily()) {
897 continue; // skip, this will be recreated separately in the child
899 aList->entries().AppendElement(
900 FontFamilyListEntry(macFamily->Name(), macFamily->Visibility(), kStandardFontFamily));
904 void gfxMacPlatformFontList::PreloadNamesList() {
905 uint32_t numFonts = mPreloadFonts.Length();
906 for (uint32_t i = 0; i < numFonts; i++) {
908 GenerateFontListKey(mPreloadFonts[i], key);
910 // only search canonical names!
911 gfxFontFamily* familyEntry = mFontFamilies.GetWeak(key);
913 familyEntry->ReadOtherFamilyNames(this);
918 nsresult gfxMacPlatformFontList::InitFontListForPlatform() {
919 nsAutoreleasePool localPool;
921 // The font registration thread was created early in startup, to give the
922 // system a head start on activating all the supplemental-language fonts.
923 // Here, we need to wait until it has finished its work.
924 gfxPlatformMac::WaitForFontRegistration();
926 Telemetry::AutoTimer<Telemetry::MAC_INITFONTLIST_TOTAL> timer;
928 InitSystemFontNames();
930 if (XRE_IsParentProcess()) {
931 static bool firstTime = true;
933 ::CFNotificationCenterAddObserver(::CFNotificationCenterGetLocalCenter(), this,
934 RegisteredFontsChangedNotificationCallback,
935 kCTFontManagerRegisteredFontsChangedNotification, 0,
936 CFNotificationSuspensionBehaviorDeliverImmediately);
940 // We're not a content process, so get the available fonts directly
942 AutoCFRelease<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames();
943 for (NSString* familyName in (NSArray*)(CFArrayRef)familyNames) {
944 AddFamily((CFStringRef)familyName);
947 // Content process: use font list passed from the chrome process via
948 // the GetXPCOMProcessAttributes message, because it's much faster than
949 // querying Core Text again in the child.
950 auto& fontList = dom::ContentChild::GetSingleton()->SystemFontList();
951 for (FontFamilyListEntry& ffe : fontList.entries()) {
952 switch (ffe.entryType()) {
953 case kStandardFontFamily:
954 // On Catalina or later, we pre-initialize system font-family entries
955 // in InitSystemFontNames(), so we can just skip them here.
956 if (nsCocoaFeatures::OnCatalinaOrLater() &&
957 (ffe.familyName() == mSystemTextFontFamilyName ||
958 ffe.familyName() == mSystemDisplayFontFamilyName)) {
961 AddFamily(ffe.familyName(), ffe.visibility());
963 case kTextSizeSystemFontFamily:
964 mSystemTextFontFamilyName = ffe.familyName();
966 case kDisplaySizeSystemFontFamily:
967 mSystemDisplayFontFamilyName = ffe.familyName();
968 mUseSizeSensitiveSystemFont = true;
972 fontList.entries().Clear();
975 InitSingleFaceList();
977 // to avoid full search of font name tables, seed the other names table with localized names from
978 // some of the prefs fonts which are accessed via their localized names. changes in the pref
979 // fonts will only cause a font lookup miss earlier. this is a simple optimization, it's not
980 // required for correctness
983 // start the delayed cmap loader
984 GetPrefsAndStartLoader();
989 void gfxMacPlatformFontList::InitSharedFontListForPlatform() {
990 nsAutoreleasePool localPool;
992 gfxPlatformMac::WaitForFontRegistration();
994 InitSystemFontNames();
996 if (XRE_IsParentProcess()) {
997 // Only the parent process listens for OS font-changed notifications;
998 // after rebuilding its list, it will update the content processes.
999 static bool firstTime = true;
1001 ::CFNotificationCenterAddObserver(::CFNotificationCenterGetLocalCenter(), this,
1002 RegisteredFontsChangedNotificationCallback,
1003 kCTFontManagerRegisteredFontsChangedNotification, 0,
1004 CFNotificationSuspensionBehaviorDeliverImmediately);
1008 AutoCFRelease<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames();
1009 nsTArray<fontlist::Family::InitData> families;
1010 for (NSString* familyName in (NSArray*)(CFArrayRef)familyNames) {
1011 nsAutoString name16;
1012 GetStringForNSString(familyName, name16);
1013 NS_ConvertUTF16toUTF8 name(name16);
1015 GenerateFontListKey(name, key);
1016 families.AppendElement(fontlist::Family::InitData(key, name, fontlist::Family::kNoIndex,
1017 GetVisibilityForFamily(name)));
1019 SharedFontList()->SetFamilyNames(families);
1020 InitAliasesForSingleFaceList();
1021 GetPrefsAndStartLoader();
1025 void gfxMacPlatformFontList::InitAliasesForSingleFaceList() {
1026 for (const auto& familyName : mSingleFaceFonts) {
1027 LOG_FONTLIST(("(fontlist-singleface) face name: %s\n", familyName.get()));
1028 // Each entry in the "single face families" list is expected to be a
1029 // colon-separated pair of FaceName:Family,
1030 // where FaceName is the individual face name (psname) of a font
1031 // that should be exposed as a separate family name,
1032 // and Family is the standard family to which that face belongs.
1033 // The only such face listed by default is
1035 auto colon = familyName.FindChar(':');
1036 if (colon == kNotFound) {
1040 // Look for the parent family in the main font family list,
1041 // and ensure we have loaded its list of available faces.
1043 GenerateFontListKey(Substring(familyName, colon + 1), key);
1044 fontlist::Family* family = SharedFontList()->FindFamily(key);
1046 // The parent family is not present, so just ignore this entry.
1049 if (!family->IsInitialized()) {
1050 if (!gfxPlatformFontList::InitializeFamily(family)) {
1051 // This shouldn't ever fail, but if it does, we can safely ignore it.
1052 MOZ_ASSERT(false, "failed to initialize font family");
1057 // Truncate the entry from prefs at the colon, so now it is just the
1058 // desired single-face-family name.
1059 nsAutoCString aliasName(Substring(familyName, 0, colon));
1061 // Look through the family's faces to see if this one is present.
1062 fontlist::FontList* list = SharedFontList();
1063 const fontlist::Pointer* facePtrs = family->Faces(list);
1064 for (size_t i = 0; i < family->NumFaces(); i++) {
1065 if (facePtrs[i].IsNull()) {
1068 auto face = static_cast<const fontlist::Face*>(facePtrs[i].ToPtr(list));
1069 if (face->mDescriptor.AsString(list).Equals(aliasName)) {
1070 // Found it! Create an entry in the Alias table.
1071 GenerateFontListKey(aliasName, key);
1072 if (SharedFontList()->FindFamily(key) || mAliasTable.Get(key)) {
1073 // If the family name is already known, something's misconfigured;
1075 MOZ_ASSERT(false, "single-face family already known");
1078 auto aliasData = mAliasTable.GetOrInsertNew(key);
1079 // The "alias" here isn't based on an existing family, so we don't call
1080 // aliasData->InitFromFamily(); the various flags are left as defaults.
1081 aliasData->mFaces.AppendElement(facePtrs[i]);
1082 aliasData->mBaseFamily = aliasName;
1083 aliasData->mVisibility = family->Visibility();
1088 if (!mAliasTable.IsEmpty()) {
1089 // This will be updated when the font loader completes, but we require
1090 // at least the Osaka-Mono alias to be available immediately.
1091 SharedFontList()->SetAliases(mAliasTable);
1095 void gfxMacPlatformFontList::InitSingleFaceList() {
1096 for (const auto& familyName : mSingleFaceFonts) {
1097 LOG_FONTLIST(("(fontlist-singleface) face name: %s\n", familyName.get()));
1098 // Each entry in the "single face families" list is expected to be a
1099 // colon-separated pair of FaceName:Family,
1100 // where FaceName is the individual face name (psname) of a font
1101 // that should be exposed as a separate family name,
1102 // and Family is the standard family to which that face belongs.
1103 // The only such face listed by default is
1105 auto colon = familyName.FindChar(':');
1106 if (colon == kNotFound) {
1110 // Look for the parent family in the main font family list,
1111 // and ensure we have loaded its list of available faces.
1112 nsAutoCString key(Substring(familyName, colon + 1));
1114 gfxFontFamily* family = mFontFamilies.GetWeak(key);
1115 if (!family || family->IsHidden()) {
1118 family->FindStyleVariations();
1120 // Truncate the entry from prefs at the colon, so now it is just the
1121 // desired single-face-family name.
1122 nsAutoCString aliasName(Substring(familyName, 0, colon));
1124 // Look through the family's faces to see if this one is present.
1125 const gfxFontEntry* fe = nullptr;
1126 for (const auto& face : family->GetFontList()) {
1127 if (face->Name().Equals(aliasName)) {
1136 // We found the correct face, so create the single-face family record.
1137 GenerateFontListKey(aliasName, key);
1138 LOG_FONTLIST(("(fontlist-singleface) family name: %s, key: %s\n", aliasName.get(), key.get()));
1140 // add only if doesn't exist already
1141 if (!mFontFamilies.GetWeak(key)) {
1142 RefPtr<gfxFontFamily> familyEntry =
1143 new gfxSingleFaceMacFontFamily(aliasName, family->Visibility());
1144 // We need a separate font entry, because its family name will
1145 // differ from the one we found in the main list.
1146 MacOSFontEntry* fontEntry = new MacOSFontEntry(
1147 fe->Name(), fe->Weight(), true, static_cast<const MacOSFontEntry*>(fe)->mSizeHint);
1148 familyEntry->AddFontEntry(fontEntry);
1149 familyEntry->SetHasStyles(true);
1150 mFontFamilies.InsertOrUpdate(key, std::move(familyEntry));
1152 ("(fontlist-singleface) added new family: %s, key: %s\n", aliasName.get(), key.get()));
1157 // System fonts under OSX may contain weird "meta" names but if we create
1158 // a new font using just the Postscript name, the NSFont api returns an object
1159 // with the actual real family name. For example, under OSX 10.11:
1161 // [[NSFont menuFontOfSize:8.0] familyName] ==> .AppleSystemUIFont
1162 // [[NSFont fontWithName:[[[NSFont menuFontOfSize:8.0] fontDescriptor] postscriptName]
1163 // size:8.0] familyName] ==> .SF NS Text
1165 static NSString* GetRealFamilyName(NSFont* aFont) {
1166 NSString* psName = [[aFont fontDescriptor] postscriptName];
1167 // With newer macOS versions and SDKs (e.g. when compiled against SDK 10.15),
1168 // [NSFont fontWithName:] fails for hidden system fonts, because the underlying
1169 // Core Text functions it uses reject such names and tell us to use the special
1170 // CTFontCreateUIFontForLanguage API instead.
1171 // To work around this, as we don't yet work directly with the CTFontUIFontType
1172 // identifiers, we create a Core Graphics font (as it doesn't reject system font
1173 // names), and use this to create a Core Text font that we can query for the
1175 // Eventually we should move to using CTFontUIFontType constants to identify
1176 // system fonts, and eliminate the need to instantiate them (indirectly) from
1177 // their postscript names.
1178 AutoCFRelease<CGFontRef> cgFont = CGFontCreateWithFontName(CFStringRef(psName));
1180 return [aFont familyName];
1183 AutoCFRelease<CTFontRef> ctFont = CTFontCreateWithGraphicsFont(cgFont, 0.0, nullptr, nullptr);
1185 return [aFont familyName];
1187 NSString* familyName = (NSString*)CTFontCopyFamilyName(ctFont);
1189 return [familyName autorelease];
1192 // Create a gfxFontFamily that corresponds to the "system" font name,
1193 // and populate it with the given font face. We only use this on Catalina or later,
1194 // so we expect the system font to be a variable-weight face rather than requiring
1195 // a number of discrete faces of different weights.
1196 static gfxFontFamily* CreateFamilyForSystemFont(NSFont* aFont, const nsACString& aFamilyName) {
1197 gfxFontFamily* familyEntry = new gfxFontFamily(aFamilyName, FontVisibility::Unknown);
1199 NSString* psNameNS = [[aFont fontDescriptor] postscriptName];
1200 nsAutoString nameUTF16;
1201 nsAutoCString psName;
1202 nsCocoaUtils::GetStringForNSString(psNameNS, nameUTF16);
1203 CopyUTF16toUTF8(nameUTF16, psName);
1205 MacOSFontEntry* fe = new MacOSFontEntry(psName, WeightRange(FontWeight::Normal()), true, 0.0);
1206 MOZ_ASSERT(gfxPlatform::GetPlatform()->HasVariationFontSupport());
1207 fe->SetupVariationRanges();
1209 familyEntry->AddFontEntry(fe);
1210 familyEntry->SetHasStyles(true);
1215 // System fonts under OSX 10.11 use a combination of two families, one
1216 // for text sizes and another for larger, display sizes. Each has a
1217 // different number of weights. There aren't efficient API's for looking
1218 // this information up, so hard code the logic here but confirm via
1219 // debug assertions that the logic is correct.
1221 const CGFloat kTextDisplayCrossover = 20.0; // use text family below this size
1223 void gfxMacPlatformFontList::InitSystemFontNames() {
1224 // On Catalina+, the system font uses optical sizing rather than individual
1225 // faces, so we don't need to look for a separate display-sized face.
1226 mUseSizeSensitiveSystemFont = !nsCocoaFeatures::OnCatalinaOrLater();
1229 NSFont* sys = [NSFont systemFontOfSize:0.0];
1230 NSString* textFamilyName = GetRealFamilyName(sys);
1231 nsAutoString familyName;
1232 nsCocoaUtils::GetStringForNSString(textFamilyName, familyName);
1233 CopyUTF16toUTF8(familyName, mSystemTextFontFamilyName);
1235 // On Catalina or later, we store an in-process gfxFontFamily for the system font
1236 // even if using the shared fontlist to manage "normal" fonts, because the hidden
1237 // system fonts may be excluded from the font list altogether.
1238 if (nsCocoaFeatures::OnCatalinaOrLater()) {
1239 RefPtr<gfxFontFamily> fam = CreateFamilyForSystemFont(sys, mSystemTextFontFamilyName);
1242 GenerateFontListKey(mSystemTextFontFamilyName, key);
1243 mFontFamilies.InsertOrUpdate(key, std::move(fam));
1247 // display font family, if on OSX 10.11 - 10.14
1248 if (mUseSizeSensitiveSystemFont) {
1249 NSFont* displaySys = [NSFont systemFontOfSize:128.0];
1250 NSString* displayFamilyName = GetRealFamilyName(displaySys);
1251 if ([displayFamilyName isEqualToString:textFamilyName]) {
1252 mUseSizeSensitiveSystemFont = false;
1254 nsCocoaUtils::GetStringForNSString(displayFamilyName, familyName);
1255 CopyUTF16toUTF8(familyName, mSystemDisplayFontFamilyName);
1260 // different system font API's always map to the same family under OSX, so
1261 // just assume that and emit a warning if that ever changes
1262 NSString* sysFamily = GetRealFamilyName([NSFont systemFontOfSize:0.0]);
1263 if ([sysFamily compare:GetRealFamilyName([NSFont boldSystemFontOfSize:0.0])] != NSOrderedSame ||
1264 [sysFamily compare:GetRealFamilyName([NSFont controlContentFontOfSize:0.0])] !=
1266 [sysFamily compare:GetRealFamilyName([NSFont menuBarFontOfSize:0.0])] != NSOrderedSame ||
1267 [sysFamily compare:GetRealFamilyName([NSFont toolTipsFontOfSize:0.0])] != NSOrderedSame) {
1268 NS_WARNING("system font types map to different font families"
1269 " -- please log a bug!!");
1274 gfxFontFamily* gfxMacPlatformFontList::FindSystemFontFamily(const nsACString& aFamily) {
1276 GenerateFontListKey(aFamily, key);
1278 gfxFontFamily* familyEntry;
1279 if ((familyEntry = mFontFamilies.GetWeak(key))) {
1280 return CheckFamily(familyEntry);
1286 void gfxMacPlatformFontList::RegisteredFontsChangedNotificationCallback(
1287 CFNotificationCenterRef center, void* observer, CFStringRef name, const void* object,
1288 CFDictionaryRef userInfo) {
1289 if (!::CFEqual(name, kCTFontManagerRegisteredFontsChangedNotification)) {
1293 gfxMacPlatformFontList* fl = static_cast<gfxMacPlatformFontList*>(observer);
1294 if (!fl->IsInitialized()) {
1298 // xxx - should be carefully pruning the list of fonts, not rebuilding it from scratch
1299 fl->UpdateFontList();
1301 gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes);
1302 dom::ContentParent::NotifyUpdatedFonts(true);
1305 gfxFontEntry* gfxMacPlatformFontList::PlatformGlobalFontFallback(nsPresContext* aPresContext,
1308 const gfxFontStyle* aMatchStyle,
1309 FontFamily& aMatchedFamily) {
1314 if (IS_IN_BMP(aCh)) {
1316 str = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, ch, 1, kCFAllocatorNull);
1318 ch[0] = H_SURROGATE(aCh);
1319 ch[1] = L_SURROGATE(aCh);
1320 str = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, ch, 2, kCFAllocatorNull);
1327 // use CoreText to find the fallback family
1329 gfxFontEntry* fontEntry = nullptr;
1330 bool cantUseFallbackFont = false;
1332 if (!mDefaultFont) {
1333 mDefaultFont = ::CTFontCreateWithName(CFSTR("LucidaGrande"), 12.f, NULL);
1336 AutoCFRelease<CTFontRef> fallback =
1337 ::CTFontCreateForString(mDefaultFont, str, ::CFRangeMake(0, length));
1340 AutoCFRelease<CFStringRef> familyNameRef = ::CTFontCopyFamilyName(fallback);
1342 if (familyNameRef &&
1343 ::CFStringCompare(familyNameRef, CFSTR("LastResort"), kCFCompareCaseInsensitive) !=
1344 kCFCompareEqualTo &&
1345 ::CFStringCompare(familyNameRef, CFSTR(".LastResort"), kCFCompareCaseInsensitive) !=
1346 kCFCompareEqualTo) {
1347 AutoTArray<UniChar, 1024> buffer;
1348 CFIndex familyNameLen = ::CFStringGetLength(familyNameRef);
1349 buffer.SetLength(familyNameLen + 1);
1350 ::CFStringGetCharacters(familyNameRef, ::CFRangeMake(0, familyNameLen), buffer.Elements());
1351 buffer[familyNameLen] = 0;
1352 NS_ConvertUTF16toUTF8 familyNameString(reinterpret_cast<char16_t*>(buffer.Elements()),
1355 if (SharedFontList()) {
1356 fontlist::Family* family = FindSharedFamily(aPresContext, familyNameString);
1358 fontlist::Face* face = family->FindFaceForStyle(SharedFontList(), *aMatchStyle);
1360 fontEntry = GetOrCreateFontEntry(face, family);
1363 if (fontEntry->HasCharacter(aCh)) {
1364 aMatchedFamily = FontFamily(family);
1366 fontEntry = nullptr;
1367 cantUseFallbackFont = true;
1373 // The macOS system font does not appear in the shared font list, so if
1374 // we didn't find the fallback font above, we should also check for an
1375 // unshared fontFamily in the system list.
1377 gfxFontFamily* family = FindSystemFontFamily(familyNameString);
1379 fontEntry = family->FindFontForStyle(*aMatchStyle);
1381 if (fontEntry->HasCharacter(aCh)) {
1382 aMatchedFamily = FontFamily(family);
1384 fontEntry = nullptr;
1385 cantUseFallbackFont = true;
1393 if (cantUseFallbackFont) {
1394 Telemetry::Accumulate(Telemetry::BAD_FALLBACK_FONT, cantUseFallbackFont);
1402 FontFamily gfxMacPlatformFontList::GetDefaultFontForPlatform(nsPresContext* aPresContext,
1403 const gfxFontStyle* aStyle,
1404 nsAtom* aLanguage) {
1405 nsAutoreleasePool localPool;
1407 NSString* defaultFamily = [[NSFont userFontOfSize:aStyle->size] familyName];
1408 nsAutoString familyName;
1410 GetStringForNSString(defaultFamily, familyName);
1411 return FindFamily(aPresContext, NS_ConvertUTF16toUTF8(familyName));
1414 int32_t gfxMacPlatformFontList::AppleWeightToCSSWeight(int32_t aAppleWeight) {
1415 if (aAppleWeight < 1)
1417 else if (aAppleWeight > kAppleMaxWeight)
1418 aAppleWeight = kAppleMaxWeight;
1419 return gAppleWeightToCSSWeight[aAppleWeight];
1422 gfxFontEntry* gfxMacPlatformFontList::LookupLocalFont(nsPresContext* aPresContext,
1423 const nsACString& aFontName,
1424 WeightRange aWeightForEntry,
1425 StretchRange aStretchForEntry,
1426 SlantStyleRange aStyleForEntry) {
1427 if (aFontName.IsEmpty() || aFontName[0] == '.') {
1431 nsAutoreleasePool localPool;
1433 NSString* faceName = GetNSStringForString(NS_ConvertUTF8toUTF16(aFontName));
1435 // lookup face based on postscript or full name
1436 AutoCFRelease<CGFontRef> fontRef = CGFontCreateWithFontName(CFStringRef(faceName));
1441 // It's possible for CGFontCreateWithFontName to return a font that has been
1442 // deactivated/uninstalled, or a font that is excluded from the font list due
1443 // to CSS font-visibility restriction. So we need to check whether this font is
1444 // allowed to be used.
1446 // CGFontRef doesn't offer a family-name API, so we go via a CTFontRef.
1447 AutoCFRelease<CTFontRef> ctFont = CTFontCreateWithGraphicsFont(fontRef, 0.0, nullptr, nullptr);
1451 AutoCFRelease<CFStringRef> name = CTFontCopyFamilyName(ctFont);
1453 // Convert the family name to a key suitable for font-list lookup (8-bit, lowercased).
1455 // CFStringGetLength is in UTF-16 code units. The maximum this count can expand
1456 // when converted to UTF-8 is 3x. We add 1 to ensure there will also be space for
1457 // null-termination of the resulting C string.
1458 key.SetLength((CFStringGetLength(name) + 1) * 3);
1459 if (!CFStringGetCString(name, key.BeginWriting(), key.Length(), kCFStringEncodingUTF8)) {
1460 // This shouldn't ever happen, but if it does we just bail.
1461 NS_WARNING("Failed to get family name?");
1464 if (key.IsEmpty()) {
1467 // Reset our string length to match the actual C string we got, which will usually
1468 // be much shorter than the maximal buffer we allocated.
1469 key.Truncate(strlen(key.get()));
1471 // If the family can't be looked up, this font is not available for use.
1472 FontFamily family = FindFamily(aPresContext, key);
1473 if (family.IsNull()) {
1477 return new MacOSFontEntry(aFontName, fontRef, aWeightForEntry, aStretchForEntry, aStyleForEntry,
1481 static void ReleaseData(void* info, const void* data, size_t size) { free((void*)data); }
1483 gfxFontEntry* gfxMacPlatformFontList::MakePlatformFont(const nsACString& aFontName,
1484 WeightRange aWeightForEntry,
1485 StretchRange aStretchForEntry,
1486 SlantStyleRange aStyleForEntry,
1487 const uint8_t* aFontData, uint32_t aLength) {
1488 NS_ASSERTION(aFontData, "MakePlatformFont called with null data");
1490 // create the font entry
1491 nsAutoString uniqueName;
1493 nsresult rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName);
1494 if (NS_FAILED(rv)) {
1498 AutoCFRelease<CGDataProviderRef> provider =
1499 ::CGDataProviderCreateWithData(nullptr, aFontData, aLength, &ReleaseData);
1500 AutoCFRelease<CGFontRef> fontRef = ::CGFontCreateWithDataProvider(provider);
1506 MakeUnique<MacOSFontEntry>(NS_ConvertUTF16toUTF8(uniqueName), fontRef, aWeightForEntry,
1507 aStretchForEntry, aStyleForEntry, true, false);
1508 return newFontEntry.release();
1511 // Webkit code uses a system font meta name, so mimic that here
1512 // WebCore/platform/graphics/mac/FontCacheMac.mm
1513 static const char kSystemFont_system[] = "-apple-system";
1515 bool gfxMacPlatformFontList::FindAndAddFamilies(nsPresContext* aPresContext,
1516 StyleGenericFontFamily aGeneric,
1517 const nsACString& aFamily,
1518 nsTArray<FamilyAndGeneric>* aOutput,
1519 FindFamiliesFlags aFlags, gfxFontStyle* aStyle,
1520 nsAtom* aLanguage, gfxFloat aDevToCssSize) {
1521 if (aFamily.EqualsLiteral(kSystemFont_system)) {
1522 // Search for special system font name, -apple-system. This is not done via
1523 // the shared fontlist on Catalina or later, because the hidden system font
1524 // may not be included there; we create a separate gfxFontFamily to manage
1526 const nsCString& systemFontFamilyName =
1527 mUseSizeSensitiveSystemFont && aStyle &&
1528 (aStyle->size * aDevToCssSize) >= kTextDisplayCrossover
1529 ? mSystemDisplayFontFamilyName
1530 : mSystemTextFontFamilyName;
1531 if (SharedFontList() && !nsCocoaFeatures::OnCatalinaOrLater()) {
1532 FindFamiliesFlags flags = aFlags | FindFamiliesFlags::eSearchHiddenFamilies;
1533 return gfxPlatformFontList::FindAndAddFamilies(aPresContext, aGeneric, systemFontFamilyName,
1534 aOutput, flags, aStyle, aLanguage,
1537 if (auto* fam = FindSystemFontFamily(systemFontFamilyName)) {
1538 aOutput->AppendElement(fam);
1545 return gfxPlatformFontList::FindAndAddFamilies(aPresContext, aGeneric, aFamily, aOutput, aFlags,
1546 aStyle, aLanguage, aDevToCssSize);
1549 void gfxMacPlatformFontList::LookupSystemFont(LookAndFeel::FontID aSystemFontID,
1550 nsACString& aSystemFontName,
1551 gfxFontStyle& aFontStyle) {
1552 // Provide a local pool because we may be called from stylo threads.
1553 nsAutoreleasePool localPool;
1555 // code moved here from widget/cocoa/nsLookAndFeel.mm
1556 NSFont* font = nullptr;
1557 char* systemFontName = nullptr;
1558 switch (aSystemFontID) {
1559 case LookAndFeel::FontID::MessageBox:
1560 case LookAndFeel::FontID::StatusBar:
1561 case LookAndFeel::FontID::MozList:
1562 case LookAndFeel::FontID::MozField:
1563 case LookAndFeel::FontID::MozButton:
1564 font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
1565 systemFontName = (char*)kSystemFont_system;
1568 case LookAndFeel::FontID::SmallCaption:
1569 font = [NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize]];
1570 systemFontName = (char*)kSystemFont_system;
1573 case LookAndFeel::FontID::Icon: // used in urlbar; tried labelFont, but too small
1574 case LookAndFeel::FontID::MozWorkspace:
1575 case LookAndFeel::FontID::MozDesktop:
1576 case LookAndFeel::FontID::MozInfo:
1577 font = [NSFont controlContentFontOfSize:0.0];
1578 systemFontName = (char*)kSystemFont_system;
1581 case LookAndFeel::FontID::MozPullDownMenu:
1582 font = [NSFont menuBarFontOfSize:0.0];
1583 systemFontName = (char*)kSystemFont_system;
1586 case LookAndFeel::FontID::Caption:
1587 case LookAndFeel::FontID::Menu:
1588 case LookAndFeel::FontID::MozDialog:
1590 font = [NSFont systemFontOfSize:0.0];
1591 systemFontName = (char*)kSystemFont_system;
1594 NS_ASSERTION(font, "system font not set");
1595 NS_ASSERTION(systemFontName, "system font name not set");
1597 if (systemFontName) {
1598 aSystemFontName.AssignASCII(systemFontName);
1601 NSFontSymbolicTraits traits = [[font fontDescriptor] symbolicTraits];
1603 (traits & NSFontItalicTrait) ? FontSlantStyle::Italic() : FontSlantStyle::Normal();
1604 aFontStyle.weight = (traits & NSFontBoldTrait) ? FontWeight::Bold() : FontWeight::Normal();
1605 aFontStyle.stretch = (traits & NSFontExpandedTrait) ? FontStretch::Expanded()
1606 : (traits & NSFontCondensedTrait) ? FontStretch::Condensed()
1607 : FontStretch::Normal();
1608 aFontStyle.size = [font pointSize];
1609 aFontStyle.systemFont = true;
1612 // used to load system-wide font info on off-main thread
1613 class MacFontInfo final : public FontInfoData {
1615 MacFontInfo(bool aLoadOtherNames, bool aLoadFaceNames, bool aLoadCmaps)
1616 : FontInfoData(aLoadOtherNames, aLoadFaceNames, aLoadCmaps) {}
1618 virtual ~MacFontInfo() = default;
1620 virtual void Load() {
1621 nsAutoreleasePool localPool;
1622 FontInfoData::Load();
1625 // loads font data for all members of a given family
1626 virtual void LoadFontFamilyData(const nsACString& aFamilyName);
1629 void MacFontInfo::LoadFontFamilyData(const nsACString& aFamilyName) {
1630 CrashReporter::AutoAnnotateCrashReport autoFontName(CrashReporter::Annotation::FontName,
1633 // family name ==> CTFontDescriptor
1634 NSString* famName = GetNSStringForString(NS_ConvertUTF8toUTF16(aFamilyName));
1635 CFStringRef family = CFStringRef(famName);
1637 AutoCFRelease<CFMutableDictionaryRef> attr = CFDictionaryCreateMutable(
1638 NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1639 CFDictionaryAddValue(attr, kCTFontFamilyNameAttribute, family);
1640 AutoCFRelease<CTFontDescriptorRef> fd = CTFontDescriptorCreateWithAttributes(attr);
1641 AutoCFRelease<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(fd, NULL);
1642 if (!matchingFonts) {
1646 nsTArray<nsCString> otherFamilyNames;
1647 bool hasOtherFamilyNames = true;
1649 // iterate over faces in the family
1650 int f, numFaces = (int)CFArrayGetCount(matchingFonts);
1651 for (f = 0; f < numFaces; f++) {
1654 CTFontDescriptorRef faceDesc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(matchingFonts, f);
1658 AutoCFRelease<CTFontRef> fontRef = CTFontCreateWithFontDescriptor(faceDesc, 0.0, nullptr);
1660 NS_WARNING("failed to create a CTFontRef");
1666 AutoCFRelease<CFStringRef> faceName =
1667 (CFStringRef)CTFontDescriptorCopyAttribute(faceDesc, kCTFontNameAttribute);
1669 AutoTArray<UniChar, 1024> buffer;
1670 CFIndex len = CFStringGetLength(faceName);
1671 buffer.SetLength(len + 1);
1672 CFStringGetCharacters(faceName, ::CFRangeMake(0, len), buffer.Elements());
1674 NS_ConvertUTF16toUTF8 fontName(reinterpret_cast<char16_t*>(buffer.Elements()), len);
1676 // load the cmap data
1677 FontFaceData fontData;
1678 AutoCFRelease<CFDataRef> cmapTable =
1679 CTFontCopyTable(fontRef, kCTFontTableCmap, kCTFontTableOptionNoOptions);
1682 const uint8_t* cmapData = (const uint8_t*)CFDataGetBytePtr(cmapTable);
1683 uint32_t cmapLen = CFDataGetLength(cmapTable);
1684 RefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
1688 rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen, *charmap, offset);
1689 if (NS_SUCCEEDED(rv)) {
1690 fontData.mCharacterMap = charmap;
1691 fontData.mUVSOffset = offset;
1696 mFontFaceData.InsertOrUpdate(fontName, fontData);
1699 if (mLoadOtherNames && hasOtherFamilyNames) {
1700 AutoCFRelease<CFDataRef> nameTable =
1701 CTFontCopyTable(fontRef, kCTFontTableName, kCTFontTableOptionNoOptions);
1704 const char* nameData = (const char*)CFDataGetBytePtr(nameTable);
1705 uint32_t nameLen = CFDataGetLength(nameTable);
1706 gfxFontUtils::ReadOtherFamilyNamesForFace(aFamilyName, nameData, nameLen, otherFamilyNames,
1708 hasOtherFamilyNames = otherFamilyNames.Length() != 0;
1713 // if found other names, insert them in the hash table
1714 if (otherFamilyNames.Length() != 0) {
1715 mOtherFamilyNames.InsertOrUpdate(aFamilyName, otherFamilyNames);
1716 mLoadStats.othernames += otherFamilyNames.Length();
1720 already_AddRefed<FontInfoData> gfxMacPlatformFontList::CreateFontInfoData() {
1722 !UsesSystemFallback() || gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
1724 RefPtr<MacFontInfo> fi = new MacFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps);
1728 gfxFontFamily* gfxMacPlatformFontList::CreateFontFamily(const nsACString& aName,
1729 FontVisibility aVisibility) const {
1730 return new gfxMacFontFamily(aName, aVisibility, 0.0);
1733 gfxFontEntry* gfxMacPlatformFontList::CreateFontEntry(fontlist::Face* aFace,
1734 const fontlist::Family* aFamily) {
1735 MacOSFontEntry* fe =
1736 new MacOSFontEntry(aFace->mDescriptor.AsString(SharedFontList()), aFace->mWeight, false,
1737 0.0); // XXX standardFace, sizeHint
1738 fe->InitializeFrom(aFace, aFamily);
1742 void gfxMacPlatformFontList::GetFacesInitDataForFamily(const fontlist::Family* aFamily,
1743 nsTArray<fontlist::Face::InitData>& aFaces,
1744 bool aLoadCmaps) const {
1745 nsAutoreleasePool localPool;
1747 NS_ConvertUTF8toUTF16 name(aFamily->Key().AsString(SharedFontList()));
1748 NSString* family = GetNSStringForString(name);
1750 // returns an array of [psname, style name, weight, traits] elements, goofy api
1751 NSArray* fontfaces = [sFontManager availableMembersOfFontFamily:family];
1752 int faceCount = [fontfaces count];
1753 for (int faceIndex = 0; faceIndex < faceCount; faceIndex++) {
1754 NSArray* face = [fontfaces objectAtIndex:faceIndex];
1755 NSString* psname = [face objectAtIndex:INDEX_FONT_POSTSCRIPT_NAME];
1756 int32_t appKitWeight = [[face objectAtIndex:INDEX_FONT_WEIGHT] unsignedIntValue];
1757 uint32_t macTraits = [[face objectAtIndex:INDEX_FONT_TRAITS] unsignedIntValue];
1758 NSString* facename = [face objectAtIndex:INDEX_FONT_FACE_NAME];
1760 if (appKitWeight == kAppleExtraLightWeight) {
1761 // if the facename contains UltraLight, set the weight to the ultralight weight value
1762 NSRange range = [facename rangeOfString:@"ultralight" options:NSCaseInsensitiveSearch];
1763 if (range.location != NSNotFound) {
1764 appKitWeight = kAppleUltraLightWeight;
1769 nsAutoString postscriptFontName;
1770 GetStringForNSString(psname, postscriptFontName);
1772 int32_t cssWeight = gfxMacPlatformFontList::AppleWeightToCSSWeight(appKitWeight);
1773 if (PR_GetCurrentThread() != sInitFontListThread) {
1774 int32_t weightOverride = GetWeightOverride(postscriptFontName);
1775 if (weightOverride) {
1776 // scale down and clamp, to get a value from 1..9
1777 cssWeight = ((weightOverride + 50) / 100);
1778 cssWeight = std::max(1, std::min(cssWeight, 9));
1781 cssWeight *= 100; // scale up to CSS values
1783 StretchRange stretch(FontStretch::Normal());
1784 if (macTraits & (NSCondensedFontMask | NSNarrowFontMask | NSCompressedFontMask)) {
1785 stretch = StretchRange(FontStretch::Condensed());
1786 } else if (macTraits & NSExpandedFontMask) {
1787 stretch = StretchRange(FontStretch::Expanded());
1789 // Cocoa fails to set the Italic traits bit for HelveticaLightItalic,
1790 // at least (see bug 611855), so check for style name endings as well
1791 SlantStyleRange slantStyle(FontSlantStyle::Normal());
1792 if ((macTraits & NSItalicFontMask) || [facename hasSuffix:@"Italic"] ||
1793 [facename hasSuffix:@"Oblique"]) {
1794 slantStyle = SlantStyleRange(FontSlantStyle::Italic());
1797 bool fixedPitch = (macTraits & NSFixedPitchFontMask) ? true : false;
1799 RefPtr<gfxCharacterMap> charmap;
1801 AutoCFRelease<CGFontRef> font = CGFontCreateWithFontName(CFStringRef(psname));
1803 uint32_t kCMAP = TRUETYPE_TAG('c', 'm', 'a', 'p');
1804 AutoCFRelease<CFDataRef> data = CGFontCopyTableForTag(font, kCMAP);
1807 charmap = new gfxCharacterMap();
1808 gfxFontUtils::ReadCMAP(CFDataGetBytePtr(data), CFDataGetLength(data), *charmap, offset);
1813 // Ensure that a face named "Regular" goes to the front of the list, so it
1814 // will take precedence over other faces with the same style attributes but
1815 // a different name (such as "Outline").
1816 auto data = fontlist::Face::InitData{
1817 NS_ConvertUTF16toUTF8(postscriptFontName),
1820 WeightRange(FontWeight(cssWeight)),
1825 if ([facename caseInsensitiveCompare:@"Regular"] == NSOrderedSame) {
1826 aFaces.InsertElementAt(0, std::move(data));
1828 aFaces.AppendElement(std::move(data));
1833 void gfxMacPlatformFontList::ReadFaceNamesForFamily(fontlist::Family* aFamily,
1834 bool aNeedFullnamePostscriptNames) {
1835 if (!aFamily->IsInitialized()) {
1836 if (!InitializeFamily(aFamily)) {
1840 const uint32_t kNAME = TRUETYPE_TAG('n', 'a', 'm', 'e');
1841 fontlist::FontList* list = SharedFontList();
1842 nsAutoCString canonicalName(aFamily->DisplayName().AsString(list));
1843 const fontlist::Pointer* facePtrs = aFamily->Faces(list);
1844 for (uint32_t i = 0, n = aFamily->NumFaces(); i < n; i++) {
1845 auto face = static_cast<fontlist::Face*>(facePtrs[i].ToPtr(list));
1849 nsAutoCString name(face->mDescriptor.AsString(list));
1850 // We create a temporary MacOSFontEntry just to read family names from the
1851 // 'name' table in the font resource. The style attributes here are ignored
1852 // as this entry is not used for font style matching.
1853 // The size hint might be used to select which face is accessed in the case
1854 // of the macOS UI font; see MacOSFontEntry::GetFontRef(). We pass 16.0 in
1855 // order to get a standard text-size face in this case, although it's
1856 // unlikely to matter for the purpose of just reading family names.
1857 auto fe = MakeUnique<MacOSFontEntry>(name, WeightRange(FontWeight::Normal()), false, 16.0);
1861 gfxFontEntry::AutoTable nameTable(fe.get(), kNAME);
1865 uint32_t dataLength;
1866 const char* nameData = hb_blob_get_data(nameTable, &dataLength);
1867 AutoTArray<nsCString, 4> otherFamilyNames;
1868 gfxFontUtils::ReadOtherFamilyNamesForFace(canonicalName, nameData, dataLength, otherFamilyNames,
1870 for (const auto& alias : otherFamilyNames) {
1872 GenerateFontListKey(alias, key);
1873 auto aliasData = mAliasTable.GetOrInsertNew(key);
1874 aliasData->InitFromFamily(aFamily, canonicalName);
1875 aliasData->mFaces.AppendElement(facePtrs[i]);