1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxPlatformMac.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,508 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "gfxPlatformMac.h" 1.10 + 1.11 +#include "gfxImageSurface.h" 1.12 +#include "gfxQuartzSurface.h" 1.13 +#include "gfxQuartzImageSurface.h" 1.14 +#include "mozilla/gfx/2D.h" 1.15 + 1.16 +#include "gfxMacPlatformFontList.h" 1.17 +#include "gfxMacFont.h" 1.18 +#include "gfxCoreTextShaper.h" 1.19 +#include "gfxUserFontSet.h" 1.20 + 1.21 +#include "nsTArray.h" 1.22 +#include "mozilla/Preferences.h" 1.23 +#include "qcms.h" 1.24 +#include "gfx2DGlue.h" 1.25 + 1.26 +#include <dlfcn.h> 1.27 + 1.28 +#include "nsCocoaFeatures.h" 1.29 + 1.30 +using namespace mozilla; 1.31 +using namespace mozilla::gfx; 1.32 + 1.33 +// cribbed from CTFontManager.h 1.34 +enum { 1.35 + kAutoActivationDisabled = 1 1.36 +}; 1.37 +typedef uint32_t AutoActivationSetting; 1.38 + 1.39 +// bug 567552 - disable auto-activation of fonts 1.40 + 1.41 +static void 1.42 +DisableFontActivation() 1.43 +{ 1.44 + // get the main bundle identifier 1.45 + CFBundleRef mainBundle = ::CFBundleGetMainBundle(); 1.46 + CFStringRef mainBundleID = nullptr; 1.47 + 1.48 + if (mainBundle) { 1.49 + mainBundleID = ::CFBundleGetIdentifier(mainBundle); 1.50 + } 1.51 + 1.52 + // bug 969388 and bug 922590 - mainBundlID as null is sometimes problematic 1.53 + if (!mainBundleID) { 1.54 + NS_WARNING("missing bundle ID, packaging set up incorrectly"); 1.55 + return; 1.56 + } 1.57 + 1.58 + // if possible, fetch CTFontManagerSetAutoActivationSetting 1.59 + void (*CTFontManagerSetAutoActivationSettingPtr) 1.60 + (CFStringRef, AutoActivationSetting); 1.61 + CTFontManagerSetAutoActivationSettingPtr = 1.62 + (void (*)(CFStringRef, AutoActivationSetting)) 1.63 + dlsym(RTLD_DEFAULT, "CTFontManagerSetAutoActivationSetting"); 1.64 + 1.65 + // bug 567552 - disable auto-activation of fonts 1.66 + if (CTFontManagerSetAutoActivationSettingPtr) { 1.67 + CTFontManagerSetAutoActivationSettingPtr(mainBundleID, 1.68 + kAutoActivationDisabled); 1.69 + } 1.70 +} 1.71 + 1.72 +gfxPlatformMac::gfxPlatformMac() 1.73 +{ 1.74 + DisableFontActivation(); 1.75 + mFontAntiAliasingThreshold = ReadAntiAliasingThreshold(); 1.76 + 1.77 + uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) | 1.78 + BackendTypeBit(BackendType::SKIA) | 1.79 + BackendTypeBit(BackendType::COREGRAPHICS); 1.80 + uint32_t contentMask = BackendTypeBit(BackendType::COREGRAPHICS); 1.81 + InitBackendPrefs(canvasMask, BackendType::COREGRAPHICS, 1.82 + contentMask, BackendType::COREGRAPHICS); 1.83 +} 1.84 + 1.85 +gfxPlatformMac::~gfxPlatformMac() 1.86 +{ 1.87 + gfxCoreTextShaper::Shutdown(); 1.88 +} 1.89 + 1.90 +gfxPlatformFontList* 1.91 +gfxPlatformMac::CreatePlatformFontList() 1.92 +{ 1.93 + gfxPlatformFontList* list = new gfxMacPlatformFontList(); 1.94 + if (NS_SUCCEEDED(list->InitFontList())) { 1.95 + return list; 1.96 + } 1.97 + gfxPlatformFontList::Shutdown(); 1.98 + return nullptr; 1.99 +} 1.100 + 1.101 +already_AddRefed<gfxASurface> 1.102 +gfxPlatformMac::CreateOffscreenSurface(const IntSize& size, 1.103 + gfxContentType contentType) 1.104 +{ 1.105 + nsRefPtr<gfxASurface> newSurface = 1.106 + new gfxQuartzSurface(ThebesIntSize(size), 1.107 + OptimalFormatForContent(contentType)); 1.108 + return newSurface.forget(); 1.109 +} 1.110 + 1.111 +already_AddRefed<gfxASurface> 1.112 +gfxPlatformMac::CreateOffscreenImageSurface(const gfxIntSize& aSize, 1.113 + gfxContentType aContentType) 1.114 +{ 1.115 + nsRefPtr<gfxASurface> surface = 1.116 + CreateOffscreenSurface(aSize.ToIntSize(), aContentType); 1.117 +#ifdef DEBUG 1.118 + nsRefPtr<gfxImageSurface> imageSurface = surface->GetAsImageSurface(); 1.119 + NS_ASSERTION(imageSurface, "Surface cannot be converted to a gfxImageSurface"); 1.120 +#endif 1.121 + return surface.forget(); 1.122 +} 1.123 + 1.124 + 1.125 +already_AddRefed<gfxASurface> 1.126 +gfxPlatformMac::OptimizeImage(gfxImageSurface *aSurface, 1.127 + gfxImageFormat format) 1.128 +{ 1.129 + const gfxIntSize& surfaceSize = aSurface->GetSize(); 1.130 + nsRefPtr<gfxImageSurface> isurf = aSurface; 1.131 + 1.132 + if (format != aSurface->Format()) { 1.133 + isurf = new gfxImageSurface (surfaceSize, format); 1.134 + if (!isurf->CopyFrom (aSurface)) { 1.135 + // don't even bother doing anything more 1.136 + nsRefPtr<gfxASurface> ret = aSurface; 1.137 + return ret.forget(); 1.138 + } 1.139 + } 1.140 + 1.141 + return nullptr; 1.142 +} 1.143 + 1.144 +TemporaryRef<ScaledFont> 1.145 +gfxPlatformMac::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont) 1.146 +{ 1.147 + gfxMacFont *font = static_cast<gfxMacFont*>(aFont); 1.148 + return font->GetScaledFont(aTarget); 1.149 +} 1.150 + 1.151 +nsresult 1.152 +gfxPlatformMac::ResolveFontName(const nsAString& aFontName, 1.153 + FontResolverCallback aCallback, 1.154 + void *aClosure, bool& aAborted) 1.155 +{ 1.156 + nsAutoString resolvedName; 1.157 + if (!gfxPlatformFontList::PlatformFontList()-> 1.158 + ResolveFontName(aFontName, resolvedName)) { 1.159 + aAborted = false; 1.160 + return NS_OK; 1.161 + } 1.162 + aAborted = !(*aCallback)(resolvedName, aClosure); 1.163 + return NS_OK; 1.164 +} 1.165 + 1.166 +nsresult 1.167 +gfxPlatformMac::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) 1.168 +{ 1.169 + gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName, aFamilyName); 1.170 + return NS_OK; 1.171 +} 1.172 + 1.173 +gfxFontGroup * 1.174 +gfxPlatformMac::CreateFontGroup(const nsAString &aFamilies, 1.175 + const gfxFontStyle *aStyle, 1.176 + gfxUserFontSet *aUserFontSet) 1.177 +{ 1.178 + return new gfxFontGroup(aFamilies, aStyle, aUserFontSet); 1.179 +} 1.180 + 1.181 +// these will move to gfxPlatform once all platforms support the fontlist 1.182 +gfxFontEntry* 1.183 +gfxPlatformMac::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, 1.184 + const nsAString& aFontName) 1.185 +{ 1.186 + return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aProxyEntry, 1.187 + aFontName); 1.188 +} 1.189 + 1.190 +gfxFontEntry* 1.191 +gfxPlatformMac::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, 1.192 + const uint8_t *aFontData, uint32_t aLength) 1.193 +{ 1.194 + // Ownership of aFontData is received here, and passed on to 1.195 + // gfxPlatformFontList::MakePlatformFont(), which must ensure the data 1.196 + // is released with NS_Free when no longer needed 1.197 + return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry, 1.198 + aFontData, 1.199 + aLength); 1.200 +} 1.201 + 1.202 +bool 1.203 +gfxPlatformMac::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) 1.204 +{ 1.205 + // check for strange format flags 1.206 + NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED), 1.207 + "strange font format hint set"); 1.208 + 1.209 + // accept supported formats 1.210 + if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_WOFF | 1.211 + gfxUserFontSet::FLAG_FORMAT_OPENTYPE | 1.212 + gfxUserFontSet::FLAG_FORMAT_TRUETYPE | 1.213 + gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT)) { 1.214 + return true; 1.215 + } 1.216 + 1.217 + // reject all other formats, known and unknown 1.218 + if (aFormatFlags != 0) { 1.219 + return false; 1.220 + } 1.221 + 1.222 + // no format hint set, need to look at data 1.223 + return true; 1.224 +} 1.225 + 1.226 +// these will also move to gfxPlatform once all platforms support the fontlist 1.227 +nsresult 1.228 +gfxPlatformMac::GetFontList(nsIAtom *aLangGroup, 1.229 + const nsACString& aGenericFamily, 1.230 + nsTArray<nsString>& aListOfFonts) 1.231 +{ 1.232 + gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup, aGenericFamily, aListOfFonts); 1.233 + return NS_OK; 1.234 +} 1.235 + 1.236 +nsresult 1.237 +gfxPlatformMac::UpdateFontList() 1.238 +{ 1.239 + gfxPlatformFontList::PlatformFontList()->UpdateFontList(); 1.240 + return NS_OK; 1.241 +} 1.242 + 1.243 +static const char kFontArialUnicodeMS[] = "Arial Unicode MS"; 1.244 +static const char kFontAppleBraille[] = "Apple Braille"; 1.245 +static const char kFontAppleColorEmoji[] = "Apple Color Emoji"; 1.246 +static const char kFontAppleSymbols[] = "Apple Symbols"; 1.247 +static const char kFontDevanagariSangamMN[] = "Devanagari Sangam MN"; 1.248 +static const char kFontEuphemiaUCAS[] = "Euphemia UCAS"; 1.249 +static const char kFontGeneva[] = "Geneva"; 1.250 +static const char kFontGeezaPro[] = "Geeza Pro"; 1.251 +static const char kFontGujaratiSangamMN[] = "Gujarati Sangam MN"; 1.252 +static const char kFontGurmukhiMN[] = "Gurmukhi MN"; 1.253 +static const char kFontHiraginoKakuGothic[] = "Hiragino Kaku Gothic ProN"; 1.254 +static const char kFontHiraginoSansGB[] = "Hiragino Sans GB"; 1.255 +static const char kFontKefa[] = "Kefa"; 1.256 +static const char kFontKhmerMN[] = "Khmer MN"; 1.257 +static const char kFontLaoMN[] = "Lao MN"; 1.258 +static const char kFontLucidaGrande[] = "Lucida Grande"; 1.259 +static const char kFontMenlo[] = "Menlo"; 1.260 +static const char kFontMicrosoftTaiLe[] = "Microsoft Tai Le"; 1.261 +static const char kFontMingLiUExtB[] = "MingLiU-ExtB"; 1.262 +static const char kFontMyanmarMN[] = "Myanmar MN"; 1.263 +static const char kFontPlantagenetCherokee[] = "Plantagenet Cherokee"; 1.264 +static const char kFontSimSunExtB[] = "SimSun-ExtB"; 1.265 +static const char kFontSongtiSC[] = "Songti SC"; 1.266 +static const char kFontSTHeiti[] = "STHeiti"; 1.267 +static const char kFontSTIXGeneral[] = "STIXGeneral"; 1.268 +static const char kFontTamilMN[] = "Tamil MN"; 1.269 + 1.270 +void 1.271 +gfxPlatformMac::GetCommonFallbackFonts(const uint32_t aCh, 1.272 + int32_t aRunScript, 1.273 + nsTArray<const char*>& aFontList) 1.274 +{ 1.275 + aFontList.AppendElement(kFontLucidaGrande); 1.276 + 1.277 + if (!IS_IN_BMP(aCh)) { 1.278 + uint32_t p = aCh >> 16; 1.279 + uint32_t b = aCh >> 8; 1.280 + if (p == 1) { 1.281 + if (b >= 0x1f0 && b < 0x1f7) { 1.282 + aFontList.AppendElement(kFontAppleColorEmoji); 1.283 + } else { 1.284 + aFontList.AppendElement(kFontAppleSymbols); 1.285 + aFontList.AppendElement(kFontSTIXGeneral); 1.286 + aFontList.AppendElement(kFontGeneva); 1.287 + } 1.288 + } else if (p == 2) { 1.289 + // OSX installations with MS Office may have these fonts 1.290 + aFontList.AppendElement(kFontMingLiUExtB); 1.291 + aFontList.AppendElement(kFontSimSunExtB); 1.292 + } 1.293 + } else { 1.294 + uint32_t b = (aCh >> 8) & 0xff; 1.295 + 1.296 + switch (b) { 1.297 + case 0x03: 1.298 + case 0x05: 1.299 + aFontList.AppendElement(kFontGeneva); 1.300 + break; 1.301 + case 0x07: 1.302 + aFontList.AppendElement(kFontGeezaPro); 1.303 + break; 1.304 + case 0x09: 1.305 + aFontList.AppendElement(kFontDevanagariSangamMN); 1.306 + break; 1.307 + case 0x0a: 1.308 + aFontList.AppendElement(kFontGurmukhiMN); 1.309 + aFontList.AppendElement(kFontGujaratiSangamMN); 1.310 + break; 1.311 + case 0x0b: 1.312 + aFontList.AppendElement(kFontTamilMN); 1.313 + break; 1.314 + case 0x0e: 1.315 + aFontList.AppendElement(kFontLaoMN); 1.316 + break; 1.317 + case 0x0f: 1.318 + aFontList.AppendElement(kFontSongtiSC); 1.319 + break; 1.320 + case 0x10: 1.321 + aFontList.AppendElement(kFontMenlo); 1.322 + aFontList.AppendElement(kFontMyanmarMN); 1.323 + break; 1.324 + case 0x13: // Cherokee 1.325 + aFontList.AppendElement(kFontPlantagenetCherokee); 1.326 + aFontList.AppendElement(kFontKefa); 1.327 + break; 1.328 + case 0x14: // Unified Canadian Aboriginal Syllabics 1.329 + case 0x15: 1.330 + case 0x16: 1.331 + aFontList.AppendElement(kFontEuphemiaUCAS); 1.332 + aFontList.AppendElement(kFontGeneva); 1.333 + break; 1.334 + case 0x18: // Mongolian, UCAS 1.335 + aFontList.AppendElement(kFontSTHeiti); 1.336 + aFontList.AppendElement(kFontEuphemiaUCAS); 1.337 + break; 1.338 + case 0x19: // Khmer 1.339 + aFontList.AppendElement(kFontKhmerMN); 1.340 + aFontList.AppendElement(kFontMicrosoftTaiLe); 1.341 + break; 1.342 + case 0x1d: 1.343 + case 0x1e: 1.344 + aFontList.AppendElement(kFontGeneva); 1.345 + break; 1.346 + case 0x20: // Symbol ranges 1.347 + case 0x21: 1.348 + case 0x22: 1.349 + case 0x23: 1.350 + case 0x24: 1.351 + case 0x25: 1.352 + case 0x26: 1.353 + case 0x27: 1.354 + case 0x29: 1.355 + case 0x2a: 1.356 + case 0x2b: 1.357 + case 0x2e: 1.358 + aFontList.AppendElement(kFontAppleSymbols); 1.359 + aFontList.AppendElement(kFontMenlo); 1.360 + aFontList.AppendElement(kFontSTIXGeneral); 1.361 + aFontList.AppendElement(kFontGeneva); 1.362 + aFontList.AppendElement(kFontHiraginoKakuGothic); 1.363 + aFontList.AppendElement(kFontAppleColorEmoji); 1.364 + break; 1.365 + case 0x2c: 1.366 + aFontList.AppendElement(kFontGeneva); 1.367 + break; 1.368 + case 0x2d: 1.369 + aFontList.AppendElement(kFontKefa); 1.370 + aFontList.AppendElement(kFontGeneva); 1.371 + break; 1.372 + case 0x28: // Braille 1.373 + aFontList.AppendElement(kFontAppleBraille); 1.374 + break; 1.375 + case 0x31: 1.376 + aFontList.AppendElement(kFontHiraginoSansGB); 1.377 + break; 1.378 + case 0x4d: 1.379 + aFontList.AppendElement(kFontAppleSymbols); 1.380 + break; 1.381 + case 0xa0: // Yi 1.382 + case 0xa1: 1.383 + case 0xa2: 1.384 + case 0xa3: 1.385 + case 0xa4: 1.386 + aFontList.AppendElement(kFontSTHeiti); 1.387 + break; 1.388 + case 0xa6: 1.389 + case 0xa7: 1.390 + aFontList.AppendElement(kFontGeneva); 1.391 + aFontList.AppendElement(kFontAppleSymbols); 1.392 + break; 1.393 + case 0xab: 1.394 + aFontList.AppendElement(kFontKefa); 1.395 + break; 1.396 + case 0xfc: 1.397 + case 0xff: 1.398 + aFontList.AppendElement(kFontAppleSymbols); 1.399 + break; 1.400 + default: 1.401 + break; 1.402 + } 1.403 + } 1.404 + 1.405 + // Arial Unicode MS has lots of glyphs for obscure, use it as a last resort 1.406 + aFontList.AppendElement(kFontArialUnicodeMS); 1.407 +} 1.408 + 1.409 +uint32_t 1.410 +gfxPlatformMac::ReadAntiAliasingThreshold() 1.411 +{ 1.412 + uint32_t threshold = 0; // default == no threshold 1.413 + 1.414 + // first read prefs flag to determine whether to use the setting or not 1.415 + bool useAntiAliasingThreshold = Preferences::GetBool("gfx.use_text_smoothing_setting", false); 1.416 + 1.417 + // if the pref setting is disabled, return 0 which effectively disables this feature 1.418 + if (!useAntiAliasingThreshold) 1.419 + return threshold; 1.420 + 1.421 + // value set via Appearance pref panel, "Turn off text smoothing for font sizes xxx and smaller" 1.422 + CFNumberRef prefValue = (CFNumberRef)CFPreferencesCopyAppValue(CFSTR("AppleAntiAliasingThreshold"), kCFPreferencesCurrentApplication); 1.423 + 1.424 + if (prefValue) { 1.425 + if (!CFNumberGetValue(prefValue, kCFNumberIntType, &threshold)) { 1.426 + threshold = 0; 1.427 + } 1.428 + CFRelease(prefValue); 1.429 + } 1.430 + 1.431 + return threshold; 1.432 +} 1.433 + 1.434 +already_AddRefed<gfxASurface> 1.435 +gfxPlatformMac::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget) 1.436 +{ 1.437 + if (aTarget->GetType() == BackendType::COREGRAPHICS_ACCELERATED) { 1.438 + RefPtr<SourceSurface> source = aTarget->Snapshot(); 1.439 + RefPtr<DataSourceSurface> sourceData = source->GetDataSurface(); 1.440 + unsigned char* data = sourceData->GetData(); 1.441 + nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(data, ThebesIntSize(sourceData->GetSize()), sourceData->Stride(), 1.442 + gfxImageFormat::ARGB32); 1.443 + // We could fix this by telling gfxImageSurface it owns data. 1.444 + nsRefPtr<gfxImageSurface> cpy = new gfxImageSurface(ThebesIntSize(sourceData->GetSize()), gfxImageFormat::ARGB32); 1.445 + cpy->CopyFrom(surf); 1.446 + return cpy.forget(); 1.447 + } else if (aTarget->GetType() == BackendType::COREGRAPHICS) { 1.448 + CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NativeSurfaceType::CGCONTEXT)); 1.449 + 1.450 + //XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize 1.451 + IntSize intSize = aTarget->GetSize(); 1.452 + gfxIntSize size(intSize.width, intSize.height); 1.453 + 1.454 + nsRefPtr<gfxASurface> surf = 1.455 + new gfxQuartzSurface(cg, size); 1.456 + 1.457 + return surf.forget(); 1.458 + } 1.459 + 1.460 + return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget); 1.461 +} 1.462 + 1.463 +bool 1.464 +gfxPlatformMac::UseAcceleratedCanvas() 1.465 +{ 1.466 + // Lion or later is required 1.467 + return nsCocoaFeatures::OnLionOrLater() && Preferences::GetBool("gfx.canvas.azure.accelerated", false); 1.468 +} 1.469 + 1.470 +bool 1.471 +gfxPlatformMac::SupportsOffMainThreadCompositing() 1.472 +{ 1.473 + return true; 1.474 +} 1.475 + 1.476 +void 1.477 +gfxPlatformMac::GetPlatformCMSOutputProfile(void* &mem, size_t &size) 1.478 +{ 1.479 + mem = nullptr; 1.480 + size = 0; 1.481 + 1.482 + CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID()); 1.483 + if (!cspace) { 1.484 + cspace = ::CGColorSpaceCreateDeviceRGB(); 1.485 + } 1.486 + if (!cspace) { 1.487 + return; 1.488 + } 1.489 + 1.490 + CFDataRef iccp = ::CGColorSpaceCopyICCProfile(cspace); 1.491 + 1.492 + ::CFRelease(cspace); 1.493 + 1.494 + if (!iccp) { 1.495 + return; 1.496 + } 1.497 + 1.498 + // copy to external buffer 1.499 + size = static_cast<size_t>(::CFDataGetLength(iccp)); 1.500 + if (size > 0) { 1.501 + void *data = malloc(size); 1.502 + if (data) { 1.503 + memcpy(data, ::CFDataGetBytePtr(iccp), size); 1.504 + mem = data; 1.505 + } else { 1.506 + size = 0; 1.507 + } 1.508 + } 1.509 + 1.510 + ::CFRelease(iccp); 1.511 +}