Bug 1962172 - Store CJK font-selection fallback order in the cached FontPrefs. r=gfx-reviewers,lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D246894
This commit is contained in:
committed by
jkew@mozilla.com
parent
c73734bdca
commit
5f22c84573
@@ -2470,131 +2470,8 @@ void gfxPlatformFontList::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[],
|
|||||||
AppendPrefLang(aPrefLangs, aLen, aPageLang);
|
AppendPrefLang(aPrefLangs, aLen, aPageLang);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if not set up, set up the default CJK order, based on accept lang
|
|
||||||
// settings and locale
|
|
||||||
if (mCJKPrefLangs.Length() == 0) {
|
|
||||||
// temp array
|
|
||||||
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
|
|
||||||
uint32_t tempLen = 0;
|
|
||||||
|
|
||||||
// Add the CJK pref fonts from accept languages, the order should be same
|
|
||||||
// order. We use gfxFontUtils::GetPrefsFontList to read the list even
|
|
||||||
// though it's not actually a list of fonts but of lang codes; the format
|
|
||||||
// is the same.
|
|
||||||
AutoTArray<nsCString, 5> list;
|
|
||||||
gfxFontUtils::GetPrefsFontList("intl.accept_languages", list, true);
|
|
||||||
for (const auto& lang : list) {
|
|
||||||
eFontPrefLang fpl = GetFontPrefLangFor(lang.get());
|
|
||||||
switch (fpl) {
|
|
||||||
case eFontPrefLang_Japanese:
|
|
||||||
case eFontPrefLang_Korean:
|
|
||||||
case eFontPrefLang_ChineseCN:
|
|
||||||
case eFontPrefLang_ChineseHK:
|
|
||||||
case eFontPrefLang_ChineseTW:
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, fpl);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try using app's locale
|
|
||||||
nsAutoCString localeStr;
|
|
||||||
LocaleService::GetInstance()->GetAppLocaleAsBCP47(localeStr);
|
|
||||||
|
|
||||||
{
|
|
||||||
Locale locale;
|
|
||||||
if (LocaleParser::TryParse(localeStr, locale).isOk() &&
|
|
||||||
locale.Canonicalize().isOk()) {
|
|
||||||
if (locale.Language().EqualTo("ja")) {
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
|
||||||
} else if (locale.Language().EqualTo("zh")) {
|
|
||||||
if (locale.Region().EqualTo("CN")) {
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
|
||||||
} else if (locale.Region().EqualTo("TW")) {
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
|
||||||
} else if (locale.Region().EqualTo("HK")) {
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
|
||||||
}
|
|
||||||
} else if (locale.Language().EqualTo("ko")) {
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then add the known CJK prefs in order of system preferred locales
|
|
||||||
AutoTArray<nsCString, 5> prefLocales;
|
|
||||||
prefLocales.AppendElement("ja"_ns);
|
|
||||||
prefLocales.AppendElement("zh-CN"_ns);
|
|
||||||
prefLocales.AppendElement("zh-TW"_ns);
|
|
||||||
prefLocales.AppendElement("zh-HK"_ns);
|
|
||||||
prefLocales.AppendElement("ko"_ns);
|
|
||||||
|
|
||||||
AutoTArray<nsCString, 16> sysLocales;
|
|
||||||
AutoTArray<nsCString, 16> negLocales;
|
|
||||||
if (NS_SUCCEEDED(
|
|
||||||
OSPreferences::GetInstance()->GetSystemLocales(sysLocales))) {
|
|
||||||
LocaleService::GetInstance()->NegotiateLanguages(
|
|
||||||
sysLocales, prefLocales, ""_ns,
|
|
||||||
LocaleService::kLangNegStrategyFiltering, negLocales);
|
|
||||||
for (const auto& localeStr : negLocales) {
|
|
||||||
Locale locale;
|
|
||||||
if (LocaleParser::TryParse(localeStr, locale).isOk() &&
|
|
||||||
locale.Canonicalize().isOk()) {
|
|
||||||
if (locale.Language().EqualTo("ja")) {
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
|
||||||
} else if (locale.Language().EqualTo("zh")) {
|
|
||||||
if (locale.Region().EqualTo("CN")) {
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
|
||||||
} else if (locale.Region().EqualTo("TW")) {
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
|
||||||
} else if (locale.Region().EqualTo("HK")) {
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
|
||||||
}
|
|
||||||
} else if (locale.Language().EqualTo("ko")) {
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last resort... set up CJK font prefs in the order listed by the user-
|
|
||||||
// configurable ordering pref.
|
|
||||||
gfxFontUtils::GetPrefsFontList(kCJKFallbackOrderPref, list);
|
|
||||||
for (const auto& item : list) {
|
|
||||||
eFontPrefLang fpl = GetFontPrefLangFor(item.get());
|
|
||||||
switch (fpl) {
|
|
||||||
case eFontPrefLang_Japanese:
|
|
||||||
case eFontPrefLang_Korean:
|
|
||||||
case eFontPrefLang_ChineseCN:
|
|
||||||
case eFontPrefLang_ChineseHK:
|
|
||||||
case eFontPrefLang_ChineseTW:
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, fpl);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Truly-last resort... try Chinese font prefs before Japanese because
|
|
||||||
// they tend to have more complete character coverage, and therefore less
|
|
||||||
// risk of "ransom-note" effects.
|
|
||||||
// (If the kCJKFallbackOrderPref was fully populated, as it is by default,
|
|
||||||
// this will do nothing as all these values are already present.)
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
|
||||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
|
||||||
|
|
||||||
// copy into the cached array
|
|
||||||
for (const auto lang : Span<eFontPrefLang>(tempPrefLangs, tempLen)) {
|
|
||||||
mCJKPrefLangs.AppendElement(lang);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// append in cached CJK langs
|
// append in cached CJK langs
|
||||||
for (const auto lang : mCJKPrefLangs) {
|
for (const auto lang : GetFontPrefs()->CJKPrefLangs()) {
|
||||||
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang(lang));
|
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang(lang));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2934,7 +2811,6 @@ void gfxPlatformFontList::ClearLangGroupPrefFontsLocked() {
|
|||||||
pref = nullptr;
|
pref = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mCJKPrefLangs.Clear();
|
|
||||||
mEmojiPrefFont = nullptr;
|
mEmojiPrefFont = nullptr;
|
||||||
|
|
||||||
// Create a new FontPrefs and replace the existing one.
|
// Create a new FontPrefs and replace the existing one.
|
||||||
@@ -3338,6 +3214,125 @@ void gfxPlatformFontList::FontPrefs::Init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mEmojiHasUserValue = Preferences::HasUserValue("font.name-list.emoji");
|
mEmojiHasUserValue = Preferences::HasUserValue("font.name-list.emoji");
|
||||||
|
|
||||||
|
// Record the default CJK order, based on accept-lang settings and locale.
|
||||||
|
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
|
||||||
|
uint32_t tempLen = 0;
|
||||||
|
|
||||||
|
// Add the CJK pref fonts from accept languages, the order should be same
|
||||||
|
// order. We use gfxFontUtils::GetPrefsFontList to read the list even
|
||||||
|
// though it's not actually a list of fonts but of lang codes; the format
|
||||||
|
// is the same.
|
||||||
|
AutoTArray<nsCString, 5> list;
|
||||||
|
gfxFontUtils::GetPrefsFontList("intl.accept_languages", list, true);
|
||||||
|
for (const auto& lang : list) {
|
||||||
|
eFontPrefLang fpl = GetFontPrefLangFor(lang.get());
|
||||||
|
switch (fpl) {
|
||||||
|
case eFontPrefLang_Japanese:
|
||||||
|
case eFontPrefLang_Korean:
|
||||||
|
case eFontPrefLang_ChineseCN:
|
||||||
|
case eFontPrefLang_ChineseHK:
|
||||||
|
case eFontPrefLang_ChineseTW:
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, fpl);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try using app's locale
|
||||||
|
nsAutoCString localeStr;
|
||||||
|
LocaleService::GetInstance()->GetAppLocaleAsBCP47(localeStr);
|
||||||
|
|
||||||
|
{
|
||||||
|
Locale locale;
|
||||||
|
if (LocaleParser::TryParse(localeStr, locale).isOk() &&
|
||||||
|
locale.Canonicalize().isOk()) {
|
||||||
|
if (locale.Language().EqualTo("ja")) {
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||||
|
} else if (locale.Language().EqualTo("zh")) {
|
||||||
|
if (locale.Region().EqualTo("CN")) {
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||||
|
} else if (locale.Region().EqualTo("TW")) {
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||||
|
} else if (locale.Region().EqualTo("HK")) {
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||||
|
}
|
||||||
|
} else if (locale.Language().EqualTo("ko")) {
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then add the known CJK prefs in order of system preferred locales
|
||||||
|
AutoTArray<nsCString, 5> prefLocales;
|
||||||
|
prefLocales.AppendElement("ja"_ns);
|
||||||
|
prefLocales.AppendElement("zh-CN"_ns);
|
||||||
|
prefLocales.AppendElement("zh-TW"_ns);
|
||||||
|
prefLocales.AppendElement("zh-HK"_ns);
|
||||||
|
prefLocales.AppendElement("ko"_ns);
|
||||||
|
|
||||||
|
AutoTArray<nsCString, 16> sysLocales;
|
||||||
|
AutoTArray<nsCString, 16> negLocales;
|
||||||
|
if (NS_SUCCEEDED(
|
||||||
|
OSPreferences::GetInstance()->GetSystemLocales(sysLocales))) {
|
||||||
|
LocaleService::GetInstance()->NegotiateLanguages(
|
||||||
|
sysLocales, prefLocales, ""_ns,
|
||||||
|
LocaleService::kLangNegStrategyFiltering, negLocales);
|
||||||
|
for (const auto& localeStr : negLocales) {
|
||||||
|
Locale locale;
|
||||||
|
if (LocaleParser::TryParse(localeStr, locale).isOk() &&
|
||||||
|
locale.Canonicalize().isOk()) {
|
||||||
|
if (locale.Language().EqualTo("ja")) {
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||||
|
} else if (locale.Language().EqualTo("zh")) {
|
||||||
|
if (locale.Region().EqualTo("CN")) {
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||||
|
} else if (locale.Region().EqualTo("TW")) {
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||||
|
} else if (locale.Region().EqualTo("HK")) {
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||||
|
}
|
||||||
|
} else if (locale.Language().EqualTo("ko")) {
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last resort... set up CJK font prefs in the order listed by the user-
|
||||||
|
// configurable ordering pref.
|
||||||
|
gfxFontUtils::GetPrefsFontList(kCJKFallbackOrderPref, list);
|
||||||
|
for (const auto& item : list) {
|
||||||
|
eFontPrefLang fpl = GetFontPrefLangFor(item.get());
|
||||||
|
switch (fpl) {
|
||||||
|
case eFontPrefLang_Japanese:
|
||||||
|
case eFontPrefLang_Korean:
|
||||||
|
case eFontPrefLang_ChineseCN:
|
||||||
|
case eFontPrefLang_ChineseHK:
|
||||||
|
case eFontPrefLang_ChineseTW:
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, fpl);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truly-last resort... try Chinese font prefs before Japanese because
|
||||||
|
// they tend to have more complete character coverage, and therefore less
|
||||||
|
// risk of "ransom-note" effects.
|
||||||
|
// (If the kCJKFallbackOrderPref was fully populated, as it is by default,
|
||||||
|
// this will do nothing as all these values are already present.)
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||||
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||||
|
|
||||||
|
// copy into the cached array
|
||||||
|
for (const auto lang : Span<eFontPrefLang>(tempPrefLangs, tempLen)) {
|
||||||
|
mCJKPrefLangs.AppendElement(lang);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gfxPlatformFontList::FontPrefs::LookupName(const nsACString& aPref,
|
bool gfxPlatformFontList::FontPrefs::LookupName(const nsACString& aPref,
|
||||||
|
|||||||
@@ -198,6 +198,8 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
|
|||||||
return mFontNameList.ConstIter();
|
return mFontNameList.ConstIter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nsTArray<uint32_t>& CJKPrefLangs() const { return mCJKPrefLangs; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr char kNamePrefix[] = "font.name.";
|
static constexpr char kNamePrefix[] = "font.name.";
|
||||||
static constexpr char kNameListPrefix[] = "font.name-list.";
|
static constexpr char kNameListPrefix[] = "font.name-list.";
|
||||||
@@ -206,6 +208,7 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
|
|||||||
|
|
||||||
HashMap mFontName;
|
HashMap mFontName;
|
||||||
HashMap mFontNameList;
|
HashMap mFontNameList;
|
||||||
|
nsTArray<uint32_t> mCJKPrefLangs;
|
||||||
bool mEmojiHasUserValue = false;
|
bool mEmojiHasUserValue = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1055,7 +1058,6 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
|
|||||||
|
|
||||||
nsLanguageAtomService* mLangService = nullptr;
|
nsLanguageAtomService* mLangService = nullptr;
|
||||||
|
|
||||||
nsTArray<uint32_t> mCJKPrefLangs MOZ_GUARDED_BY(mLock);
|
|
||||||
nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup
|
nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup
|
||||||
MOZ_GUARDED_BY(mLock);
|
MOZ_GUARDED_BY(mLock);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user