Bug 1032671 - Part 4. Font fallback should detect emoji range for color emoji font. r?jfkthame draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Sun, 12 Nov 2017 16:36:24 +0900
changeset 706549 dc20923dd31b4a4522c243175c27238b2e3ae381
parent 706548 941e679a68c83000f7a1787d8043fd347bcc976a
child 706550 b18816d7575bf7d62d76db4b6c99243cf59153ef
push id91829
push userbmo:m_kato@ga2.so-net.ne.jp
push dateSat, 02 Dec 2017 09:30:34 +0000
reviewersjfkthame
bugs1032671
milestone59.0a1
Bug 1032671 - Part 4. Font fallback should detect emoji range for color emoji font. r?jfkthame MozReview-Commit-ID: AeqSLUU9GRH
gfx/thebes/gfxAndroidPlatform.cpp
gfx/thebes/gfxPlatformGtk.cpp
gfx/thebes/gfxPlatformMac.cpp
gfx/thebes/gfxTextRun.cpp
gfx/thebes/gfxWindowsPlatform.cpp
intl/unicharutil/util/nsUnicodeProperties.h
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -17,29 +17,31 @@
 #include "gfxFT2FontList.h"
 #include "gfxImageSurface.h"
 #include "gfxTextRun.h"
 #include "mozilla/dom/ContentChild.h"
 #include "nsXULAppAPI.h"
 #include "nsIScreen.h"
 #include "nsIScreenManager.h"
 #include "nsServiceManagerUtils.h"
+#include "nsUnicodeProperties.h"
 #include "gfxPrefs.h"
 #include "cairo.h"
 #include "VsyncSource.h"
 
 #include "ft2build.h"
 #include FT_FREETYPE_H
 #include FT_MODULE_H
 
 #include "GeneratedJNINatives.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
+using namespace mozilla::unicode;
 using mozilla::intl::LocaleService;
 using mozilla::intl::OSPreferences;
 
 static FT_Library gPlatformFTLibrary = nullptr;
 
 class FreetypeReporter final : public nsIMemoryReporter,
                                public CountingAllocatorBase<FreetypeReporter>
 {
@@ -161,29 +163,27 @@ gfxAndroidPlatform::GetCommonFallbackFon
                                            Script aRunScript,
                                            nsTArray<const char*>& aFontList)
 {
     static const char kDroidSansJapanese[] = "Droid Sans Japanese";
     static const char kMotoyaLMaru[] = "MotoyaLMaru";
     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;
         switch (block) {
         case 0x05:
             aFontList.AppendElement("Droid Sans Hebrew");
             aFontList.AppendElement("Droid Sans Armenian");
             break;
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -212,35 +212,31 @@ static const char kFontDroidSansFallback
 static const char kFontWenQuanYiMicroHei[] = "WenQuanYi Micro Hei";
 static const char kFontNanumGothic[] = "NanumGothic";
 
 void
 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(kFontEmojiOneMozilla);
+    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(kFontEmojiOneMozilla);
+        }
     }
 
     aFontList.AppendElement(kFontDejaVuSerif);
     aFontList.AppendElement(kFontFreeSerif);
     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(kFontEmojiOneMozilla);
-            }
-        }
-    }
-
     // add fonts for CJK ranges
     // xxx - this isn't really correct, should use the same CJK font ordering
     // as the pref font code
     if (aCh >= 0x3000 &&
         ((aCh < 0xe000) ||
          (aCh >= 0xf900 && aCh < 0xfff0) ||
          ((aCh >> 16) == 2))) {
         aFontList.AppendElement(kFontTakaoPGothic);
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -13,27 +13,29 @@
 #include "gfxMacFont.h"
 #include "gfxCoreTextShaper.h"
 #include "gfxTextRun.h"
 #include "gfxUserFontSet.h"
 
 #include "nsTArray.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/VsyncDispatcher.h"
+#include "nsUnicodeProperties.h"
 #include "qcms.h"
 #include "gfx2DGlue.h"
 
 #include <dlfcn.h>
 #include <CoreVideo/CoreVideo.h>
 
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "VsyncSource.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
+using namespace mozilla::unicode;
 
 using mozilla::dom::SystemFontListEntry;
 
 // cribbed from CTFontManager.h
 enum {
    kAutoActivationDisabled = 1
 };
 typedef uint32_t AutoActivationSetting;
@@ -186,33 +188,34 @@ static const char kFontSTHeiti[] = "STHe
 static const char kFontSTIXGeneral[] = "STIXGeneral";
 static const char kFontTamilMN[] = "Tamil MN";
 
 void
 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);
             aFontList.AppendElement(kFontSimSunExtB);
         }
     } else {
         uint32_t b = (aCh >> 8) & 0xff;
 
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -32,19 +32,16 @@
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::unicode;
 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
 
 #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
 extern uint32_t gTextRunStorageHighWaterMark;
 extern uint32_t gTextRunStorage;
 extern uint32_t gFontCount;
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -9,16 +9,17 @@
 #include "cairo.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
 
 #include "gfxImageSurface.h"
 #include "gfxWindowsSurface.h"
 
 #include "nsUnicharUtils.h"
+#include "nsUnicodeProperties.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/WindowsVersion.h"
 #include "nsIGfxInfo.h"
 #include "nsServiceManagerUtils.h"
 #include "nsTArray.h"
@@ -79,16 +80,17 @@
 #include "mozilla/layers/DeviceAttachmentsD3D11.h"
 #include "D3D11Checks.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 using namespace mozilla::image;
+using namespace mozilla::unicode;
 
 DCFromDrawTarget::DCFromDrawTarget(DrawTarget& aDrawTarget)
 {
   mDC = nullptr;
   if (aDrawTarget.GetBackendType() == BackendType::CAIRO) {
     cairo_t* ctx = static_cast<cairo_t*>
       (aDrawTarget.GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT));
     if (ctx) {
@@ -598,38 +600,34 @@ static const char kFontTraditionalArabic
 static const char kFontUtsaah[] = "Utsaah";
 static const char kFontYuGothic[] = "Yu Gothic";
 
 void
 gfxWindowsPlatform::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
                                            Script aRunScript,
                                            nsTArray<const char*>& aFontList)
 {
-    if (aNextCh == 0xfe0fu) {
-        aFontList.AppendElement(kFontSegoeUIEmoji);
-        aFontList.AppendElement(kFontEmojiOneMozilla);
+    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(kFontSegoeUIEmoji);
+            aFontList.AppendElement(kFontEmojiOneMozilla);
+        }
     }
 
     // Arial is used as the default fallback for system fallback
     aFontList.AppendElement(kFontArial);
 
     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(kFontEmojiOneMozilla);
-            } else {
-                if (aNextCh != 0xfe0fu) {
-                    aFontList.AppendElement(kFontSegoeUIEmoji);
-                    aFontList.AppendElement(kFontEmojiOneMozilla);
-                }
-                aFontList.AppendElement(kFontSegoeUISymbol);
-            }
+            aFontList.AppendElement(kFontSegoeUISymbol);
             aFontList.AppendElement(kFontEbrima);
             aFontList.AppendElement(kFontNirmalaUI);
             aFontList.AppendElement(kFontCambriaMath);
         }
     } else {
         uint32_t b = (aCh >> 8) & 0xff;
 
         switch (b) {
--- a/intl/unicharutil/util/nsUnicodeProperties.h
+++ b/intl/unicharutil/util/nsUnicodeProperties.h
@@ -47,16 +47,19 @@ enum IdentifierType {
 };
 
 enum EmojiPresentation {
   TextOnly = 0,
   TextDefault = 1,
   EmojiDefault = 2
 };
 
+const uint32_t kVariationSelector15 = 0xFE0E; // text presentation
+const uint32_t kVariationSelector16 = 0xFE0F; // emoji presentation
+
 extern const hb_unicode_general_category_t sICUtoHBcategory[];
 
 inline uint32_t
 GetMirroredChar(uint32_t aCh)
 {
   return u_charMirror(aCh);
 }