tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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; }