1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxMacPlatformFontList.mm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1127 @@ 1.4 +/* -*- Mode: ObjC; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * ***** BEGIN LICENSE BLOCK ***** 1.6 + * Version: BSD 1.7 + * 1.8 + * Copyright (C) 2006-2009 Mozilla Corporation. All rights reserved. 1.9 + * 1.10 + * Contributor(s): 1.11 + * Vladimir Vukicevic <vladimir@pobox.com> 1.12 + * Masayuki Nakano <masayuki@d-toybox.com> 1.13 + * John Daggett <jdaggett@mozilla.com> 1.14 + * Jonathan Kew <jfkthame@gmail.com> 1.15 + * 1.16 + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. 1.17 + * 1.18 + * Redistribution and use in source and binary forms, with or without 1.19 + * modification, are permitted provided that the following conditions 1.20 + * are met: 1.21 + * 1.22 + * 1. Redistributions of source code must retain the above copyright 1.23 + * notice, this list of conditions and the following disclaimer. 1.24 + * 2. Redistributions in binary form must reproduce the above copyright 1.25 + * notice, this list of conditions and the following disclaimer in the 1.26 + * documentation and/or other materials provided with the distribution. 1.27 + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 1.28 + * its contributors may be used to endorse or promote products derived 1.29 + * from this software without specific prior written permission. 1.30 + * 1.31 + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 1.32 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1.33 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1.34 + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 1.35 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1.36 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 1.37 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 1.38 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.39 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1.40 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.41 + * 1.42 + * ***** END LICENSE BLOCK ***** */ 1.43 + 1.44 +#ifdef MOZ_LOGGING 1.45 +#define FORCE_PR_LOG /* Allow logging in the release build */ 1.46 +#endif 1.47 +#include "prlog.h" 1.48 + 1.49 +#include <algorithm> 1.50 + 1.51 +#import <AppKit/AppKit.h> 1.52 + 1.53 +#include "gfxPlatformMac.h" 1.54 +#include "gfxMacPlatformFontList.h" 1.55 +#include "gfxMacFont.h" 1.56 +#include "gfxUserFontSet.h" 1.57 +#include "harfbuzz/hb.h" 1.58 + 1.59 +#include "nsServiceManagerUtils.h" 1.60 +#include "nsTArray.h" 1.61 + 1.62 +#include "nsDirectoryServiceUtils.h" 1.63 +#include "nsDirectoryServiceDefs.h" 1.64 +#include "nsISimpleEnumerator.h" 1.65 +#include "nsCharTraits.h" 1.66 +#include "nsCocoaFeatures.h" 1.67 +#include "gfxFontConstants.h" 1.68 + 1.69 +#include "mozilla/MemoryReporting.h" 1.70 +#include "mozilla/Preferences.h" 1.71 +#include "mozilla/Telemetry.h" 1.72 +#include "mozilla/gfx/2D.h" 1.73 + 1.74 +#include <unistd.h> 1.75 +#include <time.h> 1.76 + 1.77 +using namespace mozilla; 1.78 + 1.79 +class nsAutoreleasePool { 1.80 +public: 1.81 + nsAutoreleasePool() 1.82 + { 1.83 + mLocalPool = [[NSAutoreleasePool alloc] init]; 1.84 + } 1.85 + ~nsAutoreleasePool() 1.86 + { 1.87 + [mLocalPool release]; 1.88 + } 1.89 +private: 1.90 + NSAutoreleasePool *mLocalPool; 1.91 +}; 1.92 + 1.93 +// indexes into the NSArray objects that the Cocoa font manager returns 1.94 +// as the available members of a family 1.95 +#define INDEX_FONT_POSTSCRIPT_NAME 0 1.96 +#define INDEX_FONT_FACE_NAME 1 1.97 +#define INDEX_FONT_WEIGHT 2 1.98 +#define INDEX_FONT_TRAITS 3 1.99 + 1.100 +static const int kAppleMaxWeight = 14; 1.101 +static const int kAppleExtraLightWeight = 3; 1.102 +static const int kAppleUltraLightWeight = 2; 1.103 + 1.104 +static const int gAppleWeightToCSSWeight[] = { 1.105 + 0, 1.106 + 1, // 1. 1.107 + 1, // 2. W1, ultralight 1.108 + 2, // 3. W2, extralight 1.109 + 3, // 4. W3, light 1.110 + 4, // 5. W4, semilight 1.111 + 5, // 6. W5, medium 1.112 + 6, // 7. 1.113 + 6, // 8. W6, semibold 1.114 + 7, // 9. W7, bold 1.115 + 8, // 10. W8, extrabold 1.116 + 8, // 11. 1.117 + 9, // 12. W9, ultrabold 1.118 + 9, // 13 1.119 + 9 // 14 1.120 +}; 1.121 + 1.122 +// cache Cocoa's "shared font manager" for performance 1.123 +static NSFontManager *sFontManager; 1.124 + 1.125 +static void GetStringForNSString(const NSString *aSrc, nsAString& aDist) 1.126 +{ 1.127 + aDist.SetLength([aSrc length]); 1.128 + [aSrc getCharacters:reinterpret_cast<unichar*>(aDist.BeginWriting())]; 1.129 +} 1.130 + 1.131 +static NSString* GetNSStringForString(const nsAString& aSrc) 1.132 +{ 1.133 + return [NSString stringWithCharacters:reinterpret_cast<const unichar*>(aSrc.BeginReading()) 1.134 + length:aSrc.Length()]; 1.135 +} 1.136 + 1.137 +#ifdef PR_LOGGING 1.138 + 1.139 +#define LOG_FONTLIST(args) PR_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \ 1.140 + PR_LOG_DEBUG, args) 1.141 +#define LOG_FONTLIST_ENABLED() PR_LOG_TEST( \ 1.142 + gfxPlatform::GetLog(eGfxLog_fontlist), \ 1.143 + PR_LOG_DEBUG) 1.144 +#define LOG_CMAPDATA_ENABLED() PR_LOG_TEST( \ 1.145 + gfxPlatform::GetLog(eGfxLog_cmapdata), \ 1.146 + PR_LOG_DEBUG) 1.147 + 1.148 +#endif // PR_LOGGING 1.149 + 1.150 +#pragma mark- 1.151 + 1.152 +// Complex scripts will not render correctly unless appropriate AAT or OT 1.153 +// layout tables are present. 1.154 +// For OpenType, we also check that the GSUB table supports the relevant 1.155 +// script tag, to avoid using things like Arial Unicode MS for Lao (it has 1.156 +// the characters, but lacks OpenType support). 1.157 + 1.158 +// TODO: consider whether we should move this to gfxFontEntry and do similar 1.159 +// cmap-masking on other platforms to avoid using fonts that won't shape 1.160 +// properly. 1.161 + 1.162 +nsresult 1.163 +MacOSFontEntry::ReadCMAP(FontInfoData *aFontInfoData) 1.164 +{ 1.165 + // attempt this once, if errors occur leave a blank cmap 1.166 + if (mCharacterMap) { 1.167 + return NS_OK; 1.168 + } 1.169 + 1.170 + nsRefPtr<gfxCharacterMap> charmap; 1.171 + nsresult rv; 1.172 + bool symbolFont; 1.173 + 1.174 + if (aFontInfoData && (charmap = GetCMAPFromFontInfo(aFontInfoData, 1.175 + mUVSOffset, 1.176 + symbolFont))) { 1.177 + rv = NS_OK; 1.178 + } else { 1.179 + uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p'); 1.180 + charmap = new gfxCharacterMap(); 1.181 + AutoTable cmapTable(this, kCMAP); 1.182 + 1.183 + if (cmapTable) { 1.184 + bool unicodeFont = false, symbolFont = false; // currently ignored 1.185 + uint32_t cmapLen; 1.186 + const uint8_t* cmapData = 1.187 + reinterpret_cast<const uint8_t*>(hb_blob_get_data(cmapTable, 1.188 + &cmapLen)); 1.189 + rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen, 1.190 + *charmap, mUVSOffset, 1.191 + unicodeFont, symbolFont); 1.192 + } else { 1.193 + rv = NS_ERROR_NOT_AVAILABLE; 1.194 + } 1.195 + } 1.196 + 1.197 + if (NS_SUCCEEDED(rv) && !HasGraphiteTables()) { 1.198 + // We assume a Graphite font knows what it's doing, 1.199 + // and provides whatever shaping is needed for the 1.200 + // characters it supports, so only check/clear the 1.201 + // complex-script ranges for non-Graphite fonts 1.202 + 1.203 + // for layout support, check for the presence of mort/morx and/or 1.204 + // opentype layout tables 1.205 + bool hasAATLayout = HasFontTable(TRUETYPE_TAG('m','o','r','x')) || 1.206 + HasFontTable(TRUETYPE_TAG('m','o','r','t')); 1.207 + bool hasGSUB = HasFontTable(TRUETYPE_TAG('G','S','U','B')); 1.208 + bool hasGPOS = HasFontTable(TRUETYPE_TAG('G','P','O','S')); 1.209 + if (hasAATLayout && !(hasGSUB || hasGPOS)) { 1.210 + mRequiresAAT = true; // prefer CoreText if font has no OTL tables 1.211 + } 1.212 + 1.213 + for (const ScriptRange* sr = gfxPlatformFontList::sComplexScriptRanges; 1.214 + sr->rangeStart; sr++) { 1.215 + // check to see if the cmap includes complex script codepoints 1.216 + if (charmap->TestRange(sr->rangeStart, sr->rangeEnd)) { 1.217 + if (hasAATLayout) { 1.218 + // prefer CoreText for Apple's complex-script fonts, 1.219 + // even if they also have some OpenType tables 1.220 + // (e.g. Geeza Pro Bold on 10.6; see bug 614903) 1.221 + mRequiresAAT = true; 1.222 + // and don't mask off complex-script ranges, we assume 1.223 + // the AAT tables will provide the necessary shaping 1.224 + continue; 1.225 + } 1.226 + 1.227 + // We check for GSUB here, as GPOS alone would not be ok. 1.228 + if (hasGSUB && SupportsScriptInGSUB(sr->tags)) { 1.229 + continue; 1.230 + } 1.231 + 1.232 + charmap->ClearRange(sr->rangeStart, sr->rangeEnd); 1.233 + } 1.234 + } 1.235 + } 1.236 + 1.237 + mHasCmapTable = NS_SUCCEEDED(rv); 1.238 + if (mHasCmapTable) { 1.239 + gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList(); 1.240 + mCharacterMap = pfl->FindCharMap(charmap); 1.241 + } else { 1.242 + // if error occurred, initialize to null cmap 1.243 + mCharacterMap = new gfxCharacterMap(); 1.244 + } 1.245 + 1.246 +#ifdef PR_LOGGING 1.247 + LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n", 1.248 + NS_ConvertUTF16toUTF8(mName).get(), 1.249 + charmap->SizeOfIncludingThis(moz_malloc_size_of), 1.250 + charmap->mHash, mCharacterMap == charmap ? " new" : "")); 1.251 + if (LOG_CMAPDATA_ENABLED()) { 1.252 + char prefix[256]; 1.253 + sprintf(prefix, "(cmapdata) name: %.220s", 1.254 + NS_ConvertUTF16toUTF8(mName).get()); 1.255 + charmap->Dump(prefix, eGfxLog_cmapdata); 1.256 + } 1.257 +#endif 1.258 + 1.259 + return rv; 1.260 +} 1.261 + 1.262 +gfxFont* 1.263 +MacOSFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) 1.264 +{ 1.265 + return new gfxMacFont(this, aFontStyle, aNeedsBold); 1.266 +} 1.267 + 1.268 +bool 1.269 +MacOSFontEntry::IsCFF() 1.270 +{ 1.271 + if (!mIsCFFInitialized) { 1.272 + mIsCFFInitialized = true; 1.273 + mIsCFF = HasFontTable(TRUETYPE_TAG('C','F','F',' ')); 1.274 + } 1.275 + 1.276 + return mIsCFF; 1.277 +} 1.278 + 1.279 +MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, 1.280 + int32_t aWeight, 1.281 + bool aIsStandardFace) 1.282 + : gfxFontEntry(aPostscriptName, aIsStandardFace), 1.283 + mFontRef(NULL), 1.284 + mFontRefInitialized(false), 1.285 + mRequiresAAT(false), 1.286 + mIsCFF(false), 1.287 + mIsCFFInitialized(false) 1.288 +{ 1.289 + mWeight = aWeight; 1.290 +} 1.291 + 1.292 +MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, 1.293 + CGFontRef aFontRef, 1.294 + uint16_t aWeight, uint16_t aStretch, 1.295 + uint32_t aItalicStyle, 1.296 + bool aIsUserFont, bool aIsLocal) 1.297 + : gfxFontEntry(aPostscriptName, false), 1.298 + mFontRef(NULL), 1.299 + mFontRefInitialized(false), 1.300 + mRequiresAAT(false), 1.301 + mIsCFF(false), 1.302 + mIsCFFInitialized(false) 1.303 +{ 1.304 + mFontRef = aFontRef; 1.305 + mFontRefInitialized = true; 1.306 + ::CFRetain(mFontRef); 1.307 + 1.308 + mWeight = aWeight; 1.309 + mStretch = aStretch; 1.310 + mFixedPitch = false; // xxx - do we need this for downloaded fonts? 1.311 + mItalic = (aItalicStyle & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE)) != 0; 1.312 + mIsUserFont = aIsUserFont; 1.313 + mIsLocalUserFont = aIsLocal; 1.314 +} 1.315 + 1.316 +CGFontRef 1.317 +MacOSFontEntry::GetFontRef() 1.318 +{ 1.319 + if (!mFontRefInitialized) { 1.320 + mFontRefInitialized = true; 1.321 + NSString *psname = GetNSStringForString(mName); 1.322 + mFontRef = ::CGFontCreateWithFontName(CFStringRef(psname)); 1.323 + } 1.324 + return mFontRef; 1.325 +} 1.326 + 1.327 +/*static*/ void 1.328 +MacOSFontEntry::DestroyBlobFunc(void* aUserData) 1.329 +{ 1.330 + ::CFRelease((CFDataRef)aUserData); 1.331 +} 1.332 + 1.333 +hb_blob_t * 1.334 +MacOSFontEntry::GetFontTable(uint32_t aTag) 1.335 +{ 1.336 + CGFontRef fontRef = GetFontRef(); 1.337 + if (!fontRef) { 1.338 + return nullptr; 1.339 + } 1.340 + 1.341 + CFDataRef dataRef = ::CGFontCopyTableForTag(fontRef, aTag); 1.342 + if (dataRef) { 1.343 + return hb_blob_create((const char*)::CFDataGetBytePtr(dataRef), 1.344 + ::CFDataGetLength(dataRef), 1.345 + HB_MEMORY_MODE_READONLY, 1.346 + (void*)dataRef, DestroyBlobFunc); 1.347 + } 1.348 + 1.349 + return nullptr; 1.350 +} 1.351 + 1.352 +bool 1.353 +MacOSFontEntry::HasFontTable(uint32_t aTableTag) 1.354 +{ 1.355 + nsAutoreleasePool localPool; 1.356 + 1.357 + CGFontRef fontRef = GetFontRef(); 1.358 + if (!fontRef) { 1.359 + return false; 1.360 + } 1.361 + 1.362 + CFDataRef tableData = ::CGFontCopyTableForTag(fontRef, aTableTag); 1.363 + if (!tableData) { 1.364 + return false; 1.365 + } 1.366 + 1.367 + ::CFRelease(tableData); 1.368 + return true; 1.369 +} 1.370 + 1.371 +void 1.372 +MacOSFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, 1.373 + FontListSizes* aSizes) const 1.374 +{ 1.375 + aSizes->mFontListSize += aMallocSizeOf(this); 1.376 + AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.377 +} 1.378 + 1.379 +/* gfxMacFontFamily */ 1.380 +#pragma mark- 1.381 + 1.382 +class gfxMacFontFamily : public gfxFontFamily 1.383 +{ 1.384 +public: 1.385 + gfxMacFontFamily(nsAString& aName) : 1.386 + gfxFontFamily(aName) 1.387 + {} 1.388 + 1.389 + virtual ~gfxMacFontFamily() {} 1.390 + 1.391 + virtual void LocalizedName(nsAString& aLocalizedName); 1.392 + 1.393 + virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr); 1.394 +}; 1.395 + 1.396 +void 1.397 +gfxMacFontFamily::LocalizedName(nsAString& aLocalizedName) 1.398 +{ 1.399 + nsAutoreleasePool localPool; 1.400 + 1.401 + if (!HasOtherFamilyNames()) { 1.402 + aLocalizedName = mName; 1.403 + return; 1.404 + } 1.405 + 1.406 + NSString *family = GetNSStringForString(mName); 1.407 + NSString *localized = [sFontManager 1.408 + localizedNameForFamily:family 1.409 + face:nil]; 1.410 + 1.411 + if (localized) { 1.412 + GetStringForNSString(localized, aLocalizedName); 1.413 + return; 1.414 + } 1.415 + 1.416 + // failed to get localized name, just use the canonical one 1.417 + aLocalizedName = mName; 1.418 +} 1.419 + 1.420 +// Return the CSS weight value to use for the given face, overriding what 1.421 +// AppKit gives us (used to adjust families with bad weight values, see 1.422 +// bug 931426). 1.423 +// A return value of 0 indicates no override - use the existing weight. 1.424 +static inline int 1.425 +GetWeightOverride(const nsAString& aPSName) 1.426 +{ 1.427 + nsAutoCString prefName("font.weight-override."); 1.428 + // The PostScript name is required to be ASCII; if it's not, the font is 1.429 + // broken anyway, so we really don't care that this is lossy. 1.430 + LossyAppendUTF16toASCII(aPSName, prefName); 1.431 + return Preferences::GetInt(prefName.get(), 0); 1.432 +} 1.433 + 1.434 +void 1.435 +gfxMacFontFamily::FindStyleVariations(FontInfoData *aFontInfoData) 1.436 +{ 1.437 + if (mHasStyles) 1.438 + return; 1.439 + 1.440 + nsAutoreleasePool localPool; 1.441 + 1.442 + NSString *family = GetNSStringForString(mName); 1.443 + 1.444 + // create a font entry for each face 1.445 + NSArray *fontfaces = [sFontManager 1.446 + availableMembersOfFontFamily:family]; // returns an array of [psname, style name, weight, traits] elements, goofy api 1.447 + int faceCount = [fontfaces count]; 1.448 + int faceIndex; 1.449 + 1.450 + for (faceIndex = 0; faceIndex < faceCount; faceIndex++) { 1.451 + NSArray *face = [fontfaces objectAtIndex:faceIndex]; 1.452 + NSString *psname = [face objectAtIndex:INDEX_FONT_POSTSCRIPT_NAME]; 1.453 + int32_t appKitWeight = [[face objectAtIndex:INDEX_FONT_WEIGHT] unsignedIntValue]; 1.454 + uint32_t macTraits = [[face objectAtIndex:INDEX_FONT_TRAITS] unsignedIntValue]; 1.455 + NSString *facename = [face objectAtIndex:INDEX_FONT_FACE_NAME]; 1.456 + bool isStandardFace = false; 1.457 + 1.458 + if (appKitWeight == kAppleExtraLightWeight) { 1.459 + // if the facename contains UltraLight, set the weight to the ultralight weight value 1.460 + NSRange range = [facename rangeOfString:@"ultralight" options:NSCaseInsensitiveSearch]; 1.461 + if (range.location != NSNotFound) { 1.462 + appKitWeight = kAppleUltraLightWeight; 1.463 + } 1.464 + } 1.465 + 1.466 + // make a nsString 1.467 + nsAutoString postscriptFontName; 1.468 + GetStringForNSString(psname, postscriptFontName); 1.469 + 1.470 + int32_t cssWeight = GetWeightOverride(postscriptFontName); 1.471 + if (cssWeight) { 1.472 + // scale down and clamp, to get a value from 1..9 1.473 + cssWeight = ((cssWeight + 50) / 100); 1.474 + cssWeight = std::max(1, std::min(cssWeight, 9)); 1.475 + } else { 1.476 + cssWeight = 1.477 + gfxMacPlatformFontList::AppleWeightToCSSWeight(appKitWeight); 1.478 + } 1.479 + cssWeight *= 100; // scale up to CSS values 1.480 + 1.481 + if ([facename isEqualToString:@"Regular"] || 1.482 + [facename isEqualToString:@"Bold"] || 1.483 + [facename isEqualToString:@"Italic"] || 1.484 + [facename isEqualToString:@"Oblique"] || 1.485 + [facename isEqualToString:@"Bold Italic"] || 1.486 + [facename isEqualToString:@"Bold Oblique"]) 1.487 + { 1.488 + isStandardFace = true; 1.489 + } 1.490 + 1.491 + // create a font entry 1.492 + MacOSFontEntry *fontEntry = 1.493 + new MacOSFontEntry(postscriptFontName, cssWeight, isStandardFace); 1.494 + if (!fontEntry) { 1.495 + break; 1.496 + } 1.497 + 1.498 + // set additional properties based on the traits reported by Cocoa 1.499 + if (macTraits & (NSCondensedFontMask | NSNarrowFontMask | NSCompressedFontMask)) { 1.500 + fontEntry->mStretch = NS_FONT_STRETCH_CONDENSED; 1.501 + } else if (macTraits & NSExpandedFontMask) { 1.502 + fontEntry->mStretch = NS_FONT_STRETCH_EXPANDED; 1.503 + } 1.504 + // Cocoa fails to set the Italic traits bit for HelveticaLightItalic, 1.505 + // at least (see bug 611855), so check for style name endings as well 1.506 + if ((macTraits & NSItalicFontMask) || 1.507 + [facename hasSuffix:@"Italic"] || 1.508 + [facename hasSuffix:@"Oblique"]) 1.509 + { 1.510 + fontEntry->mItalic = true; 1.511 + } 1.512 + if (macTraits & NSFixedPitchFontMask) { 1.513 + fontEntry->mFixedPitch = true; 1.514 + } 1.515 + 1.516 +#ifdef PR_LOGGING 1.517 + if (LOG_FONTLIST_ENABLED()) { 1.518 + LOG_FONTLIST(("(fontlist) added (%s) to family (%s)" 1.519 + " with style: %s weight: %d stretch: %d" 1.520 + " (apple-weight: %d macTraits: %8.8x)", 1.521 + NS_ConvertUTF16toUTF8(fontEntry->Name()).get(), 1.522 + NS_ConvertUTF16toUTF8(Name()).get(), 1.523 + fontEntry->IsItalic() ? "italic" : "normal", 1.524 + cssWeight, fontEntry->Stretch(), 1.525 + appKitWeight, macTraits)); 1.526 + } 1.527 +#endif 1.528 + 1.529 + // insert into font entry array of family 1.530 + AddFontEntry(fontEntry); 1.531 + } 1.532 + 1.533 + SortAvailableFonts(); 1.534 + SetHasStyles(true); 1.535 + 1.536 + if (mIsBadUnderlineFamily) { 1.537 + SetBadUnderlineFonts(); 1.538 + } 1.539 +} 1.540 + 1.541 + 1.542 +/* gfxSingleFaceMacFontFamily */ 1.543 +#pragma mark- 1.544 + 1.545 +class gfxSingleFaceMacFontFamily : public gfxFontFamily 1.546 +{ 1.547 +public: 1.548 + gfxSingleFaceMacFontFamily(nsAString& aName) : 1.549 + gfxFontFamily(aName) 1.550 + { 1.551 + mFaceNamesInitialized = true; // omit from face name lists 1.552 + } 1.553 + 1.554 + virtual ~gfxSingleFaceMacFontFamily() {} 1.555 + 1.556 + virtual void LocalizedName(nsAString& aLocalizedName); 1.557 + 1.558 + virtual void ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList); 1.559 +}; 1.560 + 1.561 +void 1.562 +gfxSingleFaceMacFontFamily::LocalizedName(nsAString& aLocalizedName) 1.563 +{ 1.564 + nsAutoreleasePool localPool; 1.565 + 1.566 + if (!HasOtherFamilyNames()) { 1.567 + aLocalizedName = mName; 1.568 + return; 1.569 + } 1.570 + 1.571 + gfxFontEntry *fe = mAvailableFonts[0]; 1.572 + NSFont *font = [NSFont fontWithName:GetNSStringForString(fe->Name()) 1.573 + size:0.0]; 1.574 + if (font) { 1.575 + NSString *localized = [font displayName]; 1.576 + if (localized) { 1.577 + GetStringForNSString(localized, aLocalizedName); 1.578 + return; 1.579 + } 1.580 + } 1.581 + 1.582 + // failed to get localized name, just use the canonical one 1.583 + aLocalizedName = mName; 1.584 +} 1.585 + 1.586 +void 1.587 +gfxSingleFaceMacFontFamily::ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList) 1.588 +{ 1.589 + if (mOtherFamilyNamesInitialized) { 1.590 + return; 1.591 + } 1.592 + 1.593 + gfxFontEntry *fe = mAvailableFonts[0]; 1.594 + if (!fe) { 1.595 + return; 1.596 + } 1.597 + 1.598 + const uint32_t kNAME = TRUETYPE_TAG('n','a','m','e'); 1.599 + 1.600 + gfxFontEntry::AutoTable nameTable(fe, kNAME); 1.601 + if (!nameTable) { 1.602 + return; 1.603 + } 1.604 + 1.605 + mHasOtherFamilyNames = ReadOtherFamilyNamesForFace(aPlatformFontList, 1.606 + nameTable, 1.607 + true); 1.608 + 1.609 + mOtherFamilyNamesInitialized = true; 1.610 +} 1.611 + 1.612 + 1.613 +/* gfxMacPlatformFontList */ 1.614 +#pragma mark- 1.615 + 1.616 +gfxMacPlatformFontList::gfxMacPlatformFontList() : 1.617 + gfxPlatformFontList(false), 1.618 + mDefaultFont(nullptr) 1.619 +{ 1.620 + ::CFNotificationCenterAddObserver(::CFNotificationCenterGetLocalCenter(), 1.621 + this, 1.622 + RegisteredFontsChangedNotificationCallback, 1.623 + kCTFontManagerRegisteredFontsChangedNotification, 1.624 + 0, 1.625 + CFNotificationSuspensionBehaviorDeliverImmediately); 1.626 + 1.627 + // cache this in a static variable so that MacOSFontFamily objects 1.628 + // don't have to repeatedly look it up 1.629 + sFontManager = [NSFontManager sharedFontManager]; 1.630 +} 1.631 + 1.632 +gfxMacPlatformFontList::~gfxMacPlatformFontList() 1.633 +{ 1.634 + if (mDefaultFont) { 1.635 + ::CFRelease(mDefaultFont); 1.636 + } 1.637 +} 1.638 + 1.639 +nsresult 1.640 +gfxMacPlatformFontList::InitFontList() 1.641 +{ 1.642 + nsAutoreleasePool localPool; 1.643 + 1.644 + Telemetry::AutoTimer<Telemetry::MAC_INITFONTLIST_TOTAL> timer; 1.645 + 1.646 + // reset font lists 1.647 + gfxPlatformFontList::InitFontList(); 1.648 + 1.649 + // iterate over available families 1.650 + 1.651 + CFArrayRef familyNames = CTFontManagerCopyAvailableFontFamilyNames(); 1.652 + 1.653 + // iterate over families 1.654 + uint32_t i, numFamilies; 1.655 + 1.656 + numFamilies = CFArrayGetCount(familyNames); 1.657 + for (i = 0; i < numFamilies; i++) { 1.658 + CFStringRef family = (CFStringRef)CFArrayGetValueAtIndex(familyNames, i); 1.659 + 1.660 + // CTFontManager includes weird internal family names and 1.661 + // LastResort, skip over those 1.662 + if (!family || 1.663 + ::CFStringHasPrefix(family, CFSTR(".")) || 1.664 + CFStringCompare(family, CFSTR("LastResort"), 1.665 + kCFCompareCaseInsensitive) == kCFCompareEqualTo) { 1.666 + continue; 1.667 + } 1.668 + 1.669 + nsAutoTArray<UniChar, 1024> buffer; 1.670 + CFIndex len = ::CFStringGetLength(family); 1.671 + buffer.SetLength(len+1); 1.672 + ::CFStringGetCharacters(family, ::CFRangeMake(0, len), 1.673 + buffer.Elements()); 1.674 + buffer[len] = 0; 1.675 + nsAutoString familyName(reinterpret_cast<char16_t*>(buffer.Elements()), len); 1.676 + 1.677 + // create a family entry 1.678 + gfxFontFamily *familyEntry = new gfxMacFontFamily(familyName); 1.679 + if (!familyEntry) break; 1.680 + 1.681 + // add the family entry to the hash table 1.682 + ToLowerCase(familyName); 1.683 + mFontFamilies.Put(familyName, familyEntry); 1.684 + 1.685 + // check the bad underline blacklist 1.686 + if (mBadUnderlineFamilyNames.Contains(familyName)) 1.687 + familyEntry->SetBadUnderlineFamily(); 1.688 + } 1.689 + 1.690 + CFRelease(familyNames); 1.691 + 1.692 + InitSingleFaceList(); 1.693 + 1.694 + // to avoid full search of font name tables, seed the other names table with localized names from 1.695 + // some of the prefs fonts which are accessed via their localized names. changes in the pref fonts will only cause 1.696 + // a font lookup miss earlier. this is a simple optimization, it's not required for correctness 1.697 + PreloadNamesList(); 1.698 + 1.699 + // start the delayed cmap loader 1.700 + GetPrefsAndStartLoader(); 1.701 + 1.702 + return NS_OK; 1.703 +} 1.704 + 1.705 +void 1.706 +gfxMacPlatformFontList::InitSingleFaceList() 1.707 +{ 1.708 + nsAutoTArray<nsString, 10> singleFaceFonts; 1.709 + gfxFontUtils::GetPrefsFontList("font.single-face-list", singleFaceFonts); 1.710 + 1.711 + uint32_t numFonts = singleFaceFonts.Length(); 1.712 + for (uint32_t i = 0; i < numFonts; i++) { 1.713 +#ifdef PR_LOGGING 1.714 + LOG_FONTLIST(("(fontlist-singleface) face name: %s\n", 1.715 + NS_ConvertUTF16toUTF8(singleFaceFonts[i]).get())); 1.716 +#endif 1.717 + gfxFontEntry *fontEntry = LookupLocalFont(nullptr, singleFaceFonts[i]); 1.718 + if (fontEntry) { 1.719 + nsAutoString familyName, key; 1.720 + familyName = singleFaceFonts[i]; 1.721 + GenerateFontListKey(familyName, key); 1.722 +#ifdef PR_LOGGING 1.723 + LOG_FONTLIST(("(fontlist-singleface) family name: %s, key: %s\n", 1.724 + NS_ConvertUTF16toUTF8(familyName).get(), 1.725 + NS_ConvertUTF16toUTF8(key).get())); 1.726 +#endif 1.727 + 1.728 + // add only if doesn't exist already 1.729 + if (!mFontFamilies.GetWeak(key)) { 1.730 + gfxFontFamily *familyEntry = 1.731 + new gfxSingleFaceMacFontFamily(familyName); 1.732 + familyEntry->AddFontEntry(fontEntry); 1.733 + familyEntry->SetHasStyles(true); 1.734 + mFontFamilies.Put(key, familyEntry); 1.735 +#ifdef PR_LOGGING 1.736 + LOG_FONTLIST(("(fontlist-singleface) added new family\n", 1.737 + NS_ConvertUTF16toUTF8(familyName).get(), 1.738 + NS_ConvertUTF16toUTF8(key).get())); 1.739 +#endif 1.740 + } 1.741 + } 1.742 + } 1.743 +} 1.744 + 1.745 +bool 1.746 +gfxMacPlatformFontList::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) 1.747 +{ 1.748 + gfxFontFamily *family = FindFamily(aFontName); 1.749 + if (family) { 1.750 + family->LocalizedName(aFamilyName); 1.751 + return true; 1.752 + } 1.753 + 1.754 + return false; 1.755 +} 1.756 + 1.757 +void 1.758 +gfxMacPlatformFontList::RegisteredFontsChangedNotificationCallback(CFNotificationCenterRef center, 1.759 + void *observer, 1.760 + CFStringRef name, 1.761 + const void *object, 1.762 + CFDictionaryRef userInfo) 1.763 +{ 1.764 + if (!::CFEqual(name, kCTFontManagerRegisteredFontsChangedNotification)) { 1.765 + return; 1.766 + } 1.767 + 1.768 + gfxMacPlatformFontList* fl = static_cast<gfxMacPlatformFontList*>(observer); 1.769 + 1.770 + // xxx - should be carefully pruning the list of fonts, not rebuilding it from scratch 1.771 + fl->UpdateFontList(); 1.772 + 1.773 + // modify a preference that will trigger reflow everywhere 1.774 + fl->ForceGlobalReflow(); 1.775 +} 1.776 + 1.777 +gfxFontEntry* 1.778 +gfxMacPlatformFontList::GlobalFontFallback(const uint32_t aCh, 1.779 + int32_t aRunScript, 1.780 + const gfxFontStyle* aMatchStyle, 1.781 + uint32_t& aCmapCount, 1.782 + gfxFontFamily** aMatchedFamily) 1.783 +{ 1.784 + bool useCmaps = gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); 1.785 + 1.786 + if (useCmaps) { 1.787 + return gfxPlatformFontList::GlobalFontFallback(aCh, 1.788 + aRunScript, 1.789 + aMatchStyle, 1.790 + aCmapCount, 1.791 + aMatchedFamily); 1.792 + } 1.793 + 1.794 + CFStringRef str; 1.795 + UniChar ch[2]; 1.796 + CFIndex len = 1; 1.797 + 1.798 + if (IS_IN_BMP(aCh)) { 1.799 + ch[0] = aCh; 1.800 + str = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, ch, 1, 1.801 + kCFAllocatorNull); 1.802 + } else { 1.803 + ch[0] = H_SURROGATE(aCh); 1.804 + ch[1] = L_SURROGATE(aCh); 1.805 + str = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, ch, 2, 1.806 + kCFAllocatorNull); 1.807 + if (!str) { 1.808 + return nullptr; 1.809 + } 1.810 + len = 2; 1.811 + } 1.812 + 1.813 + // use CoreText to find the fallback family 1.814 + 1.815 + gfxFontEntry *fontEntry = nullptr; 1.816 + CTFontRef fallback; 1.817 + bool cantUseFallbackFont = false; 1.818 + 1.819 + if (!mDefaultFont) { 1.820 + mDefaultFont = ::CTFontCreateWithName(CFSTR("LucidaGrande"), 12.f, 1.821 + NULL); 1.822 + } 1.823 + 1.824 + fallback = ::CTFontCreateForString(mDefaultFont, str, 1.825 + ::CFRangeMake(0, len)); 1.826 + 1.827 + if (fallback) { 1.828 + CFStringRef familyName = ::CTFontCopyFamilyName(fallback); 1.829 + ::CFRelease(fallback); 1.830 + 1.831 + if (familyName && 1.832 + ::CFStringCompare(familyName, CFSTR("LastResort"), 1.833 + kCFCompareCaseInsensitive) != kCFCompareEqualTo) 1.834 + { 1.835 + nsAutoTArray<UniChar, 1024> buffer; 1.836 + CFIndex len = ::CFStringGetLength(familyName); 1.837 + buffer.SetLength(len+1); 1.838 + ::CFStringGetCharacters(familyName, ::CFRangeMake(0, len), 1.839 + buffer.Elements()); 1.840 + buffer[len] = 0; 1.841 + nsDependentString familyName(reinterpret_cast<char16_t*>(buffer.Elements()), len); 1.842 + 1.843 + bool needsBold; // ignored in the system fallback case 1.844 + 1.845 + gfxFontFamily *family = FindFamily(familyName); 1.846 + if (family) { 1.847 + fontEntry = family->FindFontForStyle(*aMatchStyle, needsBold); 1.848 + if (fontEntry) { 1.849 + if (fontEntry->TestCharacterMap(aCh)) { 1.850 + *aMatchedFamily = family; 1.851 + } else { 1.852 + fontEntry = nullptr; 1.853 + cantUseFallbackFont = true; 1.854 + } 1.855 + } 1.856 + } 1.857 + } 1.858 + 1.859 + if (familyName) { 1.860 + ::CFRelease(familyName); 1.861 + } 1.862 + } 1.863 + 1.864 + if (cantUseFallbackFont) { 1.865 + Telemetry::Accumulate(Telemetry::BAD_FALLBACK_FONT, cantUseFallbackFont); 1.866 + } 1.867 + 1.868 + ::CFRelease(str); 1.869 + 1.870 + return fontEntry; 1.871 +} 1.872 + 1.873 +gfxFontFamily* 1.874 +gfxMacPlatformFontList::GetDefaultFont(const gfxFontStyle* aStyle) 1.875 +{ 1.876 + nsAutoreleasePool localPool; 1.877 + 1.878 + NSString *defaultFamily = [[NSFont userFontOfSize:aStyle->size] familyName]; 1.879 + nsAutoString familyName; 1.880 + 1.881 + GetStringForNSString(defaultFamily, familyName); 1.882 + return FindFamily(familyName); 1.883 +} 1.884 + 1.885 +int32_t 1.886 +gfxMacPlatformFontList::AppleWeightToCSSWeight(int32_t aAppleWeight) 1.887 +{ 1.888 + if (aAppleWeight < 1) 1.889 + aAppleWeight = 1; 1.890 + else if (aAppleWeight > kAppleMaxWeight) 1.891 + aAppleWeight = kAppleMaxWeight; 1.892 + return gAppleWeightToCSSWeight[aAppleWeight]; 1.893 +} 1.894 + 1.895 +gfxFontEntry* 1.896 +gfxMacPlatformFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, 1.897 + const nsAString& aFontName) 1.898 +{ 1.899 + nsAutoreleasePool localPool; 1.900 + 1.901 + NSString *faceName = GetNSStringForString(aFontName); 1.902 + MacOSFontEntry *newFontEntry; 1.903 + 1.904 + // lookup face based on postscript or full name 1.905 + CGFontRef fontRef = ::CGFontCreateWithFontName(CFStringRef(faceName)); 1.906 + if (!fontRef) { 1.907 + return nullptr; 1.908 + } 1.909 + 1.910 + if (aProxyEntry) { 1.911 + uint16_t w = aProxyEntry->mWeight; 1.912 + NS_ASSERTION(w >= 100 && w <= 900, "bogus font weight value!"); 1.913 + 1.914 + newFontEntry = 1.915 + new MacOSFontEntry(aFontName, fontRef, 1.916 + w, aProxyEntry->mStretch, 1.917 + aProxyEntry->mItalic ? 1.918 + NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL, 1.919 + true, true); 1.920 + } else { 1.921 + newFontEntry = 1.922 + new MacOSFontEntry(aFontName, fontRef, 1.923 + 400, 0, NS_FONT_STYLE_NORMAL, 1.924 + false, false); 1.925 + } 1.926 + ::CFRelease(fontRef); 1.927 + 1.928 + return newFontEntry; 1.929 +} 1.930 + 1.931 +static void ReleaseData(void *info, const void *data, size_t size) 1.932 +{ 1.933 + NS_Free((void*)data); 1.934 +} 1.935 + 1.936 +gfxFontEntry* 1.937 +gfxMacPlatformFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, 1.938 + const uint8_t *aFontData, 1.939 + uint32_t aLength) 1.940 +{ 1.941 + NS_ASSERTION(aFontData, "MakePlatformFont called with null data"); 1.942 + 1.943 + uint16_t w = aProxyEntry->mWeight; 1.944 + NS_ASSERTION(w >= 100 && w <= 900, "bogus font weight value!"); 1.945 + 1.946 + // create the font entry 1.947 + nsAutoString uniqueName; 1.948 + 1.949 + nsresult rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName); 1.950 + if (NS_FAILED(rv)) { 1.951 + return nullptr; 1.952 + } 1.953 + 1.954 + CGDataProviderRef provider = 1.955 + ::CGDataProviderCreateWithData(nullptr, aFontData, aLength, 1.956 + &ReleaseData); 1.957 + CGFontRef fontRef = ::CGFontCreateWithDataProvider(provider); 1.958 + ::CGDataProviderRelease(provider); 1.959 + 1.960 + if (!fontRef) { 1.961 + return nullptr; 1.962 + } 1.963 + 1.964 + nsAutoPtr<MacOSFontEntry> 1.965 + newFontEntry(new MacOSFontEntry(uniqueName, fontRef, w, 1.966 + aProxyEntry->mStretch, 1.967 + aProxyEntry->mItalic ? 1.968 + NS_FONT_STYLE_ITALIC : 1.969 + NS_FONT_STYLE_NORMAL, 1.970 + true, false)); 1.971 + ::CFRelease(fontRef); 1.972 + 1.973 + // if succeeded and font cmap is good, return the new font 1.974 + if (newFontEntry->mIsValid && NS_SUCCEEDED(newFontEntry->ReadCMAP())) { 1.975 + return newFontEntry.forget(); 1.976 + } 1.977 + 1.978 + // if something is funky about this font, delete immediately 1.979 + 1.980 +#if DEBUG 1.981 + NS_WARNING("downloaded font not loaded properly"); 1.982 +#endif 1.983 + 1.984 + return nullptr; 1.985 +} 1.986 + 1.987 +// used to load system-wide font info on off-main thread 1.988 +class MacFontInfo : public FontInfoData { 1.989 +public: 1.990 + MacFontInfo(bool aLoadOtherNames, 1.991 + bool aLoadFaceNames, 1.992 + bool aLoadCmaps) : 1.993 + FontInfoData(aLoadOtherNames, aLoadFaceNames, aLoadCmaps) 1.994 + {} 1.995 + 1.996 + virtual ~MacFontInfo() {} 1.997 + 1.998 + virtual void Load() { 1.999 + nsAutoreleasePool localPool; 1.1000 + // bug 975460 - async font loader crashes sometimes under 10.6, disable 1.1001 + if (nsCocoaFeatures::OnLionOrLater()) { 1.1002 + FontInfoData::Load(); 1.1003 + } 1.1004 + } 1.1005 + 1.1006 + // loads font data for all members of a given family 1.1007 + virtual void LoadFontFamilyData(const nsAString& aFamilyName); 1.1008 +}; 1.1009 + 1.1010 +void 1.1011 +MacFontInfo::LoadFontFamilyData(const nsAString& aFamilyName) 1.1012 +{ 1.1013 + // family name ==> CTFontDescriptor 1.1014 + NSString *famName = GetNSStringForString(aFamilyName); 1.1015 + CFStringRef family = CFStringRef(famName); 1.1016 + 1.1017 + CFMutableDictionaryRef attr = 1.1018 + CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, 1.1019 + &kCFTypeDictionaryValueCallBacks); 1.1020 + CFDictionaryAddValue(attr, kCTFontFamilyNameAttribute, family); 1.1021 + CTFontDescriptorRef fd = CTFontDescriptorCreateWithAttributes(attr); 1.1022 + CFRelease(attr); 1.1023 + CFArrayRef matchingFonts = 1.1024 + CTFontDescriptorCreateMatchingFontDescriptors(fd, NULL); 1.1025 + CFRelease(fd); 1.1026 + if (!matchingFonts) { 1.1027 + return; 1.1028 + } 1.1029 + 1.1030 + nsTArray<nsString> otherFamilyNames; 1.1031 + bool hasOtherFamilyNames = true; 1.1032 + 1.1033 + // iterate over faces in the family 1.1034 + int f, numFaces = (int) CFArrayGetCount(matchingFonts); 1.1035 + for (f = 0; f < numFaces; f++) { 1.1036 + mLoadStats.fonts++; 1.1037 + 1.1038 + CTFontDescriptorRef faceDesc = 1.1039 + (CTFontDescriptorRef)CFArrayGetValueAtIndex(matchingFonts, f); 1.1040 + if (!faceDesc) { 1.1041 + continue; 1.1042 + } 1.1043 + CTFontRef fontRef = CTFontCreateWithFontDescriptor(faceDesc, 1.1044 + 0.0, nullptr); 1.1045 + if (!fontRef) { 1.1046 + NS_WARNING("failed to create a CTFontRef"); 1.1047 + continue; 1.1048 + } 1.1049 + 1.1050 + if (mLoadCmaps) { 1.1051 + // face name 1.1052 + CFStringRef faceName = (CFStringRef) 1.1053 + CTFontDescriptorCopyAttribute(faceDesc, kCTFontNameAttribute); 1.1054 + 1.1055 + nsAutoTArray<UniChar, 1024> buffer; 1.1056 + CFIndex len = CFStringGetLength(faceName); 1.1057 + buffer.SetLength(len+1); 1.1058 + CFStringGetCharacters(faceName, ::CFRangeMake(0, len), 1.1059 + buffer.Elements()); 1.1060 + buffer[len] = 0; 1.1061 + nsAutoString fontName(reinterpret_cast<char16_t*>(buffer.Elements()), 1.1062 + len); 1.1063 + 1.1064 + // load the cmap data 1.1065 + FontFaceData fontData; 1.1066 + CFDataRef cmapTable = CTFontCopyTable(fontRef, kCTFontTableCmap, 1.1067 + kCTFontTableOptionNoOptions); 1.1068 + 1.1069 + if (cmapTable) { 1.1070 + bool unicodeFont = false, symbolFont = false; // ignored 1.1071 + const uint8_t *cmapData = 1.1072 + (const uint8_t*)CFDataGetBytePtr(cmapTable); 1.1073 + uint32_t cmapLen = CFDataGetLength(cmapTable); 1.1074 + nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap(); 1.1075 + uint32_t offset; 1.1076 + nsresult rv; 1.1077 + 1.1078 + rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen, *charmap, offset, 1.1079 + unicodeFont, symbolFont); 1.1080 + if (NS_SUCCEEDED(rv)) { 1.1081 + fontData.mCharacterMap = charmap; 1.1082 + fontData.mUVSOffset = offset; 1.1083 + fontData.mSymbolFont = symbolFont; 1.1084 + mLoadStats.cmaps++; 1.1085 + } 1.1086 + CFRelease(cmapTable); 1.1087 + } 1.1088 + 1.1089 + mFontFaceData.Put(fontName, fontData); 1.1090 + CFRelease(faceName); 1.1091 + } 1.1092 + 1.1093 + if (mLoadOtherNames && hasOtherFamilyNames) { 1.1094 + CFDataRef nameTable = CTFontCopyTable(fontRef, kCTFontTableName, 1.1095 + kCTFontTableOptionNoOptions); 1.1096 + 1.1097 + if (nameTable) { 1.1098 + const char *nameData = (const char*)CFDataGetBytePtr(nameTable); 1.1099 + uint32_t nameLen = CFDataGetLength(nameTable); 1.1100 + gfxFontFamily::ReadOtherFamilyNamesForFace(aFamilyName, 1.1101 + nameData, nameLen, 1.1102 + otherFamilyNames, 1.1103 + false); 1.1104 + hasOtherFamilyNames = otherFamilyNames.Length() != 0; 1.1105 + CFRelease(nameTable); 1.1106 + } 1.1107 + } 1.1108 + 1.1109 + CFRelease(fontRef); 1.1110 + } 1.1111 + CFRelease(matchingFonts); 1.1112 + 1.1113 + // if found other names, insert them in the hash table 1.1114 + if (otherFamilyNames.Length() != 0) { 1.1115 + mOtherFamilyNames.Put(aFamilyName, otherFamilyNames); 1.1116 + mLoadStats.othernames += otherFamilyNames.Length(); 1.1117 + } 1.1118 +} 1.1119 + 1.1120 +already_AddRefed<FontInfoData> 1.1121 +gfxMacPlatformFontList::CreateFontInfoData() 1.1122 +{ 1.1123 + bool loadCmaps = !UsesSystemFallback() || 1.1124 + gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); 1.1125 + 1.1126 + nsRefPtr<MacFontInfo> fi = 1.1127 + new MacFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps); 1.1128 + return fi.forget(); 1.1129 +} 1.1130 +