Bug 1874684 - Part 28: Return DateDuration from DifferenceISODateTime. r=mgaudet
[gecko.git] / gfx / thebes / gfxPlatformMac.cpp
blob5c99d389c8bb0def868bada7820a12912d9c6ad6
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 "gfxMacFont.h"
13 #include "gfxCoreTextShaper.h"
14 #include "gfxTextRun.h"
15 #include "gfxUserFontSet.h"
16 #include "gfxConfig.h"
18 #include "AppleUtils.h"
19 #include "nsTArray.h"
20 #include "mozilla/Preferences.h"
21 #include "mozilla/VsyncDispatcher.h"
22 #ifdef MOZ_WIDGET_COCOA
23 # include "nsCocoaFeatures.h"
24 #endif
25 #include "nsComponentManagerUtils.h"
26 #include "nsIFile.h"
27 #include "nsUnicodeProperties.h"
28 #include "qcms.h"
29 #include "gfx2DGlue.h"
30 #include "GeckoProfiler.h"
31 #include "nsThreadUtils.h"
33 #ifdef MOZ_BUNDLED_FONTS
34 # include "mozilla/Telemetry.h"
35 # include "nsDirectoryServiceDefs.h"
36 # include "mozilla/StaticPrefs_gfx.h"
37 #endif
39 #include <dlfcn.h>
40 #include <CoreVideo/CoreVideo.h>
42 #include "mozilla/layers/CompositorBridgeParent.h"
43 #include "mozilla/layers/SurfacePool.h"
44 #include "VsyncSource.h"
46 using namespace mozilla;
47 using namespace mozilla::gfx;
48 using namespace mozilla::unicode;
50 using mozilla::dom::SystemFontList;
52 #ifdef MOZ_WIDGET_COCOA
53 # include "gfxMacPlatformFontList.h"
54 using PlatformFontListClass = gfxMacPlatformFontList;
55 #else
56 # include "IOSPlatformFontList.h"
57 using PlatformFontListClass = IOSPlatformFontList;
58 #endif
60 // A bunch of fonts for "additional language support" are shipped in a
61 // "Language Support" directory, and don't show up in the standard font
62 // list returned by CTFontManagerCopyAvailableFontFamilyNames unless
63 // we explicitly activate them.
64 static const nsLiteralCString kLangFontsDirs[] = {
65 "/Library/Application Support/Apple/Fonts/Language Support"_ns,
66 "/System/Library/Fonts/Supplemental"_ns};
68 /* static */
69 void gfxPlatformMac::FontRegistrationCallback(void* aUnused) {
70 AUTO_PROFILER_REGISTER_THREAD("RegisterFonts");
71 PR_SetCurrentThreadName("RegisterFonts");
73 for (const auto& dir : kLangFontsDirs) {
74 PlatformFontListClass::ActivateFontsFromDir(dir);
78 PRThread* gfxPlatformMac::sFontRegistrationThread = nullptr;
80 /* This is called from XPCOM_Init during startup (before gfxPlatform has been
81 initialized), so that it can kick off the font activation on a secondary
82 thread, and hope that it'll be finished by the time we're ready to build
83 our font list. */
84 /* static */
85 void gfxPlatformMac::RegisterSupplementalFonts() {
86 if (XRE_GetProcessType() == GeckoProcessType_Default) {
87 // We activate the fonts on a separate thread, to minimize the startup-
88 // time cost.
89 sFontRegistrationThread = PR_CreateThread(
90 PR_USER_THREAD, FontRegistrationCallback, nullptr, PR_PRIORITY_NORMAL,
91 PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
95 /* static */
96 void gfxPlatformMac::WaitForFontRegistration() {
97 if (sFontRegistrationThread) {
98 PR_JoinThread(sFontRegistrationThread);
99 sFontRegistrationThread = nullptr;
103 gfxPlatformMac::gfxPlatformMac() {
104 mFontAntiAliasingThreshold = ReadAntiAliasingThreshold();
106 InitBackendPrefs(GetBackendPrefs());
109 gfxPlatformMac::~gfxPlatformMac() { gfxCoreTextShaper::Shutdown(); }
111 BackendPrefsData gfxPlatformMac::GetBackendPrefs() const {
112 BackendPrefsData data;
114 data.mCanvasBitmask = BackendTypeBit(BackendType::SKIA);
115 data.mContentBitmask = BackendTypeBit(BackendType::SKIA);
116 data.mCanvasDefault = BackendType::SKIA;
117 data.mContentDefault = BackendType::SKIA;
119 return data;
122 bool gfxPlatformMac::CreatePlatformFontList() {
123 return gfxPlatformFontList::Initialize(new PlatformFontListClass);
126 void gfxPlatformMac::ReadSystemFontList(SystemFontList* aFontList) {
127 PlatformFontListClass::PlatformFontList()->ReadSystemFontList(aFontList);
130 already_AddRefed<gfxASurface> gfxPlatformMac::CreateOffscreenSurface(
131 const IntSize& aSize, gfxImageFormat aFormat) {
132 if (!Factory::AllowedSurfaceSize(aSize)) {
133 return nullptr;
136 RefPtr<gfxASurface> newSurface = new gfxQuartzSurface(aSize, aFormat);
137 return newSurface.forget();
140 void gfxPlatformMac::GetCommonFallbackFonts(uint32_t aCh, Script aRunScript,
141 eFontPresentation aPresentation,
142 nsTArray<const char*>& aFontList) {
143 if (PrefersColor(aPresentation)) {
144 aFontList.AppendElement("Apple Color Emoji");
147 switch (aRunScript) {
148 case Script::INVALID:
149 case Script::NUM_SCRIPT_CODES:
150 // Ensure the switch covers all the Script enum values.
151 MOZ_ASSERT_UNREACHABLE("bad script code");
152 break;
154 case Script::COMMON:
155 case Script::INHERITED:
156 // In most cases, COMMON and INHERITED characters will be merged into
157 // their context, but if they occur without any specific script context
158 // we'll just try common default fonts here.
159 case Script::LATIN:
160 case Script::CYRILLIC:
161 case Script::GREEK:
162 aFontList.AppendElement("Lucida Grande");
163 break;
165 case Script::MATHEMATICAL_NOTATION:
166 case Script::SYMBOLS:
167 case Script::SYMBOLS_EMOJI:
168 // Not currently returned by script run resolution (but see below, after
169 // the switch).
170 break;
172 // CJK-related script codes are a bit troublesome because of unification;
173 // we'll probably just get HAN much of the time, so the choice of which
174 // language font to try for fallback is rather arbitrary. Usually, though,
175 // we hope that font prefs will have handled this earlier.
176 case Script::BOPOMOFO:
177 case Script::HAN_WITH_BOPOMOFO:
178 case Script::SIMPLIFIED_HAN:
179 case Script::HAN:
180 aFontList.AppendElement("Songti SC");
181 if (aCh > 0x10000) {
182 // macOS installations with MS Office may have these -ExtB fonts
183 aFontList.AppendElement("SimSun-ExtB");
185 break;
187 // Currently, we don't resolve script runs to this value, but we may do so
188 // in future if we get better at handling things like `lang=zh-Hant`, not
189 // just resolving based on the Unicode text.
190 case Script::TRADITIONAL_HAN:
191 aFontList.AppendElement("Songti TC");
192 if (aCh > 0x10000) {
193 // macOS installations with MS Office may have these -ExtB fonts
194 aFontList.AppendElement("MingLiU-ExtB");
196 break;
198 case Script::HIRAGANA:
199 case Script::KATAKANA:
200 case Script::KATAKANA_OR_HIRAGANA:
201 case Script::JAPANESE:
202 aFontList.AppendElement("Hiragino Sans");
203 aFontList.AppendElement("Hiragino Kaku Gothic ProN");
204 break;
206 case Script::JAMO:
207 case Script::KOREAN:
208 case Script::HANGUL:
209 aFontList.AppendElement("Nanum Gothic");
210 aFontList.AppendElement("Apple SD Gothic Neo");
211 break;
213 // For most other scripts, macOS comes with a default font we can use.
214 case Script::ARABIC:
215 aFontList.AppendElement("Geeza Pro");
216 break;
217 case Script::ARMENIAN:
218 aFontList.AppendElement("Mshtakan");
219 break;
220 case Script::BENGALI:
221 aFontList.AppendElement("Bangla Sangam MN");
222 break;
223 case Script::CHEROKEE:
224 aFontList.AppendElement("Plantagenet Cherokee");
225 break;
226 case Script::COPTIC:
227 aFontList.AppendElement("Noto Sans Coptic");
228 break;
229 case Script::DESERET:
230 aFontList.AppendElement("Baskerville");
231 break;
232 case Script::DEVANAGARI:
233 aFontList.AppendElement("Devanagari Sangam MN");
234 break;
235 case Script::ETHIOPIC:
236 aFontList.AppendElement("Kefa");
237 break;
238 case Script::GEORGIAN:
239 aFontList.AppendElement("Helvetica");
240 break;
241 case Script::GOTHIC:
242 aFontList.AppendElement("Noto Sans Gothic");
243 break;
244 case Script::GUJARATI:
245 aFontList.AppendElement("Gujarati Sangam MN");
246 break;
247 case Script::GURMUKHI:
248 aFontList.AppendElement("Gurmukhi MN");
249 break;
250 case Script::HEBREW:
251 aFontList.AppendElement("Lucida Grande");
252 break;
253 case Script::KANNADA:
254 aFontList.AppendElement("Kannada MN");
255 break;
256 case Script::KHMER:
257 aFontList.AppendElement("Khmer MN");
258 break;
259 case Script::LAO:
260 aFontList.AppendElement("Lao MN");
261 break;
262 case Script::MALAYALAM:
263 aFontList.AppendElement("Malayalam Sangam MN");
264 break;
265 case Script::MONGOLIAN:
266 aFontList.AppendElement("Noto Sans Mongolian");
267 break;
268 case Script::MYANMAR:
269 aFontList.AppendElement("Myanmar MN");
270 break;
271 case Script::OGHAM:
272 aFontList.AppendElement("Noto Sans Ogham");
273 break;
274 case Script::OLD_ITALIC:
275 aFontList.AppendElement("Noto Sans Old Italic");
276 break;
277 case Script::ORIYA:
278 aFontList.AppendElement("Oriya Sangam MN");
279 break;
280 case Script::RUNIC:
281 aFontList.AppendElement("Noto Sans Runic");
282 break;
283 case Script::SINHALA:
284 aFontList.AppendElement("Sinhala Sangam MN");
285 break;
286 case Script::SYRIAC:
287 aFontList.AppendElement("Noto Sans Syriac");
288 break;
289 case Script::TAMIL:
290 aFontList.AppendElement("Tamil MN");
291 break;
292 case Script::TELUGU:
293 aFontList.AppendElement("Telugu MN");
294 break;
295 case Script::THAANA:
296 aFontList.AppendElement("Noto Sans Thaana");
297 break;
298 case Script::THAI:
299 aFontList.AppendElement("Thonburi");
300 break;
301 case Script::TIBETAN:
302 aFontList.AppendElement("Kailasa");
303 break;
304 case Script::CANADIAN_ABORIGINAL:
305 aFontList.AppendElement("Euphemia UCAS");
306 break;
307 case Script::YI:
308 aFontList.AppendElement("Noto Sans Yi");
309 aFontList.AppendElement("STHeiti");
310 break;
311 case Script::TAGALOG:
312 aFontList.AppendElement("Noto Sans Tagalog");
313 break;
314 case Script::HANUNOO:
315 aFontList.AppendElement("Noto Sans Hanunoo");
316 break;
317 case Script::BUHID:
318 aFontList.AppendElement("Noto Sans Buhid");
319 break;
320 case Script::TAGBANWA:
321 aFontList.AppendElement("Noto Sans Tagbanwa");
322 break;
323 case Script::BRAILLE:
324 aFontList.AppendElement("Apple Braille");
325 break;
326 case Script::CYPRIOT:
327 aFontList.AppendElement("Noto Sans Cypriot");
328 break;
329 case Script::LIMBU:
330 aFontList.AppendElement("Noto Sans Limbu");
331 break;
332 case Script::LINEAR_B:
333 aFontList.AppendElement("Noto Sans Linear B");
334 break;
335 case Script::OSMANYA:
336 aFontList.AppendElement("Noto Sans Osmanya");
337 break;
338 case Script::SHAVIAN:
339 aFontList.AppendElement("Noto Sans Shavian");
340 break;
341 case Script::TAI_LE:
342 aFontList.AppendElement("Noto Sans Tai Le");
343 break;
344 case Script::UGARITIC:
345 aFontList.AppendElement("Noto Sans Ugaritic");
346 break;
347 case Script::BUGINESE:
348 aFontList.AppendElement("Noto Sans Buginese");
349 break;
350 case Script::GLAGOLITIC:
351 aFontList.AppendElement("Noto Sans Glagolitic");
352 break;
353 case Script::KHAROSHTHI:
354 aFontList.AppendElement("Noto Sans Kharoshthi");
355 break;
356 case Script::SYLOTI_NAGRI:
357 aFontList.AppendElement("Noto Sans Syloti Nagri");
358 break;
359 case Script::NEW_TAI_LUE:
360 aFontList.AppendElement("Noto Sans New Tai Lue");
361 break;
362 case Script::TIFINAGH:
363 aFontList.AppendElement("Noto Sans Tifinagh");
364 break;
365 case Script::OLD_PERSIAN:
366 aFontList.AppendElement("Noto Sans Old Persian");
367 break;
368 case Script::BALINESE:
369 aFontList.AppendElement("Noto Sans Balinese");
370 break;
371 case Script::BATAK:
372 aFontList.AppendElement("Noto Sans Batak");
373 break;
374 case Script::BRAHMI:
375 aFontList.AppendElement("Noto Sans Brahmi");
376 break;
377 case Script::CHAM:
378 aFontList.AppendElement("Noto Sans Cham");
379 break;
380 case Script::EGYPTIAN_HIEROGLYPHS:
381 aFontList.AppendElement("Noto Sans Egyptian Hieroglyphs");
382 break;
383 case Script::PAHAWH_HMONG:
384 aFontList.AppendElement("Noto Sans Pahawh Hmong");
385 break;
386 case Script::OLD_HUNGARIAN:
387 aFontList.AppendElement("Noto Sans Old Hungarian");
388 break;
389 case Script::JAVANESE:
390 aFontList.AppendElement("Noto Sans Javanese");
391 break;
392 case Script::KAYAH_LI:
393 aFontList.AppendElement("Noto Sans Kayah Li");
394 break;
395 case Script::LEPCHA:
396 aFontList.AppendElement("Noto Sans Lepcha");
397 break;
398 case Script::LINEAR_A:
399 aFontList.AppendElement("Noto Sans Linear A");
400 break;
401 case Script::MANDAIC:
402 aFontList.AppendElement("Noto Sans Mandaic");
403 break;
404 case Script::NKO:
405 aFontList.AppendElement("Noto Sans NKo");
406 break;
407 case Script::OLD_TURKIC:
408 aFontList.AppendElement("Noto Sans Old Turkic");
409 break;
410 case Script::OLD_PERMIC:
411 aFontList.AppendElement("Noto Sans Old Permic");
412 break;
413 case Script::PHAGS_PA:
414 aFontList.AppendElement("Noto Sans PhagsPa");
415 break;
416 case Script::PHOENICIAN:
417 aFontList.AppendElement("Noto Sans Phoenician");
418 break;
419 case Script::MIAO:
420 aFontList.AppendElement("Noto Sans Miao");
421 break;
422 case Script::VAI:
423 aFontList.AppendElement("Noto Sans Vai");
424 break;
425 case Script::CUNEIFORM:
426 aFontList.AppendElement("Noto Sans Cuneiform");
427 break;
428 case Script::CARIAN:
429 aFontList.AppendElement("Noto Sans Carian");
430 break;
431 case Script::TAI_THAM:
432 aFontList.AppendElement("Noto Sans Tai Tham");
433 break;
434 case Script::LYCIAN:
435 aFontList.AppendElement("Noto Sans Lycian");
436 break;
437 case Script::LYDIAN:
438 aFontList.AppendElement("Noto Sans Lydian");
439 break;
440 case Script::OL_CHIKI:
441 aFontList.AppendElement("Noto Sans Ol Chiki");
442 break;
443 case Script::REJANG:
444 aFontList.AppendElement("Noto Sans Rejang");
445 break;
446 case Script::SAURASHTRA:
447 aFontList.AppendElement("Noto Sans Saurashtra");
448 break;
449 case Script::SUNDANESE:
450 aFontList.AppendElement("Noto Sans Sundanese");
451 break;
452 case Script::MEETEI_MAYEK:
453 aFontList.AppendElement("Noto Sans Meetei Mayek");
454 break;
455 case Script::IMPERIAL_ARAMAIC:
456 aFontList.AppendElement("Noto Sans Imperial Aramaic");
457 break;
458 case Script::AVESTAN:
459 aFontList.AppendElement("Noto Sans Avestan");
460 break;
461 case Script::CHAKMA:
462 aFontList.AppendElement("Noto Sans Chakma");
463 break;
464 case Script::KAITHI:
465 aFontList.AppendElement("Noto Sans Kaithi");
466 break;
467 case Script::MANICHAEAN:
468 aFontList.AppendElement("Noto Sans Manichaean");
469 break;
470 case Script::INSCRIPTIONAL_PAHLAVI:
471 aFontList.AppendElement("Noto Sans Inscriptional Pahlavi");
472 break;
473 case Script::PSALTER_PAHLAVI:
474 aFontList.AppendElement("Noto Sans Psalter Pahlavi");
475 break;
476 case Script::INSCRIPTIONAL_PARTHIAN:
477 aFontList.AppendElement("Noto Sans Inscriptional Parthian");
478 break;
479 case Script::SAMARITAN:
480 aFontList.AppendElement("Noto Sans Samaritan");
481 break;
482 case Script::TAI_VIET:
483 aFontList.AppendElement("Noto Sans Tai Viet");
484 break;
485 case Script::BAMUM:
486 aFontList.AppendElement("Noto Sans Bamum");
487 break;
488 case Script::LISU:
489 aFontList.AppendElement("Noto Sans Lisu");
490 break;
491 case Script::OLD_SOUTH_ARABIAN:
492 aFontList.AppendElement("Noto Sans Old South Arabian");
493 break;
494 case Script::BASSA_VAH:
495 aFontList.AppendElement("Noto Sans Bassa Vah");
496 break;
497 case Script::DUPLOYAN:
498 aFontList.AppendElement("Noto Sans Duployan");
499 break;
500 case Script::ELBASAN:
501 aFontList.AppendElement("Noto Sans Elbasan");
502 break;
503 case Script::GRANTHA:
504 aFontList.AppendElement("Noto Sans Grantha");
505 break;
506 case Script::MENDE_KIKAKUI:
507 aFontList.AppendElement("Noto Sans Mende Kikakui");
508 break;
509 case Script::MEROITIC_CURSIVE:
510 case Script::MEROITIC_HIEROGLYPHS:
511 aFontList.AppendElement("Noto Sans Meroitic");
512 break;
513 case Script::OLD_NORTH_ARABIAN:
514 aFontList.AppendElement("Noto Sans Old North Arabian");
515 break;
516 case Script::NABATAEAN:
517 aFontList.AppendElement("Noto Sans Nabataean");
518 break;
519 case Script::PALMYRENE:
520 aFontList.AppendElement("Noto Sans Palmyrene");
521 break;
522 case Script::KHUDAWADI:
523 aFontList.AppendElement("Noto Sans Khudawadi");
524 break;
525 case Script::WARANG_CITI:
526 aFontList.AppendElement("Noto Sans Warang Citi");
527 break;
528 case Script::MRO:
529 aFontList.AppendElement("Noto Sans Mro");
530 break;
531 case Script::SHARADA:
532 aFontList.AppendElement("Noto Sans Sharada");
533 break;
534 case Script::SORA_SOMPENG:
535 aFontList.AppendElement("Noto Sans Sora Sompeng");
536 break;
537 case Script::TAKRI:
538 aFontList.AppendElement("Noto Sans Takri");
539 break;
540 case Script::KHOJKI:
541 aFontList.AppendElement("Noto Sans Khojki");
542 break;
543 case Script::TIRHUTA:
544 aFontList.AppendElement("Noto Sans Tirhuta");
545 break;
546 case Script::CAUCASIAN_ALBANIAN:
547 aFontList.AppendElement("Noto Sans Caucasian Albanian");
548 break;
549 case Script::MAHAJANI:
550 aFontList.AppendElement("Noto Sans Mahajani");
551 break;
552 case Script::AHOM:
553 aFontList.AppendElement("Noto Serif Ahom");
554 break;
555 case Script::HATRAN:
556 aFontList.AppendElement("Noto Sans Hatran");
557 break;
558 case Script::MODI:
559 aFontList.AppendElement("Noto Sans Modi");
560 break;
561 case Script::MULTANI:
562 aFontList.AppendElement("Noto Sans Multani");
563 break;
564 case Script::PAU_CIN_HAU:
565 aFontList.AppendElement("Noto Sans Pau Cin Hau");
566 break;
567 case Script::SIDDHAM:
568 aFontList.AppendElement("Noto Sans Siddham");
569 break;
570 case Script::ADLAM:
571 aFontList.AppendElement("Noto Sans Adlam");
572 break;
573 case Script::BHAIKSUKI:
574 aFontList.AppendElement("Noto Sans Bhaiksuki");
575 break;
576 case Script::MARCHEN:
577 aFontList.AppendElement("Noto Sans Marchen");
578 break;
579 case Script::NEWA:
580 aFontList.AppendElement("Noto Sans Newa");
581 break;
582 case Script::OSAGE:
583 aFontList.AppendElement("Noto Sans Osage");
584 break;
585 case Script::HANIFI_ROHINGYA:
586 aFontList.AppendElement("Noto Sans Hanifi Rohingya");
587 break;
588 case Script::WANCHO:
589 aFontList.AppendElement("Noto Sans Wancho");
590 break;
592 // Script codes for which no commonly-installed font is currently known.
593 // Probably future macOS versions will add Noto fonts for many of these,
594 // so we should watch for updates.
595 case Script::OLD_CHURCH_SLAVONIC_CYRILLIC:
596 case Script::DEMOTIC_EGYPTIAN:
597 case Script::HIERATIC_EGYPTIAN:
598 case Script::BLISSYMBOLS:
599 case Script::CIRTH:
600 case Script::KHUTSURI:
601 case Script::HARAPPAN_INDUS:
602 case Script::LATIN_FRAKTUR:
603 case Script::LATIN_GAELIC:
604 case Script::MAYAN_HIEROGLYPHS:
605 case Script::RONGORONGO:
606 case Script::SARATI:
607 case Script::ESTRANGELO_SYRIAC:
608 case Script::WESTERN_SYRIAC:
609 case Script::EASTERN_SYRIAC:
610 case Script::TENGWAR:
611 case Script::VISIBLE_SPEECH:
612 case Script::UNWRITTEN_LANGUAGES:
613 case Script::UNKNOWN:
614 case Script::SIGNWRITING:
615 case Script::MOON:
616 case Script::BOOK_PAHLAVI:
617 case Script::NAKHI_GEBA:
618 case Script::KPELLE:
619 case Script::LOMA:
620 case Script::AFAKA:
621 case Script::JURCHEN:
622 case Script::NUSHU:
623 case Script::TANGUT:
624 case Script::WOLEAI:
625 case Script::ANATOLIAN_HIEROGLYPHS:
626 case Script::MASARAM_GONDI:
627 case Script::SOYOMBO:
628 case Script::ZANABAZAR_SQUARE:
629 case Script::DOGRA:
630 case Script::GUNJALA_GONDI:
631 case Script::MAKASAR:
632 case Script::MEDEFAIDRIN:
633 case Script::SOGDIAN:
634 case Script::OLD_SOGDIAN:
635 case Script::ELYMAIC:
636 case Script::NYIAKENG_PUACHUE_HMONG:
637 case Script::NANDINAGARI:
638 case Script::CHORASMIAN:
639 case Script::DIVES_AKURU:
640 case Script::KHITAN_SMALL_SCRIPT:
641 case Script::YEZIDI:
642 case Script::CYPRO_MINOAN:
643 case Script::OLD_UYGHUR:
644 case Script::TANGSA:
645 case Script::TOTO:
646 case Script::VITHKUQI:
647 case Script::KAWI:
648 case Script::NAG_MUNDARI:
649 break;
652 // Symbols/dingbats are generally Script=COMMON but may be resolved to any
653 // surrounding script run. So we'll always append a couple of likely fonts
654 // for such characters.
655 const uint32_t b = aCh >> 8;
656 if (aRunScript == Script::COMMON || // Stray COMMON chars not resolved
657 (b >= 0x20 && b <= 0x2b) || b == 0x2e || // BMP symbols/punctuation/etc
658 GetGenCategory(aCh) == nsUGenCategory::kSymbol ||
659 GetGenCategory(aCh) == nsUGenCategory::kPunctuation) {
660 if (b == 0x27) {
661 aFontList.AppendElement("Zapf Dingbats");
663 aFontList.AppendElement("Geneva");
664 aFontList.AppendElement("STIXGeneral");
665 aFontList.AppendElement("Apple Symbols");
666 // Japanese fonts also cover a lot of miscellaneous symbols
667 aFontList.AppendElement("Hiragino Sans");
668 aFontList.AppendElement("Hiragino Kaku Gothic ProN");
671 // Arial Unicode MS has lots of glyphs for obscure characters; try it as a
672 // last resort.
673 aFontList.AppendElement("Arial Unicode MS");
676 /*static*/
677 void gfxPlatformMac::LookupSystemFont(
678 mozilla::LookAndFeel::FontID aSystemFontID, nsACString& aSystemFontName,
679 gfxFontStyle& aFontStyle) {
680 return PlatformFontListClass::LookupSystemFont(aSystemFontID, aSystemFontName,
681 aFontStyle);
684 uint32_t gfxPlatformMac::ReadAntiAliasingThreshold() {
685 uint32_t threshold = 0; // default == no threshold
687 // first read prefs flag to determine whether to use the setting or not
688 bool useAntiAliasingThreshold =
689 Preferences::GetBool("gfx.use_text_smoothing_setting", false);
691 // if the pref setting is disabled, return 0 which effectively disables this
692 // feature
693 if (!useAntiAliasingThreshold) return threshold;
695 // value set via Appearance pref panel, "Turn off text smoothing for font
696 // sizes xxx and smaller"
697 CFNumberRef prefValue = (CFNumberRef)CFPreferencesCopyAppValue(
698 CFSTR("AppleAntiAliasingThreshold"), kCFPreferencesCurrentApplication);
700 if (prefValue) {
701 if (!CFNumberGetValue(prefValue, kCFNumberIntType, &threshold)) {
702 threshold = 0;
704 CFRelease(prefValue);
707 return threshold;
710 bool gfxPlatformMac::AccelerateLayersByDefault() { return true; }
712 #ifdef MOZ_WIDGET_COCOA
713 // This is the renderer output callback function, called on the vsync thread
714 static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink,
715 const CVTimeStamp* aNow,
716 const CVTimeStamp* aOutputTime,
717 CVOptionFlags aFlagsIn, CVOptionFlags* aFlagsOut,
718 void* aDisplayLinkContext);
720 class OSXVsyncSource final : public VsyncSource {
721 public:
722 OSXVsyncSource()
723 : mDisplayLink(nullptr, "OSXVsyncSource::OSXDisplay::mDisplayLink") {
724 MOZ_ASSERT(NS_IsMainThread());
725 mTimer = NS_NewTimer();
726 CGDisplayRegisterReconfigurationCallback(DisplayReconfigurationCallback,
727 this);
730 virtual ~OSXVsyncSource() {
731 MOZ_ASSERT(NS_IsMainThread());
732 CGDisplayRemoveReconfigurationCallback(DisplayReconfigurationCallback,
733 this);
736 static void RetryEnableVsync(nsITimer* aTimer, void* aOsxVsyncSource) {
737 MOZ_ASSERT(NS_IsMainThread());
738 OSXVsyncSource* osxVsyncSource =
739 static_cast<OSXVsyncSource*>(aOsxVsyncSource);
740 MOZ_ASSERT(osxVsyncSource);
741 osxVsyncSource->EnableVsync();
744 void EnableVsync() override {
745 MOZ_ASSERT(NS_IsMainThread());
746 if (IsVsyncEnabled()) {
747 return;
750 auto displayLink = mDisplayLink.Lock();
752 // Create a display link capable of being used with all active displays
753 // TODO: See if we need to create an active DisplayLink for each monitor
754 // in multi-monitor situations. According to the docs, it is compatible
755 // with all displays running on the computer But if we have different
756 // monitors at different display rates, we may hit issues.
757 CVReturn retval = CVDisplayLinkCreateWithActiveCGDisplays(&*displayLink);
759 // Workaround for bug 1201401: CVDisplayLinkCreateWithCGDisplays()
760 // (called by CVDisplayLinkCreateWithActiveCGDisplays()) sometimes
761 // creates a CVDisplayLinkRef with an uninitialized (nulled) internal
762 // pointer. If we continue to use this CVDisplayLinkRef, we will
763 // eventually crash in CVCGDisplayLink::getDisplayTimes(), where the
764 // internal pointer is dereferenced. Fortunately, when this happens
765 // another internal variable is also left uninitialized (zeroed),
766 // which is accessible via CVDisplayLinkGetCurrentCGDisplay(). In
767 // normal conditions the current display is never zero.
768 if ((retval == kCVReturnSuccess) &&
769 (CVDisplayLinkGetCurrentCGDisplay(*displayLink) == 0)) {
770 retval = kCVReturnInvalidDisplay;
773 if (retval != kCVReturnSuccess) {
774 NS_WARNING(
775 "Could not create a display link with all active displays. "
776 "Retrying");
777 CVDisplayLinkRelease(*displayLink);
778 *displayLink = nullptr;
780 // bug 1142708 - When coming back from sleep,
781 // or when changing displays, active displays may not be ready yet,
782 // even if listening for the kIOMessageSystemHasPoweredOn event
783 // from OS X sleep notifications.
784 // Active displays are those that are drawable.
785 // bug 1144638 - When changing display configurations and getting
786 // notifications from CGDisplayReconfigurationCallBack, the
787 // callback gets called twice for each active display
788 // so it's difficult to know when all displays are active.
789 // Instead, try again soon. The delay is arbitrary. 100ms chosen
790 // because on a late 2013 15" retina, it takes about that
791 // long to come back up from sleep.
792 uint32_t delay = 100;
793 mTimer->InitWithNamedFuncCallback(RetryEnableVsync, this, delay,
794 nsITimer::TYPE_ONE_SHOT,
795 "RetryEnableVsync");
796 return;
799 if (CVDisplayLinkSetOutputCallback(*displayLink, &VsyncCallback, this) !=
800 kCVReturnSuccess) {
801 NS_WARNING("Could not set displaylink output callback");
802 CVDisplayLinkRelease(*displayLink);
803 *displayLink = nullptr;
804 return;
807 mPreviousTimestamp = TimeStamp::Now();
808 if (CVDisplayLinkStart(*displayLink) != kCVReturnSuccess) {
809 NS_WARNING("Could not activate the display link");
810 CVDisplayLinkRelease(*displayLink);
811 *displayLink = nullptr;
814 CVTime vsyncRate =
815 CVDisplayLinkGetNominalOutputVideoRefreshPeriod(*displayLink);
816 if (vsyncRate.flags & kCVTimeIsIndefinite) {
817 NS_WARNING("Could not get vsync rate, setting to 60.");
818 mVsyncRate = TimeDuration::FromMilliseconds(1000.0 / 60.0);
819 } else {
820 int64_t timeValue = vsyncRate.timeValue;
821 int64_t timeScale = vsyncRate.timeScale;
822 const int milliseconds = 1000;
823 float rateInMs = ((double)timeValue / (double)timeScale) * milliseconds;
824 mVsyncRate = TimeDuration::FromMilliseconds(rateInMs);
828 void DisableVsync() override {
829 MOZ_ASSERT(NS_IsMainThread());
830 if (!IsVsyncEnabled()) {
831 return;
834 // Release the display link
835 auto displayLink = mDisplayLink.Lock();
836 if (*displayLink) {
837 CVDisplayLinkRelease(*displayLink);
838 *displayLink = nullptr;
842 bool IsVsyncEnabled() override {
843 MOZ_ASSERT(NS_IsMainThread());
844 auto displayLink = mDisplayLink.Lock();
845 return *displayLink != nullptr;
848 TimeDuration GetVsyncRate() override { return mVsyncRate; }
850 void Shutdown() override {
851 MOZ_ASSERT(NS_IsMainThread());
852 mTimer->Cancel();
853 mTimer = nullptr;
854 DisableVsync();
857 // The vsync timestamps given by the CVDisplayLinkCallback are
858 // in the future for the NEXT frame. Large parts of Gecko, such
859 // as animations assume a timestamp at either now or in the past.
860 // Normalize the timestamps given to the VsyncDispatchers to the vsync
861 // that just occured, not the vsync that is upcoming.
862 TimeStamp mPreviousTimestamp;
864 private:
865 static void DisplayReconfigurationCallback(CGDirectDisplayID aDisplay,
866 CGDisplayChangeSummaryFlags aFlags,
867 void* aUserInfo) {
868 static_cast<OSXVsyncSource*>(aUserInfo)->OnDisplayReconfiguration(aDisplay,
869 aFlags);
872 void OnDisplayReconfiguration(CGDirectDisplayID aDisplay,
873 CGDisplayChangeSummaryFlags aFlags) {
874 // Display reconfiguration notifications are fired in two phases: Before
875 // the reconfiguration and after the reconfiguration.
876 // All displays are notified before (with a "BeginConfiguration" flag),
877 // and the reconfigured displays are notified again after the
878 // configuration.
879 if (aFlags & kCGDisplayBeginConfigurationFlag) {
880 // We're only interested in the "after" notification, for the display
881 // link's current display.
882 return;
885 if (!NS_IsMainThread()) {
886 return;
889 bool didReconfigureCurrentDisplayLinkDisplay = false;
890 { // scope for lock
891 auto displayLink = mDisplayLink.Lock();
892 didReconfigureCurrentDisplayLinkDisplay =
893 *displayLink &&
894 CVDisplayLinkGetCurrentCGDisplay(*displayLink) == aDisplay;
897 if (didReconfigureCurrentDisplayLinkDisplay) {
898 // The link's current display has been reconfigured.
899 // Recreate the display link, because otherwise it may be stuck with a
900 // "removed" display forever and never notify us again.
901 DisableVsync();
902 EnableVsync();
906 // Accessed from main thread and from display reconfiguration callback
907 // thread... which also happens to be the main thread.
908 DataMutex<CVDisplayLinkRef> mDisplayLink;
910 // Accessed only from the main thread.
911 RefPtr<nsITimer> mTimer;
912 TimeDuration mVsyncRate;
913 }; // OSXVsyncSource
915 static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink,
916 const CVTimeStamp* aNow,
917 const CVTimeStamp* aOutputTime,
918 CVOptionFlags aFlagsIn, CVOptionFlags* aFlagsOut,
919 void* aDisplayLinkContext) {
920 // Executed on OS X hardware vsync thread
921 OSXVsyncSource* vsyncSource = (OSXVsyncSource*)aDisplayLinkContext;
923 mozilla::TimeStamp outputTime =
924 mozilla::TimeStamp::FromSystemTime(aOutputTime->hostTime);
925 mozilla::TimeStamp nextVsync = outputTime;
926 mozilla::TimeStamp previousVsync = vsyncSource->mPreviousTimestamp;
927 mozilla::TimeStamp now = TimeStamp::Now();
929 // Snow leopard sometimes sends vsync timestamps very far in the past.
930 // Normalize the vsync timestamps to now.
931 if (nextVsync <= previousVsync) {
932 nextVsync = now;
933 previousVsync = now;
934 } else if (now < previousVsync) {
935 // Bug 1158321 - The VsyncCallback can sometimes execute before the reported
936 // vsync time. In those cases, normalize the timestamp to Now() as sending
937 // timestamps in the future has undefined behavior. See the comment above
938 // OSXVsyncSource::mPreviousTimestamp
939 previousVsync = now;
942 vsyncSource->mPreviousTimestamp = nextVsync;
944 vsyncSource->NotifyVsync(previousVsync, outputTime);
945 return kCVReturnSuccess;
947 #endif
949 already_AddRefed<mozilla::gfx::VsyncSource>
950 gfxPlatformMac::CreateGlobalHardwareVsyncSource() {
951 #ifdef MOZ_WIDGET_COCOA
952 RefPtr<VsyncSource> osxVsyncSource = new OSXVsyncSource();
953 osxVsyncSource->EnableVsync();
954 if (!osxVsyncSource->IsVsyncEnabled()) {
955 NS_WARNING(
956 "OS X Vsync source not enabled. Falling back to software vsync.");
957 return GetSoftwareVsyncSource();
960 osxVsyncSource->DisableVsync();
961 return osxVsyncSource.forget();
962 #else
963 // TODO: CADisplayLink
964 return GetSoftwareVsyncSource();
965 #endif
968 nsTArray<uint8_t> gfxPlatformMac::GetPlatformCMSOutputProfileData() {
969 nsTArray<uint8_t> prefProfileData = GetPrefCMSOutputProfileData();
970 if (!prefProfileData.IsEmpty()) {
971 return prefProfileData;
974 CGColorSpaceRef cspace = nil;
975 #ifdef MOZ_WIDGET_COCOA
976 cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID());
977 #endif
978 if (!cspace) {
979 cspace = ::CGColorSpaceCreateDeviceRGB();
981 if (!cspace) {
982 return nsTArray<uint8_t>();
985 CFDataRef iccp = ::CGColorSpaceCopyICCData(cspace);
987 ::CFRelease(cspace);
989 if (!iccp) {
990 return nsTArray<uint8_t>();
993 // copy to external buffer
994 size_t size = static_cast<size_t>(::CFDataGetLength(iccp));
996 nsTArray<uint8_t> result;
998 if (size > 0) {
999 result.AppendElements(::CFDataGetBytePtr(iccp), size);
1002 ::CFRelease(iccp);
1004 return result;
1007 bool gfxPlatformMac::CheckVariationFontSupport() { return true; }
1009 void gfxPlatformMac::InitPlatformGPUProcessPrefs() {
1010 FeatureState& gpuProc = gfxConfig::GetFeature(Feature::GPU_PROCESS);
1011 gpuProc.ForceDisable(FeatureStatus::Blocked,
1012 "GPU process does not work on Mac",
1013 "FEATURE_FAILURE_MAC_GPU_PROC"_ns);