From 84c479afa375c7cb6cd38dbaf0547636046b8cb5 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Wed, 9 May 2018 15:30:43 +0200 Subject: Use font.name-list.emoji preference for emoji presenration. --- gfx/thebes/gfxFontConstants.h | 3 +- gfx/thebes/gfxFontFamilyList.h | 1 + gfx/thebes/gfxPlatformFontList.cpp | 66 +++++++++++++++++++++++++++++++------- gfx/thebes/gfxPlatformFontList.h | 11 +++++++ gfx/thebes/gfxTextRun.cpp | 23 ++++++++++--- gfx/thebes/gfxTextRun.h | 3 +- 6 files changed, 88 insertions(+), 19 deletions(-) (limited to 'gfx') diff --git a/gfx/thebes/gfxFontConstants.h b/gfx/thebes/gfxFontConstants.h index 5aa1eb0c7..3eae49ee1 100644 --- a/gfx/thebes/gfxFontConstants.h +++ b/gfx/thebes/gfxFontConstants.h @@ -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) diff --git a/gfx/thebes/gfxFontFamilyList.h b/gfx/thebes/gfxFontFamilyList.h index e240102e0..9d1a3cf49 100644 --- a/gfx/thebes/gfxFontFamilyList.h +++ b/gfx/thebes/gfxFontFamilyList.h @@ -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, diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index 01394db14..06da75ee4 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -869,28 +869,55 @@ gfxPlatformFontList::ResolveGenericFontNames( nsIAtom* langGroup = GetLangGroupForPrefLang(aPrefLang); NS_ASSERTION(langGroup, "null lang group for pref lang"); + gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(genericFamilies, + langGroup, + aGenericFamilies); + +#if 0 // dump out generic mappings + printf("%s ===> ", prefFontName.get()); + for (uint32_t k = 0; k < aGenericFamilies->Length(); k++) { + if (k > 0) printf(", "); + printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]->Name()).get()); + } + printf("\n"); +#endif +} + +void +gfxPlatformFontList::ResolveEmojiFontNames( + nsTArray>* aGenericFamilies) +{ + // emoji preference has no lang name + AutoTArray genericFamilies; + + nsAutoCString prefFontListName("font.name-list.emoji"); + gfxFontUtils::AppendPrefsFontList(prefFontListName.get(), genericFamilies); + + gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(genericFamilies, + nullptr, + aGenericFamilies); +} + +void +gfxPlatformFontList::GetFontFamiliesFromGenericFamilies( + nsTArray& aGenericNameFamilies, + nsAtom* aLangGroup, + nsTArray>* aGenericFamilies) +{ // lookup and add platform fonts uniquely - for (const nsString& genericFamily : genericFamilies) { + for (const nsString& genericFamily : aGenericNameFamilies) { gfxFontStyle style; - style.language = langGroup; + style.language = aLangGroup; style.systemFont = false; AutoTArray families; - FindAndAddFamilies(genericFamily, &families, &style); + FindAndAddFamilies(genericFamily, &families, FindFamiliesFlags(0), + &style); for (gfxFontFamily* f : families) { if (!aGenericFamilies->Contains(f)) { aGenericFamilies->AppendElement(f); } } } - -#if 0 // dump out generic mappings - printf("%s ===> ", prefFontName.get()); - for (uint32_t k = 0; k < aGenericFamilies->Length(); k++) { - if (k > 0) printf(", "); - printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]->Name()).get()); - } - printf("\n"); -#endif } nsTArray>* @@ -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)); diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index c16994d8c..c3795a072 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -380,6 +380,15 @@ protected: eFontPrefLang aPrefLang, nsTArray>* aGenericFamilies); + void + ResolveEmojiFontNames(nsTArray>* aGenericFamilies); + + void + GetFontFamiliesFromGenericFamilies( + nsTArray& aGenericFamilies, + nsAtom* aLangGroup, + nsTArray>* aFontFamilies); + virtual nsresult InitFontListForPlatform() = 0; void ApplyWhitelist(); @@ -436,6 +445,8 @@ protected: eFontPrefLang_First, eFontPrefLang_Count> mLangGroupPrefFonts; + mozilla::UniquePtr mEmojiPrefFont; + // when system-wide font lookup fails for a character, cache it to skip future searches gfxSparseBitSet mCodepointsWithNoFonts; diff --git a/gfx/thebes/gfxTextRun.cpp b/gfx/thebes/gfxTextRun.cpp index 6718eed01..45ea7e6d0 100644 --- a/gfx/thebes/gfxTextRun.cpp +++ b/gfx/thebes/gfxTextRun.cpp @@ -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 font = WhichPrefFontSupportsChar(aCh); + RefPtr font = WhichPrefFontSupportsChar(aCh, aNextCh); if (font) { *aMatchType = gfxTextRange::kPrefsFallback; return font.forget(); @@ -3081,15 +3084,25 @@ gfxFontGroup::ContainsUserFont(const gfxUserFontEntry* aUserFont) } already_AddRefed -gfxFontGroup::WhichPrefFontSupportsChar(uint32_t aCh) +gfxFontGroup::WhichPrefFontSupportsChar(uint32_t aCh, uint32_t aNextCh) { RefPtr 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)) { diff --git a/gfx/thebes/gfxTextRun.h b/gfx/thebes/gfxTextRun.h index 0e44456ae..c3673785c 100644 --- a/gfx/thebes/gfxTextRun.h +++ b/gfx/thebes/gfxTextRun.h @@ -917,7 +917,8 @@ public: protected: // search through pref fonts for a character, return nullptr if no matching pref font - already_AddRefed WhichPrefFontSupportsChar(uint32_t aCh); + already_AddRefed WhichPrefFontSupportsChar(uint32_t aCh, + uint32_t aNextCh); already_AddRefed WhichSystemFontSupportsChar(uint32_t aCh, uint32_t aNextCh, -- cgit v1.2.3