gfx/thebes/gfxPlatformMac.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     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 "gfxImageSurface.h"
     9 #include "gfxQuartzSurface.h"
    10 #include "gfxQuartzImageSurface.h"
    11 #include "mozilla/gfx/2D.h"
    13 #include "gfxMacPlatformFontList.h"
    14 #include "gfxMacFont.h"
    15 #include "gfxCoreTextShaper.h"
    16 #include "gfxUserFontSet.h"
    18 #include "nsTArray.h"
    19 #include "mozilla/Preferences.h"
    20 #include "qcms.h"
    21 #include "gfx2DGlue.h"
    23 #include <dlfcn.h>
    25 #include "nsCocoaFeatures.h"
    27 using namespace mozilla;
    28 using namespace mozilla::gfx;
    30 // cribbed from CTFontManager.h
    31 enum {
    32    kAutoActivationDisabled = 1
    33 };
    34 typedef uint32_t AutoActivationSetting;
    36 // bug 567552 - disable auto-activation of fonts
    38 static void 
    39 DisableFontActivation()
    40 {
    41     // get the main bundle identifier
    42     CFBundleRef mainBundle = ::CFBundleGetMainBundle();
    43     CFStringRef mainBundleID = nullptr;
    45     if (mainBundle) {
    46         mainBundleID = ::CFBundleGetIdentifier(mainBundle);
    47     }
    49     // bug 969388 and bug 922590 - mainBundlID as null is sometimes problematic
    50     if (!mainBundleID) {
    51         NS_WARNING("missing bundle ID, packaging set up incorrectly");
    52         return;
    53     }
    55     // if possible, fetch CTFontManagerSetAutoActivationSetting
    56     void (*CTFontManagerSetAutoActivationSettingPtr)
    57             (CFStringRef, AutoActivationSetting);
    58     CTFontManagerSetAutoActivationSettingPtr =
    59         (void (*)(CFStringRef, AutoActivationSetting))
    60         dlsym(RTLD_DEFAULT, "CTFontManagerSetAutoActivationSetting");
    62     // bug 567552 - disable auto-activation of fonts
    63     if (CTFontManagerSetAutoActivationSettingPtr) {
    64         CTFontManagerSetAutoActivationSettingPtr(mainBundleID,
    65                                                  kAutoActivationDisabled);
    66     }
    67 }
    69 gfxPlatformMac::gfxPlatformMac()
    70 {
    71     DisableFontActivation();
    72     mFontAntiAliasingThreshold = ReadAntiAliasingThreshold();
    74     uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) |
    75                           BackendTypeBit(BackendType::SKIA) |
    76                           BackendTypeBit(BackendType::COREGRAPHICS);
    77     uint32_t contentMask = BackendTypeBit(BackendType::COREGRAPHICS);
    78     InitBackendPrefs(canvasMask, BackendType::COREGRAPHICS,
    79                      contentMask, BackendType::COREGRAPHICS);
    80 }
    82 gfxPlatformMac::~gfxPlatformMac()
    83 {
    84     gfxCoreTextShaper::Shutdown();
    85 }
    87 gfxPlatformFontList*
    88 gfxPlatformMac::CreatePlatformFontList()
    89 {
    90     gfxPlatformFontList* list = new gfxMacPlatformFontList();
    91     if (NS_SUCCEEDED(list->InitFontList())) {
    92         return list;
    93     }
    94     gfxPlatformFontList::Shutdown();
    95     return nullptr;
    96 }
    98 already_AddRefed<gfxASurface>
    99 gfxPlatformMac::CreateOffscreenSurface(const IntSize& size,
   100                                        gfxContentType contentType)
   101 {
   102     nsRefPtr<gfxASurface> newSurface =
   103       new gfxQuartzSurface(ThebesIntSize(size),
   104                            OptimalFormatForContent(contentType));
   105     return newSurface.forget();
   106 }
   108 already_AddRefed<gfxASurface>
   109 gfxPlatformMac::CreateOffscreenImageSurface(const gfxIntSize& aSize,
   110                                             gfxContentType aContentType)
   111 {
   112     nsRefPtr<gfxASurface> surface =
   113         CreateOffscreenSurface(aSize.ToIntSize(), aContentType);
   114 #ifdef DEBUG
   115     nsRefPtr<gfxImageSurface> imageSurface = surface->GetAsImageSurface();
   116     NS_ASSERTION(imageSurface, "Surface cannot be converted to a gfxImageSurface");
   117 #endif
   118     return surface.forget();
   119 }
   122 already_AddRefed<gfxASurface>
   123 gfxPlatformMac::OptimizeImage(gfxImageSurface *aSurface,
   124                               gfxImageFormat format)
   125 {
   126     const gfxIntSize& surfaceSize = aSurface->GetSize();
   127     nsRefPtr<gfxImageSurface> isurf = aSurface;
   129     if (format != aSurface->Format()) {
   130         isurf = new gfxImageSurface (surfaceSize, format);
   131         if (!isurf->CopyFrom (aSurface)) {
   132             // don't even bother doing anything more
   133             nsRefPtr<gfxASurface> ret = aSurface;
   134             return ret.forget();
   135         }
   136     }
   138     return nullptr;
   139 }
   141 TemporaryRef<ScaledFont>
   142 gfxPlatformMac::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
   143 {
   144     gfxMacFont *font = static_cast<gfxMacFont*>(aFont);
   145     return font->GetScaledFont(aTarget);
   146 }
   148 nsresult
   149 gfxPlatformMac::ResolveFontName(const nsAString& aFontName,
   150                                 FontResolverCallback aCallback,
   151                                 void *aClosure, bool& aAborted)
   152 {
   153     nsAutoString resolvedName;
   154     if (!gfxPlatformFontList::PlatformFontList()->
   155              ResolveFontName(aFontName, resolvedName)) {
   156         aAborted = false;
   157         return NS_OK;
   158     }
   159     aAborted = !(*aCallback)(resolvedName, aClosure);
   160     return NS_OK;
   161 }
   163 nsresult
   164 gfxPlatformMac::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
   165 {
   166     gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName, aFamilyName);
   167     return NS_OK;
   168 }
   170 gfxFontGroup *
   171 gfxPlatformMac::CreateFontGroup(const nsAString &aFamilies,
   172                                 const gfxFontStyle *aStyle,
   173                                 gfxUserFontSet *aUserFontSet)
   174 {
   175     return new gfxFontGroup(aFamilies, aStyle, aUserFontSet);
   176 }
   178 // these will move to gfxPlatform once all platforms support the fontlist
   179 gfxFontEntry* 
   180 gfxPlatformMac::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
   181                                 const nsAString& aFontName)
   182 {
   183     return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aProxyEntry, 
   184                                                                     aFontName);
   185 }
   187 gfxFontEntry* 
   188 gfxPlatformMac::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
   189                                  const uint8_t *aFontData, uint32_t aLength)
   190 {
   191     // Ownership of aFontData is received here, and passed on to
   192     // gfxPlatformFontList::MakePlatformFont(), which must ensure the data
   193     // is released with NS_Free when no longer needed
   194     return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
   195                                                                      aFontData,
   196                                                                      aLength);
   197 }
   199 bool
   200 gfxPlatformMac::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags)
   201 {
   202     // check for strange format flags
   203     NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
   204                  "strange font format hint set");
   206     // accept supported formats
   207     if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_WOFF     |
   208                         gfxUserFontSet::FLAG_FORMAT_OPENTYPE | 
   209                         gfxUserFontSet::FLAG_FORMAT_TRUETYPE | 
   210                         gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT)) {
   211         return true;
   212     }
   214     // reject all other formats, known and unknown
   215     if (aFormatFlags != 0) {
   216         return false;
   217     }
   219     // no format hint set, need to look at data
   220     return true;
   221 }
   223 // these will also move to gfxPlatform once all platforms support the fontlist
   224 nsresult
   225 gfxPlatformMac::GetFontList(nsIAtom *aLangGroup,
   226                             const nsACString& aGenericFamily,
   227                             nsTArray<nsString>& aListOfFonts)
   228 {
   229     gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup, aGenericFamily, aListOfFonts);
   230     return NS_OK;
   231 }
   233 nsresult
   234 gfxPlatformMac::UpdateFontList()
   235 {
   236     gfxPlatformFontList::PlatformFontList()->UpdateFontList();
   237     return NS_OK;
   238 }
   240 static const char kFontArialUnicodeMS[] = "Arial Unicode MS";
   241 static const char kFontAppleBraille[] = "Apple Braille";
   242 static const char kFontAppleColorEmoji[] = "Apple Color Emoji";
   243 static const char kFontAppleSymbols[] = "Apple Symbols";
   244 static const char kFontDevanagariSangamMN[] = "Devanagari Sangam MN";
   245 static const char kFontEuphemiaUCAS[] = "Euphemia UCAS";
   246 static const char kFontGeneva[] = "Geneva";
   247 static const char kFontGeezaPro[] = "Geeza Pro";
   248 static const char kFontGujaratiSangamMN[] = "Gujarati Sangam MN";
   249 static const char kFontGurmukhiMN[] = "Gurmukhi MN";
   250 static const char kFontHiraginoKakuGothic[] = "Hiragino Kaku Gothic ProN";
   251 static const char kFontHiraginoSansGB[] = "Hiragino Sans GB";
   252 static const char kFontKefa[] = "Kefa";
   253 static const char kFontKhmerMN[] = "Khmer MN";
   254 static const char kFontLaoMN[] = "Lao MN";
   255 static const char kFontLucidaGrande[] = "Lucida Grande";
   256 static const char kFontMenlo[] = "Menlo";
   257 static const char kFontMicrosoftTaiLe[] = "Microsoft Tai Le";
   258 static const char kFontMingLiUExtB[] = "MingLiU-ExtB";
   259 static const char kFontMyanmarMN[] = "Myanmar MN";
   260 static const char kFontPlantagenetCherokee[] = "Plantagenet Cherokee";
   261 static const char kFontSimSunExtB[] = "SimSun-ExtB";
   262 static const char kFontSongtiSC[] = "Songti SC";
   263 static const char kFontSTHeiti[] = "STHeiti";
   264 static const char kFontSTIXGeneral[] = "STIXGeneral";
   265 static const char kFontTamilMN[] = "Tamil MN";
   267 void
   268 gfxPlatformMac::GetCommonFallbackFonts(const uint32_t aCh,
   269                                        int32_t aRunScript,
   270                                        nsTArray<const char*>& aFontList)
   271 {
   272     aFontList.AppendElement(kFontLucidaGrande);
   274     if (!IS_IN_BMP(aCh)) {
   275         uint32_t p = aCh >> 16;
   276         uint32_t b = aCh >> 8;
   277         if (p == 1) {
   278             if (b >= 0x1f0 && b < 0x1f7) {
   279                 aFontList.AppendElement(kFontAppleColorEmoji);
   280             } else {
   281                 aFontList.AppendElement(kFontAppleSymbols);
   282                 aFontList.AppendElement(kFontSTIXGeneral);
   283                 aFontList.AppendElement(kFontGeneva);
   284             }
   285         } else if (p == 2) {
   286             // OSX installations with MS Office may have these fonts
   287             aFontList.AppendElement(kFontMingLiUExtB);
   288             aFontList.AppendElement(kFontSimSunExtB);
   289         }
   290     } else {
   291         uint32_t b = (aCh >> 8) & 0xff;
   293         switch (b) {
   294         case 0x03:
   295         case 0x05:
   296             aFontList.AppendElement(kFontGeneva);
   297             break;
   298         case 0x07:
   299             aFontList.AppendElement(kFontGeezaPro);
   300             break;
   301         case 0x09:
   302             aFontList.AppendElement(kFontDevanagariSangamMN);
   303             break;
   304         case 0x0a:
   305             aFontList.AppendElement(kFontGurmukhiMN);
   306             aFontList.AppendElement(kFontGujaratiSangamMN);
   307             break;
   308         case 0x0b:
   309             aFontList.AppendElement(kFontTamilMN);
   310             break;
   311         case 0x0e:
   312             aFontList.AppendElement(kFontLaoMN);
   313             break;
   314         case 0x0f:
   315             aFontList.AppendElement(kFontSongtiSC);
   316             break;
   317         case 0x10:
   318             aFontList.AppendElement(kFontMenlo);
   319             aFontList.AppendElement(kFontMyanmarMN);
   320             break;
   321         case 0x13:  // Cherokee
   322             aFontList.AppendElement(kFontPlantagenetCherokee);
   323             aFontList.AppendElement(kFontKefa);
   324             break;
   325         case 0x14:  // Unified Canadian Aboriginal Syllabics
   326         case 0x15:
   327         case 0x16:
   328             aFontList.AppendElement(kFontEuphemiaUCAS);
   329             aFontList.AppendElement(kFontGeneva);
   330             break;
   331         case 0x18:  // Mongolian, UCAS
   332             aFontList.AppendElement(kFontSTHeiti);
   333             aFontList.AppendElement(kFontEuphemiaUCAS);
   334             break;
   335         case 0x19:  // Khmer
   336             aFontList.AppendElement(kFontKhmerMN);
   337             aFontList.AppendElement(kFontMicrosoftTaiLe);
   338             break;
   339         case 0x1d:
   340         case 0x1e:
   341             aFontList.AppendElement(kFontGeneva);
   342             break;
   343         case 0x20:  // Symbol ranges
   344         case 0x21:
   345         case 0x22:
   346         case 0x23:
   347         case 0x24:
   348         case 0x25:
   349         case 0x26:
   350         case 0x27:
   351         case 0x29:
   352         case 0x2a:
   353         case 0x2b:
   354         case 0x2e:
   355             aFontList.AppendElement(kFontAppleSymbols);
   356             aFontList.AppendElement(kFontMenlo);
   357             aFontList.AppendElement(kFontSTIXGeneral);
   358             aFontList.AppendElement(kFontGeneva);
   359             aFontList.AppendElement(kFontHiraginoKakuGothic);
   360             aFontList.AppendElement(kFontAppleColorEmoji);
   361             break;
   362         case 0x2c:
   363             aFontList.AppendElement(kFontGeneva);
   364             break;
   365         case 0x2d:
   366             aFontList.AppendElement(kFontKefa);
   367             aFontList.AppendElement(kFontGeneva);
   368             break;
   369         case 0x28:  // Braille
   370             aFontList.AppendElement(kFontAppleBraille);
   371             break;
   372         case 0x31:
   373             aFontList.AppendElement(kFontHiraginoSansGB);
   374             break;
   375         case 0x4d:
   376             aFontList.AppendElement(kFontAppleSymbols);
   377             break;
   378         case 0xa0:  // Yi
   379         case 0xa1:
   380         case 0xa2:
   381         case 0xa3:
   382         case 0xa4:
   383             aFontList.AppendElement(kFontSTHeiti);
   384             break;
   385         case 0xa6:
   386         case 0xa7:
   387             aFontList.AppendElement(kFontGeneva);
   388             aFontList.AppendElement(kFontAppleSymbols);
   389             break;
   390         case 0xab:
   391             aFontList.AppendElement(kFontKefa);
   392             break;
   393         case 0xfc:
   394         case 0xff:
   395             aFontList.AppendElement(kFontAppleSymbols);
   396             break;
   397         default:
   398             break;
   399         }
   400     }
   402     // Arial Unicode MS has lots of glyphs for obscure, use it as a last resort
   403     aFontList.AppendElement(kFontArialUnicodeMS);
   404 }
   406 uint32_t
   407 gfxPlatformMac::ReadAntiAliasingThreshold()
   408 {
   409     uint32_t threshold = 0;  // default == no threshold
   411     // first read prefs flag to determine whether to use the setting or not
   412     bool useAntiAliasingThreshold = Preferences::GetBool("gfx.use_text_smoothing_setting", false);
   414     // if the pref setting is disabled, return 0 which effectively disables this feature
   415     if (!useAntiAliasingThreshold)
   416         return threshold;
   418     // value set via Appearance pref panel, "Turn off text smoothing for font sizes xxx and smaller"
   419     CFNumberRef prefValue = (CFNumberRef)CFPreferencesCopyAppValue(CFSTR("AppleAntiAliasingThreshold"), kCFPreferencesCurrentApplication);
   421     if (prefValue) {
   422         if (!CFNumberGetValue(prefValue, kCFNumberIntType, &threshold)) {
   423             threshold = 0;
   424         }
   425         CFRelease(prefValue);
   426     }
   428     return threshold;
   429 }
   431 already_AddRefed<gfxASurface>
   432 gfxPlatformMac::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
   433 {
   434   if (aTarget->GetType() == BackendType::COREGRAPHICS_ACCELERATED) {
   435     RefPtr<SourceSurface> source = aTarget->Snapshot();
   436     RefPtr<DataSourceSurface> sourceData = source->GetDataSurface();
   437     unsigned char* data = sourceData->GetData();
   438     nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(data, ThebesIntSize(sourceData->GetSize()), sourceData->Stride(),
   439                                                          gfxImageFormat::ARGB32);
   440     // We could fix this by telling gfxImageSurface it owns data.
   441     nsRefPtr<gfxImageSurface> cpy = new gfxImageSurface(ThebesIntSize(sourceData->GetSize()), gfxImageFormat::ARGB32);
   442     cpy->CopyFrom(surf);
   443     return cpy.forget();
   444   } else if (aTarget->GetType() == BackendType::COREGRAPHICS) {
   445     CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NativeSurfaceType::CGCONTEXT));
   447     //XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
   448     IntSize intSize = aTarget->GetSize();
   449     gfxIntSize size(intSize.width, intSize.height);
   451     nsRefPtr<gfxASurface> surf =
   452       new gfxQuartzSurface(cg, size);
   454     return surf.forget();
   455   }
   457   return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
   458 }
   460 bool
   461 gfxPlatformMac::UseAcceleratedCanvas()
   462 {
   463   // Lion or later is required
   464   return nsCocoaFeatures::OnLionOrLater() && Preferences::GetBool("gfx.canvas.azure.accelerated", false);
   465 }
   467 bool
   468 gfxPlatformMac::SupportsOffMainThreadCompositing()
   469 {
   470   return true;
   471 }
   473 void
   474 gfxPlatformMac::GetPlatformCMSOutputProfile(void* &mem, size_t &size)
   475 {
   476     mem = nullptr;
   477     size = 0;
   479     CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID());
   480     if (!cspace) {
   481         cspace = ::CGColorSpaceCreateDeviceRGB();
   482     }
   483     if (!cspace) {
   484         return;
   485     }
   487     CFDataRef iccp = ::CGColorSpaceCopyICCProfile(cspace);
   489     ::CFRelease(cspace);
   491     if (!iccp) {
   492         return;
   493     }
   495     // copy to external buffer
   496     size = static_cast<size_t>(::CFDataGetLength(iccp));
   497     if (size > 0) {
   498         void *data = malloc(size);
   499         if (data) {
   500             memcpy(data, ::CFDataGetBytePtr(iccp), size);
   501             mem = data;
   502         } else {
   503             size = 0;
   504         }
   505     }
   507     ::CFRelease(iccp);
   508 }

mercurial