Use font.name-list.emoji preference for emoji presenration.

This commit is contained in:
wolfbeast 2018-05-09 15:30:43 +02:00 committed by Roy Tam
commit 0022f326a5
6 changed files with 88 additions and 19 deletions

View file

@ -222,13 +222,14 @@ enum {
#define NS_FONT_SUB_SUPER_SMALL_SIZE (20.0)
#define NS_FONT_SUB_SUPER_LARGE_SIZE (45.0)
// pref lang id's for font prefs
// pref lang ids for font prefs
enum eFontPrefLang {
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) eFontPrefLang_ ## enum_id_
#include "gfxFontPrefLangList.h"
#undef FONT_PREF_LANG
, eFontPrefLang_CJKSet // special code for CJK set
, eFontPrefLang_Emoji // special code for emoji presentation
, eFontPrefLang_First = eFontPrefLang_Western
, eFontPrefLang_Last = eFontPrefLang_Others
, eFontPrefLang_Count = (eFontPrefLang_Last - eFontPrefLang_First + 1)

View file

@ -38,6 +38,7 @@ enum FontFamilyType : uint32_t {
// special
eFamily_moz_variable,
eFamily_moz_fixed,
eFamily_moz_emoji,
eFamily_generic_first = eFamily_serif,
eFamily_generic_last = eFamily_fantasy,

View file

@ -869,19 +869,9 @@ gfxPlatformFontList::ResolveGenericFontNames(
nsIAtom* langGroup = GetLangGroupForPrefLang(aPrefLang);
NS_ASSERTION(langGroup, "null lang group for pref lang");
// lookup and add platform fonts uniquely
for (const nsString& genericFamily : genericFamilies) {
gfxFontStyle style;
style.language = langGroup;
style.systemFont = false;
AutoTArray<gfxFontFamily*,10> families;
FindAndAddFamilies(genericFamily, &families, &style);
for (gfxFontFamily* f : families) {
if (!aGenericFamilies->Contains(f)) {
aGenericFamilies->AppendElement(f);
}
}
}
gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(genericFamilies,
langGroup,
aGenericFamilies);
#if 0 // dump out generic mappings
printf("%s ===> ", prefFontName.get());
@ -893,6 +883,43 @@ gfxPlatformFontList::ResolveGenericFontNames(
#endif
}
void
gfxPlatformFontList::ResolveEmojiFontNames(
nsTArray<RefPtr<gfxFontFamily>>* aGenericFamilies)
{
// emoji preference has no lang name
AutoTArray<nsString,4> genericFamilies;
nsAutoCString prefFontListName("font.name-list.emoji");
gfxFontUtils::AppendPrefsFontList(prefFontListName.get(), genericFamilies);
gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(genericFamilies,
nullptr,
aGenericFamilies);
}
void
gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(
nsTArray<nsString>& aGenericNameFamilies,
nsAtom* aLangGroup,
nsTArray<RefPtr<gfxFontFamily>>* aGenericFamilies)
{
// lookup and add platform fonts uniquely
for (const nsString& genericFamily : aGenericNameFamilies) {
gfxFontStyle style;
style.language = aLangGroup;
style.systemFont = false;
AutoTArray<gfxFontFamily*,10> families;
FindAndAddFamilies(genericFamily, &families, FindFamiliesFlags(0),
&style);
for (gfxFontFamily* f : families) {
if (!aGenericFamilies->Contains(f)) {
aGenericFamilies->AppendElement(f);
}
}
}
}
nsTArray<RefPtr<gfxFontFamily>>*
gfxPlatformFontList::GetPrefFontsLangGroup(mozilla::FontFamilyType aGenericType,
eFontPrefLang aPrefLang)
@ -902,6 +929,17 @@ gfxPlatformFontList::GetPrefFontsLangGroup(mozilla::FontFamilyType aGenericType,
aGenericType = eFamily_monospace;
}
if (aGenericType == eFamily_moz_emoji) {
// Emoji font has no lang
PrefFontList* prefFonts = mEmojiPrefFont.get();
if (MOZ_UNLIKELY(!prefFonts)) {
prefFonts = new PrefFontList;
ResolveEmojiFontNames(prefFonts);
mEmojiPrefFont.reset(prefFonts);
}
return prefFonts;
}
PrefFontList* prefFonts =
mLangGroupPrefFonts[aPrefLang][aGenericType].get();
if (MOZ_UNLIKELY(!prefFonts)) {
@ -1180,6 +1218,10 @@ gfxPlatformFontList::AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen,
mozilla::FontFamilyType
gfxPlatformFontList::GetDefaultGeneric(eFontPrefLang aLang)
{
if (aLang == eFontPrefLang_Emoji) {
return eFamily_moz_emoji;
}
// initialize lang group pref font defaults (i.e. serif/sans-serif)
if (MOZ_UNLIKELY(mDefaultGenericsLangGroup.IsEmpty())) {
mDefaultGenericsLangGroup.AppendElements(ArrayLength(gPrefLangNames));

View file

@ -380,6 +380,15 @@ protected:
eFontPrefLang aPrefLang,
nsTArray<RefPtr<gfxFontFamily>>* aGenericFamilies);
void
ResolveEmojiFontNames(nsTArray<RefPtr<gfxFontFamily>>* aGenericFamilies);
void
GetFontFamiliesFromGenericFamilies(
nsTArray<nsString>& aGenericFamilies,
nsAtom* aLangGroup,
nsTArray<RefPtr<gfxFontFamily>>* aFontFamilies);
virtual nsresult InitFontListForPlatform() = 0;
void ApplyWhitelist();
@ -436,6 +445,8 @@ protected:
eFontPrefLang_First,
eFontPrefLang_Count> mLangGroupPrefFonts;
mozilla::UniquePtr<PrefFontList> mEmojiPrefFont;
// when system-wide font lookup fails for a character, cache it to skip future searches
gfxSparseBitSet mCodepointsWithNoFonts;

View file

@ -45,6 +45,9 @@ using mozilla::services::GetObserverService;
static const char16_t kEllipsisChar[] = { 0x2026, 0x0 };
static const char16_t kASCIIPeriodsChar[] = { '.', '.', '.', 0x0 };
const uint32_t kVariationSelector15 = 0xFE0E; // text presentation
const uint32_t kVariationSelector16 = 0xFE0F; // emoji presentation
#ifdef DEBUG_roc
#define DEBUG_TEXT_RUN_STORAGE_METRICS
#endif
@ -2813,7 +2816,7 @@ gfxFontGroup::FindFontForChar(uint32_t aCh, uint32_t aPrevCh, uint32_t aNextCh,
return nullptr;
// 2. search pref fonts
RefPtr<gfxFont> font = WhichPrefFontSupportsChar(aCh);
RefPtr<gfxFont> font = WhichPrefFontSupportsChar(aCh, aNextCh);
if (font) {
*aMatchType = gfxTextRange::kPrefsFallback;
return font.forget();
@ -3081,15 +3084,25 @@ gfxFontGroup::ContainsUserFont(const gfxUserFontEntry* aUserFont)
}
already_AddRefed<gfxFont>
gfxFontGroup::WhichPrefFontSupportsChar(uint32_t aCh)
gfxFontGroup::WhichPrefFontSupportsChar(uint32_t aCh, uint32_t aNextCh)
{
RefPtr<gfxFont> font;
// get the pref font list if it hasn't been set up already
uint32_t unicodeRange = FindCharUnicodeRange(aCh);
eFontPrefLang charLang;
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
eFontPrefLang charLang = pfl->GetFontPrefLangFor(unicodeRange);
EmojiPresentation emoji = GetEmojiPresentation(aCh);
if ((emoji != EmojiPresentation::TextOnly &&
(aNextCh == kVariationSelector16 ||
(emoji == EmojiPresentation::EmojiDefault &&
aNextCh != kVariationSelector15)))) {
charLang = eFontPrefLang_Emoji;
} else {
// get the pref font list if it hasn't been set up already
uint32_t unicodeRange = FindCharUnicodeRange(aCh);
charLang = pfl->GetFontPrefLangFor(unicodeRange);
}
// if the last pref font was the first family in the pref list, no need to recheck through a list of families
if (mLastPrefFont && charLang == mLastPrefLang &&
mLastPrefFirstFont && mLastPrefFont->HasCharacter(aCh)) {

View file

@ -917,7 +917,8 @@ public:
protected:
// search through pref fonts for a character, return nullptr if no matching pref font
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(uint32_t aCh);
already_AddRefed<gfxFont> WhichPrefFontSupportsChar(uint32_t aCh,
uint32_t aNextCh);
already_AddRefed<gfxFont>
WhichSystemFontSupportsChar(uint32_t aCh, uint32_t aNextCh,