зеркало из https://github.com/mozilla/gecko-dev.git
Bug 364785 ts regression by bug 362665 and bug 364678 and Bug 364832 Family names should not be high priority rather than font name r=vlad
This commit is contained in:
Родитель
786b2b9d4e
Коммит
906acf7a9d
|
@ -196,9 +196,17 @@ private:
|
|||
nsDataHashtable<nsStringHashKey, nsRefPtr<FamilyEntry> > mFamilies;
|
||||
// The keys are the localized postscript names.
|
||||
nsDataHashtable<nsStringHashKey, nsRefPtr<FontEntry> > mPostscriptFonts;
|
||||
// The keys are ATSUI font ID.
|
||||
nsDataHashtable<nsUint32HashKey, nsRefPtr<FontEntry> > mFontIDTable;
|
||||
// The keys are family names that is cached from all fonts.
|
||||
// But at caching time, we cannot resolve to actual font.
|
||||
// Therefore, the datas are basic family name of the font.
|
||||
// You can resolve the basic family name to |postscript names| with
|
||||
// |mFontIDTable|. See |ResolveFontName|.
|
||||
nsDataHashtable<nsStringHashKey, nsString> mAppleFamilyNames;
|
||||
// The keys are all family names (including alias family names).
|
||||
// The datas are postscript name, therefore,
|
||||
// you can resolve |all family names| to |postscript nams|
|
||||
// you can resolve |all family names| to |postscript nams|
|
||||
nsDataHashtable<nsStringHashKey, nsString> mAllFamilyNames;
|
||||
// The keys are all font names (including alias font names).
|
||||
// The datas are postscript name, therefore,
|
||||
|
@ -208,8 +216,11 @@ private:
|
|||
// for different fonts. Because a family name shared in one or more fonts.
|
||||
// So, if you want to resolve the name, you MUST check as following order:
|
||||
// 1. mPostscriptFont
|
||||
// 2. mAllFamilyNames
|
||||
// 3. mAllFontNames
|
||||
// 2. mAllFontNames
|
||||
// 3. mAllFamilyNames
|
||||
|
||||
// The non-existing font names are always lowercased.
|
||||
nsStringArray mNonExistingFonts;
|
||||
};
|
||||
|
||||
#endif /* GFXQUARTZFONTCACHE_H_ */
|
||||
|
|
|
@ -146,8 +146,10 @@ gfxQuartzFontCache::gfxQuartzFontCache()
|
|||
{
|
||||
mCache.Init();
|
||||
mFamilies.Init(30);
|
||||
mAppleFamilyNames.Init(60);
|
||||
mAllFamilyNames.Init(60);
|
||||
mPostscriptFonts.Init(60);
|
||||
mFontIDTable.Init(60);
|
||||
mAllFontNames.Init(100);
|
||||
InitFontList();
|
||||
::ATSFontNotificationSubscribe(ATSNotification,
|
||||
|
@ -183,15 +185,6 @@ gfxQuartzFontCache::AppendFontFamily(NSFontManager *aFontManager,
|
|||
// we should use localized simple family name.
|
||||
NSString *name = [aFontManager localizedNameForFamily:aName face:nil];
|
||||
GetStringForNSString(name, displayName);
|
||||
|
||||
// Cache only the original name of the family.
|
||||
// (the localized names and display names will be appended)
|
||||
NSString *psName = [[NSFont fontWithName:aName size:10.0] fontName];
|
||||
nsAutoString strPsName, strFamilyName;
|
||||
GetStringForNSString(psName, strPsName);
|
||||
GetStringForNSString(aName, strFamilyName);
|
||||
GenerateFontListKey(strFamilyName, key);
|
||||
mAllFamilyNames.Put(key, strPsName);
|
||||
}
|
||||
|
||||
GenerateFontListKey(displayName, key);
|
||||
|
@ -254,7 +247,9 @@ gfxQuartzFontCache::InitFontList()
|
|||
mFamilies.Clear();
|
||||
mAllFamilyNames.Clear();
|
||||
mPostscriptFonts.Clear();
|
||||
mFontIDTable.Clear();
|
||||
mAllFontNames.Clear();
|
||||
mNonExistingFonts.Clear();
|
||||
|
||||
nsAutoString key;
|
||||
|
||||
|
@ -288,9 +283,9 @@ gfxQuartzFontCache::InitFontList()
|
|||
}
|
||||
}
|
||||
|
||||
// We should cache for all alias for all families.
|
||||
// We will use this for resolving the font names to actual fonts.
|
||||
// We should use ATSUI for this, because cocoa cannot show the all aliases.
|
||||
// We should cache for all alias for all families for resloving the given
|
||||
// font name to postscript name. But if we cache all font names here,
|
||||
// the start up time is slowly, so we should only cache the minimum list.
|
||||
ItemCount fontCount;
|
||||
OSStatus err = ::ATSUFontCount(&fontCount);
|
||||
if (err != noErr)
|
||||
|
@ -300,117 +295,109 @@ gfxQuartzFontCache::InitFontList()
|
|||
err = ::ATSUGetFontIDs(fontIDs, arraySize, &fontCount);
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
TextEncoding encoding = 0;
|
||||
TECObjectRef converter = nsnull;
|
||||
|
||||
// In principle, we should get actual length of font name,
|
||||
// but we can skip it by the enough buffer length.
|
||||
ByteCount len;
|
||||
ItemCount index;
|
||||
const ByteCount kBufLength = 1024;
|
||||
char buf[kBufLength];
|
||||
nsAutoString basicFamilyName, postscriptName, name;
|
||||
|
||||
for (ItemCount i = 0; i < fontCount; i++) {
|
||||
struct FontNames {
|
||||
FontNames() {
|
||||
mShouldProgress = PR_FALSE;
|
||||
}
|
||||
nsStringArray mNames;
|
||||
nsStringArray mFamilyNames;
|
||||
nsString mFamily;
|
||||
nsString mPostscriptName;
|
||||
PRBool mShouldProgress;
|
||||
};
|
||||
FontNames names;
|
||||
// Get postscript name, first.
|
||||
err = ATSUFindFontName(fontIDs[i], kFontPostscriptName,
|
||||
kFontNoPlatformCode, kFontNoScriptCode,
|
||||
kFontNoLanguageCode, kBufLength,
|
||||
buf, &len, &index);
|
||||
if (err != noErr || len == 0)
|
||||
continue;
|
||||
|
||||
FontNameCode nameCode;
|
||||
FontPlatformCode platformCode;
|
||||
FontScriptCode scriptCode;
|
||||
FontLanguageCode langCode;
|
||||
err = ::ATSUGetIndFontName(fontIDs[i], index, kBufLength, buf, &len,
|
||||
&nameCode, &platformCode,
|
||||
&scriptCode, &langCode);
|
||||
if (err != noErr || len == 0)
|
||||
continue;
|
||||
|
||||
postscriptName.Truncate();
|
||||
if (!GetFontNameFromBuffer(buf, len, platformCode, scriptCode,
|
||||
langCode, converter, encoding,
|
||||
postscriptName))
|
||||
continue;
|
||||
|
||||
// We should get family name from mFamilies for checking the first
|
||||
// character of the name.
|
||||
nsRefPtr<FontEntry> psFont = new FontEntry(postscriptName);
|
||||
NSFont *font = psFont->GetNSFont(10.0);
|
||||
basicFamilyName.Truncate();
|
||||
GetStringForNSString([font familyName], basicFamilyName);
|
||||
NS_ASSERTION(!basicFamilyName.IsEmpty(),
|
||||
"fail to get basic family name");
|
||||
|
||||
PRBool ignoreThisFont = PR_FALSE;
|
||||
if (basicFamilyName[0] == PRUnichar('.') ||
|
||||
basicFamilyName[0] == PRUnichar('%'))
|
||||
ignoreThisFont = PR_TRUE;
|
||||
|
||||
// Append postscript to mPostscriptFonts
|
||||
GenerateFontListKey(postscriptName, key);
|
||||
if (!ignoreThisFont) {
|
||||
mPostscriptFonts.Put(key, psFont);
|
||||
mFontIDTable.Put(PRUint32(fontIDs[i]), psFont);
|
||||
} else {
|
||||
mNonExistingFonts.AppendString(key);
|
||||
}
|
||||
|
||||
ItemCount nameCount;
|
||||
err = ::ATSUCountFontNames(fontIDs[i], &nameCount);
|
||||
if (err != noErr || nameCount == 0)
|
||||
continue;
|
||||
|
||||
for (ItemCount j = 0; j < nameCount; j++) {
|
||||
// In principle, we should get actual length of font name,
|
||||
// but we can skip it by the enough buffer length.
|
||||
ByteCount len;
|
||||
const ByteCount kBufLength = 1024;
|
||||
char buf[kBufLength];
|
||||
FontNameCode nameCode;
|
||||
FontPlatformCode platformCode;
|
||||
FontScriptCode scriptCode;
|
||||
FontLanguageCode langCode;
|
||||
err = ::ATSUGetIndFontName(fontIDs[i], j, kBufLength, buf, &len,
|
||||
&nameCode, &platformCode,
|
||||
&scriptCode, &langCode);
|
||||
if (err != noErr || len == 0)
|
||||
continue;
|
||||
switch (nameCode) {
|
||||
case kFontFamilyName:
|
||||
case kFontFullName:
|
||||
case kFontPostscriptName:
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
nsAutoString fontName;
|
||||
|
||||
if (nameCode != kFontFamilyName && nameCode != kFontFullName)
|
||||
continue;
|
||||
|
||||
// XXX the mac platform font names cannot be found by
|
||||
// ATSUFindFontFromName with UTF16 string. So, we MUST cache the
|
||||
// names here, but we can get the other names later.
|
||||
if (!ignoreThisFont && platformCode != kFontMacintoshPlatform)
|
||||
continue;
|
||||
|
||||
name.Truncate();
|
||||
if (!GetFontNameFromBuffer(buf, len, platformCode, scriptCode,
|
||||
langCode, converter, encoding, fontName))
|
||||
langCode, converter, encoding, name))
|
||||
continue;
|
||||
|
||||
if (fontName[0] == PRUnichar('.') ||
|
||||
fontName[0] == PRUnichar('%')) {
|
||||
// We should ignore this font.
|
||||
names.mShouldProgress = PR_FALSE;
|
||||
break;
|
||||
GenerateFontListKey(name, key);
|
||||
if (ignoreThisFont) {
|
||||
if (mNonExistingFonts.IndexOf(key) >= 0)
|
||||
mNonExistingFonts.AppendString(key);
|
||||
continue;
|
||||
}
|
||||
names.mShouldProgress = PR_TRUE;
|
||||
|
||||
switch (nameCode) {
|
||||
case kFontFamilyName:
|
||||
names.mFamilyNames.AppendString(fontName);
|
||||
// Find the family name of cocoa
|
||||
if (names.mFamily.IsEmpty()) {
|
||||
GenerateFontListKey(fontName, key);
|
||||
nsAutoString s;
|
||||
if (mAllFamilyNames.Get(key, &s))
|
||||
names.mFamily = s;
|
||||
}
|
||||
break;
|
||||
case kFontFullName:
|
||||
names.mNames.AppendString(fontName);
|
||||
mAllFontNames.Put(key, psFont->Name());
|
||||
break;
|
||||
case kFontPostscriptName:
|
||||
NS_ASSERTION(names.mPostscriptName.IsEmpty() ||
|
||||
names.mPostscriptName.Equals(fontName),
|
||||
"A font id has two or more postscript name!");
|
||||
names.mPostscriptName = fontName;
|
||||
case kFontFamilyName:
|
||||
// XXX we cannot resolve to postscript name, here.
|
||||
// Don't use fontName of NSFont that is buggy in some cases.
|
||||
mAppleFamilyNames.Put(key, basicFamilyName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!names.mShouldProgress)
|
||||
continue;
|
||||
if (names.mPostscriptName.IsEmpty())
|
||||
continue;
|
||||
nsRefPtr<FontEntry> psFont = new FontEntry(names.mPostscriptName);
|
||||
GenerateFontListKey(names.mPostscriptName, key);
|
||||
mPostscriptFonts.Put(key, psFont);
|
||||
|
||||
for (PRInt32 j = 0; j < names.mNames.Count(); j++) {
|
||||
GenerateFontListKey(*names.mNames[j], key);
|
||||
nsAutoString str;
|
||||
if (mAllFontNames.Get(key, &str))
|
||||
continue;
|
||||
mAllFontNames.Put(key, psFont->Name());
|
||||
}
|
||||
|
||||
if (names.mFamily.IsEmpty()) {
|
||||
NSFont *font = psFont->GetNSFont(10.0);
|
||||
nsAutoString str;
|
||||
GetStringForNSString([font familyName], str);
|
||||
if (str.IsEmpty()) {
|
||||
NS_ERROR("Why I cannot find the family name?");
|
||||
continue;
|
||||
}
|
||||
names.mFamily = str;
|
||||
}
|
||||
for (PRInt32 j = 0; j < names.mFamilyNames.Count(); j++) {
|
||||
nsAutoString str;
|
||||
GenerateFontListKey(*names.mFamilyNames[j], key);
|
||||
if (mAllFamilyNames.Get(key, &str))
|
||||
continue;
|
||||
mAllFamilyNames.Put(key, names.mFamily);
|
||||
}
|
||||
}
|
||||
if (converter)
|
||||
::TECDisposeConverter(converter);
|
||||
|
@ -616,8 +603,7 @@ gfxQuartzFontCache::FindFromSystem (const nsAString& aFamily,
|
|||
nsRefPtr<FontEntry> fe;
|
||||
GenerateFontListKey(aFamily, key);
|
||||
if (!mPostscriptFonts.Get(key, &fe)) {
|
||||
if (!mAllFamilyNames.Get(key, &fontName) &&
|
||||
!mAllFontNames.Get(key, &fontName))
|
||||
if (!ResolveFontName(aFamily, fontName))
|
||||
return kATSUInvalidFontID;
|
||||
GenerateFontListKey(fontName, key);
|
||||
if (!mPostscriptFonts.Get(key, &fe))
|
||||
|
@ -702,13 +688,69 @@ gfxQuartzFontCache::ResolveFontName(const nsAString& aFontName,
|
|||
nsAutoString name, key;
|
||||
nsRefPtr<FontEntry> fe;
|
||||
GenerateFontListKey(aFontName, key);
|
||||
if (mNonExistingFonts.IndexOf(key) >= 0)
|
||||
return PR_FALSE;
|
||||
if (mPostscriptFonts.Get(key, &fe)) {
|
||||
aResolvedFontName = fe->Name();
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (mAllFamilyNames.Get(key, &name) || mAllFontNames.Get(key, &name)) {
|
||||
|
||||
// try to find from font names.
|
||||
if (mAllFontNames.Get(key, &name)) {
|
||||
aResolvedFontName = name;
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
ATSUFontID fontID;
|
||||
OSStatus err;
|
||||
err = ATSUFindFontFromName(aFontName.BeginReading(),
|
||||
aFontName.Length() * sizeof(PRUnichar),
|
||||
kFontFullName,
|
||||
kFontNoPlatformCode,
|
||||
kFontNoScriptCode,
|
||||
kFontNoLanguageCode,
|
||||
&fontID);
|
||||
if (err == noErr && fontID != kATSUInvalidFontID) {
|
||||
if (!mFontIDTable.Get(PRUint32(fontID), &fe)) {
|
||||
mNonExistingFonts.AppendString(key);
|
||||
return PR_FALSE;
|
||||
}
|
||||
mAllFontNames.Put(key, fe->Name());
|
||||
aResolvedFontName = fe->Name();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// try to find from family names.
|
||||
if (mAllFamilyNames.Get(key, &name)) {
|
||||
aResolvedFontName = name;
|
||||
return PR_TRUE;
|
||||
}
|
||||
// try to find from apple family names.
|
||||
if (mAppleFamilyNames.Get(key, &name)) {
|
||||
NSString *familyName = GetNSStringForString(name);
|
||||
NSFont *font = [NSFont fontWithName:familyName size:10.0];
|
||||
// XXX Don't use fontName of NSFont. It is buggy in some cases.
|
||||
if (mFontIDTable.Get(PRUint32([font _atsFontID]), &fe)) {
|
||||
mAllFamilyNames.Put(key, fe->Name());
|
||||
aResolvedFontName = fe->Name();
|
||||
return PR_TRUE;
|
||||
}
|
||||
NS_ERROR("There is a font family, but cannot find the actual font");
|
||||
mNonExistingFonts.AppendString(key);
|
||||
return PR_FALSE;
|
||||
}
|
||||
err = ATSUFindFontFromName(aFontName.BeginReading(),
|
||||
aFontName.Length() * sizeof(PRUnichar),
|
||||
kFontFamilyName,
|
||||
kFontNoPlatformCode,
|
||||
kFontNoScriptCode,
|
||||
kFontNoLanguageCode,
|
||||
&fontID);
|
||||
if (err != noErr || fontID == kATSUInvalidFontID ||
|
||||
!mFontIDTable.Get(PRUint32(fontID), &fe)) {
|
||||
mNonExistingFonts.AppendString(key);
|
||||
return PR_FALSE;
|
||||
}
|
||||
mAllFamilyNames.Put(key, fe->Name());
|
||||
aResolvedFontName = fe->Name();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче