зеркало из https://github.com/mozilla/pjs.git
Bug 417444. Load in other font family names lazily to avoid doing expensive name table reads at startup. r+sr=roc
This commit is contained in:
Родитель
916ae789a1
Коммит
2b61ecf33c
|
@ -41,6 +41,7 @@
|
||||||
#define GFXQUARTZFONTCACHE_H_
|
#define GFXQUARTZFONTCACHE_H_
|
||||||
|
|
||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
|
#include "nsRefPtrHashtable.h"
|
||||||
|
|
||||||
#include "gfxFontUtils.h"
|
#include "gfxFontUtils.h"
|
||||||
#include "gfxAtsuiFonts.h"
|
#include "gfxAtsuiFonts.h"
|
||||||
|
@ -63,6 +64,7 @@ struct FontSearch {
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacOSFamilyEntry;
|
class MacOSFamilyEntry;
|
||||||
|
class gfxQuartzFontCache;
|
||||||
|
|
||||||
// a single member of a font family (i.e. a single face, such as Times Italic)
|
// a single member of a font family (i.e. a single face, such as Times Italic)
|
||||||
class MacOSFontEntry
|
class MacOSFontEntry
|
||||||
|
@ -104,6 +106,9 @@ protected:
|
||||||
PRPackedBool mATSUIDInitialized;
|
PRPackedBool mATSUIDInitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// helper class for adding other family names back into font cache
|
||||||
|
class AddOtherFamilyNameFunctor;
|
||||||
|
|
||||||
// a single font family, referencing one or more faces
|
// a single font family, referencing one or more faces
|
||||||
class MacOSFamilyEntry
|
class MacOSFamilyEntry
|
||||||
{
|
{
|
||||||
|
@ -111,7 +116,7 @@ public:
|
||||||
THEBES_INLINE_DECL_REFCOUNTING(MacOSFamilyEntry)
|
THEBES_INLINE_DECL_REFCOUNTING(MacOSFamilyEntry)
|
||||||
|
|
||||||
MacOSFamilyEntry(nsString &aName) :
|
MacOSFamilyEntry(nsString &aName) :
|
||||||
mName(aName)
|
mName(aName), mOtherFamilyNamesInitialized(PR_FALSE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +133,9 @@ public:
|
||||||
// used as part of the font fallback process
|
// used as part of the font fallback process
|
||||||
void FindFontForChar(FontSearch *aMatchData);
|
void FindFontForChar(FontSearch *aMatchData);
|
||||||
|
|
||||||
|
// read in other family names, if any, and use functor to add each into cache
|
||||||
|
void ReadOtherFamilyNames(AddOtherFamilyNameFunctor& aOtherFamilyFunctor);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// add font entries into array that match specified traits, returned in array listed by weight
|
// add font entries into array that match specified traits, returned in array listed by weight
|
||||||
|
@ -141,6 +149,7 @@ protected:
|
||||||
|
|
||||||
nsString mName; // canonical font family name returned from NSFontManager
|
nsString mName; // canonical font family name returned from NSFontManager
|
||||||
nsTArray<nsRefPtr<MacOSFontEntry> > mAvailableFonts;
|
nsTArray<nsRefPtr<MacOSFontEntry> > mAvailableFonts;
|
||||||
|
PRPackedBool mOtherFamilyNamesInitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,16 +193,28 @@ public:
|
||||||
|
|
||||||
PRBool GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<MacOSFamilyEntry> > *array);
|
PRBool GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<MacOSFamilyEntry> > *array);
|
||||||
void SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<MacOSFamilyEntry> >& array);
|
void SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<MacOSFamilyEntry> >& array);
|
||||||
|
|
||||||
|
void AddOtherFamilyName(MacOSFamilyEntry *aFamilyEntry, nsAString& aOtherFamilyName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static PLDHashOperator PR_CALLBACK FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
static PLDHashOperator PR_CALLBACK FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
||||||
nsRefPtr<MacOSFamilyEntry>& aFamilyEntry,
|
nsRefPtr<MacOSFamilyEntry>& aFamilyEntry,
|
||||||
void* userArg);
|
void* userArg);
|
||||||
|
|
||||||
static gfxQuartzFontCache *sSharedFontCache;
|
static gfxQuartzFontCache *sSharedFontCache;
|
||||||
|
|
||||||
gfxQuartzFontCache();
|
gfxQuartzFontCache();
|
||||||
|
|
||||||
|
// initialize font lists
|
||||||
void InitFontList();
|
void InitFontList();
|
||||||
|
void ReadOtherFamilyNamesForFamily(const nsAString& aFamilyName);
|
||||||
|
|
||||||
|
// separate initialization for reading in name tables, since this is expensive
|
||||||
|
void InitOtherFamilyNames();
|
||||||
|
|
||||||
|
static PLDHashOperator PR_CALLBACK InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey,
|
||||||
|
nsRefPtr<MacOSFamilyEntry>& aFamilyEntry,
|
||||||
|
void* userArg);
|
||||||
|
|
||||||
void GenerateFontListKey(const nsAString& aKeyName, nsAString& aResult);
|
void GenerateFontListKey(const nsAString& aKeyName, nsAString& aResult);
|
||||||
static void ATSNotification(ATSFontNotificationInfoRef aInfo, void* aUserArg);
|
static void ATSNotification(ATSFontNotificationInfoRef aInfo, void* aUserArg);
|
||||||
|
@ -205,11 +226,11 @@ private:
|
||||||
void* aUserArg);
|
void* aUserArg);
|
||||||
|
|
||||||
// canonical family name ==> family entry (unique, one name per family entry)
|
// canonical family name ==> family entry (unique, one name per family entry)
|
||||||
nsDataHashtable<nsStringHashKey, nsRefPtr<MacOSFamilyEntry> > mFontFamilies;
|
nsRefPtrHashtable<nsStringHashKey, MacOSFamilyEntry> mFontFamilies;
|
||||||
|
|
||||||
// localized family name ==> family entry (not unique, can have multiple names per
|
// other family name ==> family entry (not unique, can have multiple names per
|
||||||
// family entry, only names *other* than the canonical names are stored here)
|
// family entry, only names *other* than the canonical names are stored here)
|
||||||
nsDataHashtable<nsStringHashKey, nsRefPtr<MacOSFamilyEntry> > mLocalizedFamilies;
|
nsRefPtrHashtable<nsStringHashKey, MacOSFamilyEntry> mOtherFamilyNames;
|
||||||
|
|
||||||
// cached pref font lists
|
// cached pref font lists
|
||||||
// maps list of family names ==> array of family entries, one per lang group
|
// maps list of family names ==> array of family entries, one per lang group
|
||||||
|
@ -217,6 +238,9 @@ private:
|
||||||
|
|
||||||
// when system-wide font lookup fails for a character, cache it to skip future searches
|
// when system-wide font lookup fails for a character, cache it to skip future searches
|
||||||
gfxSparseBitSet mCodepointsWithNoFonts;
|
gfxSparseBitSet mCodepointsWithNoFonts;
|
||||||
|
|
||||||
|
// flag set after InitOtherFamilyNames is called upon first name lookup miss
|
||||||
|
PRPackedBool mOtherFamilyNamesInitialized;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -241,6 +241,21 @@ MacOSFontEntry::ReadCMAP()
|
||||||
/* MacOSFamilyEntry */
|
/* MacOSFamilyEntry */
|
||||||
#pragma mark-
|
#pragma mark-
|
||||||
|
|
||||||
|
// helper class for adding other family names back into font cache
|
||||||
|
class AddOtherFamilyNameFunctor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AddOtherFamilyNameFunctor(gfxQuartzFontCache *aFontCache) :
|
||||||
|
mFontCache(aFontCache)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator() (MacOSFamilyEntry *aFamilyEntry, nsAString& aOtherName) {
|
||||||
|
mFontCache->AddOtherFamilyName(aFamilyEntry, aOtherName);
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxQuartzFontCache *mFontCache;
|
||||||
|
};
|
||||||
|
|
||||||
static const PRUint32 kTraits_NonNormalWidthMask = NSNarrowFontMask | NSExpandedFontMask |
|
static const PRUint32 kTraits_NonNormalWidthMask = NSNarrowFontMask | NSExpandedFontMask |
|
||||||
NSCondensedFontMask | NSCompressedFontMask | NSFixedPitchFontMask;
|
NSCondensedFontMask | NSCompressedFontMask | NSFixedPitchFontMask;
|
||||||
|
|
||||||
|
@ -310,7 +325,7 @@ MacOSFamilyEntry::FindFontForChar(FontSearch *aMatchData)
|
||||||
rank += 20;
|
rank += 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we didn't match any characters don't bother wasting more time.
|
// if we didn't match any characters don't bother wasting more time with this face.
|
||||||
if (rank == 0)
|
if (rank == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -466,30 +481,6 @@ MacOSFamilyEntry::FindFontWeight(MacOSFontEntry* aFontsForWeights[], const gfxFo
|
||||||
return aFontsForWeights[baseMatch];
|
return aFontsForWeights[baseMatch];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gfxQuartzFontCache */
|
|
||||||
#pragma mark-
|
|
||||||
|
|
||||||
gfxQuartzFontCache *gfxQuartzFontCache::sSharedFontCache = nsnull;
|
|
||||||
|
|
||||||
gfxQuartzFontCache::gfxQuartzFontCache()
|
|
||||||
{
|
|
||||||
mFontFamilies.Init(100);
|
|
||||||
mLocalizedFamilies.Init(30);
|
|
||||||
mPrefFonts.Init(10);
|
|
||||||
|
|
||||||
InitFontList();
|
|
||||||
::ATSFontNotificationSubscribe(ATSNotification,
|
|
||||||
kATSFontNotifyOptionDefault,
|
|
||||||
(void*)this, nsnull);
|
|
||||||
|
|
||||||
// pref changes notification setup
|
|
||||||
nsCOMPtr<nsIPref> pref = do_GetService(NS_PREF_CONTRACTID);
|
|
||||||
pref->RegisterCallback("font.", PrefChangedCallback, this);
|
|
||||||
pref->RegisterCallback("font.name-list.", PrefChangedCallback, this);
|
|
||||||
pref->RegisterCallback("intl.accept_languages", PrefChangedCallback, this); // hmmmm...
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static NSString* CreateNameFromBuffer(const UInt8 *aBuf, ByteCount aLength,
|
static NSString* CreateNameFromBuffer(const UInt8 *aBuf, ByteCount aLength,
|
||||||
FontPlatformCode aPlatformCode, FontScriptCode aScriptCode, FontLanguageCode aLangCode )
|
FontPlatformCode aPlatformCode, FontScriptCode aScriptCode, FontLanguageCode aLangCode )
|
||||||
{
|
{
|
||||||
|
@ -522,7 +513,6 @@ static NSString* CreateNameFromBuffer(const UInt8 *aBuf, ByteCount aLength,
|
||||||
return (NSString*) outName;
|
return (NSString*) outName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 10.4 headers only define TT/OT name table id's up to the license id (14) but 10.5 does, so use our own enum
|
// 10.4 headers only define TT/OT name table id's up to the license id (14) but 10.5 does, so use our own enum
|
||||||
enum {
|
enum {
|
||||||
kMozillaFontPreferredFamilyName = 16,
|
kMozillaFontPreferredFamilyName = 16,
|
||||||
|
@ -531,25 +521,20 @@ enum {
|
||||||
// xxx - rather than use ATSUI calls, probably faster to load name table directly,
|
// xxx - rather than use ATSUI calls, probably faster to load name table directly,
|
||||||
// this avoids copying around strings that are of no interest
|
// this avoids copying around strings that are of no interest
|
||||||
|
|
||||||
// read in family names other than the canonical family name, including localized family names
|
// returns true if other names were found, false otherwise
|
||||||
static void ReadOtherFamilyNames(NSString *familyName, NSArray *faceArray,
|
static PRBool ReadOtherFamilyNamesForFace(AddOtherFamilyNameFunctor& aOtherFamilyFunctor, MacOSFamilyEntry *aFamilyEntry,
|
||||||
int faceIndex, NSMutableArray *localizedNames)
|
NSString *familyName, ATSUFontID fontID)
|
||||||
{
|
{
|
||||||
OSStatus err;
|
OSStatus err;
|
||||||
ItemCount i, nameCount;
|
ItemCount i, nameCount;
|
||||||
ATSUFontID fontID;
|
PRBool foundNames = PR_FALSE;
|
||||||
|
|
||||||
NSArray *face = [faceArray objectAtIndex:faceIndex];
|
|
||||||
NSString *psname = [face objectAtIndex:INDEX_FONT_POSTSCRIPT_NAME];
|
|
||||||
NSFont *font = [NSFont fontWithName:psname size:0.0];
|
|
||||||
fontID = [font _atsFontID];
|
|
||||||
|
|
||||||
if (fontID == kATSUInvalidFontID)
|
if (fontID == kATSUInvalidFontID)
|
||||||
return;
|
return foundNames;
|
||||||
|
|
||||||
err = ATSUCountFontNames(fontID, &nameCount);
|
err = ATSUCountFontNames(fontID, &nameCount);
|
||||||
if (err != noErr)
|
if (err != noErr)
|
||||||
return;
|
return foundNames;
|
||||||
|
|
||||||
for (i = 0; i < nameCount; i++) {
|
for (i = 0; i < nameCount; i++) {
|
||||||
|
|
||||||
|
@ -567,52 +552,94 @@ static void ReadOtherFamilyNames(NSString *familyName, NSArray *faceArray,
|
||||||
continue;
|
continue;
|
||||||
// any other error, bail
|
// any other error, bail
|
||||||
if (err != noErr)
|
if (err != noErr)
|
||||||
return;
|
return foundNames;
|
||||||
|
|
||||||
if (!(nameCode == kFontFamilyName || nameCode == kMozillaFontPreferredFamilyName)) continue;
|
if (!(nameCode == kFontFamilyName || nameCode == kMozillaFontPreferredFamilyName)) continue;
|
||||||
if (len >= kBufLength) continue;
|
if (len >= kBufLength) continue;
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
|
|
||||||
NSString *name = CreateNameFromBuffer((UInt8*)buf, len, platformCode, scriptCode, langCode);
|
NSString *name = CreateNameFromBuffer((UInt8*)buf, len, platformCode, scriptCode, langCode);
|
||||||
NSString *foundName = nil;
|
|
||||||
|
|
||||||
// add if not same as canonical family name or already in list of names
|
// add if not same as canonical family name or already in list of names
|
||||||
if (name) {
|
if (name) {
|
||||||
|
|
||||||
if (![name isEqualToString:familyName]) {
|
if (![name isEqualToString:familyName]) {
|
||||||
|
nsAutoString otherFamilyName;
|
||||||
// search other localized names
|
GetStringForNSString(name, otherFamilyName);
|
||||||
int j, lnameCount = [localizedNames count];
|
aOtherFamilyFunctor(aFamilyEntry, otherFamilyName);
|
||||||
NSString *lname;
|
foundNames = PR_TRUE;
|
||||||
for (j = 0; j < lnameCount; j++) {
|
|
||||||
lname = [localizedNames objectAtIndex:j];
|
|
||||||
if ([lname isEqualToString:name]) {
|
|
||||||
foundName = lname;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// didn't find it in the list? add it
|
|
||||||
if (!foundName) {
|
|
||||||
[localizedNames addObject:name];
|
|
||||||
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(init-otherfamily) canonical family: %s, other family: %s\n", [familyName UTF8String], [name UTF8String]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[name release];
|
[name release];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return foundNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MacOSFamilyEntry::ReadOtherFamilyNames(AddOtherFamilyNameFunctor& aOtherFamilyFunctor)
|
||||||
|
{
|
||||||
|
if (mOtherFamilyNamesInitialized)
|
||||||
|
return;
|
||||||
|
mOtherFamilyNamesInitialized = PR_TRUE;
|
||||||
|
|
||||||
|
NSString *familyName = GetNSStringForString(mName);
|
||||||
|
|
||||||
|
// read in other family names for the first face in the list
|
||||||
|
MacOSFontEntry *fe = mAvailableFonts[0];
|
||||||
|
|
||||||
|
PRBool foundNames = ReadOtherFamilyNamesForFace(aOtherFamilyFunctor, this, familyName, fe->GetFontID());
|
||||||
|
|
||||||
|
// read in other names for the first face in the list with the assumption
|
||||||
|
// that if extra names don't exist in that face then they don't exist in
|
||||||
|
// other faces for the same font
|
||||||
|
if (foundNames) {
|
||||||
|
PRUint32 numFonts, i;
|
||||||
|
|
||||||
|
// read in names for all faces, needed to catch cases where
|
||||||
|
// fonts all family names for individual weights (e.g. Hiragino Kaku Gothic Pro W6)
|
||||||
|
numFonts = mAvailableFonts.Length();
|
||||||
|
for (i = 1; i < numFonts; i++) {
|
||||||
|
fe = mAvailableFonts[i];
|
||||||
|
ReadOtherFamilyNamesForFace(aOtherFamilyFunctor, this, familyName, fe->GetFontID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* gfxQuartzFontCache */
|
||||||
|
#pragma mark-
|
||||||
|
|
||||||
|
gfxQuartzFontCache *gfxQuartzFontCache::sSharedFontCache = nsnull;
|
||||||
|
|
||||||
|
gfxQuartzFontCache::gfxQuartzFontCache()
|
||||||
|
{
|
||||||
|
mFontFamilies.Init(100);
|
||||||
|
mOtherFamilyNames.Init(30);
|
||||||
|
mOtherFamilyNamesInitialized = PR_FALSE;
|
||||||
|
mPrefFonts.Init(10);
|
||||||
|
|
||||||
|
InitFontList();
|
||||||
|
::ATSFontNotificationSubscribe(ATSNotification,
|
||||||
|
kATSFontNotifyOptionDefault,
|
||||||
|
(void*)this, nsnull);
|
||||||
|
|
||||||
|
// pref changes notification setup
|
||||||
|
nsCOMPtr<nsIPref> pref = do_GetService(NS_PREF_CONTRACTID);
|
||||||
|
pref->RegisterCallback("font.", PrefChangedCallback, this);
|
||||||
|
pref->RegisterCallback("font.name-list.", PrefChangedCallback, this);
|
||||||
|
pref->RegisterCallback("intl.accept_languages", PrefChangedCallback, this); // hmmmm...
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int kIndexNormalFace_NotFound = -1;
|
|
||||||
const PRUint32 kNonNormalTraits = NSItalicFontMask | NSBoldFontMask | NSNarrowFontMask | NSExpandedFontMask | NSCondensedFontMask | NSCompressedFontMask;
|
const PRUint32 kNonNormalTraits = NSItalicFontMask | NSBoldFontMask | NSNarrowFontMask | NSExpandedFontMask | NSCondensedFontMask | NSCompressedFontMask;
|
||||||
|
|
||||||
void
|
void
|
||||||
gfxQuartzFontCache::InitFontList()
|
gfxQuartzFontCache::InitFontList()
|
||||||
{
|
{
|
||||||
mFontFamilies.Clear();
|
mFontFamilies.Clear();
|
||||||
mLocalizedFamilies.Clear();
|
mOtherFamilyNames.Clear();
|
||||||
|
mOtherFamilyNamesInitialized = PR_FALSE;
|
||||||
mPrefFonts.Clear();
|
mPrefFonts.Clear();
|
||||||
mCodepointsWithNoFonts.reset();
|
mCodepointsWithNoFonts.reset();
|
||||||
|
|
||||||
|
@ -620,8 +647,7 @@ gfxQuartzFontCache::InitFontList()
|
||||||
NSFontManager *fontManager = [NSFontManager sharedFontManager];
|
NSFontManager *fontManager = [NSFontManager sharedFontManager];
|
||||||
NSEnumerator *families = [[fontManager availableFontFamilies] objectEnumerator]; // returns "canonical", non-localized family name
|
NSEnumerator *families = [[fontManager availableFontFamilies] objectEnumerator]; // returns "canonical", non-localized family name
|
||||||
|
|
||||||
NSMutableArray* localizedNames = [[NSMutableArray alloc] init];
|
nsAutoString availableFamilyName, postscriptFontName;
|
||||||
nsAutoString availableFamilyName, postscriptFontName, localizedName;
|
|
||||||
|
|
||||||
NSString *availableFamily = nil;
|
NSString *availableFamily = nil;
|
||||||
while ((availableFamily = [families nextObject])) {
|
while ((availableFamily = [families nextObject])) {
|
||||||
|
@ -630,13 +656,12 @@ gfxQuartzFontCache::InitFontList()
|
||||||
GetStringForNSString(availableFamily, availableFamilyName);
|
GetStringForNSString(availableFamily, availableFamilyName);
|
||||||
|
|
||||||
// create a family entry
|
// create a family entry
|
||||||
nsRefPtr<MacOSFamilyEntry> familyEntry = new MacOSFamilyEntry(availableFamilyName);
|
MacOSFamilyEntry *familyEntry = new MacOSFamilyEntry(availableFamilyName);
|
||||||
if (!familyEntry) break;
|
if (!familyEntry) break;
|
||||||
|
|
||||||
// create a font entry for each face
|
// create a font entry for each face
|
||||||
NSArray *fontfaces = [fontManager availableMembersOfFontFamily:availableFamily]; // returns an array of [psname, style name, weight, traits] elements, goofy api
|
NSArray *fontfaces = [fontManager availableMembersOfFontFamily:availableFamily]; // returns an array of [psname, style name, weight, traits] elements, goofy api
|
||||||
int faceCount = [fontfaces count];
|
int faceCount = [fontfaces count];
|
||||||
int normalFaceIndex = kIndexNormalFace_NotFound;
|
|
||||||
int faceIndex;
|
int faceIndex;
|
||||||
|
|
||||||
for (faceIndex = 0; faceIndex < faceCount; faceIndex++) {
|
for (faceIndex = 0; faceIndex < faceCount; faceIndex++) {
|
||||||
|
@ -651,52 +676,32 @@ gfxQuartzFontCache::InitFontList()
|
||||||
if (!(traits & NSItalicFontMask))
|
if (!(traits & NSItalicFontMask))
|
||||||
traits |= NSUnitalicFontMask;
|
traits |= NSUnitalicFontMask;
|
||||||
|
|
||||||
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(init) family: %s, psname: %s, face: %s, apple-weight: %d, css-weight: %d, traits: %8.8x\n",
|
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontinit) family: %s, psname: %s, face: %s, apple-weight: %d, css-weight: %d, traits: %8.8x\n",
|
||||||
[availableFamily UTF8String], [psname UTF8String], [[face objectAtIndex:INDEX_FONT_FACE_NAME] UTF8String], weight, gfxQuartzFontCache::AppleWeightToCSSWeight(weight), traits ));
|
[availableFamily UTF8String], [psname UTF8String], [[face objectAtIndex:INDEX_FONT_FACE_NAME] UTF8String], weight, gfxQuartzFontCache::AppleWeightToCSSWeight(weight), traits ));
|
||||||
|
|
||||||
// make a nsString
|
// make a nsString
|
||||||
GetStringForNSString(psname, postscriptFontName);
|
GetStringForNSString(psname, postscriptFontName);
|
||||||
|
|
||||||
// create a font entry
|
// create a font entry
|
||||||
nsRefPtr<MacOSFontEntry> fontEntry = new MacOSFontEntry(postscriptFontName, weight, traits, familyEntry);
|
MacOSFontEntry *fontEntry = new MacOSFontEntry(postscriptFontName, weight, traits, familyEntry);
|
||||||
if (!fontEntry) break;
|
if (!fontEntry) break;
|
||||||
|
|
||||||
// insert into font entry array of family
|
// insert into font entry array of family
|
||||||
familyEntry->AddFontEntry(fontEntry);
|
familyEntry->AddFontEntry(fontEntry);
|
||||||
|
|
||||||
// if normal face not found yet, check the traits for this one
|
|
||||||
if ( normalFaceIndex == kIndexNormalFace_NotFound && !(traits & kNonNormalTraits))
|
|
||||||
normalFaceIndex = faceIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no normal face, just use the first face in the array of available ones
|
|
||||||
if ( normalFaceIndex == kIndexNormalFace_NotFound )
|
|
||||||
normalFaceIndex = 0;
|
|
||||||
|
|
||||||
// read the name table for the normal face; if localized names exist for that face, scan all font entries for more localized names
|
|
||||||
[localizedNames removeAllObjects];
|
|
||||||
ReadOtherFamilyNames(availableFamily, fontfaces, normalFaceIndex, localizedNames);
|
|
||||||
if ([localizedNames count] != 0) {
|
|
||||||
for (faceIndex = 0; faceIndex < faceCount; faceIndex++) {
|
|
||||||
if (faceIndex == normalFaceIndex) continue;
|
|
||||||
ReadOtherFamilyNames(availableFamily, fontfaces, faceIndex, localizedNames);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the family entry to the hash table
|
// add the family entry to the hash table
|
||||||
ToLowerCase(availableFamilyName);
|
ToLowerCase(availableFamilyName);
|
||||||
mFontFamilies.Put(availableFamilyName, familyEntry);
|
mFontFamilies.Put(availableFamilyName, familyEntry);
|
||||||
|
|
||||||
// add in an entry for each of the localized names
|
|
||||||
int lnameIndex, lnameCount = [localizedNames count];
|
|
||||||
for (lnameIndex = 0; lnameIndex < lnameCount; lnameIndex++) {
|
|
||||||
GetStringForNSString([localizedNames objectAtIndex:lnameIndex], localizedName);
|
|
||||||
ToLowerCase(localizedName);
|
|
||||||
mLocalizedFamilies.Put(localizedName, familyEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
ReadOtherFamilyNamesForFamily(NS_LITERAL_STRING("Hiragino Kaku Gothic Pro"));
|
||||||
|
ReadOtherFamilyNamesForFamily(NS_LITERAL_STRING("Hiragino Mincho Pro"));
|
||||||
|
ReadOtherFamilyNamesForFamily(NS_LITERAL_STRING("STSong"));
|
||||||
|
|
||||||
// xxx - deal with quirks (e.g. Osaka-Mono)
|
// xxx - deal with quirks (e.g. Osaka-Mono)
|
||||||
|
|
||||||
// xxx - need to remove bogus Helvetica/Courier italic faces (Cocoa inanity!)
|
// xxx - need to remove bogus Helvetica/Courier italic faces (Cocoa inanity!)
|
||||||
|
@ -705,19 +710,45 @@ gfxQuartzFontCache::InitFontList()
|
||||||
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
||||||
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
|
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
|
||||||
mCodepointsWithNoFonts.set(0xfffd); // unknown
|
mCodepointsWithNoFonts.set(0xfffd); // unknown
|
||||||
|
|
||||||
[localizedNames release];
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxQuartzFontCache::InitOtherFamilyNames()
|
||||||
|
{
|
||||||
|
mOtherFamilyNamesInitialized = PR_TRUE;
|
||||||
|
|
||||||
|
// iterate over all font families and read in other family names
|
||||||
|
mFontFamilies.Enumerate(gfxQuartzFontCache::InitOtherFamilyNamesProc, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PLDHashOperator PR_CALLBACK gfxQuartzFontCache::InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey,
|
||||||
|
nsRefPtr<MacOSFamilyEntry>& aFamilyEntry,
|
||||||
|
void* userArg)
|
||||||
|
{
|
||||||
|
gfxQuartzFontCache *fc = (gfxQuartzFontCache*) userArg;
|
||||||
|
AddOtherFamilyNameFunctor addOtherNames(fc);
|
||||||
|
aFamilyEntry->ReadOtherFamilyNames(addOtherNames);
|
||||||
|
return PL_DHASH_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxQuartzFontCache::ReadOtherFamilyNamesForFamily(const nsAString& aFamilyName)
|
||||||
|
{
|
||||||
|
MacOSFamilyEntry *familyEntry = FindFamily(aFamilyName);
|
||||||
|
|
||||||
|
if (familyEntry) {
|
||||||
|
AddOtherFamilyNameFunctor addOtherNames(this);
|
||||||
|
familyEntry->ReadOtherFamilyNames(addOtherNames);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
gfxQuartzFontCache::ResolveFontName(const nsAString& aFontName, nsAString& aResolvedFontName)
|
gfxQuartzFontCache::ResolveFontName(const nsAString& aFontName, nsAString& aResolvedFontName)
|
||||||
{
|
{
|
||||||
nsAutoString key;
|
MacOSFamilyEntry *family = FindFamily(aFontName);
|
||||||
nsRefPtr<MacOSFamilyEntry> familyEntry;
|
if (family) {
|
||||||
GenerateFontListKey(aFontName, key);
|
aResolvedFontName = family->Name();
|
||||||
|
|
||||||
if (mFontFamilies.Get(key, &familyEntry) || mLocalizedFamilies.Get(key, &familyEntry)) {
|
|
||||||
aResolvedFontName = familyEntry->Name();
|
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
@ -822,12 +853,29 @@ MacOSFamilyEntry*
|
||||||
gfxQuartzFontCache::FindFamily(const nsAString& aFamily)
|
gfxQuartzFontCache::FindFamily(const nsAString& aFamily)
|
||||||
{
|
{
|
||||||
nsAutoString key;
|
nsAutoString key;
|
||||||
nsRefPtr<MacOSFamilyEntry> familyEntry;
|
MacOSFamilyEntry *familyEntry;
|
||||||
GenerateFontListKey(aFamily, key);
|
GenerateFontListKey(aFamily, key);
|
||||||
|
|
||||||
if (mFontFamilies.Get(key, &familyEntry) || mLocalizedFamilies.Get(key, &familyEntry)) {
|
// lookup in canonical (i.e. English) family name list
|
||||||
|
if (mFontFamilies.Get(key, &familyEntry)) {
|
||||||
return familyEntry;
|
return familyEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lookup in other family names list (mostly localized names)
|
||||||
|
if (mOtherFamilyNames.Get(key, &familyEntry)) {
|
||||||
|
return familyEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// name not found and other family names not yet fully initialized so
|
||||||
|
// initialize the rest of the list and try again. this is done lazily
|
||||||
|
// since reading name table entries is expensive
|
||||||
|
if (!mOtherFamilyNamesInitialized) {
|
||||||
|
InitOtherFamilyNames();
|
||||||
|
if (mOtherFamilyNames.Get(key, &familyEntry)) {
|
||||||
|
return familyEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -864,3 +912,17 @@ gfxQuartzFontCache::SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<
|
||||||
mPrefFonts.Put(PRUint32(aLangGroup), array);
|
mPrefFonts.Put(PRUint32(aLangGroup), array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxQuartzFontCache::AddOtherFamilyName(MacOSFamilyEntry *aFamilyEntry, nsAString& aOtherFamilyName)
|
||||||
|
{
|
||||||
|
nsAutoString key;
|
||||||
|
MacOSFamilyEntry *familyEntry;
|
||||||
|
GenerateFontListKey(aOtherFamilyName, key);
|
||||||
|
|
||||||
|
if (!mOtherFamilyNames.Get(key, &familyEntry)) {
|
||||||
|
mOtherFamilyNames.Put(key, aFamilyEntry);
|
||||||
|
PR_LOG(gFontInfoLog, PR_LOG_DEBUG, ("(fontinit-otherfamily) canonical family: %s, other family: %s\n",
|
||||||
|
NS_ConvertUTF16toUTF8(aFamilyEntry->Name()).get(),
|
||||||
|
NS_ConvertUTF16toUTF8(aOtherFamilyName).get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче