gecko-dev/gfx/thebes/gfxMacPlatformFontList.mm

1858 строки
63 KiB
Plaintext
Исходник Обычный вид История

/* -*- Mode: ObjC; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: BSD
*
* Copyright (C) 2006-2009 Mozilla Corporation. All rights reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
* Masayuki Nakano <masayuki@d-toybox.com>
* John Daggett <jdaggett@mozilla.com>
* Jonathan Kew <jfkthame@gmail.com>
*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/Logging.h"
#include <algorithm>
#import <AppKit/AppKit.h>
#include "gfxPlatformMac.h"
#include "gfxMacPlatformFontList.h"
#include "gfxMacFont.h"
#include "gfxUserFontSet.h"
#include "harfbuzz/hb.h"
#include "MainThreadUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsTArray.h"
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsISimpleEnumerator.h"
#include "nsCharTraits.h"
#include "nsCocoaFeatures.h"
#include "nsCocoaUtils.h"
#include "gfxFontConstants.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Preferences.h"
#include "mozilla/Sprintf.h"
#include "mozilla/Telemetry.h"
#include "mozilla/gfx/2D.h"
#include <unistd.h>
#include <time.h>
#include <dlfcn.h>
using namespace mozilla;
using namespace mozilla::gfx;
using mozilla::dom::SystemFontListEntry;
using mozilla::dom::FontFamilyListEntry;
// indexes into the NSArray objects that the Cocoa font manager returns
// as the available members of a family
#define INDEX_FONT_POSTSCRIPT_NAME 0
#define INDEX_FONT_FACE_NAME 1
#define INDEX_FONT_WEIGHT 2
#define INDEX_FONT_TRAITS 3
static const int kAppleMaxWeight = 14;
static const int kAppleExtraLightWeight = 3;
static const int kAppleUltraLightWeight = 2;
static const int gAppleWeightToCSSWeight[] = {
0,
1, // 1.
1, // 2. W1, ultralight
2, // 3. W2, extralight
3, // 4. W3, light
4, // 5. W4, semilight
5, // 6. W5, medium
6, // 7.
6, // 8. W6, semibold
7, // 9. W7, bold
8, // 10. W8, extrabold
8, // 11.
9, // 12. W9, ultrabold
9, // 13
9 // 14
};
// cache Cocoa's "shared font manager" for performance
static NSFontManager *sFontManager;
static void GetStringForNSString(const NSString *aSrc, nsAString& aDist)
{
aDist.SetLength([aSrc length]);
[aSrc getCharacters:reinterpret_cast<unichar*>(aDist.BeginWriting())];
}
static NSString* GetNSStringForString(const nsAString& aSrc)
{
return [NSString stringWithCharacters:reinterpret_cast<const unichar*>(aSrc.BeginReading())
length:aSrc.Length()];
}
#define LOG_FONTLIST(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \
mozilla::LogLevel::Debug, args)
#define LOG_FONTLIST_ENABLED() MOZ_LOG_TEST( \
gfxPlatform::GetLog(eGfxLog_fontlist), \
mozilla::LogLevel::Debug)
#define LOG_CMAPDATA_ENABLED() MOZ_LOG_TEST( \
gfxPlatform::GetLog(eGfxLog_cmapdata), \
mozilla::LogLevel::Debug)
#pragma mark-
// Complex scripts will not render correctly unless appropriate AAT or OT
// layout tables are present.
// For OpenType, we also check that the GSUB table supports the relevant
// script tag, to avoid using things like Arial Unicode MS for Lao (it has
// the characters, but lacks OpenType support).
// TODO: consider whether we should move this to gfxFontEntry and do similar
// cmap-masking on other platforms to avoid using fonts that won't shape
// properly.
nsresult
MacOSFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
{
// attempt this once, if errors occur leave a blank cmap
if (mCharacterMap) {
return NS_OK;
}
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<gfxCharacterMap> charmap;
nsresult rv;
if (aFontInfoData && (charmap = GetCMAPFromFontInfo(aFontInfoData,
mUVSOffset))) {
rv = NS_OK;
} else {
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
charmap = new gfxCharacterMap();
AutoTable cmapTable(this, kCMAP);
if (cmapTable) {
uint32_t cmapLen;
const uint8_t* cmapData =
reinterpret_cast<const uint8_t*>(hb_blob_get_data(cmapTable,
&cmapLen));
rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen,
*charmap, mUVSOffset);
} else {
rv = NS_ERROR_NOT_AVAILABLE;
}
}
if (NS_SUCCEEDED(rv) && !HasGraphiteTables()) {
// We assume a Graphite font knows what it's doing,
// and provides whatever shaping is needed for the
// characters it supports, so only check/clear the
// complex-script ranges for non-Graphite fonts
// for layout support, check for the presence of mort/morx/kerx and/or
// opentype layout tables
bool hasAATLayout = HasFontTable(TRUETYPE_TAG('m','o','r','x')) ||
HasFontTable(TRUETYPE_TAG('m','o','r','t'));
bool hasAppleKerning = HasFontTable(TRUETYPE_TAG('k','e','r','x'));
bool hasGSUB = HasFontTable(TRUETYPE_TAG('G','S','U','B'));
bool hasGPOS = HasFontTable(TRUETYPE_TAG('G','P','O','S'));
if ((hasAATLayout && !(hasGSUB || hasGPOS)) || hasAppleKerning) {
mRequiresAAT = true; // prefer CoreText if font has no OTL tables,
// or if it uses the Apple-specific 'kerx'
// variant of kerning table
}
for (const ScriptRange* sr = gfxPlatformFontList::sComplexScriptRanges;
sr->rangeStart; sr++) {
// check to see if the cmap includes complex script codepoints
if (charmap->TestRange(sr->rangeStart, sr->rangeEnd)) {
if (hasAATLayout) {
// prefer CoreText for Apple's complex-script fonts,
// even if they also have some OpenType tables
// (e.g. Geeza Pro Bold on 10.6; see bug 614903)
mRequiresAAT = true;
// and don't mask off complex-script ranges, we assume
// the AAT tables will provide the necessary shaping
continue;
}
// We check for GSUB here, as GPOS alone would not be ok.
if (hasGSUB && SupportsScriptInGSUB(sr->tags)) {
continue;
}
charmap->ClearRange(sr->rangeStart, sr->rangeEnd);
}
}
// Bug 1360309, 1393624: several of Apple's Chinese fonts have spurious
// blank glyphs for obscure Tibetan and Arabic-script codepoints.
// Blacklist these so that font fallback will not use them.
if (mRequiresAAT && (FamilyName().EqualsLiteral("Songti SC") ||
FamilyName().EqualsLiteral("Songti TC") ||
FamilyName().EqualsLiteral("STSong") ||
// Bug 1390980: on 10.11, the Kaiti fonts are also affected.
FamilyName().EqualsLiteral("Kaiti SC") ||
FamilyName().EqualsLiteral("Kaiti TC") ||
FamilyName().EqualsLiteral("STKaiti"))) {
charmap->ClearRange(0x0f6b, 0x0f70);
charmap->ClearRange(0x0f8c, 0x0f8f);
charmap->clear(0x0f98);
charmap->clear(0x0fbd);
charmap->ClearRange(0x0fcd, 0x0fff);
charmap->clear(0x0620);
charmap->clear(0x065f);
charmap->ClearRange(0x06ee, 0x06ef);
charmap->clear(0x06ff);
}
}
mHasCmapTable = NS_SUCCEEDED(rv);
if (mHasCmapTable) {
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
mCharacterMap = pfl->FindCharMap(charmap);
} else {
// if error occurred, initialize to null cmap
mCharacterMap = new gfxCharacterMap();
}
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %zu hash: %8.8x%s\n",
NS_ConvertUTF16toUTF8(mName).get(),
charmap->SizeOfIncludingThis(moz_malloc_size_of),
charmap->mHash, mCharacterMap == charmap ? " new" : ""));
if (LOG_CMAPDATA_ENABLED()) {
char prefix[256];
SprintfLiteral(prefix, "(cmapdata) name: %.220s",
NS_ConvertUTF16toUTF8(mName).get());
charmap->Dump(prefix, eGfxLog_cmapdata);
}
return rv;
}
gfxFont*
MacOSFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold)
{
RefPtr<UnscaledFontMac> unscaledFont(mUnscaledFont);
if (!unscaledFont) {
CGFontRef baseFont = GetFontRef();
if (!baseFont) {
return nullptr;
}
unscaledFont = new UnscaledFontMac(baseFont, mIsDataUserFont);
mUnscaledFont = unscaledFont;
}
return new gfxMacFont(unscaledFont, this, aFontStyle, aNeedsBold);
}
bool
MacOSFontEntry::HasVariations()
{
if (!mHasVariationsInitialized) {
mHasVariationsInitialized = true;
mHasVariations = HasFontTable(TRUETYPE_TAG('f','v','a','r'));
}
return mHasVariations;
}
bool
MacOSFontEntry::IsCFF()
{
if (!mIsCFFInitialized) {
mIsCFFInitialized = true;
mIsCFF = HasFontTable(TRUETYPE_TAG('C','F','F',' '));
}
return mIsCFF;
}
MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
int32_t aWeight,
bool aIsStandardFace,
double aSizeHint)
: gfxFontEntry(aPostscriptName, aIsStandardFace),
mFontRef(NULL),
mSizeHint(aSizeHint),
mFontRefInitialized(false),
mRequiresAAT(false),
mIsCFF(false),
mIsCFFInitialized(false),
mHasVariations(false),
mHasVariationsInitialized(false),
mHasAATSmallCaps(false),
mHasAATSmallCapsInitialized(false),
mCheckedForTracking(false),
mTrakTable(nullptr),
mTrakValues(nullptr),
mTrakSizeTable(nullptr)
{
mWeight = aWeight;
}
MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName,
CGFontRef aFontRef,
uint16_t aWeight, uint16_t aStretch,
uint8_t aStyle,
bool aIsDataUserFont,
bool aIsLocalUserFont)
: gfxFontEntry(aPostscriptName, false),
mFontRef(NULL),
mSizeHint(0.0),
mFontRefInitialized(false),
mRequiresAAT(false),
mIsCFF(false),
mIsCFFInitialized(false),
mHasVariations(false),
mHasVariationsInitialized(false),
mHasAATSmallCaps(false),
mHasAATSmallCapsInitialized(false),
mCheckedForTracking(false),
mTrakTable(nullptr),
mTrakValues(nullptr),
mTrakSizeTable(nullptr)
{
mFontRef = aFontRef;
mFontRefInitialized = true;
::CFRetain(mFontRef);
mWeight = aWeight;
mStretch = aStretch;
mFixedPitch = false; // xxx - do we need this for downloaded fonts?
mStyle = aStyle;
NS_ASSERTION(!(aIsDataUserFont && aIsLocalUserFont),
"userfont is either a data font or a local font");
mIsDataUserFont = aIsDataUserFont;
mIsLocalUserFont = aIsLocalUserFont;
}
gfxFontEntry*
MacOSFontEntry::Clone() const
{
MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!");
MacOSFontEntry* fe =
new MacOSFontEntry(Name(), mWeight, mStandardFace, mSizeHint);
fe->mStyle = mStyle;
fe->mStretch = mStretch;
fe->mFixedPitch = mFixedPitch;
return fe;
}
CGFontRef
MacOSFontEntry::GetFontRef()
{
if (!mFontRefInitialized) {
mFontRefInitialized = true;
NSString *psname = GetNSStringForString(mName);
mFontRef = ::CGFontCreateWithFontName(CFStringRef(psname));
if (!mFontRef) {
// This happens on macOS 10.12 for font entry names that start with
// .AppleSystemUIFont. For those fonts, we need to go through NSFont
// to get the correct CGFontRef.
// Both the Text and the Display variant of the display font use
// .AppleSystemUIFontSomethingSomething as their member names.
// That's why we're carrying along mSizeHint to this place so that
// we get the variant that we want for this family.
NSFont* font = [NSFont fontWithName:psname size:mSizeHint];
if (font) {
mFontRef = CTFontCopyGraphicsFont((CTFontRef)font, nullptr);
}
}
}
return mFontRef;
}
// For a logging build, we wrap the CFDataRef in a FontTableRec so that we can
// use the MOZ_COUNT_[CD]TOR macros in it. A release build without logging
// does not get this overhead.
class FontTableRec {
public:
explicit FontTableRec(CFDataRef aDataRef)
: mDataRef(aDataRef)
{
MOZ_COUNT_CTOR(FontTableRec);
}
~FontTableRec() {
MOZ_COUNT_DTOR(FontTableRec);
::CFRelease(mDataRef);
}
private:
CFDataRef mDataRef;
};
/*static*/ void
MacOSFontEntry::DestroyBlobFunc(void* aUserData)
{
#ifdef NS_BUILD_REFCNT_LOGGING
FontTableRec *ftr = static_cast<FontTableRec*>(aUserData);
delete ftr;
#else
::CFRelease((CFDataRef)aUserData);
#endif
}
hb_blob_t *
MacOSFontEntry::GetFontTable(uint32_t aTag)
{
CGFontRef fontRef = GetFontRef();
if (!fontRef) {
return nullptr;
}
CFDataRef dataRef = ::CGFontCopyTableForTag(fontRef, aTag);
if (dataRef) {
return hb_blob_create((const char*)::CFDataGetBytePtr(dataRef),
::CFDataGetLength(dataRef),
HB_MEMORY_MODE_READONLY,
#ifdef NS_BUILD_REFCNT_LOGGING
new FontTableRec(dataRef),
#else
(void*)dataRef,
#endif
DestroyBlobFunc);
}
return nullptr;
}
bool
MacOSFontEntry::HasFontTable(uint32_t aTableTag)
{
if (mAvailableTables.Count() == 0) {
nsAutoreleasePool localPool;
CGFontRef fontRef = GetFontRef();
if (!fontRef) {
return false;
}
CFArrayRef tags = ::CGFontCopyTableTags(fontRef);
if (!tags) {
return false;
}
int numTags = (int) ::CFArrayGetCount(tags);
for (int t = 0; t < numTags; t++) {
uint32_t tag = (uint32_t)(uintptr_t)::CFArrayGetValueAtIndex(tags, t);
mAvailableTables.PutEntry(tag);
}
::CFRelease(tags);
}
return mAvailableTables.GetEntry(aTableTag);
}
typedef struct {
AutoSwap_PRUint32 version;
AutoSwap_PRUint16 format;
AutoSwap_PRUint16 horizOffset;
AutoSwap_PRUint16 vertOffset;
AutoSwap_PRUint16 reserved;
// TrackData horizData;
// TrackData vertData;
} TrakHeader;
typedef struct {
AutoSwap_PRUint16 nTracks;
AutoSwap_PRUint16 nSizes;
AutoSwap_PRUint32 sizeTableOffset;
// trackTableEntry trackTable[];
// fixed32 sizeTable[];
} TrackData;
typedef struct {
AutoSwap_PRUint32 track;
AutoSwap_PRUint16 nameIndex;
AutoSwap_PRUint16 offset;
} TrackTableEntry;
bool
MacOSFontEntry::HasTrackingTable()
{
if (!mCheckedForTracking) {
mCheckedForTracking = true;
mTrakTable = GetFontTable(TRUETYPE_TAG('t','r','a','k'));
if (mTrakTable) {
if (!ParseTrakTable()) {
hb_blob_destroy(mTrakTable);
mTrakTable = nullptr;
}
}
}
return mTrakTable != nullptr;
}
bool
MacOSFontEntry::ParseTrakTable()
{
// Check table validity and set up the subtable pointers we need;
// if 'trak' table is invalid, or doesn't contain a 'normal' track,
// return false to tell the caller not to try using it.
unsigned int len;
const char* data = hb_blob_get_data(mTrakTable, &len);
if (len < sizeof(TrakHeader)) {
return false;
}
auto trak = reinterpret_cast<const TrakHeader*>(data);
uint16_t horizOffset = trak->horizOffset;
if (trak->version != 0x00010000 ||
uint16_t(trak->format) != 0 ||
horizOffset == 0 ||
uint16_t(trak->reserved) != 0) {
return false;
}
// Find the horizontal trackData, and check it doesn't overrun the buffer.
if (horizOffset > len - sizeof(TrackData)) {
return false;
}
auto trackData = reinterpret_cast<const TrackData*>(data + horizOffset);
uint16_t nTracks = trackData->nTracks;
mNumTrakSizes = trackData->nSizes;
if (nTracks == 0 || mNumTrakSizes < 2) {
return false;
}
uint32_t sizeTableOffset = trackData->sizeTableOffset;
// Find the trackTable, and check it doesn't overrun the buffer.
if (horizOffset >
len - (sizeof(TrackData) + nTracks * sizeof(TrackTableEntry))) {
return false;
}
auto trackTable = reinterpret_cast<const TrackTableEntry*>
(data + horizOffset + sizeof(TrackData));
// Look for 'normal' tracking, bail out if no such track is present.
unsigned trackIndex;
for (trackIndex = 0; trackIndex < nTracks; ++trackIndex) {
if (trackTable[trackIndex].track == 0x00000000) {
break;
}
}
if (trackIndex == nTracks) {
return false;
}
// Find list of tracking values, and check they won't overrun.
uint16_t offset = trackTable[trackIndex].offset;
if (offset > len - mNumTrakSizes * sizeof(uint16_t)) {
return false;
}
mTrakValues = reinterpret_cast<const AutoSwap_PRInt16*>(data + offset);
// Find the size subtable, and check it doesn't overrun the buffer.
mTrakSizeTable =
reinterpret_cast<const AutoSwap_PRInt32*>(data + sizeTableOffset);
if (mTrakSizeTable + mNumTrakSizes >
reinterpret_cast<const AutoSwap_PRInt32*>(data + len)) {
return false;
}
return true;
}
float
MacOSFontEntry::TrackingForCSSPx(float aSize) const
{
MOZ_ASSERT(mTrakTable && mTrakValues && mTrakSizeTable);
// Find index of first sizeTable entry that is >= the requested size.
Fixed fixedSize = X2Fix(aSize);
unsigned sizeIndex;
for (sizeIndex = 0; sizeIndex < mNumTrakSizes; ++sizeIndex) {
if (mTrakSizeTable[sizeIndex] >= fixedSize) {
break;
}
}
// Return the tracking value for the requested size, or an interpolated
// value if the exact size isn't found.
if (sizeIndex == mNumTrakSizes) {
// Request is larger than last entry in the table, so just use that.
// (We don't attempt to extrapolate more extreme tracking values than
// the largest or smallest present in the table.)
return int16_t(mTrakValues[mNumTrakSizes - 1]);
}
if (sizeIndex == 0 || mTrakSizeTable[sizeIndex] == fixedSize) {
// Found an exact match, or size was smaller than the first entry.
return int16_t(mTrakValues[sizeIndex]);
}
// Requested size falls between two entries: interpolate value.
double s0 = Fix2X(mTrakSizeTable[sizeIndex - 1]);
double s1 = Fix2X(mTrakSizeTable[sizeIndex]);
double t = (aSize - s0) / (s1 - s0);
return (1.0 - t) * int16_t(mTrakValues[sizeIndex - 1]) +
t * int16_t(mTrakValues[sizeIndex]);
}
static bool
CheckForAATSmallCaps(CFArrayRef aFeatures)
{
// Walk the array of feature descriptors from the font, and see whether
// a small-caps feature setting is available.
// Just bail out (returning false) if at any point we fail to find the
// expected dictionary keys, etc; if the font has bad data, we don't even
// try to search the rest of it.
auto numFeatures = CFArrayGetCount(aFeatures);
for (auto f = 0; f < numFeatures; ++f) {
auto featureDict = (CFDictionaryRef)
CFArrayGetValueAtIndex(aFeatures, f);
if (!featureDict) {
return false;
}
auto featureNum = (CFNumberRef)
CFDictionaryGetValue(featureDict,
CFSTR("CTFeatureTypeIdentifier"));
if (!featureNum) {
return false;
}
int16_t featureType;
if (!CFNumberGetValue(featureNum, kCFNumberSInt16Type, &featureType)) {
return false;
}
if (featureType == kLetterCaseType || featureType == kLowerCaseType) {
// Which selector to look for, depending whether we've found the
// legacy LetterCase feature or the new LowerCase one.
const uint16_t smallCaps = (featureType == kLetterCaseType)
? kSmallCapsSelector
: kLowerCaseSmallCapsSelector;
auto selectors = (CFArrayRef)
CFDictionaryGetValue(featureDict,
CFSTR("CTFeatureTypeSelectors"));
if (!selectors) {
return false;
}
auto numSelectors = CFArrayGetCount(selectors);
for (auto s = 0; s < numSelectors; s++) {
auto selectorDict =
(CFDictionaryRef)CFArrayGetValueAtIndex(selectors, s);
if (!selectorDict) {
return false;
}
auto selectorNum = (CFNumberRef)
CFDictionaryGetValue(selectorDict,
CFSTR("CTFeatureSelectorIdentifier"));
if (!selectorNum) {
return false;
}
int16_t selectorValue;
if (!CFNumberGetValue(selectorNum, kCFNumberSInt16Type,
&selectorValue)) {
return false;
}
if (selectorValue == smallCaps) {
return true;
}
}
}
}
return false;
}
bool
MacOSFontEntry::SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag)
{
// If we're going to shape with Core Text, we don't support added
// OpenType features (aside from any CT applies by default), except
// for 'smcp' which we map to an AAT feature selector.
if (RequiresAATLayout()) {
if (aFeatureTag != HB_TAG('s','m','c','p')) {
return false;
}
if (mHasAATSmallCapsInitialized) {
return mHasAATSmallCaps;
}
mHasAATSmallCapsInitialized = true;
CTFontRef ctFont =
CTFontCreateWithGraphicsFont(mFontRef, 0.0, nullptr, nullptr);
if (ctFont) {
CFArrayRef features = CTFontCopyFeatures(ctFont);
CFRelease(ctFont);
if (features) {
mHasAATSmallCaps = CheckForAATSmallCaps(features);
CFRelease(features);
}
}
return mHasAATSmallCaps;
}
return gfxFontEntry::SupportsOpenTypeFeature(aScript, aFeatureTag);
}
void
MacOSFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
FontListSizes* aSizes) const
{
aSizes->mFontListSize += aMallocSizeOf(this);
AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
}
/* gfxMacFontFamily */
#pragma mark-
class gfxMacFontFamily : public gfxFontFamily
{
public:
explicit gfxMacFontFamily(const nsAString& aName, double aSizeHint) :
gfxFontFamily(aName),
mSizeHint(aSizeHint)
{}
virtual ~gfxMacFontFamily() {}
virtual void LocalizedName(nsAString& aLocalizedName);
virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr);
virtual bool IsSingleFaceFamily() const
{
return false;
}
protected:
double mSizeHint;
};
void
gfxMacFontFamily::LocalizedName(nsAString& aLocalizedName)
{
nsAutoreleasePool localPool;
// It's unsafe to call HasOtherFamilyNames off the main thread because
// it entrains FindStyleVariations, which calls GetWeightOverride, which
// retrieves prefs. And the pref names can change (via user overrides),
// so we can't use gfxPrefs to access them.
if (NS_IsMainThread() && !HasOtherFamilyNames()) {
aLocalizedName = mName;
return;
}
NSString *family = GetNSStringForString(mName);
NSString *localized = [sFontManager
localizedNameForFamily:family
face:nil];
if (localized) {
GetStringForNSString(localized, aLocalizedName);
return;
}
// failed to get localized name, just use the canonical one
aLocalizedName = mName;
}
// Return the CSS weight value to use for the given face, overriding what
// AppKit gives us (used to adjust families with bad weight values, see
// bug 931426).
// A return value of 0 indicates no override - use the existing weight.
static inline int
GetWeightOverride(const nsAString& aPSName)
{
nsAutoCString prefName("font.weight-override.");
// The PostScript name is required to be ASCII; if it's not, the font is
// broken anyway, so we really don't care that this is lossy.
LossyAppendUTF16toASCII(aPSName, prefName);
return Preferences::GetInt(prefName.get(), 0);
}
void
gfxMacFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
{
if (mHasStyles)
return;
nsAutoreleasePool localPool;
NSString *family = GetNSStringForString(mName);
// create a font entry for each face
NSArray *fontfaces = [sFontManager
availableMembersOfFontFamily:family]; // returns an array of [psname, style name, weight, traits] elements, goofy api
int faceCount = [fontfaces count];
int faceIndex;
for (faceIndex = 0; faceIndex < faceCount; faceIndex++) {
NSArray *face = [fontfaces objectAtIndex:faceIndex];
NSString *psname = [face objectAtIndex:INDEX_FONT_POSTSCRIPT_NAME];
int32_t appKitWeight = [[face objectAtIndex:INDEX_FONT_WEIGHT] unsignedIntValue];
uint32_t macTraits = [[face objectAtIndex:INDEX_FONT_TRAITS] unsignedIntValue];
NSString *facename = [face objectAtIndex:INDEX_FONT_FACE_NAME];
bool isStandardFace = false;
if (appKitWeight == kAppleExtraLightWeight) {
// if the facename contains UltraLight, set the weight to the ultralight weight value
NSRange range = [facename rangeOfString:@"ultralight" options:NSCaseInsensitiveSearch];
if (range.location != NSNotFound) {
appKitWeight = kAppleUltraLightWeight;
}
}
// make a nsString
nsAutoString postscriptFontName;
GetStringForNSString(psname, postscriptFontName);
int32_t cssWeight = GetWeightOverride(postscriptFontName);
if (cssWeight) {
// scale down and clamp, to get a value from 1..9
cssWeight = ((cssWeight + 50) / 100);
cssWeight = std::max(1, std::min(cssWeight, 9));
} else {
cssWeight =
gfxMacPlatformFontList::AppleWeightToCSSWeight(appKitWeight);
}
cssWeight *= 100; // scale up to CSS values
if ([facename isEqualToString:@"Regular"] ||
[facename isEqualToString:@"Bold"] ||
[facename isEqualToString:@"Italic"] ||
[facename isEqualToString:@"Oblique"] ||
[facename isEqualToString:@"Bold Italic"] ||
[facename isEqualToString:@"Bold Oblique"])
{
isStandardFace = true;
}
// create a font entry
MacOSFontEntry *fontEntry =
new MacOSFontEntry(postscriptFontName, cssWeight, isStandardFace, mSizeHint);
if (!fontEntry) {
break;
}
// set additional properties based on the traits reported by Cocoa
if (macTraits & (NSCondensedFontMask | NSNarrowFontMask | NSCompressedFontMask)) {
fontEntry->mStretch = NS_FONT_STRETCH_CONDENSED;
} else if (macTraits & NSExpandedFontMask) {
fontEntry->mStretch = NS_FONT_STRETCH_EXPANDED;
}
// Cocoa fails to set the Italic traits bit for HelveticaLightItalic,
// at least (see bug 611855), so check for style name endings as well
if ((macTraits & NSItalicFontMask) ||
[facename hasSuffix:@"Italic"] ||
[facename hasSuffix:@"Oblique"])
{
fontEntry->mStyle = NS_FONT_STYLE_ITALIC;
}
if (macTraits & NSFixedPitchFontMask) {
fontEntry->mFixedPitch = true;
}
if (LOG_FONTLIST_ENABLED()) {
LOG_FONTLIST(("(fontlist) added (%s) to family (%s)"
" with style: %s weight: %d stretch: %d"
" (apple-weight: %d macTraits: %8.8x)",
NS_ConvertUTF16toUTF8(fontEntry->Name()).get(),
NS_ConvertUTF16toUTF8(Name()).get(),
fontEntry->IsItalic() ? "italic" : "normal",
cssWeight, fontEntry->Stretch(),
appKitWeight, macTraits));
}
// insert into font entry array of family
AddFontEntry(fontEntry);
}
SortAvailableFonts();
SetHasStyles(true);
if (mIsBadUnderlineFamily) {
SetBadUnderlineFonts();
}
}
/* gfxSingleFaceMacFontFamily */
#pragma mark-
class gfxSingleFaceMacFontFamily : public gfxFontFamily
{
public:
explicit gfxSingleFaceMacFontFamily(const nsAString& aName) :
gfxFontFamily(aName)
{
mFaceNamesInitialized = true; // omit from face name lists
}
virtual ~gfxSingleFaceMacFontFamily() {}
virtual void LocalizedName(nsAString& aLocalizedName);
virtual void ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList);
virtual bool IsSingleFaceFamily() const
{
return true;
}
};
void
gfxSingleFaceMacFontFamily::LocalizedName(nsAString& aLocalizedName)
{
nsAutoreleasePool localPool;
if (!HasOtherFamilyNames()) {
aLocalizedName = mName;
return;
}
gfxFontEntry *fe = mAvailableFonts[0];
NSFont *font = [NSFont fontWithName:GetNSStringForString(fe->Name())
size:0.0];
if (font) {
NSString *localized = [font displayName];
if (localized) {
GetStringForNSString(localized, aLocalizedName);
return;
}
}
// failed to get localized name, just use the canonical one
aLocalizedName = mName;
}
void
gfxSingleFaceMacFontFamily::ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList)
{
if (mOtherFamilyNamesInitialized) {
return;
}
gfxFontEntry *fe = mAvailableFonts[0];
if (!fe) {
return;
}
const uint32_t kNAME = TRUETYPE_TAG('n','a','m','e');
gfxFontEntry::AutoTable nameTable(fe, kNAME);
if (!nameTable) {
return;
}
mHasOtherFamilyNames = ReadOtherFamilyNamesForFace(aPlatformFontList,
nameTable,
true);
mOtherFamilyNamesInitialized = true;
}
/* gfxMacPlatformFontList */
#pragma mark-
// A bunch of fonts for "additional language support" are shipped in a
// "Language Support" directory, and don't show up in the standard font
// list returned by CTFontManagerCopyAvailableFontFamilyNames unless
// we explicitly activate them.
#define LANG_FONTS_DIR "/Library/Application Support/Apple/Fonts/Language Support"
gfxMacPlatformFontList::gfxMacPlatformFontList() :
gfxPlatformFontList(false),
mDefaultFont(nullptr),
mUseSizeSensitiveSystemFont(false)
{
#ifdef MOZ_BUNDLED_FONTS
ActivateBundledFonts();
#endif
nsresult rv;
nsCOMPtr<nsIFile> langFonts(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv)) {
rv = langFonts->InitWithNativePath(NS_LITERAL_CSTRING(LANG_FONTS_DIR));
if (NS_SUCCEEDED(rv)) {
ActivateFontsFromDir(langFonts);
}
}
// Only the parent process listens for OS font-changed notifications;
// after rebuilding its list, it will update the content processes.
if (XRE_IsParentProcess()) {
::CFNotificationCenterAddObserver(
::CFNotificationCenterGetLocalCenter(),
this,
RegisteredFontsChangedNotificationCallback,
kCTFontManagerRegisteredFontsChangedNotification,
0,
CFNotificationSuspensionBehaviorDeliverImmediately);
}
// cache this in a static variable so that MacOSFontFamily objects
// don't have to repeatedly look it up
sFontManager = [NSFontManager sharedFontManager];
}
gfxMacPlatformFontList::~gfxMacPlatformFontList()
{
if (XRE_IsParentProcess()) {
::CFNotificationCenterRemoveObserver(
::CFNotificationCenterGetLocalCenter(),
this,
kCTFontManagerRegisteredFontsChangedNotification,
0);
}
if (mDefaultFont) {
::CFRelease(mDefaultFont);
}
}
void
gfxMacPlatformFontList::AddFamily(const nsAString& aFamilyName,
bool aSystemFont)
{
FontFamilyTable& table =
aSystemFont ? mSystemFontFamilies : mFontFamilies;
double sizeHint = 0.0;
if (aSystemFont && mUseSizeSensitiveSystemFont &&
mSystemDisplayFontFamilyName.Equals(aFamilyName)) {
sizeHint = 128.0;
}
nsAutoString key;
ToLowerCase(aFamilyName, key);
RefPtr<gfxFontFamily> familyEntry =
new gfxMacFontFamily(aFamilyName, sizeHint);
table.Put(key, familyEntry);
// check the bad underline blacklist
if (mBadUnderlineFamilyNames.Contains(key)) {
familyEntry->SetBadUnderlineFamily();
}
}
void
gfxMacPlatformFontList::AddFamily(CFStringRef aFamily)
{
NSString* family = (NSString*)aFamily;
// CTFontManager includes weird internal family names and
// LastResort, skip over those
if (!family || [family caseInsensitiveCompare:@"LastResort"] == NSOrderedSame) {
return;
}
nsAutoString familyName;
nsCocoaUtils::GetStringForNSString(family, familyName);
bool isHiddenSystemFont = familyName[0] == '.';
AddFamily(familyName, isHiddenSystemFont);
}
void
gfxMacPlatformFontList::ReadSystemFontList(
InfallibleTArray<SystemFontListEntry>* aList)
{
// Note: We rely on the records for mSystemTextFontFamilyName and
// mSystemDisplayFontFamilyName (if present) being *before* the main
// font list, so that those names are known in the content process
// by the time we add the actual family records to the font list.
aList->AppendElement(FontFamilyListEntry(mSystemTextFontFamilyName,
kTextSizeSystemFontFamily));
if (mUseSizeSensitiveSystemFont) {
aList->AppendElement(FontFamilyListEntry(mSystemDisplayFontFamilyName,
kDisplaySizeSystemFontFamily));
}
// Now collect the lists of available families, both hidden and visible.
for (auto f = mSystemFontFamilies.Iter(); !f.Done(); f.Next()) {
aList->AppendElement(FontFamilyListEntry(f.Data()->Name(),
kHiddenSystemFontFamily));
}
for (auto f = mFontFamilies.Iter(); !f.Done(); f.Next()) {
auto macFamily = static_cast<gfxMacFontFamily*>(f.Data().get());
if (macFamily->IsSingleFaceFamily()) {
continue; // skip, this will be recreated separately in the child
}
aList->AppendElement(FontFamilyListEntry(macFamily->Name(),
kStandardFontFamily));
}
}
nsresult
gfxMacPlatformFontList::InitFontListForPlatform()
{
nsAutoreleasePool localPool;
Telemetry::AutoTimer<Telemetry::MAC_INITFONTLIST_TOTAL> timer;
// reset system font list
mSystemFontFamilies.Clear();
if (XRE_IsContentProcess()) {
// Content process: use font list passed from the chrome process via
// the GetXPCOMProcessAttributes message, because it's much faster than
// querying Core Text again in the child.
auto& fontList = dom::ContentChild::GetSingleton()->SystemFontList();
for (SystemFontListEntry& fle : fontList) {
MOZ_ASSERT(fle.type() ==
SystemFontListEntry::Type::TFontFamilyListEntry);
FontFamilyListEntry& ffe(fle);
switch (ffe.entryType()) {
case kStandardFontFamily:
AddFamily(ffe.familyName(), false);
break;
case kHiddenSystemFontFamily:
AddFamily(ffe.familyName(), true);
break;
case kTextSizeSystemFontFamily:
mSystemTextFontFamilyName = ffe.familyName();
break;
case kDisplaySizeSystemFontFamily:
mSystemDisplayFontFamilyName = ffe.familyName();
mUseSizeSensitiveSystemFont = true;
break;
}
}
fontList.Clear();
} else {
// We're not a content process, so get the available fonts directly
// from Core Text.
InitSystemFontNames();
CFArrayRef familyNames = CTFontManagerCopyAvailableFontFamilyNames();
for (NSString* familyName in (NSArray*)familyNames) {
AddFamily((CFStringRef)familyName);
}
CFRelease(familyNames);
}
InitSingleFaceList();
// to avoid full search of font name tables, seed the other names table with localized names from
// some of the prefs fonts which are accessed via their localized names. changes in the pref fonts will only cause
// a font lookup miss earlier. this is a simple optimization, it's not required for correctness
PreloadNamesList();
// start the delayed cmap loader
GetPrefsAndStartLoader();
return NS_OK;
}
void
gfxMacPlatformFontList::InitSingleFaceList()
{
AutoTArray<nsString, 10> singleFaceFonts;
gfxFontUtils::GetPrefsFontList("font.single-face-list", singleFaceFonts);
Bug 1315752 - Avoid using LookupLocalFont to find the Osaka-Mono face in InitSingleFaceList, so we don't risk triggering a font-download prompt. r=mstange The issue is that with Osaka becoming a downloadable asset rather than a universally pre-installed font, it's possible for a user's system to be in a state where the Osaka-Regular face is present (and therefore the Osaka family shows up in the main font family list), but Osaka-Mono has still not been downloaded. Until recently, I wasn't aware that the family could be in that partially-installed state, but apparently it does happen (perhaps depending on how the download was originally triggered). The download prompt then occurs when we use LookupLocalFont() to find the Osaka-Mono face, because that calls CGFontCreateWithFontName, which is aware of the downloadable font assets; so when it is asked for Osaka-Mono, and sees that it hasn't been downloaded, it offers to help out. We tried to avoid this by checking for the presence of the Osaka family before calling LookupLocalFont(), and that solved things for most users (where the Osaka family was either fully installed or not installed at all), but it fails in the case where the Regular face is present but Mono isn't. So this patch works around that by avoiding LookupLocalFont (and therefore CGFontCreateWithFontName) altogether, and instead searching the faces actually present in the main Osaka family. If Osaka-Mono is installed, it will be found there and we can then duplicate its font entry and create the separate Osaka-Mono family; and if not, we safely (and silently) ignore it.
2017-02-14 00:47:16 +03:00
for (const auto& singleFaceFamily : singleFaceFonts) {
LOG_FONTLIST(("(fontlist-singleface) face name: %s\n",
Bug 1315752 - Avoid using LookupLocalFont to find the Osaka-Mono face in InitSingleFaceList, so we don't risk triggering a font-download prompt. r=mstange The issue is that with Osaka becoming a downloadable asset rather than a universally pre-installed font, it's possible for a user's system to be in a state where the Osaka-Regular face is present (and therefore the Osaka family shows up in the main font family list), but Osaka-Mono has still not been downloaded. Until recently, I wasn't aware that the family could be in that partially-installed state, but apparently it does happen (perhaps depending on how the download was originally triggered). The download prompt then occurs when we use LookupLocalFont() to find the Osaka-Mono face, because that calls CGFontCreateWithFontName, which is aware of the downloadable font assets; so when it is asked for Osaka-Mono, and sees that it hasn't been downloaded, it offers to help out. We tried to avoid this by checking for the presence of the Osaka family before calling LookupLocalFont(), and that solved things for most users (where the Osaka family was either fully installed or not installed at all), but it fails in the case where the Regular face is present but Mono isn't. So this patch works around that by avoiding LookupLocalFont (and therefore CGFontCreateWithFontName) altogether, and instead searching the faces actually present in the main Osaka family. If Osaka-Mono is installed, it will be found there and we can then duplicate its font entry and create the separate Osaka-Mono family; and if not, we safely (and silently) ignore it.
2017-02-14 00:47:16 +03:00
NS_ConvertUTF16toUTF8(singleFaceFamily).get()));
// Each entry in the "single face families" list is expected to be a
// colon-separated pair of FaceName:Family,
// where FaceName is the individual face name (psname) of a font
// that should be exposed as a separate family name,
// and Family is the standard family to which that face belongs.
// The only such face listed by default is
// Osaka-Mono:Osaka
nsAutoString familyName(singleFaceFamily);
auto colon = familyName.FindChar(':');
Bug 1315752 - Avoid using LookupLocalFont to find the Osaka-Mono face in InitSingleFaceList, so we don't risk triggering a font-download prompt. r=mstange The issue is that with Osaka becoming a downloadable asset rather than a universally pre-installed font, it's possible for a user's system to be in a state where the Osaka-Regular face is present (and therefore the Osaka family shows up in the main font family list), but Osaka-Mono has still not been downloaded. Until recently, I wasn't aware that the family could be in that partially-installed state, but apparently it does happen (perhaps depending on how the download was originally triggered). The download prompt then occurs when we use LookupLocalFont() to find the Osaka-Mono face, because that calls CGFontCreateWithFontName, which is aware of the downloadable font assets; so when it is asked for Osaka-Mono, and sees that it hasn't been downloaded, it offers to help out. We tried to avoid this by checking for the presence of the Osaka family before calling LookupLocalFont(), and that solved things for most users (where the Osaka family was either fully installed or not installed at all), but it fails in the case where the Regular face is present but Mono isn't. So this patch works around that by avoiding LookupLocalFont (and therefore CGFontCreateWithFontName) altogether, and instead searching the faces actually present in the main Osaka family. If Osaka-Mono is installed, it will be found there and we can then duplicate its font entry and create the separate Osaka-Mono family; and if not, we safely (and silently) ignore it.
2017-02-14 00:47:16 +03:00
if (colon == kNotFound) {
continue;
}
// Look for the parent family in the main font family list,
// and ensure we have loaded its list of available faces.
nsAutoString key(Substring(familyName, colon + 1));
ToLowerCase(key);
gfxFontFamily* family = mFontFamilies.GetWeak(key);
if (!family) {
continue;
}
family->FindStyleVariations();
// Truncate the entry from prefs at the colon, so now it is just the
// desired single-face-family name.
familyName.Truncate(colon);
// Look through the family's faces to see if this one is present.
const gfxFontEntry* fe = nullptr;
for (const auto& face : family->GetFontList()) {
if (face->Name().Equals(familyName)) {
fe = face;
break;
}
}
Bug 1315752 - Avoid using LookupLocalFont to find the Osaka-Mono face in InitSingleFaceList, so we don't risk triggering a font-download prompt. r=mstange The issue is that with Osaka becoming a downloadable asset rather than a universally pre-installed font, it's possible for a user's system to be in a state where the Osaka-Regular face is present (and therefore the Osaka family shows up in the main font family list), but Osaka-Mono has still not been downloaded. Until recently, I wasn't aware that the family could be in that partially-installed state, but apparently it does happen (perhaps depending on how the download was originally triggered). The download prompt then occurs when we use LookupLocalFont() to find the Osaka-Mono face, because that calls CGFontCreateWithFontName, which is aware of the downloadable font assets; so when it is asked for Osaka-Mono, and sees that it hasn't been downloaded, it offers to help out. We tried to avoid this by checking for the presence of the Osaka family before calling LookupLocalFont(), and that solved things for most users (where the Osaka family was either fully installed or not installed at all), but it fails in the case where the Regular face is present but Mono isn't. So this patch works around that by avoiding LookupLocalFont (and therefore CGFontCreateWithFontName) altogether, and instead searching the faces actually present in the main Osaka family. If Osaka-Mono is installed, it will be found there and we can then duplicate its font entry and create the separate Osaka-Mono family; and if not, we safely (and silently) ignore it.
2017-02-14 00:47:16 +03:00
if (!fe) {
continue;
}
// We found the correct face, so create the single-face family record.
GenerateFontListKey(familyName, key);
LOG_FONTLIST(("(fontlist-singleface) family name: %s, key: %s\n",
NS_ConvertUTF16toUTF8(familyName).get(),
NS_ConvertUTF16toUTF8(key).get()));
// add only if doesn't exist already
if (!mFontFamilies.GetWeak(key)) {
RefPtr<gfxFontFamily> familyEntry =
new gfxSingleFaceMacFontFamily(familyName);
// We need a separate font entry, because its family name will
// differ from the one we found in the main list.
MacOSFontEntry* fontEntry =
new MacOSFontEntry(fe->Name(), fe->mWeight, true,
static_cast<const MacOSFontEntry*>(fe)->
mSizeHint);
familyEntry->AddFontEntry(fontEntry);
familyEntry->SetHasStyles(true);
mFontFamilies.Put(key, familyEntry);
LOG_FONTLIST(("(fontlist-singleface) added new family: %s, key: %s\n",
NS_ConvertUTF16toUTF8(familyName).get(),
NS_ConvertUTF16toUTF8(key).get()));
}
}
}
// System fonts under OSX may contain weird "meta" names but if we create
// a new font using just the Postscript name, the NSFont api returns an object
// with the actual real family name. For example, under OSX 10.11:
//
// [[NSFont menuFontOfSize:8.0] familyName] ==> .AppleSystemUIFont
// [[NSFont fontWithName:[[[NSFont menuFontOfSize:8.0] fontDescriptor] postscriptName]
// size:8.0] familyName] ==> .SF NS Text
static NSString* GetRealFamilyName(NSFont* aFont)
{
NSFont* f = [NSFont fontWithName: [[aFont fontDescriptor] postscriptName]
size: 0.0];
return [f familyName];
}
// System fonts under OSX 10.11 use a combination of two families, one
// for text sizes and another for larger, display sizes. Each has a
// different number of weights. There aren't efficient API's for looking
// this information up, so hard code the logic here but confirm via
// debug assertions that the logic is correct.
const CGFloat kTextDisplayCrossover = 20.0; // use text family below this size
void
gfxMacPlatformFontList::InitSystemFontNames()
{
// system font under 10.11 are two distinct families for text/display sizes
if (nsCocoaFeatures::OnElCapitanOrLater()) {
mUseSizeSensitiveSystemFont = true;
}
// text font family
NSFont* sys = [NSFont systemFontOfSize: 0.0];
NSString* textFamilyName = GetRealFamilyName(sys);
nsAutoString familyName;
nsCocoaUtils::GetStringForNSString(textFamilyName, familyName);
mSystemTextFontFamilyName = familyName;
// display font family, if on OSX 10.11
if (mUseSizeSensitiveSystemFont) {
NSFont* displaySys = [NSFont systemFontOfSize: 128.0];
NSString* displayFamilyName = GetRealFamilyName(displaySys);
nsCocoaUtils::GetStringForNSString(displayFamilyName, familyName);
mSystemDisplayFontFamilyName = familyName;
#if DEBUG
// confirm that the optical size switch is at 20.0
NS_ASSERTION([textFamilyName compare:displayFamilyName] != NSOrderedSame,
"system text/display fonts are the same!");
NSString* fam19 = GetRealFamilyName([NSFont systemFontOfSize:
(kTextDisplayCrossover - 1.0)]);
NSString* fam20 = GetRealFamilyName([NSFont systemFontOfSize:
kTextDisplayCrossover]);
NS_ASSERTION(fam19 && fam20 && [fam19 compare:fam20] != NSOrderedSame,
"system text/display font size switch point is not as expected!");
#endif
}
#ifdef DEBUG
// different system font API's always map to the same family under OSX, so
// just assume that and emit a warning if that ever changes
NSString *sysFamily = GetRealFamilyName([NSFont systemFontOfSize:0.0]);
if ([sysFamily compare:GetRealFamilyName([NSFont boldSystemFontOfSize:0.0])] != NSOrderedSame ||
[sysFamily compare:GetRealFamilyName([NSFont controlContentFontOfSize:0.0])] != NSOrderedSame ||
[sysFamily compare:GetRealFamilyName([NSFont menuBarFontOfSize:0.0])] != NSOrderedSame ||
[sysFamily compare:GetRealFamilyName([NSFont toolTipsFontOfSize:0.0])] != NSOrderedSame) {
NS_WARNING("system font types map to different font families"
" -- please log a bug!!");
}
#endif
}
gfxFontFamily*
gfxMacPlatformFontList::FindSystemFontFamily(const nsAString& aFamily)
{
nsAutoString key;
GenerateFontListKey(aFamily, key);
gfxFontFamily* familyEntry;
// lookup in hidden system family name list
if ((familyEntry = mSystemFontFamilies.GetWeak(key))) {
return CheckFamily(familyEntry);
}
// lookup in user-exposed family name list
if ((familyEntry = mFontFamilies.GetWeak(key))) {
return CheckFamily(familyEntry);
}
return nullptr;
}
bool
gfxMacPlatformFontList::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
{
gfxFontFamily *family = FindFamily(aFontName);
if (family) {
family->LocalizedName(aFamilyName);
return true;
}
return false;
}
void
gfxMacPlatformFontList::RegisteredFontsChangedNotificationCallback(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
if (!::CFEqual(name, kCTFontManagerRegisteredFontsChangedNotification)) {
return;
}
gfxMacPlatformFontList* fl = static_cast<gfxMacPlatformFontList*>(observer);
// xxx - should be carefully pruning the list of fonts, not rebuilding it from scratch
fl->UpdateFontList();
// modify a preference that will trigger reflow everywhere
fl->ForceGlobalReflow();
mozilla::dom::ContentParent::NotifyUpdatedFonts();
}
gfxFontEntry*
gfxMacPlatformFontList::PlatformGlobalFontFallback(const uint32_t aCh,
Script aRunScript,
const gfxFontStyle* aMatchStyle,
gfxFontFamily** aMatchedFamily)
{
CFStringRef str;
UniChar ch[2];
CFIndex length = 1;
if (IS_IN_BMP(aCh)) {
ch[0] = aCh;
str = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, ch, 1,
kCFAllocatorNull);
} else {
ch[0] = H_SURROGATE(aCh);
ch[1] = L_SURROGATE(aCh);
str = ::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, ch, 2,
kCFAllocatorNull);
if (!str) {
return nullptr;
}
length = 2;
}
// use CoreText to find the fallback family
gfxFontEntry *fontEntry = nullptr;
CTFontRef fallback;
bool cantUseFallbackFont = false;
if (!mDefaultFont) {
mDefaultFont = ::CTFontCreateWithName(CFSTR("LucidaGrande"), 12.f,
NULL);
}
fallback = ::CTFontCreateForString(mDefaultFont, str,
::CFRangeMake(0, length));
if (fallback) {
CFStringRef familyNameRef = ::CTFontCopyFamilyName(fallback);
::CFRelease(fallback);
if (familyNameRef &&
::CFStringCompare(familyNameRef, CFSTR("LastResort"),
kCFCompareCaseInsensitive) != kCFCompareEqualTo)
{
AutoTArray<UniChar, 1024> buffer;
CFIndex familyNameLen = ::CFStringGetLength(familyNameRef);
buffer.SetLength(familyNameLen+1);
::CFStringGetCharacters(familyNameRef, ::CFRangeMake(0, familyNameLen),
buffer.Elements());
buffer[familyNameLen] = 0;
nsDependentString familyNameString(reinterpret_cast<char16_t*>(buffer.Elements()), familyNameLen);
bool needsBold; // ignored in the system fallback case
gfxFontFamily *family = FindSystemFontFamily(familyNameString);
if (family) {
fontEntry = family->FindFontForStyle(*aMatchStyle, needsBold);
if (fontEntry) {
if (fontEntry->HasCharacter(aCh)) {
*aMatchedFamily = family;
} else {
fontEntry = nullptr;
cantUseFallbackFont = true;
}
}
}
}
if (familyNameRef) {
::CFRelease(familyNameRef);
}
}
if (cantUseFallbackFont) {
Telemetry::Accumulate(Telemetry::BAD_FALLBACK_FONT, cantUseFallbackFont);
}
::CFRelease(str);
return fontEntry;
}
gfxFontFamily*
gfxMacPlatformFontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle)
{
nsAutoreleasePool localPool;
NSString *defaultFamily = [[NSFont userFontOfSize:aStyle->size] familyName];
nsAutoString familyName;
GetStringForNSString(defaultFamily, familyName);
return FindFamily(familyName);
}
int32_t
gfxMacPlatformFontList::AppleWeightToCSSWeight(int32_t aAppleWeight)
{
if (aAppleWeight < 1)
aAppleWeight = 1;
else if (aAppleWeight > kAppleMaxWeight)
aAppleWeight = kAppleMaxWeight;
return gAppleWeightToCSSWeight[aAppleWeight];
}
gfxFontEntry*
gfxMacPlatformFontList::LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
int16_t aStretch,
uint8_t aStyle)
{
nsAutoreleasePool localPool;
NSString *faceName = GetNSStringForString(aFontName);
MacOSFontEntry *newFontEntry;
// lookup face based on postscript or full name
CGFontRef fontRef = ::CGFontCreateWithFontName(CFStringRef(faceName));
if (!fontRef) {
return nullptr;
}
NS_ASSERTION(aWeight >= 100 && aWeight <= 900,
"bogus font weight value!");
newFontEntry =
new MacOSFontEntry(aFontName, fontRef, aWeight, aStretch, aStyle,
false, true);
::CFRelease(fontRef);
return newFontEntry;
}
static void ReleaseData(void *info, const void *data, size_t size)
{
free((void*)data);
}
gfxFontEntry*
gfxMacPlatformFontList::MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,
uint32_t aLength)
{
NS_ASSERTION(aFontData, "MakePlatformFont called with null data");
NS_ASSERTION(aWeight >= 100 && aWeight <= 900, "bogus font weight value!");
// create the font entry
nsAutoString uniqueName;
nsresult rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName);
if (NS_FAILED(rv)) {
return nullptr;
}
CGDataProviderRef provider =
::CGDataProviderCreateWithData(nullptr, aFontData, aLength,
&ReleaseData);
CGFontRef fontRef = ::CGFontCreateWithDataProvider(provider);
::CGDataProviderRelease(provider);
if (!fontRef) {
return nullptr;
}
auto newFontEntry =
MakeUnique<MacOSFontEntry>(uniqueName, fontRef, aWeight, aStretch,
aStyle, true, false);
::CFRelease(fontRef);
// if succeeded and font cmap is good, return the new font
if (NS_SUCCEEDED(newFontEntry->ReadCMAP())) {
return newFontEntry.release();
}
// if something is funky about this font, delete immediately
#if DEBUG
NS_WARNING("downloaded font not loaded properly");
#endif
return nullptr;
}
// Webkit code uses a system font meta name, so mimic that here
// WebCore/platform/graphics/mac/FontCacheMac.mm
static const char kSystemFont_system[] = "-apple-system";
bool
gfxMacPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
nsTArray<gfxFontFamily*>* aOutput,
FindFamiliesFlags aFlags,
gfxFontStyle* aStyle,
gfxFloat aDevToCssSize)
{
// search for special system font name, -apple-system
if (aFamily.EqualsLiteral(kSystemFont_system)) {
if (mUseSizeSensitiveSystemFont &&
aStyle && (aStyle->size * aDevToCssSize) >= kTextDisplayCrossover) {
aOutput->AppendElement(FindSystemFontFamily(mSystemDisplayFontFamilyName));
return true;
}
aOutput->AppendElement(FindSystemFontFamily(mSystemTextFontFamilyName));
return true;
}
return gfxPlatformFontList::FindAndAddFamilies(aFamily,
aOutput,
aFlags,
aStyle,
aDevToCssSize);
}
void
gfxMacPlatformFontList::LookupSystemFont(LookAndFeel::FontID aSystemFontID,
nsAString& aSystemFontName,
gfxFontStyle &aFontStyle,
float aDevPixPerCSSPixel)
{
// code moved here from widget/cocoa/nsLookAndFeel.mm
NSFont *font = nullptr;
char* systemFontName = nullptr;
switch (aSystemFontID) {
case LookAndFeel::eFont_MessageBox:
case LookAndFeel::eFont_StatusBar:
case LookAndFeel::eFont_List:
case LookAndFeel::eFont_Field:
case LookAndFeel::eFont_Button:
case LookAndFeel::eFont_Widget:
font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
systemFontName = (char*) kSystemFont_system;
break;
case LookAndFeel::eFont_SmallCaption:
font = [NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize]];
systemFontName = (char*) kSystemFont_system;
break;
case LookAndFeel::eFont_Icon: // used in urlbar; tried labelFont, but too small
case LookAndFeel::eFont_Workspace:
case LookAndFeel::eFont_Desktop:
case LookAndFeel::eFont_Info:
font = [NSFont controlContentFontOfSize:0.0];
systemFontName = (char*) kSystemFont_system;
break;
case LookAndFeel::eFont_PullDownMenu:
font = [NSFont menuBarFontOfSize:0.0];
systemFontName = (char*) kSystemFont_system;
break;
case LookAndFeel::eFont_Tooltips:
font = [NSFont toolTipsFontOfSize:0.0];
systemFontName = (char*) kSystemFont_system;
break;
case LookAndFeel::eFont_Caption:
case LookAndFeel::eFont_Menu:
case LookAndFeel::eFont_Dialog:
default:
font = [NSFont systemFontOfSize:0.0];
systemFontName = (char*) kSystemFont_system;
break;
}
NS_ASSERTION(font, "system font not set");
NS_ASSERTION(systemFontName, "system font name not set");
if (systemFontName) {
aSystemFontName.AssignASCII(systemFontName);
}
NSFontSymbolicTraits traits = [[font fontDescriptor] symbolicTraits];
aFontStyle.style =
(traits & NSFontItalicTrait) ? NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL;
aFontStyle.weight =
(traits & NSFontBoldTrait) ? NS_FONT_WEIGHT_BOLD : NS_FONT_WEIGHT_NORMAL;
aFontStyle.stretch =
(traits & NSFontExpandedTrait) ?
NS_FONT_STRETCH_EXPANDED : (traits & NSFontCondensedTrait) ?
NS_FONT_STRETCH_CONDENSED : NS_FONT_STRETCH_NORMAL;
// convert size from css pixels to device pixels
aFontStyle.size = [font pointSize] * aDevPixPerCSSPixel;
aFontStyle.systemFont = true;
}
// used to load system-wide font info on off-main thread
class MacFontInfo : public FontInfoData {
public:
MacFontInfo(bool aLoadOtherNames,
bool aLoadFaceNames,
bool aLoadCmaps) :
FontInfoData(aLoadOtherNames, aLoadFaceNames, aLoadCmaps)
{}
virtual ~MacFontInfo() {}
virtual void Load() {
nsAutoreleasePool localPool;
FontInfoData::Load();
}
// loads font data for all members of a given family
virtual void LoadFontFamilyData(const nsAString& aFamilyName);
};
void
MacFontInfo::LoadFontFamilyData(const nsAString& aFamilyName)
{
// family name ==> CTFontDescriptor
NSString *famName = GetNSStringForString(aFamilyName);
CFStringRef family = CFStringRef(famName);
CFMutableDictionaryRef attr =
CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(attr, kCTFontFamilyNameAttribute, family);
CTFontDescriptorRef fd = CTFontDescriptorCreateWithAttributes(attr);
CFRelease(attr);
CFArrayRef matchingFonts =
CTFontDescriptorCreateMatchingFontDescriptors(fd, NULL);
CFRelease(fd);
if (!matchingFonts) {
return;
}
nsTArray<nsString> otherFamilyNames;
bool hasOtherFamilyNames = true;
// iterate over faces in the family
int f, numFaces = (int) CFArrayGetCount(matchingFonts);
for (f = 0; f < numFaces; f++) {
mLoadStats.fonts++;
CTFontDescriptorRef faceDesc =
(CTFontDescriptorRef)CFArrayGetValueAtIndex(matchingFonts, f);
if (!faceDesc) {
continue;
}
CTFontRef fontRef = CTFontCreateWithFontDescriptor(faceDesc,
0.0, nullptr);
if (!fontRef) {
NS_WARNING("failed to create a CTFontRef");
continue;
}
if (mLoadCmaps) {
// face name
CFStringRef faceName = (CFStringRef)
CTFontDescriptorCopyAttribute(faceDesc, kCTFontNameAttribute);
AutoTArray<UniChar, 1024> buffer;
CFIndex len = CFStringGetLength(faceName);
buffer.SetLength(len+1);
CFStringGetCharacters(faceName, ::CFRangeMake(0, len),
buffer.Elements());
buffer[len] = 0;
nsAutoString fontName(reinterpret_cast<char16_t*>(buffer.Elements()),
len);
// load the cmap data
FontFaceData fontData;
CFDataRef cmapTable = CTFontCopyTable(fontRef, kCTFontTableCmap,
kCTFontTableOptionNoOptions);
if (cmapTable) {
const uint8_t *cmapData =
(const uint8_t*)CFDataGetBytePtr(cmapTable);
uint32_t cmapLen = CFDataGetLength(cmapTable);
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
uint32_t offset;
nsresult rv;
rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen, *charmap, offset);
if (NS_SUCCEEDED(rv)) {
fontData.mCharacterMap = charmap;
fontData.mUVSOffset = offset;
mLoadStats.cmaps++;
}
CFRelease(cmapTable);
}
mFontFaceData.Put(fontName, fontData);
CFRelease(faceName);
}
if (mLoadOtherNames && hasOtherFamilyNames) {
CFDataRef nameTable = CTFontCopyTable(fontRef, kCTFontTableName,
kCTFontTableOptionNoOptions);
if (nameTable) {
const char *nameData = (const char*)CFDataGetBytePtr(nameTable);
uint32_t nameLen = CFDataGetLength(nameTable);
gfxFontFamily::ReadOtherFamilyNamesForFace(aFamilyName,
nameData, nameLen,
otherFamilyNames,
false);
hasOtherFamilyNames = otherFamilyNames.Length() != 0;
CFRelease(nameTable);
}
}
CFRelease(fontRef);
}
CFRelease(matchingFonts);
// if found other names, insert them in the hash table
if (otherFamilyNames.Length() != 0) {
mOtherFamilyNames.Put(aFamilyName, otherFamilyNames);
mLoadStats.othernames += otherFamilyNames.Length();
}
}
already_AddRefed<FontInfoData>
gfxMacPlatformFontList::CreateFontInfoData()
{
bool loadCmaps = !UsesSystemFallback() ||
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<MacFontInfo> fi =
new MacFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps);
return fi.forget();
}
gfxFontFamily*
gfxMacPlatformFontList::CreateFontFamily(const nsAString& aName) const
{
return new gfxMacFontFamily(aName, 0.0);
}
void
gfxMacPlatformFontList::ActivateFontsFromDir(nsIFile* aDir)
{
bool isDir;
if (NS_FAILED(aDir->IsDirectory(&isDir)) || !isDir) {
return;
}
nsCOMPtr<nsISimpleEnumerator> e;
if (NS_FAILED(aDir->GetDirectoryEntries(getter_AddRefs(e)))) {
return;
}
CFMutableArrayRef urls =
::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
bool hasMore;
while (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> entry;
if (NS_FAILED(e->GetNext(getter_AddRefs(entry)))) {
break;
}
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
if (!file) {
continue;
}
nsCString path;
if (NS_FAILED(file->GetNativePath(path))) {
continue;
}
CFURLRef fontURL =
::CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
(uint8_t*)path.get(),
path.Length(),
false);
if (fontURL) {
::CFArrayAppendValue(urls, fontURL);
::CFRelease(fontURL);
}
}
::CTFontManagerRegisterFontsForURLs(urls,
kCTFontManagerScopeProcess,
nullptr);
::CFRelease(urls);
}
#ifdef MOZ_BUNDLED_FONTS
void
gfxMacPlatformFontList::ActivateBundledFonts()
{
nsCOMPtr<nsIFile> localDir;
if (NS_FAILED(NS_GetSpecialDirectory(NS_GRE_DIR,
getter_AddRefs(localDir)))) {
return;
}
if (NS_FAILED(localDir->Append(NS_LITERAL_STRING("fonts")))) {
return;
}
ActivateFontsFromDir(localDir);
}
#endif