gfxPlatformMac.cpp (35045B)
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/. */ 5 6 #include "gfxPlatformMac.h" 7 8 #include "gfxQuartzSurface.h" 9 #include "mozilla/DataMutex.h" 10 #include "mozilla/gfx/2D.h" 11 12 #include "gfxMacFont.h" 13 #include "gfxCoreTextShaper.h" 14 #include "gfxTextRun.h" 15 #include "gfxUserFontSet.h" 16 #include "gfxConfig.h" 17 18 #include "AppleUtils.h" 19 #include "CFTypeRefPtr.h" 20 #include "nsTArray.h" 21 #include "mozilla/Preferences.h" 22 #include "mozilla/VsyncDispatcher.h" 23 #ifdef MOZ_WIDGET_COCOA 24 # include "nsCocoaFeatures.h" 25 #endif 26 #include "nsComponentManagerUtils.h" 27 #include "nsIFile.h" 28 #include "nsUnicodeProperties.h" 29 #include "qcms.h" 30 #include "gfx2DGlue.h" 31 #include "GeckoProfiler.h" 32 #include "nsThreadUtils.h" 33 34 #ifdef MOZ_BUNDLED_FONTS 35 # include "nsDirectoryServiceDefs.h" 36 # include "mozilla/StaticPrefs_gfx.h" 37 #endif 38 39 #include <dlfcn.h> 40 #include <CoreVideo/CoreVideo.h> 41 42 #include "mozilla/layers/CompositorBridgeParent.h" 43 #include "mozilla/layers/SurfacePool.h" 44 #include "VsyncSource.h" 45 46 using namespace mozilla; 47 using namespace mozilla::gfx; 48 using namespace mozilla::unicode; 49 50 using mozilla::dom::SystemFontList; 51 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 59 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}; 67 68 /* static */ 69 void gfxPlatformMac::FontRegistrationCallback(void* aUnused) { 70 AUTO_PROFILER_REGISTER_THREAD("RegisterFonts"); 71 PR_SetCurrentThreadName("RegisterFonts"); 72 73 for (const auto& dir : kLangFontsDirs) { 74 PlatformFontListClass::ActivateFontsFromDir(dir); 75 } 76 } 77 78 PRThread* gfxPlatformMac::sFontRegistrationThread = nullptr; 79 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); 92 } 93 } 94 95 /* static */ 96 void gfxPlatformMac::WaitForFontRegistration() { 97 if (sFontRegistrationThread) { 98 PR_JoinThread(sFontRegistrationThread); 99 sFontRegistrationThread = nullptr; 100 } 101 } 102 103 gfxPlatformMac::gfxPlatformMac() { 104 mFontAntiAliasingThreshold = ReadAntiAliasingThreshold(); 105 106 InitBackendPrefs(GetBackendPrefs()); 107 } 108 109 gfxPlatformMac::~gfxPlatformMac() { gfxCoreTextShaper::Shutdown(); } 110 111 BackendPrefsData gfxPlatformMac::GetBackendPrefs() const { 112 BackendPrefsData data; 113 114 data.mCanvasBitmask = BackendTypeBit(BackendType::SKIA); 115 data.mContentBitmask = BackendTypeBit(BackendType::SKIA); 116 data.mCanvasDefault = BackendType::SKIA; 117 data.mContentDefault = BackendType::SKIA; 118 119 return data; 120 } 121 122 bool gfxPlatformMac::CreatePlatformFontList() { 123 return gfxPlatformFontList::Initialize(new PlatformFontListClass); 124 } 125 126 void gfxPlatformMac::ReadSystemFontList(SystemFontList* aFontList) { 127 PlatformFontListClass::PlatformFontList()->ReadSystemFontList(aFontList); 128 } 129 130 already_AddRefed<gfxASurface> gfxPlatformMac::CreateOffscreenSurface( 131 const IntSize& aSize, gfxImageFormat aFormat) { 132 if (!Factory::AllowedSurfaceSize(aSize)) { 133 return nullptr; 134 } 135 136 RefPtr<gfxASurface> newSurface = new gfxQuartzSurface(aSize, aFormat); 137 return newSurface.forget(); 138 } 139 140 void gfxPlatformMac::GetCommonFallbackFonts(uint32_t aCh, Script aRunScript, 141 FontPresentation aPresentation, 142 nsTArray<const char*>& aFontList) { 143 if (PrefersColor(aPresentation)) { 144 aFontList.AppendElement("Apple Color Emoji"); 145 } 146 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; 153 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; 164 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; 171 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"); 184 } 185 break; 186 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 case Script::TRADITIONAL_HAN_WITH_LATIN: 192 aFontList.AppendElement("Songti TC"); 193 if (aCh > 0x10000) { 194 // macOS installations with MS Office may have these -ExtB fonts 195 aFontList.AppendElement("MingLiU-ExtB"); 196 } 197 break; 198 199 case Script::HIRAGANA: 200 case Script::KATAKANA: 201 case Script::KATAKANA_OR_HIRAGANA: 202 case Script::JAPANESE: 203 aFontList.AppendElement("Hiragino Sans"); 204 aFontList.AppendElement("Hiragino Kaku Gothic ProN"); 205 break; 206 207 case Script::JAMO: 208 case Script::KOREAN: 209 case Script::HANGUL: 210 aFontList.AppendElement("Nanum Gothic"); 211 aFontList.AppendElement("Apple SD Gothic Neo"); 212 break; 213 214 // For most other scripts, macOS comes with a default font we can use. 215 case Script::ARABIC: 216 aFontList.AppendElement("Geeza Pro"); 217 break; 218 case Script::ARMENIAN: 219 aFontList.AppendElement("Mshtakan"); 220 break; 221 case Script::BENGALI: 222 aFontList.AppendElement("Bangla Sangam MN"); 223 break; 224 case Script::CHEROKEE: 225 aFontList.AppendElement("Plantagenet Cherokee"); 226 break; 227 case Script::COPTIC: 228 aFontList.AppendElement("Noto Sans Coptic"); 229 break; 230 case Script::DESERET: 231 aFontList.AppendElement("Baskerville"); 232 break; 233 case Script::DEVANAGARI: 234 aFontList.AppendElement("Devanagari Sangam MN"); 235 break; 236 case Script::ETHIOPIC: 237 aFontList.AppendElement("Kefa"); 238 break; 239 case Script::GEORGIAN: 240 aFontList.AppendElement("Helvetica"); 241 break; 242 case Script::GOTHIC: 243 aFontList.AppendElement("Noto Sans Gothic"); 244 break; 245 case Script::GUJARATI: 246 aFontList.AppendElement("Gujarati Sangam MN"); 247 break; 248 case Script::GURMUKHI: 249 aFontList.AppendElement("Gurmukhi MN"); 250 break; 251 case Script::HEBREW: 252 aFontList.AppendElement("Lucida Grande"); 253 break; 254 case Script::KANNADA: 255 aFontList.AppendElement("Kannada MN"); 256 break; 257 case Script::KHMER: 258 aFontList.AppendElement("Khmer MN"); 259 break; 260 case Script::LAO: 261 aFontList.AppendElement("Lao MN"); 262 break; 263 case Script::MALAYALAM: 264 aFontList.AppendElement("Malayalam Sangam MN"); 265 break; 266 case Script::MONGOLIAN: 267 aFontList.AppendElement("Noto Sans Mongolian"); 268 break; 269 case Script::MYANMAR: 270 aFontList.AppendElement("Myanmar MN"); 271 break; 272 case Script::OGHAM: 273 aFontList.AppendElement("Noto Sans Ogham"); 274 break; 275 case Script::OLD_ITALIC: 276 aFontList.AppendElement("Noto Sans Old Italic"); 277 break; 278 case Script::ORIYA: 279 aFontList.AppendElement("Oriya Sangam MN"); 280 break; 281 case Script::RUNIC: 282 aFontList.AppendElement("Noto Sans Runic"); 283 break; 284 case Script::SINHALA: 285 aFontList.AppendElement("Sinhala Sangam MN"); 286 break; 287 case Script::SYRIAC: 288 aFontList.AppendElement("Noto Sans Syriac"); 289 break; 290 case Script::TAMIL: 291 aFontList.AppendElement("Tamil MN"); 292 break; 293 case Script::TELUGU: 294 aFontList.AppendElement("Telugu MN"); 295 break; 296 case Script::THAANA: 297 aFontList.AppendElement("Noto Sans Thaana"); 298 break; 299 case Script::THAI: 300 aFontList.AppendElement("Thonburi"); 301 break; 302 case Script::TIBETAN: 303 aFontList.AppendElement("Kailasa"); 304 break; 305 case Script::CANADIAN_ABORIGINAL: 306 aFontList.AppendElement("Euphemia UCAS"); 307 break; 308 case Script::YI: 309 aFontList.AppendElement("Noto Sans Yi"); 310 aFontList.AppendElement("STHeiti"); 311 break; 312 case Script::TAGALOG: 313 aFontList.AppendElement("Noto Sans Tagalog"); 314 break; 315 case Script::HANUNOO: 316 aFontList.AppendElement("Noto Sans Hanunoo"); 317 break; 318 case Script::BUHID: 319 aFontList.AppendElement("Noto Sans Buhid"); 320 break; 321 case Script::TAGBANWA: 322 aFontList.AppendElement("Noto Sans Tagbanwa"); 323 break; 324 case Script::BRAILLE: 325 aFontList.AppendElement("Apple Braille"); 326 break; 327 case Script::CYPRIOT: 328 aFontList.AppendElement("Noto Sans Cypriot"); 329 break; 330 case Script::LIMBU: 331 aFontList.AppendElement("Noto Sans Limbu"); 332 break; 333 case Script::LINEAR_B: 334 aFontList.AppendElement("Noto Sans Linear B"); 335 break; 336 case Script::OSMANYA: 337 aFontList.AppendElement("Noto Sans Osmanya"); 338 break; 339 case Script::SHAVIAN: 340 aFontList.AppendElement("Noto Sans Shavian"); 341 break; 342 case Script::TAI_LE: 343 aFontList.AppendElement("Noto Sans Tai Le"); 344 break; 345 case Script::UGARITIC: 346 aFontList.AppendElement("Noto Sans Ugaritic"); 347 break; 348 case Script::BUGINESE: 349 aFontList.AppendElement("Noto Sans Buginese"); 350 break; 351 case Script::GLAGOLITIC: 352 aFontList.AppendElement("Noto Sans Glagolitic"); 353 break; 354 case Script::KHAROSHTHI: 355 aFontList.AppendElement("Noto Sans Kharoshthi"); 356 break; 357 case Script::SYLOTI_NAGRI: 358 aFontList.AppendElement("Noto Sans Syloti Nagri"); 359 break; 360 case Script::NEW_TAI_LUE: 361 aFontList.AppendElement("Noto Sans New Tai Lue"); 362 break; 363 case Script::TIFINAGH: 364 aFontList.AppendElement("Noto Sans Tifinagh"); 365 break; 366 case Script::OLD_PERSIAN: 367 aFontList.AppendElement("Noto Sans Old Persian"); 368 break; 369 case Script::BALINESE: 370 aFontList.AppendElement("Noto Sans Balinese"); 371 break; 372 case Script::BATAK: 373 aFontList.AppendElement("Noto Sans Batak"); 374 break; 375 case Script::BRAHMI: 376 aFontList.AppendElement("Noto Sans Brahmi"); 377 break; 378 case Script::CHAM: 379 aFontList.AppendElement("Noto Sans Cham"); 380 break; 381 case Script::EGYPTIAN_HIEROGLYPHS: 382 aFontList.AppendElement("Noto Sans Egyptian Hieroglyphs"); 383 break; 384 case Script::PAHAWH_HMONG: 385 aFontList.AppendElement("Noto Sans Pahawh Hmong"); 386 break; 387 case Script::OLD_HUNGARIAN: 388 aFontList.AppendElement("Noto Sans Old Hungarian"); 389 break; 390 case Script::JAVANESE: 391 aFontList.AppendElement("Noto Sans Javanese"); 392 break; 393 case Script::KAYAH_LI: 394 aFontList.AppendElement("Noto Sans Kayah Li"); 395 break; 396 case Script::LEPCHA: 397 aFontList.AppendElement("Noto Sans Lepcha"); 398 break; 399 case Script::LINEAR_A: 400 aFontList.AppendElement("Noto Sans Linear A"); 401 break; 402 case Script::MANDAIC: 403 aFontList.AppendElement("Noto Sans Mandaic"); 404 break; 405 case Script::NKO: 406 aFontList.AppendElement("Noto Sans NKo"); 407 break; 408 case Script::OLD_TURKIC: 409 aFontList.AppendElement("Noto Sans Old Turkic"); 410 break; 411 case Script::OLD_PERMIC: 412 aFontList.AppendElement("Noto Sans Old Permic"); 413 break; 414 case Script::PHAGS_PA: 415 aFontList.AppendElement("Noto Sans PhagsPa"); 416 break; 417 case Script::PHOENICIAN: 418 aFontList.AppendElement("Noto Sans Phoenician"); 419 break; 420 case Script::MIAO: 421 aFontList.AppendElement("Noto Sans Miao"); 422 break; 423 case Script::VAI: 424 aFontList.AppendElement("Noto Sans Vai"); 425 break; 426 case Script::CUNEIFORM: 427 aFontList.AppendElement("Noto Sans Cuneiform"); 428 break; 429 case Script::CARIAN: 430 aFontList.AppendElement("Noto Sans Carian"); 431 break; 432 case Script::TAI_THAM: 433 aFontList.AppendElement("Noto Sans Tai Tham"); 434 break; 435 case Script::LYCIAN: 436 aFontList.AppendElement("Noto Sans Lycian"); 437 break; 438 case Script::LYDIAN: 439 aFontList.AppendElement("Noto Sans Lydian"); 440 break; 441 case Script::OL_CHIKI: 442 aFontList.AppendElement("Noto Sans Ol Chiki"); 443 break; 444 case Script::REJANG: 445 aFontList.AppendElement("Noto Sans Rejang"); 446 break; 447 case Script::SAURASHTRA: 448 aFontList.AppendElement("Noto Sans Saurashtra"); 449 break; 450 case Script::SUNDANESE: 451 aFontList.AppendElement("Noto Sans Sundanese"); 452 break; 453 case Script::MEETEI_MAYEK: 454 aFontList.AppendElement("Noto Sans Meetei Mayek"); 455 break; 456 case Script::IMPERIAL_ARAMAIC: 457 aFontList.AppendElement("Noto Sans Imperial Aramaic"); 458 break; 459 case Script::AVESTAN: 460 aFontList.AppendElement("Noto Sans Avestan"); 461 break; 462 case Script::CHAKMA: 463 aFontList.AppendElement("Noto Sans Chakma"); 464 break; 465 case Script::KAITHI: 466 aFontList.AppendElement("Noto Sans Kaithi"); 467 break; 468 case Script::MANICHAEAN: 469 aFontList.AppendElement("Noto Sans Manichaean"); 470 break; 471 case Script::INSCRIPTIONAL_PAHLAVI: 472 aFontList.AppendElement("Noto Sans Inscriptional Pahlavi"); 473 break; 474 case Script::PSALTER_PAHLAVI: 475 aFontList.AppendElement("Noto Sans Psalter Pahlavi"); 476 break; 477 case Script::INSCRIPTIONAL_PARTHIAN: 478 aFontList.AppendElement("Noto Sans Inscriptional Parthian"); 479 break; 480 case Script::SAMARITAN: 481 aFontList.AppendElement("Noto Sans Samaritan"); 482 break; 483 case Script::TAI_VIET: 484 aFontList.AppendElement("Noto Sans Tai Viet"); 485 break; 486 case Script::BAMUM: 487 aFontList.AppendElement("Noto Sans Bamum"); 488 break; 489 case Script::LISU: 490 aFontList.AppendElement("Noto Sans Lisu"); 491 break; 492 case Script::OLD_SOUTH_ARABIAN: 493 aFontList.AppendElement("Noto Sans Old South Arabian"); 494 break; 495 case Script::BASSA_VAH: 496 aFontList.AppendElement("Noto Sans Bassa Vah"); 497 break; 498 case Script::DUPLOYAN: 499 aFontList.AppendElement("Noto Sans Duployan"); 500 break; 501 case Script::ELBASAN: 502 aFontList.AppendElement("Noto Sans Elbasan"); 503 break; 504 case Script::GRANTHA: 505 aFontList.AppendElement("Noto Sans Grantha"); 506 break; 507 case Script::MENDE_KIKAKUI: 508 aFontList.AppendElement("Noto Sans Mende Kikakui"); 509 break; 510 case Script::MEROITIC_CURSIVE: 511 case Script::MEROITIC_HIEROGLYPHS: 512 aFontList.AppendElement("Noto Sans Meroitic"); 513 break; 514 case Script::OLD_NORTH_ARABIAN: 515 aFontList.AppendElement("Noto Sans Old North Arabian"); 516 break; 517 case Script::NABATAEAN: 518 aFontList.AppendElement("Noto Sans Nabataean"); 519 break; 520 case Script::PALMYRENE: 521 aFontList.AppendElement("Noto Sans Palmyrene"); 522 break; 523 case Script::KHUDAWADI: 524 aFontList.AppendElement("Noto Sans Khudawadi"); 525 break; 526 case Script::WARANG_CITI: 527 aFontList.AppendElement("Noto Sans Warang Citi"); 528 break; 529 case Script::MRO: 530 aFontList.AppendElement("Noto Sans Mro"); 531 break; 532 case Script::SHARADA: 533 aFontList.AppendElement("Noto Sans Sharada"); 534 break; 535 case Script::SORA_SOMPENG: 536 aFontList.AppendElement("Noto Sans Sora Sompeng"); 537 break; 538 case Script::TAKRI: 539 aFontList.AppendElement("Noto Sans Takri"); 540 break; 541 case Script::KHOJKI: 542 aFontList.AppendElement("Noto Sans Khojki"); 543 break; 544 case Script::TIRHUTA: 545 aFontList.AppendElement("Noto Sans Tirhuta"); 546 break; 547 case Script::CAUCASIAN_ALBANIAN: 548 aFontList.AppendElement("Noto Sans Caucasian Albanian"); 549 break; 550 case Script::MAHAJANI: 551 aFontList.AppendElement("Noto Sans Mahajani"); 552 break; 553 case Script::AHOM: 554 aFontList.AppendElement("Noto Serif Ahom"); 555 break; 556 case Script::HATRAN: 557 aFontList.AppendElement("Noto Sans Hatran"); 558 break; 559 case Script::MODI: 560 aFontList.AppendElement("Noto Sans Modi"); 561 break; 562 case Script::MULTANI: 563 aFontList.AppendElement("Noto Sans Multani"); 564 break; 565 case Script::PAU_CIN_HAU: 566 aFontList.AppendElement("Noto Sans Pau Cin Hau"); 567 break; 568 case Script::SIDDHAM: 569 aFontList.AppendElement("Noto Sans Siddham"); 570 break; 571 case Script::ADLAM: 572 aFontList.AppendElement("Noto Sans Adlam"); 573 break; 574 case Script::BHAIKSUKI: 575 aFontList.AppendElement("Noto Sans Bhaiksuki"); 576 break; 577 case Script::MARCHEN: 578 aFontList.AppendElement("Noto Sans Marchen"); 579 break; 580 case Script::NEWA: 581 aFontList.AppendElement("Noto Sans Newa"); 582 break; 583 case Script::OSAGE: 584 aFontList.AppendElement("Noto Sans Osage"); 585 break; 586 case Script::HANIFI_ROHINGYA: 587 aFontList.AppendElement("Noto Sans Hanifi Rohingya"); 588 break; 589 case Script::WANCHO: 590 aFontList.AppendElement("Noto Sans Wancho"); 591 break; 592 case Script::ARABIC_NASTALIQ: 593 aFontList.AppendElement("Noto Nastaliq Urdu"); 594 break; 595 596 // Script codes for which no commonly-installed font is currently known. 597 // Probably future macOS versions will add Noto fonts for many of these, 598 // so we should watch for updates. 599 case Script::OLD_CHURCH_SLAVONIC_CYRILLIC: 600 case Script::DEMOTIC_EGYPTIAN: 601 case Script::HIERATIC_EGYPTIAN: 602 case Script::BLISSYMBOLS: 603 case Script::CIRTH: 604 case Script::KHUTSURI: 605 case Script::HARAPPAN_INDUS: 606 case Script::LATIN_FRAKTUR: 607 case Script::LATIN_GAELIC: 608 case Script::MAYAN_HIEROGLYPHS: 609 case Script::RONGORONGO: 610 case Script::SARATI: 611 case Script::ESTRANGELO_SYRIAC: 612 case Script::WESTERN_SYRIAC: 613 case Script::EASTERN_SYRIAC: 614 case Script::TENGWAR: 615 case Script::VISIBLE_SPEECH: 616 case Script::UNWRITTEN_LANGUAGES: 617 case Script::UNKNOWN: 618 case Script::SIGNWRITING: 619 case Script::MOON: 620 case Script::BOOK_PAHLAVI: 621 case Script::NAKHI_GEBA: 622 case Script::KPELLE: 623 case Script::LOMA: 624 case Script::AFAKA: 625 case Script::JURCHEN: 626 case Script::NUSHU: 627 case Script::TANGUT: 628 case Script::WOLEAI: 629 case Script::ANATOLIAN_HIEROGLYPHS: 630 case Script::MASARAM_GONDI: 631 case Script::SOYOMBO: 632 case Script::ZANABAZAR_SQUARE: 633 case Script::DOGRA: 634 case Script::GUNJALA_GONDI: 635 case Script::MAKASAR: 636 case Script::MEDEFAIDRIN: 637 case Script::SOGDIAN: 638 case Script::OLD_SOGDIAN: 639 case Script::ELYMAIC: 640 case Script::NYIAKENG_PUACHUE_HMONG: 641 case Script::NANDINAGARI: 642 case Script::CHORASMIAN: 643 case Script::DIVES_AKURU: 644 case Script::KHITAN_SMALL_SCRIPT: 645 case Script::YEZIDI: 646 case Script::CYPRO_MINOAN: 647 case Script::OLD_UYGHUR: 648 case Script::TANGSA: 649 case Script::TOTO: 650 case Script::VITHKUQI: 651 case Script::KAWI: 652 case Script::NAG_MUNDARI: 653 case Script::GARAY: 654 case Script::GURUNG_KHEMA: 655 case Script::KIRAT_RAI: 656 case Script::OL_ONAL: 657 case Script::SUNUWAR: 658 case Script::TODHRI: 659 case Script::TULU_TIGALARI: 660 case Script::BERIA_ERFE: 661 case Script::SIDETIC: 662 case Script::TAI_YO: 663 case Script::TOLONG_SIKI: 664 break; 665 } 666 667 // Symbols/dingbats are generally Script=COMMON but may be resolved to any 668 // surrounding script run. So we'll always append a couple of likely fonts 669 // for such characters. 670 const uint32_t b = aCh >> 8; 671 if (aRunScript == Script::COMMON || // Stray COMMON chars not resolved 672 (b >= 0x20 && b <= 0x2b) || b == 0x2e || // BMP symbols/punctuation/etc 673 GetGenCategory(aCh) == nsUGenCategory::kSymbol || 674 GetGenCategory(aCh) == nsUGenCategory::kPunctuation) { 675 if (b == 0x27) { 676 aFontList.AppendElement("Zapf Dingbats"); 677 } 678 aFontList.AppendElement("Geneva"); 679 aFontList.AppendElement("STIXGeneral"); 680 aFontList.AppendElement("Apple Symbols"); 681 // Japanese fonts also cover a lot of miscellaneous symbols 682 aFontList.AppendElement("Hiragino Sans"); 683 aFontList.AppendElement("Hiragino Kaku Gothic ProN"); 684 } 685 686 // Arial Unicode MS has lots of glyphs for obscure characters; try it as a 687 // last resort. 688 aFontList.AppendElement("Arial Unicode MS"); 689 } 690 691 /*static*/ 692 void gfxPlatformMac::LookupSystemFont( 693 mozilla::LookAndFeel::FontID aSystemFontID, nsACString& aSystemFontName, 694 gfxFontStyle& aFontStyle) { 695 return PlatformFontListClass::LookupSystemFont(aSystemFontID, aSystemFontName, 696 aFontStyle); 697 } 698 699 uint32_t gfxPlatformMac::ReadAntiAliasingThreshold() { 700 uint32_t threshold = 0; // default == no threshold 701 702 // first read prefs flag to determine whether to use the setting or not 703 bool useAntiAliasingThreshold = 704 Preferences::GetBool("gfx.use_text_smoothing_setting", false); 705 706 // if the pref setting is disabled, return 0 which effectively disables this 707 // feature 708 if (!useAntiAliasingThreshold) return threshold; 709 710 // value set via Appearance pref panel, "Turn off text smoothing for font 711 // sizes xxx and smaller" 712 auto prefValue = CFTypeRefPtr<CFPropertyListRef>::WrapUnderCreateRule( 713 CFPreferencesCopyAppValue(CFSTR("AppleAntiAliasingThreshold"), 714 kCFPreferencesCurrentApplication)); 715 716 if (prefValue) { 717 if (CFGetTypeID(prefValue.get()) != CFNumberGetTypeID() || 718 !CFNumberGetValue(static_cast<CFNumberRef>(prefValue.get()), 719 kCFNumberIntType, &threshold)) { 720 threshold = 0; 721 } 722 } 723 724 return threshold; 725 } 726 727 bool gfxPlatformMac::AccelerateLayersByDefault() { return true; } 728 729 #ifdef MOZ_WIDGET_COCOA 730 // This is the renderer output callback function, called on the vsync thread 731 static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink, 732 const CVTimeStamp* aNow, 733 const CVTimeStamp* aOutputTime, 734 CVOptionFlags aFlagsIn, CVOptionFlags* aFlagsOut, 735 void* aDisplayLinkContext); 736 737 class OSXVsyncSource final : public VsyncSource { 738 public: 739 OSXVsyncSource() : mDisplayLink(nullptr, "OSXVsyncSource::mDisplayLink") { 740 MOZ_ASSERT(NS_IsMainThread()); 741 mTimer = NS_NewTimer(); 742 CGError err = CGDisplayRegisterReconfigurationCallback( 743 DisplayReconfigurationCallback, this); 744 if (err != kCGErrorSuccess) { 745 gfxWarning() << "Failed to register display reconfiguration callback"; 746 // We're in a tricky situation. Without a working reconfiguration 747 // callback, we might fail to recover from sleep. Best to early exit 748 // without creating a display link, and fall back to software vsync. 749 return; 750 } 751 752 CreateDisplayLink(); 753 auto displayLink = mDisplayLink.Lock(); 754 if (!*displayLink) { 755 gfxWarning() 756 << "Could not create a display link during construction. This is " 757 "unrecoverable. We'll fallback to software vsync."; 758 } 759 } 760 761 virtual ~OSXVsyncSource() { 762 MOZ_ASSERT(NS_IsMainThread()); 763 Shutdown(); 764 } 765 766 static void RetryCreateDisplayLinkAndEnableVsync(nsITimer* aTimer, 767 void* aOsxVsyncSource) { 768 MOZ_ASSERT(NS_IsMainThread()); 769 OSXVsyncSource* osxVsyncSource = 770 static_cast<OSXVsyncSource*>(aOsxVsyncSource); 771 MOZ_ASSERT(osxVsyncSource); 772 773 osxVsyncSource->DisableVsync(); 774 osxVsyncSource->DestroyDisplayLink(); 775 osxVsyncSource->CreateDisplayLink(); 776 osxVsyncSource->EnableVsync(); 777 778 if (!osxVsyncSource->IsVsyncEnabled()) { 779 gfxWarning() << "Display reconfiguration vsync has failed; giving up."; 780 osxVsyncSource->Shutdown(); 781 gfxPlatform::ResetHardwareVsyncSource(); 782 gfxPlatform::ReInitFrameRate(nullptr, nullptr); 783 } 784 } 785 786 void CreateDisplayLink() { 787 MOZ_ASSERT(NS_IsMainThread()); 788 auto displayLink = mDisplayLink.Lock(); 789 MOZ_ASSERT(!*displayLink); 790 791 // Create a display link capable of being used with all active displays 792 // TODO: See if we need to create an active DisplayLink for each monitor 793 // in multi-monitor situations. According to the docs, it is compatible 794 // with all displays running on the computer But if we have different 795 // monitors at different display rates, we may hit issues. 796 CVReturn retval = CVDisplayLinkCreateWithActiveCGDisplays(&*displayLink); 797 if (!*displayLink) { 798 gfxWarning() 799 << "Could not create a display link with all active displays."; 800 return; 801 } 802 803 // Workaround for bug 1201401: CVDisplayLinkCreateWithCGDisplays() 804 // (called by CVDisplayLinkCreateWithActiveCGDisplays()) sometimes 805 // creates a CVDisplayLinkRef with an uninitialized (nulled) internal 806 // pointer. If we continue to use this CVDisplayLinkRef, we will 807 // eventually crash in CVCGDisplayLink::getDisplayTimes(), where the 808 // internal pointer is dereferenced. Fortunately, when this happens 809 // another internal variable is also left uninitialized (zeroed), 810 // which is accessible via CVDisplayLinkGetCurrentCGDisplay(). In 811 // normal conditions the current display is never zero. 812 if ((retval == kCVReturnSuccess) && 813 (CVDisplayLinkGetCurrentCGDisplay(*displayLink) == 0)) { 814 retval = kCVReturnInvalidDisplay; 815 } 816 817 if (retval != kCVReturnSuccess) { 818 gfxWarning() 819 << "Display link was created, but is malformed; destroying it."; 820 CVDisplayLinkRelease(*displayLink); 821 *displayLink = nullptr; 822 return; 823 } 824 825 if (CVDisplayLinkSetOutputCallback(*displayLink, &VsyncCallback, this) != 826 kCVReturnSuccess) { 827 gfxWarning() 828 << "Could not set display link output callback; destroying it."; 829 CVDisplayLinkRelease(*displayLink); 830 *displayLink = nullptr; 831 } 832 } 833 834 void DestroyDisplayLink() { 835 MOZ_ASSERT(NS_IsMainThread()); 836 auto displayLink = mDisplayLink.Lock(); 837 if (*displayLink) { 838 CVDisplayLinkRelease(*displayLink); 839 *displayLink = nullptr; 840 } 841 } 842 843 void EnableVsync() override { 844 MOZ_ASSERT(NS_IsMainThread()); 845 if (IsVsyncEnabled()) { 846 return; 847 } 848 849 auto displayLink = mDisplayLink.Lock(); 850 if (!*displayLink) { 851 gfxWarning() << "No display link available when starting vsync."; 852 return; 853 } 854 855 mPreviousTimestamp = TimeStamp::Now(); 856 if (CVDisplayLinkStart(*displayLink) != kCVReturnSuccess) { 857 gfxWarning() << "Could not activate the display link."; 858 return; 859 } 860 861 CVTime vsyncRate = 862 CVDisplayLinkGetNominalOutputVideoRefreshPeriod(*displayLink); 863 if (vsyncRate.flags & kCVTimeIsIndefinite) { 864 gfxWarning() << "Could not get vsync rate, setting to 60."; 865 mVsyncRate = TimeDuration::FromMilliseconds(1000.0 / 60.0); 866 } else { 867 int64_t timeValue = vsyncRate.timeValue; 868 int64_t timeScale = vsyncRate.timeScale; 869 const int milliseconds = 1000; 870 float rateInMs = ((double)timeValue / (double)timeScale) * milliseconds; 871 mVsyncRate = TimeDuration::FromMilliseconds(rateInMs); 872 } 873 } 874 875 void DisableVsync() override { 876 MOZ_ASSERT(NS_IsMainThread()); 877 if (!IsVsyncEnabled()) { 878 return; 879 } 880 881 auto displayLink = mDisplayLink.Lock(); 882 883 if (*displayLink) { 884 CVDisplayLinkStop(*displayLink); 885 } 886 } 887 888 bool IsVsyncEnabled() override { 889 auto displayLink = mDisplayLink.Lock(); 890 if (!*displayLink) { 891 return false; 892 } 893 894 return CVDisplayLinkIsRunning(*displayLink); 895 } 896 897 TimeDuration GetVsyncRate() override { return mVsyncRate; } 898 899 void Shutdown() override { 900 MOZ_ASSERT(NS_IsMainThread()); 901 if (mTimer) { 902 mTimer->Cancel(); 903 mTimer = nullptr; 904 } 905 CGDisplayRemoveReconfigurationCallback(DisplayReconfigurationCallback, 906 this); 907 DisableVsync(); 908 DestroyDisplayLink(); 909 } 910 911 // The vsync timestamps given by the CVDisplayLinkCallback are 912 // in the future for the NEXT frame. Large parts of Gecko, such 913 // as animations assume a timestamp at either now or in the past. 914 // Normalize the timestamps given to the VsyncDispatchers to the vsync 915 // that just occured, not the vsync that is upcoming. 916 TimeStamp mPreviousTimestamp; 917 918 private: 919 static void DisplayReconfigurationCallback(CGDirectDisplayID aDisplay, 920 CGDisplayChangeSummaryFlags aFlags, 921 void* aUserInfo) { 922 static_cast<OSXVsyncSource*>(aUserInfo)->OnDisplayReconfiguration(aDisplay, 923 aFlags); 924 } 925 926 void OnDisplayReconfiguration(CGDirectDisplayID aDisplay, 927 CGDisplayChangeSummaryFlags aFlags) { 928 // Display reconfiguration notifications are fired in two phases: Before 929 // the reconfiguration and after the reconfiguration. 930 // All displays are notified before (with a "BeginConfiguration" flag), 931 // and the reconfigured displays are notified again after the 932 // configuration. 933 if (aFlags & kCGDisplayBeginConfigurationFlag) { 934 // We're only interested in the "after" notification, for the display 935 // link's current display. 936 return; 937 } 938 939 if (!NS_IsMainThread()) { 940 return; 941 } 942 943 bool didReconfigureCurrentDisplayLinkDisplay = false; 944 { // scope for lock 945 auto displayLink = mDisplayLink.Lock(); 946 didReconfigureCurrentDisplayLinkDisplay = 947 *displayLink && 948 CVDisplayLinkGetCurrentCGDisplay(*displayLink) == aDisplay; 949 } 950 951 if (didReconfigureCurrentDisplayLinkDisplay) { 952 // The link's current display has been reconfigured. 953 // Recreate the display link, because otherwise it may be stuck with a 954 // "removed" display forever and never notify us again. 955 DisableVsync(); 956 DestroyDisplayLink(); 957 CreateDisplayLink(); 958 EnableVsync(); 959 960 // Check if we actually succeeded in enabling vsync, and if we didn't, 961 // retry one time. 962 if (!IsVsyncEnabled()) { 963 gfxWarning() 964 << "Display reconfiguration vsync has failed; retrying one time."; 965 uint32_t delay = 100; 966 mTimer->InitWithNamedFuncCallback( 967 RetryCreateDisplayLinkAndEnableVsync, this, delay, 968 nsITimer::TYPE_ONE_SHOT, "RetryCreateDisplayLinkAndEnableVsync"_ns); 969 } 970 } 971 } 972 973 // Accessed from main thread and from display reconfiguration callback 974 // thread... which also happens to be the main thread. 975 DataMutex<CVDisplayLinkRef> mDisplayLink; 976 977 // Accessed only from the main thread. 978 RefPtr<nsITimer> mTimer; 979 TimeDuration mVsyncRate; 980 }; // OSXVsyncSource 981 982 static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink, 983 const CVTimeStamp* aNow, 984 const CVTimeStamp* aOutputTime, 985 CVOptionFlags aFlagsIn, CVOptionFlags* aFlagsOut, 986 void* aDisplayLinkContext) { 987 // Executed on OS X hardware vsync thread 988 OSXVsyncSource* vsyncSource = (OSXVsyncSource*)aDisplayLinkContext; 989 990 mozilla::TimeStamp outputTime = 991 mozilla::TimeStamp::FromSystemTime(aOutputTime->hostTime); 992 mozilla::TimeStamp nextVsync = outputTime; 993 mozilla::TimeStamp previousVsync = vsyncSource->mPreviousTimestamp; 994 mozilla::TimeStamp now = TimeStamp::Now(); 995 996 // Snow leopard sometimes sends vsync timestamps very far in the past. 997 // Normalize the vsync timestamps to now. 998 if (nextVsync <= previousVsync) { 999 nextVsync = now; 1000 previousVsync = now; 1001 } else if (now < previousVsync) { 1002 // Bug 1158321 - The VsyncCallback can sometimes execute before the reported 1003 // vsync time. In those cases, normalize the timestamp to Now() as sending 1004 // timestamps in the future has undefined behavior. See the comment above 1005 // OSXVsyncSource::mPreviousTimestamp 1006 previousVsync = now; 1007 } 1008 1009 vsyncSource->mPreviousTimestamp = nextVsync; 1010 1011 vsyncSource->NotifyVsync(previousVsync, outputTime); 1012 return kCVReturnSuccess; 1013 } 1014 #endif 1015 1016 already_AddRefed<mozilla::gfx::VsyncSource> 1017 gfxPlatformMac::CreateGlobalHardwareVsyncSource() { 1018 #ifdef MOZ_WIDGET_COCOA 1019 RefPtr<VsyncSource> osxVsyncSource = new OSXVsyncSource(); 1020 osxVsyncSource->EnableVsync(); 1021 if (!osxVsyncSource->IsVsyncEnabled()) { 1022 gfxWarning() 1023 << "OS X Vsync source not enabled. Falling back to software vsync."; 1024 return GetSoftwareVsyncSource(); 1025 } 1026 1027 osxVsyncSource->DisableVsync(); 1028 return osxVsyncSource.forget(); 1029 #else 1030 // TODO: CADisplayLink 1031 return GetSoftwareVsyncSource(); 1032 #endif 1033 } 1034 1035 nsTArray<uint8_t> gfxPlatformMac::GetPlatformCMSOutputProfileData() { 1036 nsTArray<uint8_t> prefProfileData = GetPrefCMSOutputProfileData(); 1037 if (!prefProfileData.IsEmpty()) { 1038 return prefProfileData; 1039 } 1040 1041 CGColorSpaceRef cspace = nil; 1042 #ifdef MOZ_WIDGET_COCOA 1043 cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID()); 1044 #endif 1045 if (!cspace) { 1046 cspace = ::CGColorSpaceCreateDeviceRGB(); 1047 } 1048 if (!cspace) { 1049 return nsTArray<uint8_t>(); 1050 } 1051 1052 CFDataRef iccp = ::CGColorSpaceCopyICCData(cspace); 1053 1054 ::CFRelease(cspace); 1055 1056 if (!iccp) { 1057 return nsTArray<uint8_t>(); 1058 } 1059 1060 // copy to external buffer 1061 size_t size = static_cast<size_t>(::CFDataGetLength(iccp)); 1062 1063 nsTArray<uint8_t> result; 1064 1065 if (size > 0) { 1066 result.AppendElements(::CFDataGetBytePtr(iccp), size); 1067 } 1068 1069 ::CFRelease(iccp); 1070 1071 return result; 1072 } 1073 1074 bool gfxPlatformMac::CheckVariationFontSupport() { return true; }