summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gfx/thebes/gfxAndroidPlatform.cpp22
-rw-r--r--gfx/thebes/gfxFontConstants.h3
-rw-r--r--gfx/thebes/gfxFontFamilyList.h1
-rw-r--r--gfx/thebes/gfxPlatformFontList.cpp65
-rw-r--r--gfx/thebes/gfxPlatformFontList.h11
-rw-r--r--gfx/thebes/gfxPlatformGtk.cpp20
-rw-r--r--gfx/thebes/gfxPlatformMac.cpp23
-rw-r--r--gfx/thebes/gfxTextRun.cpp20
-rw-r--r--gfx/thebes/gfxTextRun.h3
-rwxr-xr-xgfx/thebes/gfxWindowsPlatform.cpp26
-rw-r--r--intl/unicharutil/util/nsUnicodeProperties.h22
-rw-r--r--modules/libpref/init/all.js12
12 files changed, 162 insertions, 66 deletions
diff --git a/gfx/thebes/gfxAndroidPlatform.cpp b/gfx/thebes/gfxAndroidPlatform.cpp
index f587737b5..76427d88c 100644
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -21,6 +21,7 @@
#include "nsIScreenManager.h"
#include "nsILocaleService.h"
#include "nsServiceManagerUtils.h"
+#include "nsUnicodeProperties.h"
#include "gfxPrefs.h"
#include "cairo.h"
#include "VsyncSource.h"
@@ -32,6 +33,7 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::gfx;
+using namespace mozilla::unicode;
static FT_Library gPlatformFTLibrary = nullptr;
@@ -168,19 +170,17 @@ gfxAndroidPlatform::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
static const char kNotoSansCJKJP[] = "Noto Sans CJK JP";
static const char kNotoColorEmoji[] = "Noto Color Emoji";
- if (aNextCh == 0xfe0fu) {
- // if char is followed by VS16, try for a color emoji glyph
- aFontList.AppendElement(kNotoColorEmoji);
+ EmojiPresentation emoji = GetEmojiPresentation(aCh);
+ if (emoji != EmojiPresentation::TextOnly) {
+ if (aNextCh == kVariationSelector16 ||
+ (aNextCh != kVariationSelector15 &&
+ emoji == EmojiPresentation::EmojiDefault)) {
+ // if char is followed by VS16, try for a color emoji glyph
+ aFontList.AppendElement(kNotoColorEmoji);
+ }
}
- if (!IS_IN_BMP(aCh)) {
- uint32_t p = aCh >> 16;
- if (p == 1) { // try color emoji font, unless VS15 (text style) present
- if (aNextCh != 0xfe0fu && aNextCh != 0xfe0eu) {
- aFontList.AppendElement(kNotoColorEmoji);
- }
- }
- } else {
+ if (IS_IN_BMP(aCh)) {
// try language-specific "Droid Sans *" and "Noto Sans *" fonts for
// certain blocks, as most devices probably have these
uint8_t block = (aCh >> 8) & 0xff;
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..e12f4e197 100644
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -869,28 +869,54 @@ 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<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,
+ nsIAtom* aLangGroup,
+ nsTArray<RefPtr<gfxFontFamily>>* 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<gfxFontFamily*,10> families;
- FindAndAddFamilies(genericFamily, &families, &style);
+ FindAndAddFamilies(genericFamily, &families, &style, 1.0);
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<RefPtr<gfxFontFamily>>*
@@ -902,6 +928,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 +1217,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..d77c12059 100644
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -380,6 +380,15 @@ protected:
eFontPrefLang aPrefLang,
nsTArray<RefPtr<gfxFontFamily>>* aGenericFamilies);
+ void
+ ResolveEmojiFontNames(nsTArray<RefPtr<gfxFontFamily>>* aGenericFamilies);
+
+ void
+ GetFontFamiliesFromGenericFamilies(
+ nsTArray<nsString>& aGenericFamilies,
+ nsIAtom* 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;
diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp
index 1fb3bc4fd..be75332d6 100644
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -240,9 +240,14 @@ gfxPlatformGtk::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
Script aRunScript,
nsTArray<const char*>& aFontList)
{
- if (aNextCh == 0xfe0fu) {
- // if char is followed by VS16, try for a color emoji glyph
- aFontList.AppendElement(kFontTwemojiMozilla);
+ EmojiPresentation emoji = GetEmojiPresentation(aCh);
+ if (emoji != EmojiPresentation::TextOnly) {
+ if (aNextCh == kVariationSelector16 ||
+ (aNextCh != kVariationSelector15 &&
+ emoji == EmojiPresentation::EmojiDefault)) {
+ // if char is followed by VS16, try for a color emoji glyph
+ aFontList.AppendElement(kFontTwemojiMozilla);
+ }
}
aFontList.AppendElement(kFontDejaVuSerif);
@@ -250,15 +255,6 @@ gfxPlatformGtk::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
aFontList.AppendElement(kFontDejaVuSans);
aFontList.AppendElement(kFontFreeSans);
- if (!IS_IN_BMP(aCh)) {
- uint32_t p = aCh >> 16;
- if (p == 1) { // try color emoji font, unless VS15 (text style) present
- if (aNextCh != 0xfe0fu && aNextCh != 0xfe0eu) {
- aFontList.AppendElement(kFontTwemojiMozilla);
- }
- }
- }
-
// add fonts for CJK ranges
// xxx - this isn't really correct, should use the same CJK font ordering
// as the pref font code
diff --git a/gfx/thebes/gfxPlatformMac.cpp b/gfx/thebes/gfxPlatformMac.cpp
index 3216f0f07..79684dd19 100644
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -18,6 +18,7 @@
#include "nsTArray.h"
#include "mozilla/Preferences.h"
#include "mozilla/VsyncDispatcher.h"
+#include "nsUnicodeProperties.h"
#include "qcms.h"
#include "gfx2DGlue.h"
@@ -29,6 +30,7 @@
using namespace mozilla;
using namespace mozilla::gfx;
+using namespace mozilla::unicode;
// cribbed from CTFontManager.h
enum {
@@ -195,23 +197,24 @@ gfxPlatformMac::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
Script aRunScript,
nsTArray<const char*>& aFontList)
{
- if (aNextCh == 0xfe0f) {
- aFontList.AppendElement(kFontAppleColorEmoji);
+ EmojiPresentation emoji = GetEmojiPresentation(aCh);
+ if (emoji != EmojiPresentation::TextOnly) {
+ if (aNextCh == kVariationSelector16 ||
+ (aNextCh != kVariationSelector15 &&
+ emoji == EmojiPresentation::EmojiDefault)) {
+ // if char is followed by VS16, try for a color emoji glyph
+ aFontList.AppendElement(kFontAppleColorEmoji);
+ }
}
aFontList.AppendElement(kFontLucidaGrande);
if (!IS_IN_BMP(aCh)) {
uint32_t p = aCh >> 16;
- uint32_t b = aCh >> 8;
if (p == 1) {
- if (b >= 0x1f0 && b < 0x1f7) {
- aFontList.AppendElement(kFontAppleColorEmoji);
- } else {
- aFontList.AppendElement(kFontAppleSymbols);
- aFontList.AppendElement(kFontSTIXGeneral);
- aFontList.AppendElement(kFontGeneva);
- }
+ aFontList.AppendElement(kFontAppleSymbols);
+ aFontList.AppendElement(kFontSTIXGeneral);
+ aFontList.AppendElement(kFontGeneva);
} else if (p == 2) {
// OSX installations with MS Office may have these fonts
aFontList.AppendElement(kFontMingLiUExtB);
diff --git a/gfx/thebes/gfxTextRun.cpp b/gfx/thebes/gfxTextRun.cpp
index 6718eed01..1702cab66 100644
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -2813,7 +2813,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 +3081,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)) {
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<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,
diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp
index af4d932a9..c68f622c6 100755
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -13,6 +13,7 @@
#include "gfxWindowsSurface.h"
#include "nsUnicharUtils.h"
+#include "nsUnicodeProperties.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
@@ -81,6 +82,7 @@ using namespace mozilla::gfx;
using namespace mozilla::layers;
using namespace mozilla::widget;
using namespace mozilla::image;
+using namespace mozilla::unicode;
IDWriteRenderingParams* GetDwriteRenderingParams(bool aGDI)
{
@@ -669,9 +671,15 @@ gfxWindowsPlatform::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
Script aRunScript,
nsTArray<const char*>& aFontList)
{
- if (aNextCh == 0xfe0fu) {
- aFontList.AppendElement(kFontSegoeUIEmoji);
- aFontList.AppendElement(kFontTwemojiMozilla);
+ EmojiPresentation emoji = GetEmojiPresentation(aCh);
+ if (emoji != EmojiPresentation::TextOnly) {
+ if (aNextCh == kVariationSelector16 ||
+ (aNextCh != kVariationSelector15 &&
+ emoji == EmojiPresentation::EmojiDefault)) {
+ // if char is followed by VS16, try for a color emoji glyph
+ // XXX: For Win8+ native, aFontList.AppendElement(kFontSegoeUIEmoji);
+ aFontList.AppendElement(kFontTwemojiMozilla);
+ }
}
// Arial is used as the default fallback for system fallback
@@ -680,17 +688,7 @@ gfxWindowsPlatform::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
if (!IS_IN_BMP(aCh)) {
uint32_t p = aCh >> 16;
if (p == 1) { // SMP plane
- if (aNextCh == 0xfe0eu) {
- aFontList.AppendElement(kFontSegoeUISymbol);
- aFontList.AppendElement(kFontSegoeUIEmoji);
- aFontList.AppendElement(kFontTwemojiMozilla);
- } else {
- if (aNextCh != 0xfe0fu) {
- aFontList.AppendElement(kFontSegoeUIEmoji);
- aFontList.AppendElement(kFontTwemojiMozilla);
- }
- aFontList.AppendElement(kFontSegoeUISymbol);
- }
+ aFontList.AppendElement(kFontSegoeUISymbol);
aFontList.AppendElement(kFontEbrima);
aFontList.AppendElement(kFontNirmalaUI);
aFontList.AppendElement(kFontCambriaMath);
diff --git a/intl/unicharutil/util/nsUnicodeProperties.h b/intl/unicharutil/util/nsUnicodeProperties.h
index 303582f99..ee1d77252 100644
--- a/intl/unicharutil/util/nsUnicodeProperties.h
+++ b/intl/unicharutil/util/nsUnicodeProperties.h
@@ -54,6 +54,15 @@ enum XidmodType {
XIDMOD_NOT_CHARS
};
+enum EmojiPresentation {
+ TextOnly = 0,
+ TextDefault = 1,
+ EmojiDefault = 2
+};
+
+const uint32_t kVariationSelector15 = 0xFE0E; // text presentation
+const uint32_t kVariationSelector16 = 0xFE0F; // emoji presentation
+
// ICU is available, so simply forward to its API
extern const hb_unicode_general_category_t sICUtoHBcategory[];
@@ -170,6 +179,19 @@ IsEastAsianWidthFWH(uint32_t aCh)
return false;
}
+inline EmojiPresentation
+GetEmojiPresentation(uint32_t aCh)
+{
+ if (!u_hasBinaryProperty(aCh, UCHAR_EMOJI)) {
+ return TextOnly;
+ }
+
+ if (u_hasBinaryProperty(aCh, UCHAR_EMOJI_PRESENTATION)) {
+ return EmojiDefault;
+ }
+ return TextDefault;
+}
+
// returns the simplified Gen Category as defined in nsIUGenCategory
inline nsIUGenCategory::nsUGenCategory GetGenCategory(uint32_t aCh) {
return sDetailedToGeneralCategory[GetGeneralCategory(aCh)];
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 88a9af2da..6506d4bce 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -3171,6 +3171,10 @@ pref("ui.mouse.radius.inputSource.touchOnly", true);
#ifdef XP_WIN
+// Be as uniform as possible, use Twemoji everywhere.
+// Optional: prefix with `Segoe UI Emoji` to use Win8+ Segoe UI font emoji where available.
+pref("font.name-list.emoji", "Twemoji Mozilla");
+
pref("font.name.serif.ar", "Times New Roman");
pref("font.name.sans-serif.ar", "Segoe UI");
pref("font.name-list.sans-serif.ar", "Segoe UI, Tahoma, Arial");
@@ -3596,6 +3600,8 @@ pref("ui.osk.debug.keyboardDisplayReason", "");
pref("browser.drag_out_of_frame_style", 1);
pref("ui.key.saveLink.shift", false); // true = shift, false = meta
+pref("font.name-list.emoji", "Apple Color Emoji");
+
// default fonts (in UTF8 and using canonical names)
// to determine canonical font names, use a debug build and
// enable NSPR logging for module fontInfoLog:5
@@ -4018,6 +4024,10 @@ pref("print.print_extra_margin", 0); // twips
// font names
+// fontconfig doesn't support emoji yet
+// https://lists.freedesktop.org/archives/fontconfig/2016-October/005842.html
+pref("font.name-list.emoji", "Twemoji Mozilla");
+
pref("font.name.serif.ar", "serif");
pref("font.name.sans-serif.ar", "sans-serif");
pref("font.name.monospace.ar", "monospace");
@@ -4262,6 +4272,8 @@ pref("font.name.monospace.x-math", "Fira Mono");
#elif defined(ANDROID)
// We use the bundled fonts for Firefox for Android
+pref("font.name-list.emoji", "Noto Color Emoji");
+
// ar
pref("font.name.serif.el", "Droid Serif"); // not Charis SIL Compact, only has a few Greek chars