Bug 1728955: part 6) Log result of Windows' `OleSetClipboardResult`. r=masayuki
[gecko.git] / gfx / thebes / gfxPlatformMac.cpp
blobe1cbed95b74fd2990fc4761efbb2ffc7e9d6b755
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"
20 #include "nsTArray.h"
21 #include "mozilla/Preferences.h"
22 #include "mozilla/VsyncDispatcher.h"
23 #include "nsCocoaFeatures.h"
24 #include "nsComponentManagerUtils.h"
25 #include "nsIFile.h"
26 #include "nsUnicodeProperties.h"
27 #include "qcms.h"
28 #include "gfx2DGlue.h"
29 #include "GeckoProfiler.h"
30 #include "nsThreadUtils.h"
32 #include <dlfcn.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;
56 if (mainBundle) {
57 mainBundleID = ::CFBundleGetIdentifier(mainBundle);
60 // bug 969388 and bug 922590 - mainBundlID as null is sometimes problematic
61 if (!mainBundleID) {
62 NS_WARNING("missing bundle ID, packaging set up incorrectly");
63 return;
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(),
84 aDir.Length(), true);
85 if (!directory) {
86 return;
88 AutoCFRelease<CFURLEnumeratorRef> enumerator =
89 CFURLEnumeratorCreateForDirectoryURL(kCFAllocatorDefault, directory,
90 kCFURLEnumeratorDefaultBehavior,
91 nullptr);
92 if (!enumerator) {
93 return;
95 AutoCFRelease<CFMutableArrayRef> urls =
96 ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
97 if (!urls) {
98 return;
101 CFURLRef url;
102 CFURLEnumeratorResult result;
103 do {
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)))) {
117 return;
119 if (NS_FAILED(localDir->Append(u"fonts"_ns))) {
120 return;
122 nsAutoCString path;
123 if (NS_FAILED(localDir->GetNativePath(path))) {
124 return;
126 ActivateFontsFromDir(path);
128 #endif
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};
142 #else
143 static const nsLiteralCString kLangFontsDirs[] = {
144 "/Library/Application Support/Apple/Fonts/Language Support"_ns,
145 "/System/Library/Fonts/Supplemental"_ns};
146 #endif
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
162 our font list. */
163 /* static */
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);
185 /* static */
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());
205 #endif
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;
230 return data;
233 bool gfxPlatformMac::UsesTiling() const {
234 // The non-tiling ContentClient requires CrossProcessSemaphore which
235 // isn't implemented for OSX.
236 return true;
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)) {
250 return nullptr;
253 RefPtr<gfxASurface> newSurface = new gfxQuartzSurface(aSize, aFormat);
254 return newSurface.forget();
257 bool gfxPlatformMac::IsFontFormatSupported(uint32_t aFormatFlags) {
258 if (gfxPlatform::IsFontFormatSupported(aFormatFlags)) {
259 return true;
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) {
265 return true;
268 return false;
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");
283 break;
285 case Script::COMMON:
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.
290 case Script::LATIN:
291 case Script::CYRILLIC:
292 case Script::GREEK:
293 aFontList.AppendElement("Lucida Grande");
294 break;
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
300 // the switch).
301 break;
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:
310 case Script::HAN:
311 aFontList.AppendElement("Songti SC");
312 if (aCh > 0x10000) {
313 // macOS installations with MS Office may have these -ExtB fonts
314 aFontList.AppendElement("SimSun-ExtB");
316 break;
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");
323 if (aCh > 0x10000) {
324 // macOS installations with MS Office may have these -ExtB fonts
325 aFontList.AppendElement("MingLiU-ExtB");
327 break;
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");
335 break;
337 case Script::JAMO:
338 case Script::KOREAN:
339 case Script::HANGUL:
340 aFontList.AppendElement("Nanum Gothic");
341 aFontList.AppendElement("Apple SD Gothic Neo");
342 break;
344 // For most other scripts, macOS comes with a default font we can use.
345 case Script::ARABIC:
346 aFontList.AppendElement("Geeza Pro");
347 break;
348 case Script::ARMENIAN:
349 aFontList.AppendElement("Mshtakan");
350 break;
351 case Script::BENGALI:
352 aFontList.AppendElement("Bangla Sangam MN");
353 break;
354 case Script::CHEROKEE:
355 aFontList.AppendElement("Plantagenet Cherokee");
356 break;
357 case Script::COPTIC:
358 aFontList.AppendElement("Noto Sans Coptic");
359 break;
360 case Script::DESERET:
361 aFontList.AppendElement("Baskerville");
362 break;
363 case Script::DEVANAGARI:
364 aFontList.AppendElement("Devanagari Sangam MN");
365 break;
366 case Script::ETHIOPIC:
367 aFontList.AppendElement("Kefa");
368 break;
369 case Script::GEORGIAN:
370 aFontList.AppendElement("Helvetica");
371 break;
372 case Script::GOTHIC:
373 aFontList.AppendElement("Noto Sans Gothic");
374 break;
375 case Script::GUJARATI:
376 aFontList.AppendElement("Gujarati Sangam MN");
377 break;
378 case Script::GURMUKHI:
379 aFontList.AppendElement("Gurmukhi MN");
380 break;
381 case Script::HEBREW:
382 aFontList.AppendElement("Lucida Grande");
383 break;
384 case Script::KANNADA:
385 aFontList.AppendElement("Kannada MN");
386 break;
387 case Script::KHMER:
388 aFontList.AppendElement("Khmer MN");
389 break;
390 case Script::LAO:
391 aFontList.AppendElement("Lao MN");
392 break;
393 case Script::MALAYALAM:
394 aFontList.AppendElement("Malayalam Sangam MN");
395 break;
396 case Script::MONGOLIAN:
397 aFontList.AppendElement("Noto Sans Mongolian");
398 break;
399 case Script::MYANMAR:
400 aFontList.AppendElement("Myanmar MN");
401 break;
402 case Script::OGHAM:
403 aFontList.AppendElement("Noto Sans Ogham");
404 break;
405 case Script::OLD_ITALIC:
406 aFontList.AppendElement("Noto Sans Old Italic");
407 break;
408 case Script::ORIYA:
409 aFontList.AppendElement("Oriya Sangam MN");
410 break;
411 case Script::RUNIC:
412 aFontList.AppendElement("Noto Sans Runic");
413 break;
414 case Script::SINHALA:
415 aFontList.AppendElement("Sinhala Sangam MN");
416 break;
417 case Script::SYRIAC:
418 aFontList.AppendElement("Noto Sans Syriac");
419 break;
420 case Script::TAMIL:
421 aFontList.AppendElement("Tamil MN");
422 break;
423 case Script::TELUGU:
424 aFontList.AppendElement("Telugu MN");
425 break;
426 case Script::THAANA:
427 aFontList.AppendElement("Noto Sans Thaana");
428 break;
429 case Script::THAI:
430 aFontList.AppendElement("Thonburi");
431 break;
432 case Script::TIBETAN:
433 aFontList.AppendElement("Kailasa");
434 break;
435 case Script::CANADIAN_ABORIGINAL:
436 aFontList.AppendElement("Euphemia UCAS");
437 break;
438 case Script::YI:
439 aFontList.AppendElement("Noto Sans Yi");
440 aFontList.AppendElement("STHeiti");
441 break;
442 case Script::TAGALOG:
443 aFontList.AppendElement("Noto Sans Tagalog");
444 break;
445 case Script::HANUNOO:
446 aFontList.AppendElement("Noto Sans Hanunoo");
447 break;
448 case Script::BUHID:
449 aFontList.AppendElement("Noto Sans Buhid");
450 break;
451 case Script::TAGBANWA:
452 aFontList.AppendElement("Noto Sans Tagbanwa");
453 break;
454 case Script::BRAILLE:
455 aFontList.AppendElement("Apple Braille");
456 break;
457 case Script::CYPRIOT:
458 aFontList.AppendElement("Noto Sans Cypriot");
459 break;
460 case Script::LIMBU:
461 aFontList.AppendElement("Noto Sans Limbu");
462 break;
463 case Script::LINEAR_B:
464 aFontList.AppendElement("Noto Sans Linear B");
465 break;
466 case Script::OSMANYA:
467 aFontList.AppendElement("Noto Sans Osmanya");
468 break;
469 case Script::SHAVIAN:
470 aFontList.AppendElement("Noto Sans Shavian");
471 break;
472 case Script::TAI_LE:
473 aFontList.AppendElement("Noto Sans Tai Le");
474 break;
475 case Script::UGARITIC:
476 aFontList.AppendElement("Noto Sans Ugaritic");
477 break;
478 case Script::BUGINESE:
479 aFontList.AppendElement("Noto Sans Buginese");
480 break;
481 case Script::GLAGOLITIC:
482 aFontList.AppendElement("Noto Sans Glagolitic");
483 break;
484 case Script::KHAROSHTHI:
485 aFontList.AppendElement("Noto Sans Kharoshthi");
486 break;
487 case Script::SYLOTI_NAGRI:
488 aFontList.AppendElement("Noto Sans Syloti Nagri");
489 break;
490 case Script::NEW_TAI_LUE:
491 aFontList.AppendElement("Noto Sans New Tai Lue");
492 break;
493 case Script::TIFINAGH:
494 aFontList.AppendElement("Noto Sans Tifinagh");
495 break;
496 case Script::OLD_PERSIAN:
497 aFontList.AppendElement("Noto Sans Old Persian");
498 break;
499 case Script::BALINESE:
500 aFontList.AppendElement("Noto Sans Balinese");
501 break;
502 case Script::BATAK:
503 aFontList.AppendElement("Noto Sans Batak");
504 break;
505 case Script::BRAHMI:
506 aFontList.AppendElement("Noto Sans Brahmi");
507 break;
508 case Script::CHAM:
509 aFontList.AppendElement("Noto Sans Cham");
510 break;
511 case Script::EGYPTIAN_HIEROGLYPHS:
512 aFontList.AppendElement("Noto Sans Egyptian Hieroglyphs");
513 break;
514 case Script::PAHAWH_HMONG:
515 aFontList.AppendElement("Noto Sans Pahawh Hmong");
516 break;
517 case Script::OLD_HUNGARIAN:
518 aFontList.AppendElement("Noto Sans Old Hungarian");
519 break;
520 case Script::JAVANESE:
521 aFontList.AppendElement("Noto Sans Javanese");
522 break;
523 case Script::KAYAH_LI:
524 aFontList.AppendElement("Noto Sans Kayah Li");
525 break;
526 case Script::LEPCHA:
527 aFontList.AppendElement("Noto Sans Lepcha");
528 break;
529 case Script::LINEAR_A:
530 aFontList.AppendElement("Noto Sans Linear A");
531 break;
532 case Script::MANDAIC:
533 aFontList.AppendElement("Noto Sans Mandaic");
534 break;
535 case Script::NKO:
536 aFontList.AppendElement("Noto Sans NKo");
537 break;
538 case Script::OLD_TURKIC:
539 aFontList.AppendElement("Noto Sans Old Turkic");
540 break;
541 case Script::OLD_PERMIC:
542 aFontList.AppendElement("Noto Sans Old Permic");
543 break;
544 case Script::PHAGS_PA:
545 aFontList.AppendElement("Noto Sans PhagsPa");
546 break;
547 case Script::PHOENICIAN:
548 aFontList.AppendElement("Noto Sans Phoenician");
549 break;
550 case Script::MIAO:
551 aFontList.AppendElement("Noto Sans Miao");
552 break;
553 case Script::VAI:
554 aFontList.AppendElement("Noto Sans Vai");
555 break;
556 case Script::CUNEIFORM:
557 aFontList.AppendElement("Noto Sans Cuneiform");
558 break;
559 case Script::CARIAN:
560 aFontList.AppendElement("Noto Sans Carian");
561 break;
562 case Script::TAI_THAM:
563 aFontList.AppendElement("Noto Sans Tai Tham");
564 break;
565 case Script::LYCIAN:
566 aFontList.AppendElement("Noto Sans Lycian");
567 break;
568 case Script::LYDIAN:
569 aFontList.AppendElement("Noto Sans Lydian");
570 break;
571 case Script::OL_CHIKI:
572 aFontList.AppendElement("Noto Sans Ol Chiki");
573 break;
574 case Script::REJANG:
575 aFontList.AppendElement("Noto Sans Rejang");
576 break;
577 case Script::SAURASHTRA:
578 aFontList.AppendElement("Noto Sans Saurashtra");
579 break;
580 case Script::SUNDANESE:
581 aFontList.AppendElement("Noto Sans Sundanese");
582 break;
583 case Script::MEETEI_MAYEK:
584 aFontList.AppendElement("Noto Sans Meetei Mayek");
585 break;
586 case Script::IMPERIAL_ARAMAIC:
587 aFontList.AppendElement("Noto Sans Imperial Aramaic");
588 break;
589 case Script::AVESTAN:
590 aFontList.AppendElement("Noto Sans Avestan");
591 break;
592 case Script::CHAKMA:
593 aFontList.AppendElement("Noto Sans Chakma");
594 break;
595 case Script::KAITHI:
596 aFontList.AppendElement("Noto Sans Kaithi");
597 break;
598 case Script::MANICHAEAN:
599 aFontList.AppendElement("Noto Sans Manichaean");
600 break;
601 case Script::INSCRIPTIONAL_PAHLAVI:
602 aFontList.AppendElement("Noto Sans Inscriptional Pahlavi");
603 break;
604 case Script::PSALTER_PAHLAVI:
605 aFontList.AppendElement("Noto Sans Psalter Pahlavi");
606 break;
607 case Script::INSCRIPTIONAL_PARTHIAN:
608 aFontList.AppendElement("Noto Sans Inscriptional Parthian");
609 break;
610 case Script::SAMARITAN:
611 aFontList.AppendElement("Noto Sans Samaritan");
612 break;
613 case Script::TAI_VIET:
614 aFontList.AppendElement("Noto Sans Tai Viet");
615 break;
616 case Script::BAMUM:
617 aFontList.AppendElement("Noto Sans Bamum");
618 break;
619 case Script::LISU:
620 aFontList.AppendElement("Noto Sans Lisu");
621 break;
622 case Script::OLD_SOUTH_ARABIAN:
623 aFontList.AppendElement("Noto Sans Old South Arabian");
624 break;
625 case Script::BASSA_VAH:
626 aFontList.AppendElement("Noto Sans Bassa Vah");
627 break;
628 case Script::DUPLOYAN:
629 aFontList.AppendElement("Noto Sans Duployan");
630 break;
631 case Script::ELBASAN:
632 aFontList.AppendElement("Noto Sans Elbasan");
633 break;
634 case Script::GRANTHA:
635 aFontList.AppendElement("Noto Sans Grantha");
636 break;
637 case Script::MENDE_KIKAKUI:
638 aFontList.AppendElement("Noto Sans Mende Kikakui");
639 break;
640 case Script::MEROITIC_CURSIVE:
641 case Script::MEROITIC_HIEROGLYPHS:
642 aFontList.AppendElement("Noto Sans Meroitic");
643 break;
644 case Script::OLD_NORTH_ARABIAN:
645 aFontList.AppendElement("Noto Sans Old North Arabian");
646 break;
647 case Script::NABATAEAN:
648 aFontList.AppendElement("Noto Sans Nabataean");
649 break;
650 case Script::PALMYRENE:
651 aFontList.AppendElement("Noto Sans Palmyrene");
652 break;
653 case Script::KHUDAWADI:
654 aFontList.AppendElement("Noto Sans Khudawadi");
655 break;
656 case Script::WARANG_CITI:
657 aFontList.AppendElement("Noto Sans Warang Citi");
658 break;
659 case Script::MRO:
660 aFontList.AppendElement("Noto Sans Mro");
661 break;
662 case Script::SHARADA:
663 aFontList.AppendElement("Noto Sans Sharada");
664 break;
665 case Script::SORA_SOMPENG:
666 aFontList.AppendElement("Noto Sans Sora Sompeng");
667 break;
668 case Script::TAKRI:
669 aFontList.AppendElement("Noto Sans Takri");
670 break;
671 case Script::KHOJKI:
672 aFontList.AppendElement("Noto Sans Khojki");
673 break;
674 case Script::TIRHUTA:
675 aFontList.AppendElement("Noto Sans Tirhuta");
676 break;
677 case Script::CAUCASIAN_ALBANIAN:
678 aFontList.AppendElement("Noto Sans Caucasian Albanian");
679 break;
680 case Script::MAHAJANI:
681 aFontList.AppendElement("Noto Sans Mahajani");
682 break;
683 case Script::AHOM:
684 aFontList.AppendElement("Noto Serif Ahom");
685 break;
686 case Script::HATRAN:
687 aFontList.AppendElement("Noto Sans Hatran");
688 break;
689 case Script::MODI:
690 aFontList.AppendElement("Noto Sans Modi");
691 break;
692 case Script::MULTANI:
693 aFontList.AppendElement("Noto Sans Multani");
694 break;
695 case Script::PAU_CIN_HAU:
696 aFontList.AppendElement("Noto Sans Pau Cin Hau");
697 break;
698 case Script::SIDDHAM:
699 aFontList.AppendElement("Noto Sans Siddham");
700 break;
701 case Script::ADLAM:
702 aFontList.AppendElement("Noto Sans Adlam");
703 break;
704 case Script::BHAIKSUKI:
705 aFontList.AppendElement("Noto Sans Bhaiksuki");
706 break;
707 case Script::MARCHEN:
708 aFontList.AppendElement("Noto Sans Marchen");
709 break;
710 case Script::NEWA:
711 aFontList.AppendElement("Noto Sans Newa");
712 break;
713 case Script::OSAGE:
714 aFontList.AppendElement("Noto Sans Osage");
715 break;
716 case Script::HANIFI_ROHINGYA:
717 aFontList.AppendElement("Noto Sans Hanifi Rohingya");
718 break;
719 case Script::WANCHO:
720 aFontList.AppendElement("Noto Sans Wancho");
721 break;
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:
730 case Script::CIRTH:
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:
737 case Script::SARATI:
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:
746 case Script::MOON:
747 case Script::BOOK_PAHLAVI:
748 case Script::NAKHI_GEBA:
749 case Script::KPELLE:
750 case Script::LOMA:
751 case Script::AFAKA:
752 case Script::JURCHEN:
753 case Script::NUSHU:
754 case Script::TANGUT:
755 case Script::WOLEAI:
756 case Script::ANATOLIAN_HIEROGLYPHS:
757 case Script::MASARAM_GONDI:
758 case Script::SOYOMBO:
759 case Script::ZANABAZAR_SQUARE:
760 case Script::DOGRA:
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:
772 case Script::YEZIDI:
773 break;
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) {
784 if (b == 0x27) {
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
796 // last resort.
797 aFontList.AppendElement("Arial Unicode MS");
800 /*static*/
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
816 // feature
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);
824 if (prefValue) {
825 if (!CFNumberGetValue(prefValue, kCFNumberIntType, &threshold)) {
826 threshold = 0;
828 CFRelease(prefValue);
831 return threshold;
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 {
844 public:
845 OSXVsyncSource() : mGlobalDisplay(new OSXDisplay()) {}
847 Display& GetGlobalDisplay() override { return *mGlobalDisplay; }
849 class OSXDisplay final : public VsyncSource::Display {
850 public:
851 OSXDisplay()
852 : mDisplayLink(nullptr, "OSXVsyncSource::OSXDisplay::mDisplayLink") {
853 MOZ_ASSERT(NS_IsMainThread());
854 mTimer = NS_NewTimer();
855 CGDisplayRegisterReconfigurationCallback(DisplayReconfigurationCallback,
856 this);
859 virtual ~OSXDisplay() {
860 MOZ_ASSERT(NS_IsMainThread());
861 CGDisplayRemoveReconfigurationCallback(DisplayReconfigurationCallback,
862 this);
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()) {
875 return;
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) {
902 NS_WARNING(
903 "Could not create a display link with all active displays. "
904 "Retrying");
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,
923 "RetryEnableVsync");
924 return;
927 if (CVDisplayLinkSetOutputCallback(*displayLink, &VsyncCallback, this) !=
928 kCVReturnSuccess) {
929 NS_WARNING("Could not set displaylink output callback");
930 CVDisplayLinkRelease(*displayLink);
931 *displayLink = nullptr;
932 return;
935 mPreviousTimestamp = TimeStamp::Now();
936 if (CVDisplayLinkStart(*displayLink) != kCVReturnSuccess) {
937 NS_WARNING("Could not activate the display link");
938 CVDisplayLinkRelease(*displayLink);
939 *displayLink = nullptr;
942 CVTime vsyncRate =
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);
947 } else {
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()) {
959 return;
962 // Release the display link
963 auto displayLink = mDisplayLink.Lock();
964 if (*displayLink) {
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());
980 mTimer->Cancel();
981 mTimer = nullptr;
982 DisableVsync();
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;
992 private:
993 static void DisplayReconfigurationCallback(
994 CGDirectDisplayID aDisplay, CGDisplayChangeSummaryFlags aFlags,
995 void* aUserInfo) {
996 static_cast<OSXDisplay*>(aUserInfo)->OnDisplayReconfiguration(aDisplay,
997 aFlags);
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
1006 // configuration.
1007 if (aFlags & kCGDisplayBeginConfigurationFlag) {
1008 // We're only interested in the "after" notification, for the display
1009 // link's current display.
1010 return;
1013 if (!NS_IsMainThread()) {
1014 return;
1017 bool didReconfigureCurrentDisplayLinkDisplay = false;
1018 { // scope for lock
1019 auto displayLink = mDisplayLink.Lock();
1020 didReconfigureCurrentDisplayLinkDisplay =
1021 *displayLink &&
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.
1029 DisableVsync();
1030 EnableVsync();
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;
1041 }; // OSXDisplay
1043 private:
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) {
1067 nextVsync = now;
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()) {
1089 NS_WARNING(
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());
1105 if (!cspace) {
1106 cspace = ::CGColorSpaceCreateDeviceRGB();
1108 if (!cspace) {
1109 return nsTArray<uint8_t>();
1112 CFDataRef iccp = ::CGColorSpaceCopyICCProfile(cspace);
1114 ::CFRelease(cspace);
1116 if (!iccp) {
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;
1125 if (size > 0) {
1126 result.AppendElements(::CFDataGetBytePtr(iccp), size);
1129 ::CFRelease(iccp);
1131 return result;
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
1137 // fairly buggy.
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);