1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "AppleUtils.h"
7 #include "CoreTextFontList.h"
8 #include "gfxFontConstants.h"
9 #include "gfxMacFont.h"
10 #include "gfxUserFontSet.h"
12 #include "harfbuzz/hb.h"
14 #include "MainThreadUtils.h"
16 #include "mozilla/dom/ContentChild.h"
17 #include "mozilla/dom/ContentParent.h"
18 #include "mozilla/gfx/2D.h"
19 #include "mozilla/Logging.h"
20 #include "mozilla/Preferences.h"
21 #include "mozilla/ProfilerLabels.h"
22 #include "mozilla/Sprintf.h"
23 #include "mozilla/StaticPrefs_gfx.h"
24 #include "mozilla/Telemetry.h"
26 #include "nsAppDirectoryServiceDefs.h"
27 #include "nsCharTraits.h"
28 #include "nsComponentManagerUtils.h"
29 #include "nsDirectoryServiceDefs.h"
30 #include "nsDirectoryServiceUtils.h"
31 #include "nsIDirectoryEnumerator.h"
32 #include "nsServiceManagerUtils.h"
33 #include "SharedFontList-impl.h"
35 using namespace mozilla
;
36 using namespace mozilla::gfx
;
38 #ifdef MOZ_WIDGET_COCOA
39 // Building with newer macOS SDKs can cause a bunch of font-family names to be
40 // hidden from the Core Text API we use to enumerate available fonts. Because
41 // some content still benefits from having these names recognized, we forcibly
42 // include them in the list. Some day we might want to drop support for these.
43 # define USE_DEPRECATED_FONT_FAMILY_NAMES 1
46 #if USE_DEPRECATED_FONT_FAMILY_NAMES
47 // List generated by diffing the arrays returned by
48 // CTFontManagerCopyAvailableFontFamilyNames() when built with
49 // MACOSX_DEPLOYMENT_TARGET=10.12 vs 11.0, to identify the font family names
50 // that Core Text is treating as "deprecated" and hiding from the app on newer
52 constexpr nsLiteralCString kDeprecatedFontFamilies
[] = {
53 // Dot-prefixed font families are supposed to be hidden from the
55 // font list anyhow, so we don't need to add them here.
56 // ".Al Bayan PUA"_ns,
58 // ".Al Tarikh PUA"_ns,
59 // ".Apple Color Emoji UI"_ns,
60 // ".Apple SD Gothic NeoI"_ns,
62 // ".Arial Hebrew Desk Interface"_ns,
65 // ".Damascus PUA"_ns,
66 // ".DecoType Naskh PUA"_ns,
67 // ".Diwan Kufi PUA"_ns,
69 // ".Geeza Pro Interface"_ns,
70 // ".Geeza Pro PUA"_ns,
71 // ".Helvetica LT MM"_ns,
72 // ".Hiragino Kaku Gothic Interface"_ns,
73 // ".Hiragino Sans GB Interface"_ns,
75 // ".KufiStandardGK PUA"_ns,
77 // ".Lucida Grande UI"_ns,
81 // ".Noto Nastaliq Urdu UI"_ns,
86 // ".Savoye LET CC."_ns,
88 // ".SF Compact Rounded"_ns,
91 // ".SF NS Rounded"_ns,
94 "Hiragino Kaku Gothic Pro"_ns
,
95 "Hiragino Kaku Gothic ProN"_ns
,
96 "Hiragino Kaku Gothic Std"_ns
,
97 "Hiragino Kaku Gothic StdN"_ns
,
98 "Hiragino Maru Gothic Pro"_ns
,
99 "Hiragino Mincho Pro"_ns
,
100 "Iowan Old Style"_ns
,
101 "Noto Sans Adlam"_ns
,
102 "Noto Sans Armenian"_ns
,
103 "Noto Sans Avestan"_ns
,
104 "Noto Sans Bamum"_ns
,
105 "Noto Sans Bassa Vah"_ns
,
106 "Noto Sans Batak"_ns
,
107 "Noto Sans Bhaiksuki"_ns
,
108 "Noto Sans Brahmi"_ns
,
109 "Noto Sans Buginese"_ns
,
110 "Noto Sans Buhid"_ns
,
111 "Noto Sans Carian"_ns
,
112 "Noto Sans Caucasian Albanian"_ns
,
113 "Noto Sans Chakma"_ns
,
115 "Noto Sans Coptic"_ns
,
116 "Noto Sans Cuneiform"_ns
,
117 "Noto Sans Cypriot"_ns
,
118 "Noto Sans Duployan"_ns
,
119 "Noto Sans Egyptian Hieroglyphs"_ns
,
120 "Noto Sans Elbasan"_ns
,
121 "Noto Sans Glagolitic"_ns
,
122 "Noto Sans Gothic"_ns
,
123 "Noto Sans Gunjala Gondi"_ns
,
124 "Noto Sans Hanifi Rohingya"_ns
,
125 "Noto Sans Hanunoo"_ns
,
126 "Noto Sans Hatran"_ns
,
127 "Noto Sans Imperial Aramaic"_ns
,
128 "Noto Sans Inscriptional Pahlavi"_ns
,
129 "Noto Sans Inscriptional Parthian"_ns
,
130 "Noto Sans Javanese"_ns
,
131 "Noto Sans Kaithi"_ns
,
132 "Noto Sans Kayah Li"_ns
,
133 "Noto Sans Kharoshthi"_ns
,
134 "Noto Sans Khojki"_ns
,
135 "Noto Sans Khudawadi"_ns
,
136 "Noto Sans Lepcha"_ns
,
137 "Noto Sans Limbu"_ns
,
138 "Noto Sans Linear A"_ns
,
139 "Noto Sans Linear B"_ns
,
141 "Noto Sans Lycian"_ns
,
142 "Noto Sans Lydian"_ns
,
143 "Noto Sans Mahajani"_ns
,
144 "Noto Sans Mandaic"_ns
,
145 "Noto Sans Manichaean"_ns
,
146 "Noto Sans Marchen"_ns
,
147 "Noto Sans Masaram Gondi"_ns
,
148 "Noto Sans Meetei Mayek"_ns
,
149 "Noto Sans Mende Kikakui"_ns
,
150 "Noto Sans Meroitic"_ns
,
153 "Noto Sans Mongolian"_ns
,
155 "Noto Sans Multani"_ns
,
156 "Noto Sans Nabataean"_ns
,
157 "Noto Sans New Tai Lue"_ns
,
160 "Noto Sans Ol Chiki"_ns
,
161 "Noto Sans Old Hungarian"_ns
,
162 "Noto Sans Old Italic"_ns
,
163 "Noto Sans Old North Arabian"_ns
,
164 "Noto Sans Old Permic"_ns
,
165 "Noto Sans Old Persian"_ns
,
166 "Noto Sans Old South Arabian"_ns
,
167 "Noto Sans Old Turkic"_ns
,
168 "Noto Sans Osage"_ns
,
169 "Noto Sans Osmanya"_ns
,
170 "Noto Sans Pahawh Hmong"_ns
,
171 "Noto Sans Palmyrene"_ns
,
172 "Noto Sans Pau Cin Hau"_ns
,
173 "Noto Sans PhagsPa"_ns
,
174 "Noto Sans Phoenician"_ns
,
175 "Noto Sans Psalter Pahlavi"_ns
,
176 "Noto Sans Rejang"_ns
,
177 "Noto Sans Samaritan"_ns
,
178 "Noto Sans Saurashtra"_ns
,
179 "Noto Sans Sharada"_ns
,
180 "Noto Sans Siddham"_ns
,
181 "Noto Sans Sora Sompeng"_ns
,
182 "Noto Sans Sundanese"_ns
,
183 "Noto Sans Syloti Nagri"_ns
,
184 "Noto Sans Syriac"_ns
,
185 "Noto Sans Tagalog"_ns
,
186 "Noto Sans Tagbanwa"_ns
,
187 "Noto Sans Tai Le"_ns
,
188 "Noto Sans Tai Tham"_ns
,
189 "Noto Sans Tai Viet"_ns
,
190 "Noto Sans Takri"_ns
,
191 "Noto Sans Thaana"_ns
,
192 "Noto Sans Tifinagh"_ns
,
193 "Noto Sans Tirhuta"_ns
,
194 "Noto Sans Ugaritic"_ns
,
196 "Noto Sans Wancho"_ns
,
197 "Noto Sans Warang Citi"_ns
,
199 "Noto Sans Zawgyi"_ns
,
200 "Noto Serif Ahom"_ns
,
201 "Noto Serif Balinese"_ns
,
202 "Noto Serif Yezidi"_ns
,
210 #endif // USE_DEPRECATED_FONT_FAMILY_NAMES
212 static void GetStringForCFString(CFStringRef aSrc
, nsAString
& aDest
) {
213 auto len
= CFStringGetLength(aSrc
);
214 aDest
.SetLength(len
);
215 CFStringGetCharacters(aSrc
, CFRangeMake(0, len
),
216 (UniChar
*)aDest
.BeginWriting());
219 static CFStringRef
CreateCFStringForString(const nsACString
& aSrc
) {
220 return CFStringCreateWithBytes(kCFAllocatorDefault
,
221 (const UInt8
*)aSrc
.BeginReading(),
222 aSrc
.Length(), kCFStringEncodingUTF8
, false);
225 #define LOG_FONTLIST(args) \
226 MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), mozilla::LogLevel::Debug, args)
227 #define LOG_FONTLIST_ENABLED() \
228 MOZ_LOG_TEST(gfxPlatform::GetLog(eGfxLog_fontlist), mozilla::LogLevel::Debug)
229 #define LOG_CMAPDATA_ENABLED() \
230 MOZ_LOG_TEST(gfxPlatform::GetLog(eGfxLog_cmapdata), mozilla::LogLevel::Debug)
234 // Complex scripts will not render correctly unless appropriate AAT or OT
235 // layout tables are present.
236 // For OpenType, we also check that the GSUB table supports the relevant
237 // script tag, to avoid using things like Arial Unicode MS for Lao (it has
238 // the characters, but lacks OpenType support).
240 // TODO: consider whether we should move this to gfxFontEntry and do similar
241 // cmap-masking on other platforms to avoid using fonts that won't shape
244 nsresult
CTFontEntry::ReadCMAP(FontInfoData
* aFontInfoData
) {
245 // attempt this once, if errors occur leave a blank cmap
246 if (mCharacterMap
|| mShmemCharacterMap
) {
250 RefPtr
<gfxCharacterMap
> charmap
;
253 uint32_t uvsOffset
= 0;
255 (charmap
= GetCMAPFromFontInfo(aFontInfoData
, uvsOffset
))) {
258 uint32_t kCMAP
= TRUETYPE_TAG('c', 'm', 'a', 'p');
259 charmap
= new gfxCharacterMap();
260 AutoTable
cmapTable(this, kCMAP
);
264 const uint8_t* cmapData
= reinterpret_cast<const uint8_t*>(
265 hb_blob_get_data(cmapTable
, &cmapLen
));
266 rv
= gfxFontUtils::ReadCMAP(cmapData
, cmapLen
, *charmap
, uvsOffset
);
268 rv
= NS_ERROR_NOT_AVAILABLE
;
271 mUVSOffset
.exchange(uvsOffset
);
273 if (NS_SUCCEEDED(rv
) && !mIsDataUserFont
&& !HasGraphiteTables()) {
274 // For downloadable fonts, trust the author and don't
275 // try to munge the cmap based on script shaping support.
277 // We also assume a Graphite font knows what it's doing,
278 // and provides whatever shaping is needed for the
279 // characters it supports, so only check/clear the
280 // complex-script ranges for non-Graphite fonts
282 // for layout support, check for the presence of mort/morx/kerx and/or
283 // opentype layout tables
284 bool hasAATLayout
= HasFontTable(TRUETYPE_TAG('m', 'o', 'r', 'x')) ||
285 HasFontTable(TRUETYPE_TAG('m', 'o', 'r', 't'));
286 bool hasAppleKerning
= HasFontTable(TRUETYPE_TAG('k', 'e', 'r', 'x'));
287 bool hasGSUB
= HasFontTable(TRUETYPE_TAG('G', 'S', 'U', 'B'));
288 bool hasGPOS
= HasFontTable(TRUETYPE_TAG('G', 'P', 'O', 'S'));
289 if ((hasAATLayout
&& !(hasGSUB
|| hasGPOS
)) || hasAppleKerning
) {
290 mRequiresAAT
= true; // prefer CoreText if font has no OTL tables,
291 // or if it uses the Apple-specific 'kerx'
292 // variant of kerning table
295 for (const ScriptRange
* sr
= gfxPlatformFontList::sComplexScriptRanges
;
296 sr
->rangeStart
; sr
++) {
297 // check to see if the cmap includes complex script codepoints
298 if (charmap
->TestRange(sr
->rangeStart
, sr
->rangeEnd
)) {
300 // prefer CoreText for Apple's complex-script fonts,
301 // even if they also have some OpenType tables
302 // (e.g. Geeza Pro Bold on 10.6; see bug 614903)
304 // and don't mask off complex-script ranges, we assume
305 // the AAT tables will provide the necessary shaping
309 // We check for GSUB here, as GPOS alone would not be ok.
310 if (hasGSUB
&& SupportsScriptInGSUB(sr
->tags
, sr
->numTags
)) {
314 charmap
->ClearRange(sr
->rangeStart
, sr
->rangeEnd
);
318 // Bug 1360309, 1393624: several of Apple's Chinese fonts have spurious
319 // blank glyphs for obscure Tibetan and Arabic-script codepoints.
320 // Blocklist these so that font fallback will not use them.
322 (FamilyName().EqualsLiteral("Songti SC") ||
323 FamilyName().EqualsLiteral("Songti TC") ||
324 FamilyName().EqualsLiteral("STSong") ||
325 // Bug 1390980: on 10.11, the Kaiti fonts are also affected.
326 FamilyName().EqualsLiteral("Kaiti SC") ||
327 FamilyName().EqualsLiteral("Kaiti TC") ||
328 FamilyName().EqualsLiteral("STKaiti"))) {
329 charmap
->ClearRange(0x0f6b, 0x0f70);
330 charmap
->ClearRange(0x0f8c, 0x0f8f);
331 charmap
->clear(0x0f98);
332 charmap
->clear(0x0fbd);
333 charmap
->ClearRange(0x0fcd, 0x0fff);
334 charmap
->clear(0x0620);
335 charmap
->clear(0x065f);
336 charmap
->ClearRange(0x06ee, 0x06ef);
337 charmap
->clear(0x06ff);
341 bool setCharMap
= true;
342 if (NS_SUCCEEDED(rv
)) {
343 gfxPlatformFontList
* pfl
= gfxPlatformFontList::PlatformFontList();
344 fontlist::FontList
* sharedFontList
= pfl
->SharedFontList();
345 if (!IsUserFont() && mShmemFace
&& mShmemFamily
) {
346 mShmemFace
->SetCharacterMap(sharedFontList
, charmap
, mShmemFamily
);
347 if (TrySetShmemCharacterMap()) {
351 charmap
= pfl
->FindCharMap(charmap
);
353 mHasCmapTable
= true;
355 // if error occurred, initialize to null cmap
356 charmap
= new gfxCharacterMap();
357 mHasCmapTable
= false;
360 // Temporarily retain charmap, until the shared version is
362 if (mCharacterMap
.compareExchange(nullptr, charmap
.get())) {
363 charmap
.get()->AddRef();
367 LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %zu hash: %8.8x%s\n",
368 mName
.get(), charmap
->SizeOfIncludingThis(moz_malloc_size_of
),
369 charmap
->mHash
, mCharacterMap
== charmap
? " new" : ""));
370 if (LOG_CMAPDATA_ENABLED()) {
372 SprintfLiteral(prefix
, "(cmapdata) name: %.220s", mName
.get());
373 charmap
->Dump(prefix
, eGfxLog_cmapdata
);
379 gfxFont
* CTFontEntry::CreateFontInstance(const gfxFontStyle
* aFontStyle
) {
380 RefPtr
<UnscaledFontMac
> unscaledFont(mUnscaledFont
);
382 CGFontRef baseFont
= GetFontRef();
386 unscaledFont
= new UnscaledFontMac(baseFont
, mIsDataUserFont
);
387 mUnscaledFont
= unscaledFont
;
390 return new gfxMacFont(unscaledFont
, this, aFontStyle
);
393 bool CTFontEntry::HasVariations() {
394 if (!mHasVariationsInitialized
) {
395 mHasVariationsInitialized
= true;
396 mHasVariations
= gfxPlatform::HasVariationFontSupport() &&
397 HasFontTable(TRUETYPE_TAG('f', 'v', 'a', 'r'));
400 return mHasVariations
;
403 void CTFontEntry::GetVariationAxes(
404 nsTArray
<gfxFontVariationAxis
>& aVariationAxes
) {
405 // We could do this by creating a CTFont and calling CTFontCopyVariationAxes,
406 // but it is expensive to instantiate a CTFont for every face just to set up
407 // the axis information.
408 // Instead we use gfxFontUtils to read the font tables directly.
409 gfxFontUtils::GetVariationData(this, &aVariationAxes
, nullptr);
412 void CTFontEntry::GetVariationInstances(
413 nsTArray
<gfxFontVariationInstance
>& aInstances
) {
414 // Core Text doesn't offer API for this, so we use gfxFontUtils to read the
415 // font tables directly.
416 gfxFontUtils::GetVariationData(this, nullptr, &aInstances
);
419 bool CTFontEntry::IsCFF() {
420 if (!mIsCFFInitialized
) {
421 mIsCFFInitialized
= true;
422 mIsCFF
= HasFontTable(TRUETYPE_TAG('C', 'F', 'F', ' '));
428 CTFontEntry::CTFontEntry(const nsACString
& aPostscriptName
, WeightRange aWeight
,
429 bool aIsStandardFace
, double aSizeHint
)
430 : gfxFontEntry(aPostscriptName
, aIsStandardFace
),
432 mSizeHint(aSizeHint
),
433 mFontRefInitialized(false),
436 mIsCFFInitialized(false),
437 mHasVariations(false),
438 mHasVariationsInitialized(false),
439 mHasAATSmallCaps(false),
440 mHasAATSmallCapsInitialized(false) {
441 mWeightRange
= aWeight
;
445 CTFontEntry::CTFontEntry(const nsACString
& aPostscriptName
, CGFontRef aFontRef
,
446 WeightRange aWeight
, StretchRange aStretch
,
447 SlantStyleRange aStyle
, bool aIsDataUserFont
,
448 bool aIsLocalUserFont
)
449 : gfxFontEntry(aPostscriptName
, false),
452 mFontRefInitialized(false),
455 mIsCFFInitialized(false),
456 mHasVariations(false),
457 mHasVariationsInitialized(false),
458 mHasAATSmallCaps(false),
459 mHasAATSmallCapsInitialized(false) {
461 mFontRefInitialized
= true;
464 mWeightRange
= aWeight
;
465 mStretchRange
= aStretch
;
466 mFixedPitch
= false; // xxx - do we need this for downloaded fonts?
467 mStyleRange
= aStyle
;
470 NS_ASSERTION(!(aIsDataUserFont
&& aIsLocalUserFont
),
471 "userfont is either a data font or a local font");
472 mIsDataUserFont
= aIsDataUserFont
;
473 mIsLocalUserFont
= aIsLocalUserFont
;
476 gfxFontEntry
* CTFontEntry::Clone() const {
477 MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!");
478 CTFontEntry
* fe
= new CTFontEntry(Name(), Weight(), mStandardFace
, mSizeHint
);
479 fe
->mStyleRange
= mStyleRange
;
480 fe
->mStretchRange
= mStretchRange
;
481 fe
->mFixedPitch
= mFixedPitch
;
485 CGFontRef
CTFontEntry::GetFontRef() {
487 AutoReadLock
lock(mLock
);
488 if (mFontRefInitialized
) {
492 AutoWriteLock
lock(mLock
);
493 if (!mFontRefInitialized
) {
494 // Cache the CGFontRef, to be released by our destructor.
495 mFontRef
= CreateOrCopyFontRef();
496 mFontRefInitialized
= true;
498 // Return a non-retained reference; caller does not need to release.
502 CGFontRef
CTFontEntry::CreateOrCopyFontRef() {
504 // We have a cached CGFont, just add a reference. Caller must
505 // release, but we'll still own our reference.
506 ::CGFontRetain(mFontRef
);
510 CrashReporter::AutoRecordAnnotation
autoFontName(
511 CrashReporter::Annotation::FontName
, mName
);
513 // Create a new CGFont; caller will own the only reference to it.
514 AutoCFRelease
<CFStringRef
> psname
= CreateCFStringForString(mName
);
519 CGFontRef ref
= CGFontCreateWithFontName(psname
);
520 return ref
; // Not saved in mFontRef; caller will own the reference
523 // For a logging build, we wrap the CFDataRef in a FontTableRec so that we can
524 // use the MOZ_COUNT_[CD]TOR macros in it. A release build without logging
525 // does not get this overhead.
528 explicit FontTableRec(CFDataRef aDataRef
) : mDataRef(aDataRef
) {
529 MOZ_COUNT_CTOR(FontTableRec
);
533 MOZ_COUNT_DTOR(FontTableRec
);
541 /*static*/ void CTFontEntry::DestroyBlobFunc(void* aUserData
) {
542 #ifdef NS_BUILD_REFCNT_LOGGING
543 FontTableRec
* ftr
= static_cast<FontTableRec
*>(aUserData
);
546 CFRelease((CFDataRef
)aUserData
);
550 hb_blob_t
* CTFontEntry::GetFontTable(uint32_t aTag
) {
552 AutoCFRelease
<CGFontRef
> fontRef
= CreateOrCopyFontRef();
558 CFDataRef dataRef
= ::CGFontCopyTableForTag(fontRef
, aTag
);
560 return hb_blob_create((const char*)CFDataGetBytePtr(dataRef
),
561 CFDataGetLength(dataRef
), HB_MEMORY_MODE_READONLY
,
562 #ifdef NS_BUILD_REFCNT_LOGGING
563 new FontTableRec(dataRef
),
573 bool CTFontEntry::HasFontTable(uint32_t aTableTag
) {
575 // If we've already initialized mAvailableTables, we can return without
576 // needing to take an exclusive lock.
577 AutoReadLock
lock(mLock
);
578 if (mAvailableTables
.Count()) {
579 return mAvailableTables
.GetEntry(aTableTag
);
583 AutoWriteLock
lock(mLock
);
584 if (mAvailableTables
.Count() == 0) {
585 AutoCFRelease
<CGFontRef
> fontRef
= CreateOrCopyFontRef();
589 AutoCFRelease
<CFArrayRef
> tags
= ::CGFontCopyTableTags(fontRef
);
593 int numTags
= (int)CFArrayGetCount(tags
);
594 for (int t
= 0; t
< numTags
; t
++) {
595 uint32_t tag
= (uint32_t)(uintptr_t)CFArrayGetValueAtIndex(tags
, t
);
596 mAvailableTables
.PutEntry(tag
);
600 return mAvailableTables
.GetEntry(aTableTag
);
603 static bool CheckForAATSmallCaps(CFArrayRef aFeatures
) {
604 // Walk the array of feature descriptors from the font, and see whether
605 // a small-caps feature setting is available.
606 // Just bail out (returning false) if at any point we fail to find the
607 // expected dictionary keys, etc; if the font has bad data, we don't even
608 // try to search the rest of it.
609 auto numFeatures
= CFArrayGetCount(aFeatures
);
610 for (auto f
= 0; f
< numFeatures
; ++f
) {
611 auto featureDict
= (CFDictionaryRef
)CFArrayGetValueAtIndex(aFeatures
, f
);
615 auto featureNum
= (CFNumberRef
)CFDictionaryGetValue(
616 featureDict
, CFSTR("CTFeatureTypeIdentifier"));
621 if (!CFNumberGetValue(featureNum
, kCFNumberSInt16Type
, &featureType
)) {
624 if (featureType
== kLetterCaseType
|| featureType
== kLowerCaseType
) {
625 // Which selector to look for, depending whether we've found the
626 // legacy LetterCase feature or the new LowerCase one.
627 const uint16_t smallCaps
= (featureType
== kLetterCaseType
)
629 : kLowerCaseSmallCapsSelector
;
630 auto selectors
= (CFArrayRef
)CFDictionaryGetValue(
631 featureDict
, CFSTR("CTFeatureTypeSelectors"));
635 auto numSelectors
= CFArrayGetCount(selectors
);
636 for (auto s
= 0; s
< numSelectors
; s
++) {
638 (CFDictionaryRef
)CFArrayGetValueAtIndex(selectors
, s
);
642 auto selectorNum
= (CFNumberRef
)CFDictionaryGetValue(
643 selectorDict
, CFSTR("CTFeatureSelectorIdentifier"));
647 int16_t selectorValue
;
648 if (!CFNumberGetValue(selectorNum
, kCFNumberSInt16Type
,
652 if (selectorValue
== smallCaps
) {
661 bool CTFontEntry::SupportsOpenTypeFeature(Script aScript
,
662 uint32_t aFeatureTag
) {
663 // If we're going to shape with Core Text, we don't support added
664 // OpenType features (aside from any CT applies by default), except
665 // for 'smcp' which we map to an AAT feature selector.
666 if (RequiresAATLayout()) {
667 if (aFeatureTag
!= HB_TAG('s', 'm', 'c', 'p')) {
670 if (mHasAATSmallCapsInitialized
) {
671 return mHasAATSmallCaps
;
673 mHasAATSmallCapsInitialized
= true;
674 CGFontRef cgFont
= GetFontRef();
676 return mHasAATSmallCaps
;
679 CrashReporter::AutoRecordAnnotation
autoFontName(
680 CrashReporter::Annotation::FontName
, FamilyName());
682 AutoCFRelease
<CTFontRef
> ctFont
=
683 CTFontCreateWithGraphicsFont(cgFont
, 0.0, nullptr, nullptr);
685 AutoCFRelease
<CFArrayRef
> features
= CTFontCopyFeatures(ctFont
);
687 mHasAATSmallCaps
= CheckForAATSmallCaps(features
);
690 return mHasAATSmallCaps
;
692 return gfxFontEntry::SupportsOpenTypeFeature(aScript
, aFeatureTag
);
695 void CTFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf
,
696 FontListSizes
* aSizes
) const {
697 aSizes
->mFontListSize
+= aMallocSizeOf(this);
698 AddSizeOfExcludingThis(aMallocSizeOf
, aSizes
);
701 static CTFontDescriptorRef
CreateDescriptorForFamily(
702 const nsACString
& aFamilyName
, bool aNormalized
) {
703 AutoCFRelease
<CFStringRef
> family
= CreateCFStringForString(aFamilyName
);
704 const void* values
[] = {family
};
705 const void* keys
[] = {kCTFontFamilyNameAttribute
};
706 AutoCFRelease
<CFDictionaryRef
> attributes
= CFDictionaryCreate(
707 kCFAllocatorDefault
, keys
, values
, 1, &kCFTypeDictionaryKeyCallBacks
,
708 &kCFTypeDictionaryValueCallBacks
);
710 // Not AutoCFRelease, because we might return it.
711 CTFontDescriptorRef descriptor
=
712 CTFontDescriptorCreateWithAttributes(attributes
);
715 CTFontDescriptorRef normalized
=
716 CTFontDescriptorCreateMatchingFontDescriptor(descriptor
, nullptr);
718 CFRelease(descriptor
);
726 void CTFontFamily::LocalizedName(nsACString
& aLocalizedName
) {
727 AutoCFRelease
<CTFontDescriptorRef
> descriptor
=
728 CreateDescriptorForFamily(mName
, true);
730 AutoCFRelease
<CFStringRef
> name
=
731 static_cast<CFStringRef
>(CTFontDescriptorCopyLocalizedAttribute(
732 descriptor
, kCTFontFamilyNameAttribute
, nullptr));
734 nsAutoString localized
;
735 GetStringForCFString(name
, localized
);
736 if (!localized
.IsEmpty()) {
737 CopyUTF16toUTF8(localized
, aLocalizedName
);
743 // failed to get localized name, just use the canonical one
744 aLocalizedName
= mName
;
747 // Return the CSS weight value to use for the given face, overriding what
748 // AppKit gives us (used to adjust families with bad weight values, see
750 // A return value of 0 indicates no override - use the existing weight.
751 static inline int GetWeightOverride(const nsAString
& aPSName
) {
752 nsAutoCString
prefName("font.weight-override.");
753 // The PostScript name is required to be ASCII; if it's not, the font is
754 // broken anyway, so we really don't care that this is lossy.
755 LossyAppendUTF16toASCII(aPSName
, prefName
);
756 return Preferences::GetInt(prefName
.get(), 0);
759 // The Core Text weight trait is documented as
761 // ...a float value between -1.0 and 1.0 for normalized weight.
762 // The value of 0.0 corresponds to the regular or medium font weight.
764 // (https://developer.apple.com/documentation/coretext/kctfontweighttrait)
766 // CSS 'normal' font-weight is defined as 400, so we map 0.0 to this.
767 // The exact mapping to use for other values is not well defined; the table
768 // here is empirically determined by looking at what Core Text returns for
769 // the various system fonts that have a range of weights.
770 static inline int32_t CoreTextWeightToCSSWeight(CGFloat aCTWeight
) {
771 using Mapping
= std::pair
<CGFloat
, int32_t>;
772 constexpr Mapping kCoreTextToCSSWeights
[] = {
778 {0.0, 400}, // standard 'regular' weight
781 {0.4, 700}, // standard 'bold' weight
783 {0.62, 900}, // Core Text seems to return 0.62 for faces with both
784 // usWeightClass=800 and 900 in their OS/2 tables!
785 // We use 900 as there are also fonts that return 0.56,
786 // so we want an intermediate value for that.
790 const auto* begin
= &kCoreTextToCSSWeights
[0];
791 const auto* end
= begin
+ ArrayLength(kCoreTextToCSSWeights
);
792 auto m
= std::upper_bound(begin
, end
, aCTWeight
,
793 [](CGFloat aValue
, const Mapping
& aMapping
) {
794 return aValue
<= aMapping
.first
;
797 NS_WARNING("Core Text weight out of range");
800 if (m
->first
== aCTWeight
|| m
== begin
) {
803 // Interpolate between the preceding and found entries:
804 const auto* prev
= m
- 1;
805 const auto t
= (aCTWeight
- prev
->first
) / (m
->first
- prev
->first
);
806 return NS_round(prev
->second
* (1.0 - t
) + m
->second
* t
);
809 // The Core Text width trait is documented as
811 // ...a float between -1.0 and 1.0. The value of 0.0 corresponds to regular
812 // glyph spacing, and negative values represent condensed glyph spacing
814 // (https://developer.apple.com/documentation/coretext/kctfontweighttrait)
816 // CSS 'normal' font-stretch is 100%; 'ultra-expanded' is 200%, and 'ultra-
817 // condensed' is 50%. We map the extremes of the Core Text trait to these
818 // values, and interpolate in between these and normal.
819 static inline FontStretch
CoreTextWidthToCSSStretch(CGFloat aCTWidth
) {
820 if (aCTWidth
>= 0.0) {
821 return FontStretch::FromFloat(100.0 + aCTWidth
* 100.0);
823 return FontStretch::FromFloat(100.0 + aCTWidth
* 50.0);
826 void CTFontFamily::AddFace(CTFontDescriptorRef aFace
) {
827 AutoCFRelease
<CFStringRef
> psname
=
828 (CFStringRef
)CTFontDescriptorCopyAttribute(aFace
, kCTFontNameAttribute
);
829 AutoCFRelease
<CFStringRef
> facename
=
830 (CFStringRef
)CTFontDescriptorCopyAttribute(aFace
,
831 kCTFontStyleNameAttribute
);
833 AutoCFRelease
<CFDictionaryRef
> traitsDict
=
834 (CFDictionaryRef
)CTFontDescriptorCopyAttribute(aFace
,
835 kCTFontTraitsAttribute
);
837 (CFNumberRef
)CFDictionaryGetValue(traitsDict
, kCTFontWeightTrait
);
839 (CFNumberRef
)CFDictionaryGetValue(traitsDict
, kCTFontWidthTrait
);
840 CFNumberRef symbolicTraits
=
841 (CFNumberRef
)CFDictionaryGetValue(traitsDict
, kCTFontSymbolicTrait
);
843 bool isStandardFace
= false;
846 nsAutoString postscriptFontName
;
847 GetStringForCFString(psname
, postscriptFontName
);
849 int32_t cssWeight
= GetWeightOverride(postscriptFontName
);
851 // scale down and clamp, to get a value from 1..9
852 cssWeight
= ((cssWeight
+ 50) / 100);
853 cssWeight
= std::max(1, std::min(cssWeight
, 9));
854 cssWeight
*= 100; // scale up to CSS values
857 CFNumberGetValue(weight
, kCFNumberCGFloatType
, &weightValue
);
858 cssWeight
= CoreTextWeightToCSSWeight(weightValue
);
861 if (kCFCompareEqualTo
== CFStringCompare(facename
, CFSTR("Regular"), 0) ||
862 kCFCompareEqualTo
== CFStringCompare(facename
, CFSTR("Bold"), 0) ||
863 kCFCompareEqualTo
== CFStringCompare(facename
, CFSTR("Italic"), 0) ||
864 kCFCompareEqualTo
== CFStringCompare(facename
, CFSTR("Oblique"), 0) ||
865 kCFCompareEqualTo
== CFStringCompare(facename
, CFSTR("Bold Italic"), 0) ||
867 CFStringCompare(facename
, CFSTR("Bold Oblique"), 0)) {
868 isStandardFace
= true;
871 // create a font entry
872 CTFontEntry
* fontEntry
= new CTFontEntry(
873 NS_ConvertUTF16toUTF8(postscriptFontName
),
874 WeightRange(FontWeight::FromInt(cssWeight
)), isStandardFace
);
877 CFNumberGetValue(width
, kCFNumberCGFloatType
, &widthValue
);
878 fontEntry
->mStretchRange
=
879 StretchRange(CoreTextWidthToCSSStretch(widthValue
));
882 CFNumberGetValue(symbolicTraits
, kCFNumberSInt32Type
, &traitsValue
);
883 if (traitsValue
& kCTFontItalicTrait
) {
884 fontEntry
->mStyleRange
= SlantStyleRange(FontSlantStyle::ITALIC
);
887 if (traitsValue
& kCTFontMonoSpaceTrait
) {
888 fontEntry
->mFixedPitch
= true;
891 if (gfxPlatform::HasVariationFontSupport()) {
892 fontEntry
->SetupVariationRanges();
895 if (LOG_FONTLIST_ENABLED()) {
896 nsAutoCString weightString
;
897 fontEntry
->Weight().ToString(weightString
);
898 nsAutoCString stretchString
;
899 fontEntry
->Stretch().ToString(stretchString
);
901 ("(fontlist) added (%s) to family (%s)"
902 " with style: %s weight: %s stretch: %s",
903 fontEntry
->Name().get(), Name().get(),
904 fontEntry
->IsItalic() ? "italic" : "normal", weightString
.get(),
905 stretchString
.get()));
908 // insert into font entry array of family
909 AddFontEntryLocked(fontEntry
);
912 void CTFontFamily::FindStyleVariationsLocked(FontInfoData
* aFontInfoData
) {
917 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("CTFontFamily::FindStyleVariations",
920 if (mForSystemFont
) {
921 MOZ_ASSERT(gfxPlatform::HasVariationFontSupport());
923 auto addToFamily
= [&](CTFontRef aFont
) MOZ_REQUIRES(mLock
) {
924 AutoCFRelease
<CFStringRef
> psName
= CTFontCopyPostScriptName(aFont
);
925 nsAutoString nameUTF16
;
926 nsAutoCString nameUTF8
;
927 GetStringForCFString(psName
, nameUTF16
);
928 CopyUTF16toUTF8(nameUTF16
, nameUTF8
);
931 new CTFontEntry(nameUTF8
, WeightRange(FontWeight::NORMAL
), true, 0.0);
933 // Set the appropriate style, assuming it may not have a variation range.
934 CTFontSymbolicTraits traits
= CTFontGetSymbolicTraits(aFont
);
935 fe
->mStyleRange
= SlantStyleRange((traits
& kCTFontTraitItalic
)
936 ? FontSlantStyle::ITALIC
937 : FontSlantStyle::NORMAL
);
939 // Set up weight (and width, if present) ranges.
940 fe
->SetupVariationRanges();
941 AddFontEntryLocked(fe
);
944 addToFamily(mForSystemFont
);
946 // See if there is a corresponding italic face, and add it to the family.
947 AutoCFRelease
<CTFontRef
> italicFont
= CTFontCreateCopyWithSymbolicTraits(
948 mForSystemFont
, 0.0, nullptr, kCTFontTraitItalic
, kCTFontTraitItalic
);
949 if (italicFont
!= mForSystemFont
) {
950 addToFamily(italicFont
);
953 CFRelease(mForSystemFont
);
954 mForSystemFont
= nullptr;
962 CTFontFamily
* family
;
963 const void* prevValue
= nullptr;
966 auto addFaceFunc
= [](const void* aValue
, void* aContext
) -> void {
967 Context
* context
= (Context
*)aContext
;
968 if (aValue
== context
->prevValue
) {
971 context
->prevValue
= aValue
;
972 CTFontFamily
* family
= context
->family
;
973 // Calling family->AddFace requires that family->mLock is held. We know
974 // this will be true because FindStyleVariationsLocked already requires it,
975 // but the thread-safety analysis can't track that through into the lambda
976 // here, so we disable the check to avoid a spurious warning.
977 MOZ_PUSH_IGNORE_THREAD_SAFETY
;
978 family
->AddFace((CTFontDescriptorRef
)aValue
);
979 MOZ_POP_THREAD_SAFETY
;
982 AutoCFRelease
<CTFontDescriptorRef
> descriptor
=
983 CreateDescriptorForFamily(mName
, false);
984 AutoCFRelease
<CFArrayRef
> faces
=
985 CTFontDescriptorCreateMatchingFontDescriptors(descriptor
, nullptr);
988 Context context
{this};
989 CFArrayApplyFunction(faces
, CFRangeMake(0, CFArrayGetCount(faces
)),
990 addFaceFunc
, &context
);
993 SortAvailableFonts();
996 if (mIsBadUnderlineFamily
) {
997 SetBadUnderlineFonts();
1000 CheckForSimpleFamily();
1003 /* CoreTextFontList */
1006 CoreTextFontList::CoreTextFontList()
1007 : gfxPlatformFontList(false), mDefaultFont(nullptr) {
1008 #ifdef MOZ_BUNDLED_FONTS
1009 // We activate bundled fonts if the pref is > 0 (on) or < 0 (auto), only an
1010 // explicit value of 0 (off) will disable them.
1011 if (StaticPrefs::gfx_bundled_fonts_activate_AtStartup() != 0) {
1012 TimeStamp start
= TimeStamp::Now();
1013 ActivateBundledFonts();
1014 TimeStamp end
= TimeStamp::Now();
1015 Telemetry::Accumulate(Telemetry::FONTLIST_BUNDLEDFONTS_ACTIVATE
,
1016 (end
- start
).ToMilliseconds());
1020 // Load the font-list preferences now, so that we don't have to do it from
1021 // Init[Shared]FontListForPlatform, which may be called off-main-thread.
1022 gfxFontUtils::GetPrefsFontList("font.preload-names-list", mPreloadFonts
);
1025 CoreTextFontList::~CoreTextFontList() {
1026 AutoLock
lock(mLock
);
1028 if (XRE_IsParentProcess()) {
1029 CFNotificationCenterRemoveObserver(
1030 CFNotificationCenterGetLocalCenter(), this,
1031 kCTFontManagerRegisteredFontsChangedNotification
, 0);
1035 CFRelease(mDefaultFont
);
1039 void CoreTextFontList::AddFamily(const nsACString
& aFamilyName
,
1040 FontVisibility aVisibility
) {
1042 ToLowerCase(aFamilyName
, key
);
1044 RefPtr
<gfxFontFamily
> familyEntry
=
1045 new CTFontFamily(aFamilyName
, aVisibility
);
1046 mFontFamilies
.InsertOrUpdate(key
, RefPtr
{familyEntry
});
1048 // check the bad underline blocklist
1049 if (mBadUnderlineFamilyNames
.ContainsSorted(key
)) {
1050 familyEntry
->SetBadUnderlineFamily();
1054 void CoreTextFontList::AddFamily(CFStringRef aFamily
) {
1055 // CTFontManager includes internal family names and LastResort; skip those.
1057 CFStringCompare(aFamily
, CFSTR("LastResort"),
1058 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
||
1059 CFStringCompare(aFamily
, CFSTR(".LastResort"),
1060 kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
1064 nsAutoString familyName
;
1065 GetStringForCFString(aFamily
, familyName
);
1067 NS_ConvertUTF16toUTF8
nameUtf8(familyName
);
1068 AddFamily(nameUtf8
, GetVisibilityForFamily(nameUtf8
));
1072 void CoreTextFontList::ActivateFontsFromDir(
1073 const nsACString
& aDir
, nsTHashSet
<nsCStringHashKey
>* aLoadedFamilies
) {
1074 AutoCFRelease
<CFURLRef
> directory
= CFURLCreateFromFileSystemRepresentation(
1075 kCFAllocatorDefault
, (const UInt8
*)nsPromiseFlatCString(aDir
).get(),
1076 aDir
.Length(), true);
1080 AutoCFRelease
<CFURLEnumeratorRef
> enumerator
=
1081 CFURLEnumeratorCreateForDirectoryURL(kCFAllocatorDefault
, directory
,
1082 kCFURLEnumeratorDefaultBehavior
,
1087 AutoCFRelease
<CFMutableArrayRef
> urls
=
1088 CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
1094 CFURLEnumeratorResult result
;
1096 result
= CFURLEnumeratorGetNextURL(enumerator
, &url
, nullptr);
1097 if (result
!= kCFURLEnumeratorSuccess
) {
1100 CFArrayAppendValue(urls
, url
);
1102 if (!aLoadedFamilies
) {
1105 AutoCFRelease
<CFArrayRef
> descriptors
=
1106 CTFontManagerCreateFontDescriptorsFromURL(url
);
1107 if (!descriptors
|| !CFArrayGetCount(descriptors
)) {
1110 CTFontDescriptorRef desc
=
1111 (CTFontDescriptorRef
)CFArrayGetValueAtIndex(descriptors
, 0);
1112 AutoCFRelease
<CFStringRef
> name
=
1113 (CFStringRef
)CTFontDescriptorCopyAttribute(desc
,
1114 kCTFontFamilyNameAttribute
);
1116 key
.SetLength((CFStringGetLength(name
) + 1) * 3);
1117 if (CFStringGetCString(name
, key
.BeginWriting(), key
.Length(),
1118 kCFStringEncodingUTF8
)) {
1119 key
.SetLength(strlen(key
.get()));
1120 aLoadedFamilies
->Insert(key
);
1122 } while (result
!= kCFURLEnumeratorEnd
);
1124 CTFontManagerRegisterFontURLs(urls
, kCTFontManagerScopeProcess
, false,
1128 void CoreTextFontList::ReadSystemFontList(dom::SystemFontList
* aList
)
1129 MOZ_NO_THREAD_SAFETY_ANALYSIS
{
1130 // Note: We rely on the records for mSystemFontFamilyName (if present) being
1131 // *before* the main font list, so that name is known in the content process
1132 // by the time we add the actual family records to the font list.
1133 aList
->entries().AppendElement(FontFamilyListEntry(
1134 mSystemFontFamilyName
, FontVisibility::Unknown
, kSystemFontFamily
));
1136 // Now collect the list of available families, with visibility attributes.
1137 for (auto f
= mFontFamilies
.Iter(); !f
.Done(); f
.Next()) {
1138 auto macFamily
= f
.Data().get();
1139 aList
->entries().AppendElement(FontFamilyListEntry(
1140 macFamily
->Name(), macFamily
->Visibility(), kStandardFontFamily
));
1144 void CoreTextFontList::PreloadNamesList() {
1145 uint32_t numFonts
= mPreloadFonts
.Length();
1146 for (uint32_t i
= 0; i
< numFonts
; i
++) {
1148 GenerateFontListKey(mPreloadFonts
[i
], key
);
1150 // only search canonical names!
1151 gfxFontFamily
* familyEntry
= mFontFamilies
.GetWeak(key
);
1153 familyEntry
->ReadOtherFamilyNames(this);
1158 nsresult
CoreTextFontList::InitFontListForPlatform() {
1159 // The font registration thread was created early in startup, to give the
1160 // system a head start on activating all the supplemental-language fonts.
1161 // Here, we need to wait until it has finished its work.
1162 gfxPlatformMac::WaitForFontRegistration();
1164 Telemetry::AutoTimer
<Telemetry::MAC_INITFONTLIST_TOTAL
> timer
;
1166 InitSystemFontNames();
1168 if (XRE_IsParentProcess()) {
1169 static bool firstTime
= true;
1171 CFNotificationCenterAddObserver(
1172 CFNotificationCenterGetLocalCenter(), this,
1173 RegisteredFontsChangedNotificationCallback
,
1174 kCTFontManagerRegisteredFontsChangedNotification
, 0,
1175 CFNotificationSuspensionBehaviorDeliverImmediately
);
1179 // We're not a content process, so get the available fonts directly
1181 AutoCFRelease
<CFArrayRef
> familyNames
=
1182 CTFontManagerCopyAvailableFontFamilyNames();
1183 for (CFIndex i
= 0; i
< CFArrayGetCount(familyNames
); i
++) {
1184 CFStringRef familyName
=
1185 (CFStringRef
)CFArrayGetValueAtIndex(familyNames
, i
);
1186 AddFamily(familyName
);
1188 #if USE_DEPRECATED_FONT_FAMILY_NAMES
1189 for (const auto& name
: kDeprecatedFontFamilies
) {
1190 if (DeprecatedFamilyIsAvailable(name
)) {
1191 AddFamily(name
, GetVisibilityForFamily(name
));
1196 // Content process: use font list passed from the chrome process via
1197 // the GetXPCOMProcessAttributes message, because it's much faster than
1198 // querying Core Text again in the child.
1199 auto& fontList
= dom::ContentChild::GetSingleton()->SystemFontList();
1200 for (FontFamilyListEntry
& ffe
: fontList
.entries()) {
1201 switch (ffe
.entryType()) {
1202 case kStandardFontFamily
:
1203 if (ffe
.familyName() == mSystemFontFamilyName
) {
1206 AddFamily(ffe
.familyName(), ffe
.visibility());
1208 case kSystemFontFamily
:
1209 mSystemFontFamilyName
= ffe
.familyName();
1213 fontList
.entries().Clear();
1216 InitSingleFaceList();
1218 // to avoid full search of font name tables, seed the other names table with
1219 // localized names from some of the prefs fonts which are accessed via their
1220 // localized names. changes in the pref fonts will only cause a font lookup
1221 // miss earlier. this is a simple optimization, it's not required for
1225 // start the delayed cmap loader
1226 GetPrefsAndStartLoader();
1231 void CoreTextFontList::InitSharedFontListForPlatform() {
1232 gfxPlatformMac::WaitForFontRegistration();
1234 InitSystemFontNames();
1236 if (XRE_IsParentProcess()) {
1237 // Only the parent process listens for OS font-changed notifications;
1238 // after rebuilding its list, it will update the content processes.
1239 static bool firstTime
= true;
1241 CFNotificationCenterAddObserver(
1242 CFNotificationCenterGetLocalCenter(), this,
1243 RegisteredFontsChangedNotificationCallback
,
1244 kCTFontManagerRegisteredFontsChangedNotification
, 0,
1245 CFNotificationSuspensionBehaviorDeliverImmediately
);
1249 AutoCFRelease
<CFArrayRef
> familyNames
=
1250 CTFontManagerCopyAvailableFontFamilyNames();
1251 nsTArray
<fontlist::Family::InitData
> families
;
1252 families
.SetCapacity(CFArrayGetCount(familyNames
)
1253 #if USE_DEPRECATED_FONT_FAMILY_NAMES
1254 + ArrayLength(kDeprecatedFontFamilies
)
1257 for (CFIndex i
= 0; i
< CFArrayGetCount(familyNames
); ++i
) {
1258 nsAutoString name16
;
1259 CFStringRef familyName
=
1260 (CFStringRef
)CFArrayGetValueAtIndex(familyNames
, i
);
1261 GetStringForCFString(familyName
, name16
);
1262 NS_ConvertUTF16toUTF8
name(name16
);
1264 GenerateFontListKey(name
, key
);
1265 families
.AppendElement(fontlist::Family::InitData(
1266 key
, name
, fontlist::Family::kNoIndex
, GetVisibilityForFamily(name
)));
1268 #if USE_DEPRECATED_FONT_FAMILY_NAMES
1269 for (const nsACString
& name
: kDeprecatedFontFamilies
) {
1270 if (DeprecatedFamilyIsAvailable(name
)) {
1272 GenerateFontListKey(name
, key
);
1273 families
.AppendElement(
1274 fontlist::Family::InitData(key
, name
, fontlist::Family::kNoIndex
,
1275 GetVisibilityForFamily(name
)));
1279 SharedFontList()->SetFamilyNames(families
);
1280 InitAliasesForSingleFaceList();
1281 GetPrefsAndStartLoader();
1285 gfxFontFamily
* CoreTextFontList::FindSystemFontFamily(
1286 const nsACString
& aFamily
) {
1288 GenerateFontListKey(aFamily
, key
);
1290 gfxFontFamily
* familyEntry
;
1291 if ((familyEntry
= mFontFamilies
.GetWeak(key
))) {
1292 return CheckFamily(familyEntry
);
1298 void CoreTextFontList::RegisteredFontsChangedNotificationCallback(
1299 CFNotificationCenterRef center
, void* observer
, CFStringRef name
,
1300 const void* object
, CFDictionaryRef userInfo
) {
1301 if (!CFEqual(name
, kCTFontManagerRegisteredFontsChangedNotification
)) {
1305 CoreTextFontList
* fl
= static_cast<CoreTextFontList
*>(observer
);
1306 if (!fl
->IsInitialized()) {
1310 // xxx - should be carefully pruning the list of fonts, not rebuilding it from
1312 fl
->UpdateFontList();
1314 gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes
);
1315 dom::ContentParent::NotifyUpdatedFonts(true);
1318 gfxFontEntry
* CoreTextFontList::PlatformGlobalFontFallback(
1319 nsPresContext
* aPresContext
, const uint32_t aCh
, Script aRunScript
,
1320 const gfxFontStyle
* aMatchStyle
, FontFamily
& aMatchedFamily
) {
1325 if (IS_IN_BMP(aCh
)) {
1327 str
= CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault
, ch
, 1,
1330 ch
[0] = H_SURROGATE(aCh
);
1331 ch
[1] = L_SURROGATE(aCh
);
1332 str
= CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault
, ch
, 2,
1340 // use CoreText to find the fallback family
1342 gfxFontEntry
* fontEntry
= nullptr;
1343 bool cantUseFallbackFont
= false;
1345 if (!mDefaultFont
) {
1346 mDefaultFont
= CTFontCreateWithName(CFSTR("LucidaGrande"), 12.f
, NULL
);
1349 AutoCFRelease
<CTFontRef
> fallback
=
1350 CTFontCreateForString(mDefaultFont
, str
, CFRangeMake(0, length
));
1353 AutoCFRelease
<CFStringRef
> familyNameRef
= CTFontCopyFamilyName(fallback
);
1355 if (familyNameRef
&&
1356 CFStringCompare(familyNameRef
, CFSTR("LastResort"),
1357 kCFCompareCaseInsensitive
) != kCFCompareEqualTo
&&
1358 CFStringCompare(familyNameRef
, CFSTR(".LastResort"),
1359 kCFCompareCaseInsensitive
) != kCFCompareEqualTo
) {
1360 AutoTArray
<UniChar
, 1024> buffer
;
1361 CFIndex familyNameLen
= CFStringGetLength(familyNameRef
);
1362 buffer
.SetLength(familyNameLen
+ 1);
1363 CFStringGetCharacters(familyNameRef
, CFRangeMake(0, familyNameLen
),
1365 buffer
[familyNameLen
] = 0;
1366 NS_ConvertUTF16toUTF8
familyNameString(
1367 reinterpret_cast<char16_t
*>(buffer
.Elements()), familyNameLen
);
1369 if (SharedFontList()) {
1370 fontlist::Family
* family
=
1371 FindSharedFamily(aPresContext
, familyNameString
);
1373 fontlist::Face
* face
=
1374 family
->FindFaceForStyle(SharedFontList(), *aMatchStyle
);
1376 fontEntry
= GetOrCreateFontEntryLocked(face
, family
);
1379 if (fontEntry
->HasCharacter(aCh
)) {
1380 aMatchedFamily
= FontFamily(family
);
1382 fontEntry
= nullptr;
1383 cantUseFallbackFont
= true;
1389 // The macOS system font does not appear in the shared font list, so if
1390 // we didn't find the fallback font above, we should also check for an
1391 // unshared fontFamily in the system list.
1393 gfxFontFamily
* family
= FindSystemFontFamily(familyNameString
);
1395 fontEntry
= family
->FindFontForStyle(*aMatchStyle
);
1397 if (fontEntry
->HasCharacter(aCh
)) {
1398 aMatchedFamily
= FontFamily(family
);
1400 fontEntry
= nullptr;
1401 cantUseFallbackFont
= true;
1409 if (cantUseFallbackFont
) {
1410 Telemetry::Accumulate(Telemetry::BAD_FALLBACK_FONT
, cantUseFallbackFont
);
1418 gfxFontEntry
* CoreTextFontList::LookupLocalFont(
1419 nsPresContext
* aPresContext
, const nsACString
& aFontName
,
1420 WeightRange aWeightForEntry
, StretchRange aStretchForEntry
,
1421 SlantStyleRange aStyleForEntry
) {
1422 if (aFontName
.IsEmpty() || aFontName
[0] == '.') {
1426 AutoLock
lock(mLock
);
1428 CrashReporter::AutoRecordAnnotation
autoFontName(
1429 CrashReporter::Annotation::FontName
, aFontName
);
1431 AutoCFRelease
<CFStringRef
> faceName
= CreateCFStringForString(aFontName
);
1436 // lookup face based on postscript or full name
1437 AutoCFRelease
<CGFontRef
> fontRef
= CGFontCreateWithFontName(faceName
);
1442 // It's possible for CGFontCreateWithFontName to return a font that has been
1443 // deactivated/uninstalled, or a font that is excluded from the font list due
1444 // to CSS font-visibility restriction. So we need to check whether this font
1445 // is allowed to be used.
1447 // CGFontRef doesn't offer a family-name API, so we go via a CTFontRef.
1448 AutoCFRelease
<CTFontRef
> ctFont
=
1449 CTFontCreateWithGraphicsFont(fontRef
, 0.0, nullptr, nullptr);
1453 AutoCFRelease
<CFStringRef
> name
= CTFontCopyFamilyName(ctFont
);
1455 // Convert the family name to a key suitable for font-list lookup (8-bit,
1458 // CFStringGetLength is in UTF-16 code units. The maximum this count can
1459 // expand when converted to UTF-8 is 3x. We add 1 to ensure there will also be
1460 // space for null-termination of the resulting C string.
1461 key
.SetLength((CFStringGetLength(name
) + 1) * 3);
1462 if (!CFStringGetCString(name
, key
.BeginWriting(), key
.Length(),
1463 kCFStringEncodingUTF8
)) {
1464 // This shouldn't ever happen, but if it does we just bail.
1465 NS_WARNING("Failed to get family name?");
1468 if (key
.IsEmpty()) {
1471 // Reset our string length to match the actual C string we got, which will
1472 // usually be much shorter than the maximal buffer we allocated.
1473 key
.Truncate(strlen(key
.get()));
1475 // If the family can't be looked up, this font is not available for use.
1476 FontFamily family
= FindFamily(aPresContext
, key
);
1477 if (family
.IsNull()) {
1481 return new CTFontEntry(aFontName
, fontRef
, aWeightForEntry
, aStretchForEntry
,
1482 aStyleForEntry
, false, true);
1485 static void ReleaseData(void* info
, const void* data
, size_t size
) {
1489 gfxFontEntry
* CoreTextFontList::MakePlatformFont(const nsACString
& aFontName
,
1490 WeightRange aWeightForEntry
,
1491 StretchRange aStretchForEntry
,
1492 SlantStyleRange aStyleForEntry
,
1493 const uint8_t* aFontData
,
1495 NS_ASSERTION(aFontData
, "MakePlatformFont called with null data");
1497 // create the font entry
1498 nsAutoString uniqueName
;
1500 nsresult rv
= gfxFontUtils::MakeUniqueUserFontName(uniqueName
);
1501 if (NS_FAILED(rv
)) {
1505 CrashReporter::AutoRecordAnnotation
autoFontName(
1506 CrashReporter::Annotation::FontName
, aFontName
);
1508 AutoCFRelease
<CGDataProviderRef
> provider
=
1509 ::CGDataProviderCreateWithData(nullptr, aFontData
, aLength
, &ReleaseData
);
1510 AutoCFRelease
<CGFontRef
> fontRef
= ::CGFontCreateWithDataProvider(provider
);
1515 auto newFontEntry
= MakeUnique
<CTFontEntry
>(
1516 NS_ConvertUTF16toUTF8(uniqueName
), fontRef
, aWeightForEntry
,
1517 aStretchForEntry
, aStyleForEntry
, true, false);
1518 return newFontEntry
.release();
1521 // Webkit code uses a system font meta name, so mimic that here
1522 // WebCore/platform/graphics/mac/FontCacheMac.mm
1523 static const char kSystemFont_system
[] = "-apple-system";
1525 bool CoreTextFontList::FindAndAddFamiliesLocked(
1526 nsPresContext
* aPresContext
, StyleGenericFontFamily aGeneric
,
1527 const nsACString
& aFamily
, nsTArray
<FamilyAndGeneric
>* aOutput
,
1528 FindFamiliesFlags aFlags
, gfxFontStyle
* aStyle
, nsAtom
* aLanguage
,
1529 gfxFloat aDevToCssSize
) {
1530 if (aFamily
.EqualsLiteral(kSystemFont_system
)) {
1531 // Search for special system font name, -apple-system. This is not done via
1532 // the shared fontlist because the hidden system font may not be included
1533 // there; we create a separate gfxFontFamily to manage this family.
1534 if (auto* fam
= FindSystemFontFamily(mSystemFontFamilyName
)) {
1535 aOutput
->AppendElement(fam
);
1541 return gfxPlatformFontList::FindAndAddFamiliesLocked(
1542 aPresContext
, aGeneric
, aFamily
, aOutput
, aFlags
, aStyle
, aLanguage
,
1546 // used to load system-wide font info on off-main thread
1547 class CTFontInfo final
: public FontInfoData
{
1549 CTFontInfo(bool aLoadOtherNames
, bool aLoadFaceNames
, bool aLoadCmaps
,
1550 RecursiveMutex
& aLock
)
1551 : FontInfoData(aLoadOtherNames
, aLoadFaceNames
, aLoadCmaps
),
1554 virtual ~CTFontInfo() = default;
1556 virtual void Load() { FontInfoData::Load(); }
1558 // loads font data for all members of a given family
1559 virtual void LoadFontFamilyData(const nsACString
& aFamilyName
);
1561 RecursiveMutex
& mLock
;
1564 void CTFontInfo::LoadFontFamilyData(const nsACString
& aFamilyName
) {
1565 CrashReporter::AutoRecordAnnotation
autoFontName(
1566 CrashReporter::Annotation::FontName
, aFamilyName
);
1567 // Prevent this from running concurrently with CGFont operations on the main
1568 // thread, because the macOS font cache is fragile with concurrent access.
1569 // This appears to be a vulnerability within CoreText in versions of macOS
1570 // before macOS 13. In time, we can remove this lock.
1571 RecursiveMutexAutoLock
lock(mLock
);
1573 // family name ==> CTFontDescriptor
1574 AutoCFRelease
<CFStringRef
> family
= CreateCFStringForString(aFamilyName
);
1576 AutoCFRelease
<CFMutableDictionaryRef
> attr
=
1577 CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
,
1578 &kCFTypeDictionaryValueCallBacks
);
1579 CFDictionaryAddValue(attr
, kCTFontFamilyNameAttribute
, family
);
1580 AutoCFRelease
<CTFontDescriptorRef
> fd
=
1581 CTFontDescriptorCreateWithAttributes(attr
);
1582 AutoCFRelease
<CFArrayRef
> matchingFonts
=
1583 CTFontDescriptorCreateMatchingFontDescriptors(fd
, NULL
);
1584 if (!matchingFonts
) {
1588 nsTArray
<nsCString
> otherFamilyNames
;
1589 bool hasOtherFamilyNames
= true;
1591 // iterate over faces in the family
1592 int f
, numFaces
= (int)CFArrayGetCount(matchingFonts
);
1593 CTFontDescriptorRef prevFace
= nullptr;
1594 for (f
= 0; f
< numFaces
; f
++) {
1597 CTFontDescriptorRef faceDesc
=
1598 (CTFontDescriptorRef
)CFArrayGetValueAtIndex(matchingFonts
, f
);
1603 if (faceDesc
== prevFace
) {
1606 prevFace
= faceDesc
;
1608 AutoCFRelease
<CTFontRef
> fontRef
=
1609 CTFontCreateWithFontDescriptor(faceDesc
, 0.0, nullptr);
1611 NS_WARNING("failed to create a CTFontRef");
1617 AutoCFRelease
<CFStringRef
> faceName
=
1618 (CFStringRef
)CTFontDescriptorCopyAttribute(faceDesc
,
1619 kCTFontNameAttribute
);
1621 AutoTArray
<UniChar
, 1024> buffer
;
1622 CFIndex len
= CFStringGetLength(faceName
);
1623 buffer
.SetLength(len
+ 1);
1624 CFStringGetCharacters(faceName
, CFRangeMake(0, len
), buffer
.Elements());
1626 NS_ConvertUTF16toUTF8
fontName(
1627 reinterpret_cast<char16_t
*>(buffer
.Elements()), len
);
1629 // load the cmap data
1630 FontFaceData fontData
;
1631 AutoCFRelease
<CFDataRef
> cmapTable
= CTFontCopyTable(
1632 fontRef
, kCTFontTableCmap
, kCTFontTableOptionNoOptions
);
1635 const uint8_t* cmapData
= (const uint8_t*)CFDataGetBytePtr(cmapTable
);
1636 uint32_t cmapLen
= CFDataGetLength(cmapTable
);
1637 RefPtr
<gfxCharacterMap
> charmap
= new gfxCharacterMap();
1641 rv
= gfxFontUtils::ReadCMAP(cmapData
, cmapLen
, *charmap
, offset
);
1642 if (NS_SUCCEEDED(rv
)) {
1643 fontData
.mCharacterMap
= charmap
;
1644 fontData
.mUVSOffset
= offset
;
1649 mFontFaceData
.InsertOrUpdate(fontName
, fontData
);
1652 if (mLoadOtherNames
&& hasOtherFamilyNames
) {
1653 AutoCFRelease
<CFDataRef
> nameTable
= CTFontCopyTable(
1654 fontRef
, kCTFontTableName
, kCTFontTableOptionNoOptions
);
1657 const char* nameData
= (const char*)CFDataGetBytePtr(nameTable
);
1658 uint32_t nameLen
= CFDataGetLength(nameTable
);
1659 gfxFontUtils::ReadOtherFamilyNamesForFace(
1660 aFamilyName
, nameData
, nameLen
, otherFamilyNames
, false);
1661 hasOtherFamilyNames
= otherFamilyNames
.Length() != 0;
1666 // if found other names, insert them in the hash table
1667 if (otherFamilyNames
.Length() != 0) {
1668 mOtherFamilyNames
.InsertOrUpdate(aFamilyName
, otherFamilyNames
);
1669 mLoadStats
.othernames
+= otherFamilyNames
.Length();
1673 already_AddRefed
<FontInfoData
> CoreTextFontList::CreateFontInfoData() {
1674 bool loadCmaps
= !UsesSystemFallback() ||
1675 gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
1677 mLock
.AssertCurrentThreadIn();
1678 RefPtr
<CTFontInfo
> fi
=
1679 new CTFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps
, mLock
);
1683 gfxFontFamily
* CoreTextFontList::CreateFontFamily(
1684 const nsACString
& aName
, FontVisibility aVisibility
) const {
1685 return new CTFontFamily(aName
, aVisibility
);
1688 gfxFontEntry
* CoreTextFontList::CreateFontEntry(
1689 fontlist::Face
* aFace
, const fontlist::Family
* aFamily
) {
1690 CTFontEntry
* fe
= new CTFontEntry(
1691 aFace
->mDescriptor
.AsString(SharedFontList()), aFace
->mWeight
, false,
1692 0.0); // XXX standardFace, sizeHint
1693 fe
->InitializeFrom(aFace
, aFamily
);
1697 void CoreTextFontList::AddFaceInitData(
1698 CTFontDescriptorRef aFontDesc
, nsTArray
<fontlist::Face::InitData
>& aFaces
,
1700 AutoCFRelease
<CFStringRef
> psname
=
1701 (CFStringRef
)CTFontDescriptorCopyAttribute(aFontDesc
,
1702 kCTFontNameAttribute
);
1703 AutoCFRelease
<CFStringRef
> facename
=
1704 (CFStringRef
)CTFontDescriptorCopyAttribute(aFontDesc
,
1705 kCTFontStyleNameAttribute
);
1706 AutoCFRelease
<CFDictionaryRef
> traitsDict
=
1707 (CFDictionaryRef
)CTFontDescriptorCopyAttribute(aFontDesc
,
1708 kCTFontTraitsAttribute
);
1710 CFNumberRef weight
=
1711 (CFNumberRef
)CFDictionaryGetValue(traitsDict
, kCTFontWeightTrait
);
1713 (CFNumberRef
)CFDictionaryGetValue(traitsDict
, kCTFontWidthTrait
);
1714 CFNumberRef symbolicTraits
=
1715 (CFNumberRef
)CFDictionaryGetValue(traitsDict
, kCTFontSymbolicTrait
);
1718 nsAutoString postscriptFontName
;
1719 GetStringForCFString(psname
, postscriptFontName
);
1721 int32_t cssWeight
= PR_GetCurrentThread() == sInitFontListThread
1723 : GetWeightOverride(postscriptFontName
);
1725 // scale down and clamp, to get a value from 1..9
1726 cssWeight
= ((cssWeight
+ 50) / 100);
1727 cssWeight
= std::max(1, std::min(cssWeight
, 9));
1728 cssWeight
*= 100; // scale up to CSS values
1730 CGFloat weightValue
;
1731 CFNumberGetValue(weight
, kCFNumberCGFloatType
, &weightValue
);
1732 cssWeight
= CoreTextWeightToCSSWeight(weightValue
);
1736 CFNumberGetValue(width
, kCFNumberCGFloatType
, &widthValue
);
1737 StretchRange
stretch(CoreTextWidthToCSSStretch(widthValue
));
1739 SlantStyleRange
slantStyle(FontSlantStyle::NORMAL
);
1741 CFNumberGetValue(symbolicTraits
, kCFNumberSInt32Type
, &traitsValue
);
1742 if (traitsValue
& kCTFontItalicTrait
) {
1743 slantStyle
= SlantStyleRange(FontSlantStyle::ITALIC
);
1746 bool fixedPitch
= traitsValue
& kCTFontMonoSpaceTrait
;
1748 RefPtr
<gfxCharacterMap
> charmap
;
1750 AutoCFRelease
<CGFontRef
> font
=
1751 CGFontCreateWithFontName(CFStringRef(psname
));
1753 uint32_t kCMAP
= TRUETYPE_TAG('c', 'm', 'a', 'p');
1754 AutoCFRelease
<CFDataRef
> data
= CGFontCopyTableForTag(font
, kCMAP
);
1757 charmap
= new gfxCharacterMap();
1758 gfxFontUtils::ReadCMAP(CFDataGetBytePtr(data
), CFDataGetLength(data
),
1764 // Ensure that a face named "Regular" goes to the front of the list, so it
1765 // will take precedence over other faces with the same style attributes but
1766 // a different name (such as "Outline").
1767 auto data
= fontlist::Face::InitData
{
1768 NS_ConvertUTF16toUTF8(postscriptFontName
),
1771 WeightRange(FontWeight::FromInt(cssWeight
)),
1776 if (kCFCompareEqualTo
== CFStringCompare(facename
, CFSTR("Regular"), 0)) {
1777 aFaces
.InsertElementAt(0, std::move(data
));
1779 aFaces
.AppendElement(std::move(data
));
1783 void CoreTextFontList::GetFacesInitDataForFamily(
1784 const fontlist::Family
* aFamily
, nsTArray
<fontlist::Face::InitData
>& aFaces
,
1785 bool aLoadCmaps
) const {
1786 auto name
= aFamily
->Key().AsString(SharedFontList());
1787 CrashReporter::AutoRecordAnnotation
autoFontName(
1788 CrashReporter::Annotation::FontName
, name
);
1791 nsTArray
<fontlist::Face::InitData
>& mFaces
;
1793 const void* prevValue
= nullptr;
1795 auto addFaceFunc
= [](const void* aValue
, void* aContext
) -> void {
1796 Context
* context
= (Context
*)aContext
;
1797 if (aValue
== context
->prevValue
) {
1800 context
->prevValue
= aValue
;
1801 CTFontDescriptorRef fontDesc
= (CTFontDescriptorRef
)aValue
;
1802 CoreTextFontList::AddFaceInitData(fontDesc
, context
->mFaces
,
1803 context
->mLoadCmaps
);
1806 AutoCFRelease
<CTFontDescriptorRef
> descriptor
=
1807 CreateDescriptorForFamily(name
, false);
1808 AutoCFRelease
<CFArrayRef
> faces
=
1809 CTFontDescriptorCreateMatchingFontDescriptors(descriptor
, nullptr);
1812 Context context
{aFaces
, aLoadCmaps
};
1813 CFArrayApplyFunction(faces
, CFRangeMake(0, CFArrayGetCount(faces
)),
1814 addFaceFunc
, &context
);
1818 void CoreTextFontList::ReadFaceNamesForFamily(
1819 fontlist::Family
* aFamily
, bool aNeedFullnamePostscriptNames
) {
1820 if (!aFamily
->IsInitialized()) {
1821 if (!InitializeFamily(aFamily
)) {
1825 const uint32_t kNAME
= TRUETYPE_TAG('n', 'a', 'm', 'e');
1826 fontlist::FontList
* list
= SharedFontList();
1827 nsAutoCString
canonicalName(aFamily
->DisplayName().AsString(list
));
1828 const auto* facePtrs
= aFamily
->Faces(list
);
1829 for (uint32_t i
= 0, n
= aFamily
->NumFaces(); i
< n
; i
++) {
1830 auto* face
= facePtrs
[i
].ToPtr
<const fontlist::Face
>(list
);
1834 nsAutoCString
name(face
->mDescriptor
.AsString(list
));
1835 // We create a temporary CTFontEntry just to read family names from the
1836 // 'name' table in the font resource. The style attributes here are ignored
1837 // as this entry is not used for font style matching.
1838 // The size hint might be used to select which face is accessed in the case
1839 // of the macOS UI font; see CTFontEntry::GetFontRef(). We pass 16.0 in
1840 // order to get a standard text-size face in this case, although it's
1841 // unlikely to matter for the purpose of just reading family names.
1842 auto fe
= MakeUnique
<CTFontEntry
>(name
, WeightRange(FontWeight::NORMAL
),
1847 gfxFontEntry::AutoTable
nameTable(fe
.get(), kNAME
);
1851 uint32_t dataLength
;
1852 const char* nameData
= hb_blob_get_data(nameTable
, &dataLength
);
1853 AutoTArray
<nsCString
, 4> otherFamilyNames
;
1854 gfxFontUtils::ReadOtherFamilyNamesForFace(
1855 canonicalName
, nameData
, dataLength
, otherFamilyNames
, false);
1856 for (const auto& alias
: otherFamilyNames
) {
1858 GenerateFontListKey(alias
, key
);
1859 auto aliasData
= mAliasTable
.GetOrInsertNew(key
);
1860 aliasData
->InitFromFamily(aFamily
, canonicalName
);
1861 aliasData
->mFaces
.AppendElement(facePtrs
[i
]);
1866 static CFStringRef
CopyRealFamilyName(CTFontRef aFont
) {
1867 AutoCFRelease
<CFStringRef
> psName
= CTFontCopyPostScriptName(aFont
);
1868 AutoCFRelease
<CGFontRef
> cgFont
=
1869 CGFontCreateWithFontName(CFStringRef(psName
));
1871 return CTFontCopyFamilyName(aFont
);
1873 AutoCFRelease
<CTFontRef
> ctFont
=
1874 CTFontCreateWithGraphicsFont(cgFont
, 0.0, nullptr, nullptr);
1876 return CTFontCopyFamilyName(aFont
);
1878 return CTFontCopyFamilyName(ctFont
);
1881 void CoreTextFontList::InitSystemFontNames() {
1883 AutoCFRelease
<CTFontRef
> font
= CTFontCreateUIFontForLanguage(
1884 kCTFontUIFontSystem
, 0.0, nullptr); // TODO: language
1885 AutoCFRelease
<CFStringRef
> name
= CopyRealFamilyName(font
);
1887 nsAutoString familyName
;
1888 GetStringForCFString(name
, familyName
);
1889 CopyUTF16toUTF8(familyName
, mSystemFontFamilyName
);
1891 // We store an in-process gfxFontFamily for the system font even if using the
1892 // shared fontlist to manage "normal" fonts, because the hidden system fonts
1893 // may be excluded from the font list altogether. This family will be
1894 // populated based on the given NSFont.
1895 RefPtr
<gfxFontFamily
> fam
= new CTFontFamily(mSystemFontFamilyName
, font
);
1898 GenerateFontListKey(mSystemFontFamilyName
, key
);
1899 mFontFamilies
.InsertOrUpdate(key
, std::move(fam
));
1903 FontFamily
CoreTextFontList::GetDefaultFontForPlatform(
1904 nsPresContext
* aPresContext
, const gfxFontStyle
* aStyle
,
1905 nsAtom
* aLanguage
) {
1906 AutoCFRelease
<CTFontRef
> font
= CTFontCreateUIFontForLanguage(
1907 kCTFontUIFontUser
, 0.0, nullptr); // TODO: language
1908 AutoCFRelease
<CFStringRef
> name
= CTFontCopyFamilyName(font
);
1910 nsAutoString familyName
;
1911 GetStringForCFString(name
, familyName
);
1913 return FindFamily(aPresContext
, NS_ConvertUTF16toUTF8(familyName
));
1916 #ifdef MOZ_BUNDLED_FONTS
1917 void CoreTextFontList::ActivateBundledFonts() {
1918 nsCOMPtr
<nsIFile
> localDir
;
1919 if (NS_FAILED(NS_GetSpecialDirectory(NS_GRE_DIR
, getter_AddRefs(localDir
)))) {
1922 if (NS_FAILED(localDir
->Append(u
"fonts"_ns
))) {
1926 if (NS_FAILED(localDir
->GetNativePath(path
))) {
1929 ActivateFontsFromDir(path
, &mBundledFamilies
);