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 "gfxPlatformMac.h"
8 #include "gfxQuartzSurface.h"
9 #include "mozilla/DataMutex.h"
10 #include "mozilla/gfx/2D.h"
12 #include "gfxMacPlatformFontList.h"
13 #include "gfxMacFont.h"
14 #include "gfxCoreTextShaper.h"
15 #include "gfxTextRun.h"
16 #include "gfxUserFontSet.h"
17 #include "gfxConfig.h"
19 #include "AppleUtils.h"
21 #include "mozilla/Preferences.h"
22 #include "mozilla/VsyncDispatcher.h"
23 #include "nsCocoaFeatures.h"
24 #include "nsComponentManagerUtils.h"
26 #include "nsUnicodeProperties.h"
28 #include "gfx2DGlue.h"
29 #include "GeckoProfiler.h"
30 #include "nsThreadUtils.h"
33 #include <CoreVideo/CoreVideo.h>
35 #include "mozilla/layers/CompositorBridgeParent.h"
36 #include "mozilla/layers/SurfacePool.h"
37 #include "VsyncSource.h"
39 using namespace mozilla
;
40 using namespace mozilla::gfx
;
41 using namespace mozilla::unicode
;
43 using mozilla::dom::SystemFontList
;
45 // cribbed from CTFontManager.h
46 enum { kAutoActivationDisabled
= 1 };
47 typedef uint32_t AutoActivationSetting
;
49 // bug 567552 - disable auto-activation of fonts
51 static void DisableFontActivation() {
52 // get the main bundle identifier
53 CFBundleRef mainBundle
= ::CFBundleGetMainBundle();
54 CFStringRef mainBundleID
= nullptr;
57 mainBundleID
= ::CFBundleGetIdentifier(mainBundle
);
60 // bug 969388 and bug 922590 - mainBundlID as null is sometimes problematic
62 NS_WARNING("missing bundle ID, packaging set up incorrectly");
66 // if possible, fetch CTFontManagerSetAutoActivationSetting
67 void (*CTFontManagerSetAutoActivationSettingPtr
)(CFStringRef
,
68 AutoActivationSetting
);
69 CTFontManagerSetAutoActivationSettingPtr
=
70 (void (*)(CFStringRef
, AutoActivationSetting
))dlsym(
71 RTLD_DEFAULT
, "CTFontManagerSetAutoActivationSetting");
73 // bug 567552 - disable auto-activation of fonts
74 if (CTFontManagerSetAutoActivationSettingPtr
) {
75 CTFontManagerSetAutoActivationSettingPtr(mainBundleID
,
76 kAutoActivationDisabled
);
80 // Helpers for gfxPlatformMac::RegisterSupplementalFonts below.
81 static void ActivateFontsFromDir(const nsACString
& aDir
) {
82 AutoCFRelease
<CFURLRef
> directory
= CFURLCreateFromFileSystemRepresentation(
83 kCFAllocatorDefault
, (const UInt8
*)nsPromiseFlatCString(aDir
).get(),
88 AutoCFRelease
<CFURLEnumeratorRef
> enumerator
=
89 CFURLEnumeratorCreateForDirectoryURL(kCFAllocatorDefault
, directory
,
90 kCFURLEnumeratorDefaultBehavior
,
95 AutoCFRelease
<CFMutableArrayRef
> urls
=
96 ::CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
102 CFURLEnumeratorResult result
;
104 result
= CFURLEnumeratorGetNextURL(enumerator
, &url
, nullptr);
105 if (result
== kCFURLEnumeratorSuccess
) {
106 CFArrayAppendValue(urls
, url
);
108 } while (result
!= kCFURLEnumeratorEnd
);
110 CTFontManagerRegisterFontsForURLs(urls
, kCTFontManagerScopeProcess
, nullptr);
113 #ifdef MOZ_BUNDLED_FONTS
114 static void ActivateBundledFonts() {
115 nsCOMPtr
<nsIFile
> localDir
;
116 if (NS_FAILED(NS_GetSpecialDirectory(NS_GRE_DIR
, getter_AddRefs(localDir
)))) {
119 if (NS_FAILED(localDir
->Append(u
"fonts"_ns
))) {
123 if (NS_FAILED(localDir
->GetNativePath(path
))) {
126 ActivateFontsFromDir(path
);
130 // A bunch of fonts for "additional language support" are shipped in a
131 // "Language Support" directory, and don't show up in the standard font
132 // list returned by CTFontManagerCopyAvailableFontFamilyNames unless
133 // we explicitly activate them.
135 // On macOS Big Sur, the various Noto fonts etc have moved to a new location
136 // under /System/Fonts. Whether they're exposed in the font list by default
137 // depends on the SDK used; when built with SDK 10.15, they're absent. So
138 // we explicitly activate them to be sure they'll be available.
139 #if __MAC_OS_X_VERSION_MAX_ALLOWED < 101500
140 static const nsLiteralCString kLangFontsDirs
[] = {
141 "/Library/Application Support/Apple/Fonts/Language Support"_ns
};
143 static const nsLiteralCString kLangFontsDirs
[] = {
144 "/Library/Application Support/Apple/Fonts/Language Support"_ns
,
145 "/System/Library/Fonts/Supplemental"_ns
};
148 static void FontRegistrationCallback(void* aUnused
) {
149 AUTO_PROFILER_REGISTER_THREAD("RegisterFonts");
150 PR_SetCurrentThreadName("RegisterFonts");
152 for (const auto& dir
: kLangFontsDirs
) {
153 ActivateFontsFromDir(dir
);
157 PRThread
* gfxPlatformMac::sFontRegistrationThread
= nullptr;
159 /* This is called from XPCOM_Init during startup (before gfxPlatform has been
160 initialized), so that it can kick off the font activation on a secondary
161 thread, and hope that it'll be finished by the time we're ready to build
164 void gfxPlatformMac::RegisterSupplementalFonts() {
165 if (XRE_IsParentProcess()) {
166 sFontRegistrationThread
= PR_CreateThread(
167 PR_USER_THREAD
, FontRegistrationCallback
, nullptr, PR_PRIORITY_NORMAL
,
168 PR_GLOBAL_THREAD
, PR_JOINABLE_THREAD
, 0);
169 } else if (!nsCocoaFeatures::OnCatalinaOrLater()) {
170 // On Catalina+, it appears to be sufficient to activate fonts in the
171 // parent process; they are then also usable in child processes. But on
172 // pre-Catalina systems we need to explicitly activate them in each child
173 // process (per bug 1704273).
175 // But at least on 10.14 (Mojave), doing font registration on a separate
176 // thread in the content process seems crashy (bug 1708821), despite the
177 // CTFontManager.h header claiming that it's thread-safe. So we just do it
178 // immediately on the main thread, and accept the startup-time hit (sigh).
179 for (const auto& dir
: kLangFontsDirs
) {
180 ActivateFontsFromDir(dir
);
186 void gfxPlatformMac::WaitForFontRegistration() {
187 if (sFontRegistrationThread
) {
188 PR_JoinThread(sFontRegistrationThread
);
189 sFontRegistrationThread
= nullptr;
191 #ifdef MOZ_BUNDLED_FONTS
192 // This is not done by the font registration thread because it uses the
193 // XPCOM directory service, which is not yet available at the time we start
194 // the registration thread.
196 // We activate bundled fonts if the pref is > 0 (on) or < 0 (auto), only an
197 // explicit value of 0 (off) will disable them.
198 if (StaticPrefs::gfx_bundled_fonts_activate_AtStartup() != 0) {
199 TimeStamp start
= TimeStamp::Now();
200 ActivateBundledFonts();
201 TimeStamp end
= TimeStamp::Now();
202 Telemetry::Accumulate(Telemetry::FONTLIST_BUNDLEDFONTS_ACTIVATE
,
203 (end
- start
).ToMilliseconds());
209 gfxPlatformMac::gfxPlatformMac() {
210 DisableFontActivation();
211 mFontAntiAliasingThreshold
= ReadAntiAliasingThreshold();
213 InitBackendPrefs(GetBackendPrefs());
215 if (nsCocoaFeatures::OnHighSierraOrLater()) {
216 mHasNativeColrFontSupport
= true;
220 gfxPlatformMac::~gfxPlatformMac() { gfxCoreTextShaper::Shutdown(); }
222 BackendPrefsData
gfxPlatformMac::GetBackendPrefs() const {
223 BackendPrefsData data
;
225 data
.mCanvasBitmask
= BackendTypeBit(BackendType::SKIA
);
226 data
.mContentBitmask
= BackendTypeBit(BackendType::SKIA
);
227 data
.mCanvasDefault
= BackendType::SKIA
;
228 data
.mContentDefault
= BackendType::SKIA
;
233 bool gfxPlatformMac::UsesTiling() const {
234 // The non-tiling ContentClient requires CrossProcessSemaphore which
235 // isn't implemented for OSX.
239 bool gfxPlatformMac::CreatePlatformFontList() {
240 return gfxPlatformFontList::Initialize(new gfxMacPlatformFontList
);
243 void gfxPlatformMac::ReadSystemFontList(SystemFontList
* aFontList
) {
244 gfxMacPlatformFontList::PlatformFontList()->ReadSystemFontList(aFontList
);
247 already_AddRefed
<gfxASurface
> gfxPlatformMac::CreateOffscreenSurface(
248 const IntSize
& aSize
, gfxImageFormat aFormat
) {
249 if (!Factory::AllowedSurfaceSize(aSize
)) {
253 RefPtr
<gfxASurface
> newSurface
= new gfxQuartzSurface(aSize
, aFormat
);
254 return newSurface
.forget();
257 bool gfxPlatformMac::IsFontFormatSupported(uint32_t aFormatFlags
) {
258 if (gfxPlatform::IsFontFormatSupported(aFormatFlags
)) {
262 // If the generic method rejected the format hint, then check for any
263 // platform-specific format we know about.
264 if (aFormatFlags
& gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT
) {
271 void gfxPlatformMac::GetCommonFallbackFonts(uint32_t aCh
, Script aRunScript
,
272 eFontPresentation aPresentation
,
273 nsTArray
<const char*>& aFontList
) {
274 if (PrefersColor(aPresentation
)) {
275 aFontList
.AppendElement("Apple Color Emoji");
278 switch (aRunScript
) {
279 case Script::INVALID
:
280 case Script::NUM_SCRIPT_CODES
:
281 // Ensure the switch covers all the Script enum values.
282 MOZ_ASSERT_UNREACHABLE("bad script code");
286 case Script::INHERITED
:
287 // In most cases, COMMON and INHERITED characters will be merged into
288 // their context, but if they occur without any specific script context
289 // we'll just try common default fonts here.
291 case Script::CYRILLIC
:
293 aFontList
.AppendElement("Lucida Grande");
296 case Script::MATHEMATICAL_NOTATION
:
297 case Script::SYMBOLS
:
298 case Script::SYMBOLS_EMOJI
:
299 // Not currently returned by script run resolution (but see below, after
303 // CJK-related script codes are a bit troublesome because of unification;
304 // we'll probably just get HAN much of the time, so the choice of which
305 // language font to try for fallback is rather arbitrary. Usually, though,
306 // we hope that font prefs will have handled this earlier.
307 case Script::BOPOMOFO
:
308 case Script::HAN_WITH_BOPOMOFO
:
309 case Script::SIMPLIFIED_HAN
:
311 aFontList
.AppendElement("Songti SC");
313 // macOS installations with MS Office may have these -ExtB fonts
314 aFontList
.AppendElement("SimSun-ExtB");
318 // Currently, we don't resolve script runs to this value, but we may do so
319 // in future if we get better at handling things like `lang=zh-Hant`, not
320 // just resolving based on the Unicode text.
321 case Script::TRADITIONAL_HAN
:
322 aFontList
.AppendElement("Songti TC");
324 // macOS installations with MS Office may have these -ExtB fonts
325 aFontList
.AppendElement("MingLiU-ExtB");
329 case Script::HIRAGANA
:
330 case Script::KATAKANA
:
331 case Script::KATAKANA_OR_HIRAGANA
:
332 case Script::JAPANESE
:
333 aFontList
.AppendElement("Hiragino Sans");
334 aFontList
.AppendElement("Hiragino Kaku Gothic ProN");
340 aFontList
.AppendElement("Nanum Gothic");
341 aFontList
.AppendElement("Apple SD Gothic Neo");
344 // For most other scripts, macOS comes with a default font we can use.
346 aFontList
.AppendElement("Geeza Pro");
348 case Script::ARMENIAN
:
349 aFontList
.AppendElement("Mshtakan");
351 case Script::BENGALI
:
352 aFontList
.AppendElement("Bangla Sangam MN");
354 case Script::CHEROKEE
:
355 aFontList
.AppendElement("Plantagenet Cherokee");
358 aFontList
.AppendElement("Noto Sans Coptic");
360 case Script::DESERET
:
361 aFontList
.AppendElement("Baskerville");
363 case Script::DEVANAGARI
:
364 aFontList
.AppendElement("Devanagari Sangam MN");
366 case Script::ETHIOPIC
:
367 aFontList
.AppendElement("Kefa");
369 case Script::GEORGIAN
:
370 aFontList
.AppendElement("Helvetica");
373 aFontList
.AppendElement("Noto Sans Gothic");
375 case Script::GUJARATI
:
376 aFontList
.AppendElement("Gujarati Sangam MN");
378 case Script::GURMUKHI
:
379 aFontList
.AppendElement("Gurmukhi MN");
382 aFontList
.AppendElement("Lucida Grande");
384 case Script::KANNADA
:
385 aFontList
.AppendElement("Kannada MN");
388 aFontList
.AppendElement("Khmer MN");
391 aFontList
.AppendElement("Lao MN");
393 case Script::MALAYALAM
:
394 aFontList
.AppendElement("Malayalam Sangam MN");
396 case Script::MONGOLIAN
:
397 aFontList
.AppendElement("Noto Sans Mongolian");
399 case Script::MYANMAR
:
400 aFontList
.AppendElement("Myanmar MN");
403 aFontList
.AppendElement("Noto Sans Ogham");
405 case Script::OLD_ITALIC
:
406 aFontList
.AppendElement("Noto Sans Old Italic");
409 aFontList
.AppendElement("Oriya Sangam MN");
412 aFontList
.AppendElement("Noto Sans Runic");
414 case Script::SINHALA
:
415 aFontList
.AppendElement("Sinhala Sangam MN");
418 aFontList
.AppendElement("Noto Sans Syriac");
421 aFontList
.AppendElement("Tamil MN");
424 aFontList
.AppendElement("Telugu MN");
427 aFontList
.AppendElement("Noto Sans Thaana");
430 aFontList
.AppendElement("Thonburi");
432 case Script::TIBETAN
:
433 aFontList
.AppendElement("Kailasa");
435 case Script::CANADIAN_ABORIGINAL
:
436 aFontList
.AppendElement("Euphemia UCAS");
439 aFontList
.AppendElement("Noto Sans Yi");
440 aFontList
.AppendElement("STHeiti");
442 case Script::TAGALOG
:
443 aFontList
.AppendElement("Noto Sans Tagalog");
445 case Script::HANUNOO
:
446 aFontList
.AppendElement("Noto Sans Hanunoo");
449 aFontList
.AppendElement("Noto Sans Buhid");
451 case Script::TAGBANWA
:
452 aFontList
.AppendElement("Noto Sans Tagbanwa");
454 case Script::BRAILLE
:
455 aFontList
.AppendElement("Apple Braille");
457 case Script::CYPRIOT
:
458 aFontList
.AppendElement("Noto Sans Cypriot");
461 aFontList
.AppendElement("Noto Sans Limbu");
463 case Script::LINEAR_B
:
464 aFontList
.AppendElement("Noto Sans Linear B");
466 case Script::OSMANYA
:
467 aFontList
.AppendElement("Noto Sans Osmanya");
469 case Script::SHAVIAN
:
470 aFontList
.AppendElement("Noto Sans Shavian");
473 aFontList
.AppendElement("Noto Sans Tai Le");
475 case Script::UGARITIC
:
476 aFontList
.AppendElement("Noto Sans Ugaritic");
478 case Script::BUGINESE
:
479 aFontList
.AppendElement("Noto Sans Buginese");
481 case Script::GLAGOLITIC
:
482 aFontList
.AppendElement("Noto Sans Glagolitic");
484 case Script::KHAROSHTHI
:
485 aFontList
.AppendElement("Noto Sans Kharoshthi");
487 case Script::SYLOTI_NAGRI
:
488 aFontList
.AppendElement("Noto Sans Syloti Nagri");
490 case Script::NEW_TAI_LUE
:
491 aFontList
.AppendElement("Noto Sans New Tai Lue");
493 case Script::TIFINAGH
:
494 aFontList
.AppendElement("Noto Sans Tifinagh");
496 case Script::OLD_PERSIAN
:
497 aFontList
.AppendElement("Noto Sans Old Persian");
499 case Script::BALINESE
:
500 aFontList
.AppendElement("Noto Sans Balinese");
503 aFontList
.AppendElement("Noto Sans Batak");
506 aFontList
.AppendElement("Noto Sans Brahmi");
509 aFontList
.AppendElement("Noto Sans Cham");
511 case Script::EGYPTIAN_HIEROGLYPHS
:
512 aFontList
.AppendElement("Noto Sans Egyptian Hieroglyphs");
514 case Script::PAHAWH_HMONG
:
515 aFontList
.AppendElement("Noto Sans Pahawh Hmong");
517 case Script::OLD_HUNGARIAN
:
518 aFontList
.AppendElement("Noto Sans Old Hungarian");
520 case Script::JAVANESE
:
521 aFontList
.AppendElement("Noto Sans Javanese");
523 case Script::KAYAH_LI
:
524 aFontList
.AppendElement("Noto Sans Kayah Li");
527 aFontList
.AppendElement("Noto Sans Lepcha");
529 case Script::LINEAR_A
:
530 aFontList
.AppendElement("Noto Sans Linear A");
532 case Script::MANDAIC
:
533 aFontList
.AppendElement("Noto Sans Mandaic");
536 aFontList
.AppendElement("Noto Sans NKo");
538 case Script::OLD_TURKIC
:
539 aFontList
.AppendElement("Noto Sans Old Turkic");
541 case Script::OLD_PERMIC
:
542 aFontList
.AppendElement("Noto Sans Old Permic");
544 case Script::PHAGS_PA
:
545 aFontList
.AppendElement("Noto Sans PhagsPa");
547 case Script::PHOENICIAN
:
548 aFontList
.AppendElement("Noto Sans Phoenician");
551 aFontList
.AppendElement("Noto Sans Miao");
554 aFontList
.AppendElement("Noto Sans Vai");
556 case Script::CUNEIFORM
:
557 aFontList
.AppendElement("Noto Sans Cuneiform");
560 aFontList
.AppendElement("Noto Sans Carian");
562 case Script::TAI_THAM
:
563 aFontList
.AppendElement("Noto Sans Tai Tham");
566 aFontList
.AppendElement("Noto Sans Lycian");
569 aFontList
.AppendElement("Noto Sans Lydian");
571 case Script::OL_CHIKI
:
572 aFontList
.AppendElement("Noto Sans Ol Chiki");
575 aFontList
.AppendElement("Noto Sans Rejang");
577 case Script::SAURASHTRA
:
578 aFontList
.AppendElement("Noto Sans Saurashtra");
580 case Script::SUNDANESE
:
581 aFontList
.AppendElement("Noto Sans Sundanese");
583 case Script::MEETEI_MAYEK
:
584 aFontList
.AppendElement("Noto Sans Meetei Mayek");
586 case Script::IMPERIAL_ARAMAIC
:
587 aFontList
.AppendElement("Noto Sans Imperial Aramaic");
589 case Script::AVESTAN
:
590 aFontList
.AppendElement("Noto Sans Avestan");
593 aFontList
.AppendElement("Noto Sans Chakma");
596 aFontList
.AppendElement("Noto Sans Kaithi");
598 case Script::MANICHAEAN
:
599 aFontList
.AppendElement("Noto Sans Manichaean");
601 case Script::INSCRIPTIONAL_PAHLAVI
:
602 aFontList
.AppendElement("Noto Sans Inscriptional Pahlavi");
604 case Script::PSALTER_PAHLAVI
:
605 aFontList
.AppendElement("Noto Sans Psalter Pahlavi");
607 case Script::INSCRIPTIONAL_PARTHIAN
:
608 aFontList
.AppendElement("Noto Sans Inscriptional Parthian");
610 case Script::SAMARITAN
:
611 aFontList
.AppendElement("Noto Sans Samaritan");
613 case Script::TAI_VIET
:
614 aFontList
.AppendElement("Noto Sans Tai Viet");
617 aFontList
.AppendElement("Noto Sans Bamum");
620 aFontList
.AppendElement("Noto Sans Lisu");
622 case Script::OLD_SOUTH_ARABIAN
:
623 aFontList
.AppendElement("Noto Sans Old South Arabian");
625 case Script::BASSA_VAH
:
626 aFontList
.AppendElement("Noto Sans Bassa Vah");
628 case Script::DUPLOYAN
:
629 aFontList
.AppendElement("Noto Sans Duployan");
631 case Script::ELBASAN
:
632 aFontList
.AppendElement("Noto Sans Elbasan");
634 case Script::GRANTHA
:
635 aFontList
.AppendElement("Noto Sans Grantha");
637 case Script::MENDE_KIKAKUI
:
638 aFontList
.AppendElement("Noto Sans Mende Kikakui");
640 case Script::MEROITIC_CURSIVE
:
641 case Script::MEROITIC_HIEROGLYPHS
:
642 aFontList
.AppendElement("Noto Sans Meroitic");
644 case Script::OLD_NORTH_ARABIAN
:
645 aFontList
.AppendElement("Noto Sans Old North Arabian");
647 case Script::NABATAEAN
:
648 aFontList
.AppendElement("Noto Sans Nabataean");
650 case Script::PALMYRENE
:
651 aFontList
.AppendElement("Noto Sans Palmyrene");
653 case Script::KHUDAWADI
:
654 aFontList
.AppendElement("Noto Sans Khudawadi");
656 case Script::WARANG_CITI
:
657 aFontList
.AppendElement("Noto Sans Warang Citi");
660 aFontList
.AppendElement("Noto Sans Mro");
662 case Script::SHARADA
:
663 aFontList
.AppendElement("Noto Sans Sharada");
665 case Script::SORA_SOMPENG
:
666 aFontList
.AppendElement("Noto Sans Sora Sompeng");
669 aFontList
.AppendElement("Noto Sans Takri");
672 aFontList
.AppendElement("Noto Sans Khojki");
674 case Script::TIRHUTA
:
675 aFontList
.AppendElement("Noto Sans Tirhuta");
677 case Script::CAUCASIAN_ALBANIAN
:
678 aFontList
.AppendElement("Noto Sans Caucasian Albanian");
680 case Script::MAHAJANI
:
681 aFontList
.AppendElement("Noto Sans Mahajani");
684 aFontList
.AppendElement("Noto Serif Ahom");
687 aFontList
.AppendElement("Noto Sans Hatran");
690 aFontList
.AppendElement("Noto Sans Modi");
692 case Script::MULTANI
:
693 aFontList
.AppendElement("Noto Sans Multani");
695 case Script::PAU_CIN_HAU
:
696 aFontList
.AppendElement("Noto Sans Pau Cin Hau");
698 case Script::SIDDHAM
:
699 aFontList
.AppendElement("Noto Sans Siddham");
702 aFontList
.AppendElement("Noto Sans Adlam");
704 case Script::BHAIKSUKI
:
705 aFontList
.AppendElement("Noto Sans Bhaiksuki");
707 case Script::MARCHEN
:
708 aFontList
.AppendElement("Noto Sans Marchen");
711 aFontList
.AppendElement("Noto Sans Newa");
714 aFontList
.AppendElement("Noto Sans Osage");
716 case Script::HANIFI_ROHINGYA
:
717 aFontList
.AppendElement("Noto Sans Hanifi Rohingya");
720 aFontList
.AppendElement("Noto Sans Wancho");
723 // Script codes for which no commonly-installed font is currently known.
724 // Probably future macOS versions will add Noto fonts for many of these,
725 // so we should watch for updates.
726 case Script::OLD_CHURCH_SLAVONIC_CYRILLIC
:
727 case Script::DEMOTIC_EGYPTIAN
:
728 case Script::HIERATIC_EGYPTIAN
:
729 case Script::BLISSYMBOLS
:
731 case Script::KHUTSURI
:
732 case Script::HARAPPAN_INDUS
:
733 case Script::LATIN_FRAKTUR
:
734 case Script::LATIN_GAELIC
:
735 case Script::MAYAN_HIEROGLYPHS
:
736 case Script::RONGORONGO
:
738 case Script::ESTRANGELO_SYRIAC
:
739 case Script::WESTERN_SYRIAC
:
740 case Script::EASTERN_SYRIAC
:
741 case Script::TENGWAR
:
742 case Script::VISIBLE_SPEECH
:
743 case Script::UNWRITTEN_LANGUAGES
:
744 case Script::UNKNOWN
:
745 case Script::SIGNWRITING
:
747 case Script::BOOK_PAHLAVI
:
748 case Script::NAKHI_GEBA
:
752 case Script::JURCHEN
:
756 case Script::ANATOLIAN_HIEROGLYPHS
:
757 case Script::MASARAM_GONDI
:
758 case Script::SOYOMBO
:
759 case Script::ZANABAZAR_SQUARE
:
761 case Script::GUNJALA_GONDI
:
762 case Script::MAKASAR
:
763 case Script::MEDEFAIDRIN
:
764 case Script::SOGDIAN
:
765 case Script::OLD_SOGDIAN
:
766 case Script::ELYMAIC
:
767 case Script::NYIAKENG_PUACHUE_HMONG
:
768 case Script::NANDINAGARI
:
769 case Script::CHORASMIAN
:
770 case Script::DIVES_AKURU
:
771 case Script::KHITAN_SMALL_SCRIPT
:
776 // Symbols/dingbats are generally Script=COMMON but may be resolved to any
777 // surrounding script run. So we'll always append a couple of likely fonts
778 // for such characters.
779 const uint32_t b
= aCh
>> 8;
780 if (aRunScript
== Script::COMMON
|| // Stray COMMON chars not resolved
781 (b
>= 0x20 && b
<= 0x2b) || b
== 0x2e || // BMP symbols/punctuation/etc
782 GetGenCategory(aCh
) == nsUGenCategory::kSymbol
||
783 GetGenCategory(aCh
) == nsUGenCategory::kPunctuation
) {
785 aFontList
.AppendElement("Zapf Dingbats");
787 aFontList
.AppendElement("Geneva");
788 aFontList
.AppendElement("STIXGeneral");
789 aFontList
.AppendElement("Apple Symbols");
790 // Japanese fonts also cover a lot of miscellaneous symbols
791 aFontList
.AppendElement("Hiragino Sans");
792 aFontList
.AppendElement("Hiragino Kaku Gothic ProN");
795 // Arial Unicode MS has lots of glyphs for obscure characters; try it as a
797 aFontList
.AppendElement("Arial Unicode MS");
801 void gfxPlatformMac::LookupSystemFont(
802 mozilla::LookAndFeel::FontID aSystemFontID
, nsACString
& aSystemFontName
,
803 gfxFontStyle
& aFontStyle
) {
804 gfxMacPlatformFontList
* pfl
= gfxMacPlatformFontList::PlatformFontList();
805 return pfl
->LookupSystemFont(aSystemFontID
, aSystemFontName
, aFontStyle
);
808 uint32_t gfxPlatformMac::ReadAntiAliasingThreshold() {
809 uint32_t threshold
= 0; // default == no threshold
811 // first read prefs flag to determine whether to use the setting or not
812 bool useAntiAliasingThreshold
=
813 Preferences::GetBool("gfx.use_text_smoothing_setting", false);
815 // if the pref setting is disabled, return 0 which effectively disables this
817 if (!useAntiAliasingThreshold
) return threshold
;
819 // value set via Appearance pref panel, "Turn off text smoothing for font
820 // sizes xxx and smaller"
821 CFNumberRef prefValue
= (CFNumberRef
)CFPreferencesCopyAppValue(
822 CFSTR("AppleAntiAliasingThreshold"), kCFPreferencesCurrentApplication
);
825 if (!CFNumberGetValue(prefValue
, kCFNumberIntType
, &threshold
)) {
828 CFRelease(prefValue
);
834 bool gfxPlatformMac::AccelerateLayersByDefault() { return true; }
836 // This is the renderer output callback function, called on the vsync thread
837 static CVReturn
VsyncCallback(CVDisplayLinkRef aDisplayLink
,
838 const CVTimeStamp
* aNow
,
839 const CVTimeStamp
* aOutputTime
,
840 CVOptionFlags aFlagsIn
, CVOptionFlags
* aFlagsOut
,
841 void* aDisplayLinkContext
);
843 class OSXVsyncSource final
: public VsyncSource
{
845 OSXVsyncSource() : mGlobalDisplay(new OSXDisplay()) {}
847 Display
& GetGlobalDisplay() override
{ return *mGlobalDisplay
; }
849 class OSXDisplay final
: public VsyncSource::Display
{
852 : mDisplayLink(nullptr, "OSXVsyncSource::OSXDisplay::mDisplayLink") {
853 MOZ_ASSERT(NS_IsMainThread());
854 mTimer
= NS_NewTimer();
855 CGDisplayRegisterReconfigurationCallback(DisplayReconfigurationCallback
,
859 virtual ~OSXDisplay() {
860 MOZ_ASSERT(NS_IsMainThread());
861 CGDisplayRemoveReconfigurationCallback(DisplayReconfigurationCallback
,
865 static void RetryEnableVsync(nsITimer
* aTimer
, void* aOsxDisplay
) {
866 MOZ_ASSERT(NS_IsMainThread());
867 OSXDisplay
* osxDisplay
= static_cast<OSXDisplay
*>(aOsxDisplay
);
868 MOZ_ASSERT(osxDisplay
);
869 osxDisplay
->EnableVsync();
872 void EnableVsync() override
{
873 MOZ_ASSERT(NS_IsMainThread());
874 if (IsVsyncEnabled()) {
878 auto displayLink
= mDisplayLink
.Lock();
880 // Create a display link capable of being used with all active displays
881 // TODO: See if we need to create an active DisplayLink for each monitor
882 // in multi-monitor situations. According to the docs, it is compatible
883 // with all displays running on the computer But if we have different
884 // monitors at different display rates, we may hit issues.
885 CVReturn retval
= CVDisplayLinkCreateWithActiveCGDisplays(&*displayLink
);
887 // Workaround for bug 1201401: CVDisplayLinkCreateWithCGDisplays()
888 // (called by CVDisplayLinkCreateWithActiveCGDisplays()) sometimes
889 // creates a CVDisplayLinkRef with an uninitialized (nulled) internal
890 // pointer. If we continue to use this CVDisplayLinkRef, we will
891 // eventually crash in CVCGDisplayLink::getDisplayTimes(), where the
892 // internal pointer is dereferenced. Fortunately, when this happens
893 // another internal variable is also left uninitialized (zeroed),
894 // which is accessible via CVDisplayLinkGetCurrentCGDisplay(). In
895 // normal conditions the current display is never zero.
896 if ((retval
== kCVReturnSuccess
) &&
897 (CVDisplayLinkGetCurrentCGDisplay(*displayLink
) == 0)) {
898 retval
= kCVReturnInvalidDisplay
;
901 if (retval
!= kCVReturnSuccess
) {
903 "Could not create a display link with all active displays. "
905 CVDisplayLinkRelease(*displayLink
);
906 *displayLink
= nullptr;
908 // bug 1142708 - When coming back from sleep,
909 // or when changing displays, active displays may not be ready yet,
910 // even if listening for the kIOMessageSystemHasPoweredOn event
911 // from OS X sleep notifications.
912 // Active displays are those that are drawable.
913 // bug 1144638 - When changing display configurations and getting
914 // notifications from CGDisplayReconfigurationCallBack, the
915 // callback gets called twice for each active display
916 // so it's difficult to know when all displays are active.
917 // Instead, try again soon. The delay is arbitrary. 100ms chosen
918 // because on a late 2013 15" retina, it takes about that
919 // long to come back up from sleep.
920 uint32_t delay
= 100;
921 mTimer
->InitWithNamedFuncCallback(RetryEnableVsync
, this, delay
,
922 nsITimer::TYPE_ONE_SHOT
,
927 if (CVDisplayLinkSetOutputCallback(*displayLink
, &VsyncCallback
, this) !=
929 NS_WARNING("Could not set displaylink output callback");
930 CVDisplayLinkRelease(*displayLink
);
931 *displayLink
= nullptr;
935 mPreviousTimestamp
= TimeStamp::Now();
936 if (CVDisplayLinkStart(*displayLink
) != kCVReturnSuccess
) {
937 NS_WARNING("Could not activate the display link");
938 CVDisplayLinkRelease(*displayLink
);
939 *displayLink
= nullptr;
943 CVDisplayLinkGetNominalOutputVideoRefreshPeriod(*displayLink
);
944 if (vsyncRate
.flags
& kCVTimeIsIndefinite
) {
945 NS_WARNING("Could not get vsync rate, setting to 60.");
946 mVsyncRate
= TimeDuration::FromMilliseconds(1000.0 / 60.0);
948 int64_t timeValue
= vsyncRate
.timeValue
;
949 int64_t timeScale
= vsyncRate
.timeScale
;
950 const int milliseconds
= 1000;
951 float rateInMs
= ((double)timeValue
/ (double)timeScale
) * milliseconds
;
952 mVsyncRate
= TimeDuration::FromMilliseconds(rateInMs
);
956 void DisableVsync() override
{
957 MOZ_ASSERT(NS_IsMainThread());
958 if (!IsVsyncEnabled()) {
962 // Release the display link
963 auto displayLink
= mDisplayLink
.Lock();
965 CVDisplayLinkRelease(*displayLink
);
966 *displayLink
= nullptr;
970 bool IsVsyncEnabled() override
{
971 MOZ_ASSERT(NS_IsMainThread());
972 auto displayLink
= mDisplayLink
.Lock();
973 return *displayLink
!= nullptr;
976 TimeDuration
GetVsyncRate() override
{ return mVsyncRate
; }
978 void Shutdown() override
{
979 MOZ_ASSERT(NS_IsMainThread());
985 // The vsync timestamps given by the CVDisplayLinkCallback are
986 // in the future for the NEXT frame. Large parts of Gecko, such
987 // as animations assume a timestamp at either now or in the past.
988 // Normalize the timestamps given to the VsyncDispatchers to the vsync
989 // that just occured, not the vsync that is upcoming.
990 TimeStamp mPreviousTimestamp
;
993 static void DisplayReconfigurationCallback(
994 CGDirectDisplayID aDisplay
, CGDisplayChangeSummaryFlags aFlags
,
996 static_cast<OSXDisplay
*>(aUserInfo
)->OnDisplayReconfiguration(aDisplay
,
1000 void OnDisplayReconfiguration(CGDirectDisplayID aDisplay
,
1001 CGDisplayChangeSummaryFlags aFlags
) {
1002 // Display reconfiguration notifications are fired in two phases: Before
1003 // the reconfiguration and after the reconfiguration.
1004 // All displays are notified before (with a "BeginConfiguration" flag),
1005 // and the reconfigured displays are notified again after the
1007 if (aFlags
& kCGDisplayBeginConfigurationFlag
) {
1008 // We're only interested in the "after" notification, for the display
1009 // link's current display.
1013 if (!NS_IsMainThread()) {
1017 bool didReconfigureCurrentDisplayLinkDisplay
= false;
1019 auto displayLink
= mDisplayLink
.Lock();
1020 didReconfigureCurrentDisplayLinkDisplay
=
1022 CVDisplayLinkGetCurrentCGDisplay(*displayLink
) == aDisplay
;
1025 if (didReconfigureCurrentDisplayLinkDisplay
) {
1026 // The link's current display has been reconfigured.
1027 // Recreate the display link, because otherwise it may be stuck with a
1028 // "removed" display forever and never notify us again.
1034 // Accessed from main thread and from display reconfiguration callback
1035 // thread... which also happens to be the main thread.
1036 DataMutex
<CVDisplayLinkRef
> mDisplayLink
;
1038 // Accessed only from the main thread.
1039 RefPtr
<nsITimer
> mTimer
;
1040 TimeDuration mVsyncRate
;
1044 virtual ~OSXVsyncSource() = default;
1046 RefPtr
<OSXDisplay
> mGlobalDisplay
;
1047 }; // OSXVsyncSource
1049 static CVReturn
VsyncCallback(CVDisplayLinkRef aDisplayLink
,
1050 const CVTimeStamp
* aNow
,
1051 const CVTimeStamp
* aOutputTime
,
1052 CVOptionFlags aFlagsIn
, CVOptionFlags
* aFlagsOut
,
1053 void* aDisplayLinkContext
) {
1054 // Executed on OS X hardware vsync thread
1055 OSXVsyncSource::OSXDisplay
* display
=
1056 (OSXVsyncSource::OSXDisplay
*)aDisplayLinkContext
;
1058 mozilla::TimeStamp outputTime
=
1059 mozilla::TimeStamp::FromSystemTime(aOutputTime
->hostTime
);
1060 mozilla::TimeStamp nextVsync
= outputTime
;
1061 mozilla::TimeStamp previousVsync
= display
->mPreviousTimestamp
;
1062 mozilla::TimeStamp now
= TimeStamp::Now();
1064 // Snow leopard sometimes sends vsync timestamps very far in the past.
1065 // Normalize the vsync timestamps to now.
1066 if (nextVsync
<= previousVsync
) {
1068 previousVsync
= now
;
1069 } else if (now
< previousVsync
) {
1070 // Bug 1158321 - The VsyncCallback can sometimes execute before the reported
1071 // vsync time. In those cases, normalize the timestamp to Now() as sending
1072 // timestamps in the future has undefined behavior. See the comment above
1073 // OSXDisplay::mPreviousTimestamp
1074 previousVsync
= now
;
1077 display
->mPreviousTimestamp
= nextVsync
;
1079 display
->NotifyVsync(previousVsync
, outputTime
);
1080 return kCVReturnSuccess
;
1083 already_AddRefed
<mozilla::gfx::VsyncSource
>
1084 gfxPlatformMac::CreateHardwareVsyncSource() {
1085 RefPtr
<VsyncSource
> osxVsyncSource
= new OSXVsyncSource();
1086 VsyncSource::Display
& primaryDisplay
= osxVsyncSource
->GetGlobalDisplay();
1087 primaryDisplay
.EnableVsync();
1088 if (!primaryDisplay
.IsVsyncEnabled()) {
1090 "OS X Vsync source not enabled. Falling back to software vsync.");
1091 return gfxPlatform::CreateHardwareVsyncSource();
1094 primaryDisplay
.DisableVsync();
1095 return osxVsyncSource
.forget();
1098 nsTArray
<uint8_t> gfxPlatformMac::GetPlatformCMSOutputProfileData() {
1099 nsTArray
<uint8_t> prefProfileData
= GetPrefCMSOutputProfileData();
1100 if (!prefProfileData
.IsEmpty()) {
1101 return prefProfileData
;
1104 CGColorSpaceRef cspace
= ::CGDisplayCopyColorSpace(::CGMainDisplayID());
1106 cspace
= ::CGColorSpaceCreateDeviceRGB();
1109 return nsTArray
<uint8_t>();
1112 CFDataRef iccp
= ::CGColorSpaceCopyICCProfile(cspace
);
1114 ::CFRelease(cspace
);
1117 return nsTArray
<uint8_t>();
1120 // copy to external buffer
1121 size_t size
= static_cast<size_t>(::CFDataGetLength(iccp
));
1123 nsTArray
<uint8_t> result
;
1126 result
.AppendElements(::CFDataGetBytePtr(iccp
), size
);
1134 bool gfxPlatformMac::CheckVariationFontSupport() {
1135 // We don't allow variation fonts to be enabled before 10.13,
1136 // as although the Core Text APIs existed, they are known to be
1138 // (Note that Safari also requires 10.13 for variation-font support.)
1139 return nsCocoaFeatures::OnHighSierraOrLater();
1142 void gfxPlatformMac::InitPlatformGPUProcessPrefs() {
1143 FeatureState
& gpuProc
= gfxConfig::GetFeature(Feature::GPU_PROCESS
);
1144 gpuProc
.ForceDisable(FeatureStatus::Blocked
,
1145 "GPU process does not work on Mac",
1146 "FEATURE_FAILURE_MAC_GPU_PROC"_ns
);