Bug 1928458 - Make local font name lookup prefer face [postscript/full] names that are more similar to their family name, in case of duplicates.. r=dshin

Differential Revision: https://phabricator.services.mozilla.com/D228340
This commit is contained in:
Jonathan Kew 2024-11-07 22:54:04 +00:00
parent c251285770
commit 5a21337fae
6 changed files with 85 additions and 30 deletions

View File

@ -1539,16 +1539,16 @@ void gfxDWriteFontList::ReadFaceNamesForFamily(
if (NS_SUCCEEDED(gfxFontUtils::ReadCanonicalName(
data, size, gfxFontUtils::NAME_ID_POSTSCRIPT, psname))) {
ToLowerCase(psname);
mLocalNameTable.InsertOrUpdate(
psname, fontlist::LocalFaceRec::InitData(key, i));
MaybeAddToLocalNameTable(psname,
fontlist::LocalFaceRec::InitData(key, i));
}
}
if (NS_SUCCEEDED(gfxFontUtils::ReadCanonicalName(
data, size, gfxFontUtils::NAME_ID_FULL, fullname))) {
ToLowerCase(fullname);
if (fullname != psname) {
mLocalNameTable.InsertOrUpdate(
fullname, fontlist::LocalFaceRec::InitData(key, i));
MaybeAddToLocalNameTable(fullname,
fontlist::LocalFaceRec::InitData(key, i));
}
}

View File

@ -702,13 +702,13 @@ void gfxFT2FontList::CollectInitData(const FontListEntry& aFLE,
nsAutoCString psname(aPSName), fullname(aFullName);
if (!psname.IsEmpty()) {
ToLowerCase(psname);
mLocalNameTable.InsertOrUpdate(
MaybeAddToLocalNameTable(
psname, fontlist::LocalFaceRec::InitData(key, aFLE.filepath()));
}
if (!fullname.IsEmpty()) {
ToLowerCase(fullname);
if (fullname != psname) {
mLocalNameTable.InsertOrUpdate(
MaybeAddToLocalNameTable(
fullname, fontlist::LocalFaceRec::InitData(key, aFLE.filepath()));
}
}
@ -1207,15 +1207,18 @@ void gfxFT2FontList::AppendFacesFromFontFile(const nsCString& aFileName,
uint32_t(s.st_mtime) == timestamp && s.st_size == filesize) {
CollectFunc unshared =
[](const FontListEntry& aFLE, const nsCString& aPSName,
const nsCString& aFullName, StandardFile aStdFile) {
auto* pfl = PlatformFontList();
pfl->mLock.AssertCurrentThreadIn();
pfl->AppendFaceFromFontListEntry(aFLE, aStdFile);
};
const nsCString& aFullName, StandardFile aStdFile)
MOZ_REQUIRES(PlatformFontList()->mLock) {
auto* pfl = PlatformFontList();
pfl->mLock.AssertCurrentThreadIn();
pfl->AppendFaceFromFontListEntry(aFLE, aStdFile);
};
CollectFunc shared = [](const FontListEntry& aFLE, const nsCString& aPSName,
const nsCString& aFullName, StandardFile aStdFile) {
PlatformFontList()->CollectInitData(aFLE, aPSName, aFullName, aStdFile);
};
const nsCString& aFullName, StandardFile aStdFile)
MOZ_REQUIRES(PlatformFontList()->mLock) {
PlatformFontList()->CollectInitData(
aFLE, aPSName, aFullName, aStdFile);
};
if (AppendFacesFromCachedFaceList(SharedFontList() ? shared : unshared,
aFileName, cachedFaceList, aStdFile)) {
LOG(("using cached font info for %s", aFileName.get()));
@ -1495,10 +1498,11 @@ void gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
};
CollectFunc shared = [](const FontListEntry& aFLE,
const nsCString& aPSName,
const nsCString& aFullName,
StandardFile aStdFile) {
PlatformFontList()->CollectInitData(aFLE, aPSName, aFullName, aStdFile);
};
const nsCString& aFullName, StandardFile aStdFile)
MOZ_REQUIRES(PlatformFontList()->mLock) {
PlatformFontList()->CollectInitData(
aFLE, aPSName, aFullName, aStdFile);
};
if (AppendFacesFromCachedFaceList(SharedFontList() ? shared : unshared,
aEntryName, faceList, kStandard)) {
return;

View File

@ -208,7 +208,8 @@ class gfxFT2FontList final : public gfxPlatformFontList {
void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock) override;
void CollectInitData(const FontListEntry& aFLE, const nsCString& aPSName,
const nsCString& aFullName, StandardFile aStdFile);
const nsCString& aFullName, StandardFile aStdFile)
MOZ_REQUIRES(mLock);
nsTArray<std::pair<const char**, uint32_t>> GetFilteredPlatformFontLists()
override;

View File

@ -1860,26 +1860,25 @@ void gfxFcPlatformFontList::InitSharedFontListForPlatform() {
// map the psname, fullname ==> font family for local font lookups
nsAutoCString psname, fullname;
GetFaceNames(aPattern, aFamilyName, psname, fullname);
MOZ_PUSH_IGNORE_THREAD_SAFETY
if (!psname.IsEmpty()) {
ToLowerCase(psname);
mLocalNameTable.InsertOrUpdate(
MaybeAddToLocalNameTable(
psname, fontlist::LocalFaceRec::InitData(keyName, descriptor));
}
if (!fullname.IsEmpty()) {
ToLowerCase(fullname);
if (fullname != psname) {
mLocalNameTable.WithEntryHandle(fullname, [&](auto&& entry) {
if (entry && !singleName) {
// We only override an existing entry if this is the only way to
// name this family. This prevents dubious aliases from clobbering
// the local name table.
return;
}
entry.InsertOrUpdate(
fontlist::LocalFaceRec::InitData(keyName, descriptor));
});
// We only consider overriding an existing entry if this is the only
// way to name this family. This prevents dubious aliases from
// clobbering the local name table.
if (singleName || !mLocalNameTable.Contains(fullname)) {
MaybeAddToLocalNameTable(
fullname, fontlist::LocalFaceRec::InitData(keyName, descriptor));
}
}
}
MOZ_POP_THREAD_SAFETY
return visibility == FontVisibility::Base;
};
@ -1938,6 +1937,7 @@ void gfxFcPlatformFontList::InitSharedFontListForPlatform() {
// This substantially reduces the pressure on shared memory (bug 1664151)
// due to the large font descriptors (serialized patterns).
FcChar8* fontFormat;
MOZ_PUSH_IGNORE_THREAD_SAFETY
if (FcPatternGetString(clone, FC_FONTFORMAT, 0, &fontFormat) ==
FcResultMatch &&
(!FcStrCmp(fontFormat, (const FcChar8*)"TrueType") ||
@ -1951,6 +1951,7 @@ void gfxFcPlatformFontList::InitSharedFontListForPlatform() {
++count;
}
}
MOZ_POP_THREAD_SAFETY
FcPatternDestroy(clone);
}

View File

@ -941,6 +941,47 @@ gfxFontEntry* gfxPlatformFontList::LookupInSharedFaceNameList(
return fe;
}
void gfxPlatformFontList::MaybeAddToLocalNameTable(
const nsACString& aName, const fontlist::LocalFaceRec::InitData& aData) {
// Compute a measure of the similarity between aName (which will be a PSName
// or FullName) and aReference (a font family name).
auto nameSimilarity = [](const nsACString& aName,
const nsACString& aReference) -> uint32_t {
uint32_t nameIdx = 0, refIdx = 0, matchCount = 0;
while (nameIdx < aName.Length() && refIdx < aReference.Length()) {
// Ignore non-alphanumerics in the ASCII range, so that a PSname like
// "TimesNewRomanPSMT" is a good match for family "Times New Roman".
while (nameIdx < aName.Length() && IsAscii(aName[nameIdx]) &&
!IsAsciiAlphanumeric(aName[nameIdx])) {
++nameIdx;
}
while (refIdx < aReference.Length() && IsAscii(aReference[refIdx]) &&
!IsAsciiAlphanumeric(aReference[refIdx])) {
++refIdx;
}
if (nameIdx == aName.Length() || refIdx == aReference.Length() ||
aName[nameIdx] != aReference[refIdx]) {
break;
}
++nameIdx;
++refIdx;
++matchCount;
}
return matchCount;
};
mLocalNameTable.WithEntryHandle(aName, [&](auto entry) -> void {
if (entry) {
if (nameSimilarity(aName, aData.mFamilyName) >
nameSimilarity(aName, entry.Data().mFamilyName)) {
entry.Update(aData);
}
} else {
entry.OrInsert(aData);
}
});
}
void gfxPlatformFontList::LoadBadUnderlineList() {
gfxFontUtils::GetPrefsFontList("font.blacklist.underline_offset",
mBadUnderlineFamilyNames);

View File

@ -871,6 +871,14 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
SlantStyleRange aStyleForEntry)
MOZ_REQUIRES(mLock);
// Add an entry for aName to the local names table, but only if it is not
// already present, or aName and aData.mFamilyName look like a better match
// than the existing entry.
void MaybeAddToLocalNameTable(
const nsACString& aName,
const mozilla::fontlist::LocalFaceRec::InitData& aData)
MOZ_REQUIRES(mLock);
// load the bad underline blocklist from pref.
void LoadBadUnderlineList();