Changeset 239822 in webkit


Ignore:
Timestamp:
Jan 10, 2019 2:03:53 AM (5 years ago)
Author:
Carlos Garcia Campos
Message:

[FreeType] Color emoji not properly supported
https://bugs.webkit.org/show_bug.cgi?id=191976

Reviewed by Michael Catanzaro.

Source/WebCore:

Always try to fallback to a colored font for emojis.

Test: platform/gtk/fonts/font-emoji-system-fallback.html

  • platform/graphics/ComplexTextController.cpp:

(WebCore::advanceByCombiningCharacterSequence): Group regional indicators in pairs.

  • platform/graphics/Font.cpp:

(WebCore::CharacterFallbackMapKey::CharacterFallbackMapKey):
(WebCore::Font::systemFallbackFontForCharacter const): Pass PreferColoredFont::No to FontCache::systemFallbackForCharacters.

  • platform/graphics/Font.h: Add IsForPlatformFont enum to replace the bool parameter in systemFallbackFontForCharacter().
  • platform/graphics/FontCache.h:
  • platform/graphics/FontCascadeFonts.cpp:

(WebCore::FontCascadeFonts::glyphDataForSystemFallback):

  • platform/graphics/cairo/FontCairoHarfbuzzNG.cpp:

(WebCore::characterSequenceIsEmoji): Check whether the character sequence is an emoji.
(WebCore::FontCascade::fontForCombiningCharacterSequence const): In case of emojis try to fallback to a colored
font even if base font can render the emoji in black and white.

  • platform/graphics/cocoa/FontCacheCoreText.cpp:

(WebCore::FontCache::systemFallbackForCharacters): Add PreferColoredFont parameter that is ignored.

  • platform/graphics/freetype/FontCacheFreeType.cpp:

(WebCore::FontCache::systemFallbackForCharacters): Add PreferColoredFont parameter.

  • platform/graphics/freetype/FontPlatformDataFreeType.cpp:

(WebCore::FontPlatformData::FontPlatformData): Initialize m_isColorBitmapFont.

  • platform/graphics/freetype/SimpleFontDataFreeType.cpp:

(WebCore::Font::variantCapsSupportsCharacterForSynthesis const): Moved from cross-platform file.
(WebCore::Font::platformSupportsCodePoint const): Add freetype implementation.

  • platform/graphics/win/FontCacheWin.cpp:

(WebCore::FontCache::systemFallbackForCharacters): Add PreferColoredFont parameter that is ignored.

  • platform/text/CharacterProperties.h:

(WebCore::isEmojiKeycapBase):
(WebCore::isEmojiRegionalIndicator):
(WebCore::isEmojiWithPresentationByDefault):
(WebCore::isEmojiModifierBase):

Source/WTF:

Add a name for combining enclosing keycap character.

  • wtf/unicode/CharacterNames.h:

LayoutTests:

Add new test to ensure we fallback to noto color emoji for emojis.

  • platform/gtk/fonts/font-emoji-system-fallback-expected.html: Added.
  • platform/gtk/fonts/font-emoji-system-fallback.html: Added.
Location:
trunk
Files:
2 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r239821 r239822  
     12019-01-10  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [FreeType] Color emoji not properly supported
     4        https://bugs.webkit.org/show_bug.cgi?id=191976
     5
     6        Reviewed by Michael Catanzaro.
     7
     8        Add new test to ensure we fallback to noto color emoji for emojis.
     9
     10        * platform/gtk/fonts/font-emoji-system-fallback-expected.html: Added.
     11        * platform/gtk/fonts/font-emoji-system-fallback.html: Added.
     12
    1132019-01-10  cathie chen  <cathiechen@igalia.com>
    214
  • trunk/Source/WTF/ChangeLog

    r239813 r239822  
     12019-01-10  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [FreeType] Color emoji not properly supported
     4        https://bugs.webkit.org/show_bug.cgi?id=191976
     5
     6        Reviewed by Michael Catanzaro.
     7
     8        Add a name for combining enclosing keycap character.
     9
     10        * wtf/unicode/CharacterNames.h:
     11
    1122019-01-09  Carlos Eduardo Ramalho  <cadubentzen@gmail.com> and Fujii Hironori  <Hironori.Fujii@sony.com>
    213
  • trunk/Source/WTF/wtf/unicode/CharacterNames.h

    r237099 r239822  
    4747const UChar bullseye = 0x25CE;
    4848const UChar carriageReturn = 0x000D;
     49const UChar combiningEnclosingKeycap = 0x20E3;
    4950const UChar ethiopicPrefaceColon = 0x1366;
    5051const UChar ethiopicWordspace = 0x1361;
     
    115116using WTF::Unicode::bullseye;
    116117using WTF::Unicode::carriageReturn;
     118using WTF::Unicode::combiningEnclosingKeycap;
    117119using WTF::Unicode::ethiopicPrefaceColon;
    118120using WTF::Unicode::ethiopicWordspace;
  • trunk/Source/WebCore/ChangeLog

    r239820 r239822  
     12019-01-10  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [FreeType] Color emoji not properly supported
     4        https://bugs.webkit.org/show_bug.cgi?id=191976
     5
     6        Reviewed by Michael Catanzaro.
     7
     8        Always try to fallback to a colored font for emojis.
     9
     10        Test: platform/gtk/fonts/font-emoji-system-fallback.html
     11
     12        * platform/graphics/ComplexTextController.cpp:
     13        (WebCore::advanceByCombiningCharacterSequence): Group regional indicators in pairs.
     14        * platform/graphics/Font.cpp:
     15        (WebCore::CharacterFallbackMapKey::CharacterFallbackMapKey):
     16        (WebCore::Font::systemFallbackFontForCharacter const): Pass PreferColoredFont::No to FontCache::systemFallbackForCharacters.
     17        * platform/graphics/Font.h: Add IsForPlatformFont enum to replace the bool parameter in systemFallbackFontForCharacter().
     18        * platform/graphics/FontCache.h:
     19        * platform/graphics/FontCascadeFonts.cpp:
     20        (WebCore::FontCascadeFonts::glyphDataForSystemFallback):
     21        * platform/graphics/cairo/FontCairoHarfbuzzNG.cpp:
     22        (WebCore::characterSequenceIsEmoji): Check whether the character sequence is an emoji.
     23        (WebCore::FontCascade::fontForCombiningCharacterSequence const): In case of emojis try to fallback to a colored
     24        font even if base font can render the emoji in black and white.
     25        * platform/graphics/cocoa/FontCacheCoreText.cpp:
     26        (WebCore::FontCache::systemFallbackForCharacters): Add PreferColoredFont parameter that is ignored.
     27        * platform/graphics/freetype/FontCacheFreeType.cpp:
     28        (WebCore::FontCache::systemFallbackForCharacters): Add PreferColoredFont parameter.
     29        * platform/graphics/freetype/FontPlatformDataFreeType.cpp:
     30        (WebCore::FontPlatformData::FontPlatformData): Initialize m_isColorBitmapFont.
     31        * platform/graphics/freetype/SimpleFontDataFreeType.cpp:
     32        (WebCore::Font::variantCapsSupportsCharacterForSynthesis const): Moved from cross-platform file.
     33        (WebCore::Font::platformSupportsCodePoint const): Add freetype implementation.
     34        * platform/graphics/win/FontCacheWin.cpp:
     35        (WebCore::FontCache::systemFallbackForCharacters): Add PreferColoredFont parameter that is ignored.
     36        * platform/text/CharacterProperties.h:
     37        (WebCore::isEmojiKeycapBase):
     38        (WebCore::isEmojiRegionalIndicator):
     39        (WebCore::isEmojiWithPresentationByDefault):
     40        (WebCore::isEmojiModifierBase):
     41
    1422019-01-09  Antoine Quint  <graouts@apple.com>
    243
  • trunk/Source/WebCore/platform/graphics/ComplexTextController.cpp

    r239461 r239822  
    287287    bool sawEmojiGroupCandidate = isEmojiGroupCandidate(baseCharacter);
    288288    bool sawJoiner = false;
     289    bool sawRegionalIndicator = isEmojiRegionalIndicator(baseCharacter);
    289290    while (iterator < end) {
    290291        UChar32 nextCharacter;
     
    296297        if (isVariationSelector(nextCharacter) || isEmojiFitzpatrickModifier(nextCharacter))
    297298            shouldContinue = true;
     299
     300        if (sawRegionalIndicator && isEmojiRegionalIndicator(nextCharacter)) {
     301            shouldContinue = true;
     302            sawRegionalIndicator = false;
     303        }
    298304
    299305        if (sawJoiner && isEmojiGroupCandidate(nextCharacter))
  • trunk/Source/WebCore/platform/graphics/Font.cpp

    r239427 r239822  
    503503    }
    504504
    505     CharacterFallbackMapKey(const AtomicString& locale, UChar32 character, bool isForPlatformFont)
     505    CharacterFallbackMapKey(const AtomicString& locale, UChar32 character, IsForPlatformFont isForPlatformFont)
    506506        : locale(locale)
    507507        , character(character)
    508         , isForPlatformFont(isForPlatformFont)
     508        , isForPlatformFont(isForPlatformFont == IsForPlatformFont::Yes)
    509509    {
    510510    }
     
    561561}
    562562
    563 RefPtr<Font> Font::systemFallbackFontForCharacter(UChar32 character, const FontDescription& description, bool isForPlatformFont) const
     563RefPtr<Font> Font::systemFallbackFontForCharacter(UChar32 character, const FontDescription& description, IsForPlatformFont isForPlatformFont) const
    564564{
    565565    auto fontAddResult = systemFallbackCache().add(this, CharacterFallbackMap());
     
    567567    if (!character) {
    568568        UChar codeUnit = 0;
    569         return FontCache::singleton().systemFallbackForCharacters(description, this, isForPlatformFont, &codeUnit, 1);
     569        return FontCache::singleton().systemFallbackForCharacters(description, this, isForPlatformFont, FontCache::PreferColoredFont::No, &codeUnit, 1);
    570570    }
    571571
     
    587587        }
    588588
    589         fallbackFont = FontCache::singleton().systemFallbackForCharacters(description, this, isForPlatformFont, codeUnits, codeUnitsLength).get();
     589        fallbackFont = FontCache::singleton().systemFallbackForCharacters(description, this, isForPlatformFont, FontCache::PreferColoredFont::No, codeUnits, codeUnitsLength).get();
    590590        if (fallbackFont)
    591591            fallbackFont->m_isUsedInSystemFallbackCache = true;
     
    613613}
    614614
    615 #if !PLATFORM(COCOA)
     615#if !PLATFORM(COCOA) && !USE(FREETYPE)
    616616bool Font::variantCapsSupportsCharacterForSynthesis(FontVariantCaps fontVariantCaps, UChar32) const
    617617{
  • trunk/Source/WebCore/platform/graphics/Font.h

    r239427 r239822  
    6666enum FontVariant { AutoVariant, NormalVariant, SmallCapsVariant, EmphasisMarkVariant, BrokenIdeographVariant };
    6767enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
     68enum class IsForPlatformFont : uint8_t { No, Yes };
    6869
    6970class Font : public RefCounted<Font> {
     
    177178    bool platformSupportsCodePoint(UChar32) const;
    178179
    179     RefPtr<Font> systemFallbackFontForCharacter(UChar32, const FontDescription&, bool isForPlatformFont) const;
     180    RefPtr<Font> systemFallbackFontForCharacter(UChar32, const FontDescription&, IsForPlatformFont) const;
    180181
    181182    const GlyphPage* glyphPage(unsigned pageNumber) const;
  • trunk/Source/WebCore/platform/graphics/FontCache.h

    r239461 r239822  
    6161class OpenTypeVerticalData;
    6262class Font;
     63enum class IsForPlatformFont : uint8_t;
    6364
    6465#if PLATFORM(WIN)
     
    191192
    192193    // These methods are implemented by the platform.
    193     RefPtr<Font> systemFallbackForCharacters(const FontDescription&, const Font* originalFontData, bool isPlatformFont, const UChar* characters, unsigned length);
     194    enum class PreferColoredFont : uint8_t { No, Yes };
     195    RefPtr<Font> systemFallbackForCharacters(const FontDescription&, const Font* originalFontData, IsForPlatformFont, PreferColoredFont, const UChar* characters, unsigned length);
    194196    Vector<String> systemFontFamilies();
    195197    void platformInit();
  • trunk/Source/WebCore/platform/graphics/FontCascadeFonts.cpp

    r233851 r239822  
    346346        font = &realizeFallbackRangesAt(description, 0).fontForFirstRange();
    347347
    348     auto systemFallbackFont = font->systemFallbackFontForCharacter(character, description, m_isForPlatformFont);
     348    auto systemFallbackFont = font->systemFallbackFontForCharacter(character, description, m_isForPlatformFont ? IsForPlatformFont::Yes : IsForPlatformFont::No);
    349349    if (!systemFallbackFont)
    350350        return GlyphData();
  • trunk/Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp

    r235935 r239822  
    3030#if USE(CAIRO)
    3131
     32#include "CharacterProperties.h"
    3233#include "FontCache.h"
    3334#include "SurrogatePairAwareTextIterator.h"
     
    4344bool FontCascade::canExpandAroundIdeographsInComplexText()
    4445{
     46    return false;
     47}
     48
     49static bool characterSequenceIsEmoji(const Vector<UChar, 4>& normalizedCharacters, int32_t normalizedLength)
     50{
     51    UChar32 character;
     52    unsigned clusterLength = 0;
     53    SurrogatePairAwareTextIterator iterator(normalizedCharacters.data(), 0, normalizedLength, normalizedLength);
     54    if (!iterator.consume(character, clusterLength))
     55        return false;
     56
     57    if (isEmojiKeycapBase(character)) {
     58        iterator.advance(clusterLength);
     59        UChar32 nextCharacter;
     60        if (!iterator.consume(nextCharacter, clusterLength))
     61            return false;
     62
     63        if (nextCharacter == combiningEnclosingKeycap)
     64            return true;
     65
     66        // Variation selector 16.
     67        if (nextCharacter == 0xFE0F) {
     68            iterator.advance(clusterLength);
     69            if (!iterator.consume(nextCharacter, clusterLength))
     70                return false;
     71
     72            if (nextCharacter == combiningEnclosingKeycap)
     73                return true;
     74        }
     75
     76        return false;
     77    }
     78
     79    // Regional indicator.
     80    if (isEmojiRegionalIndicator(character)) {
     81        iterator.advance(clusterLength);
     82        UChar32 nextCharacter;
     83        if (!iterator.consume(nextCharacter, clusterLength))
     84            return false;
     85
     86        if (isEmojiRegionalIndicator(nextCharacter))
     87            return true;
     88
     89        return false;
     90    }
     91
     92    if (character == combiningEnclosingKeycap)
     93        return true;
     94
     95    if (isEmojiWithPresentationByDefault(character)
     96        || isEmojiModifierBase(character)
     97        || isEmojiFitzpatrickModifier(character))
     98        return true;
     99
    45100    return false;
    46101}
     
    62117        return nullptr;
    63118
     119    bool isEmoji = characterSequenceIsEmoji(normalizedCharacters, normalizedLength);
     120
    64121    const Font* baseFont = glyphDataForCharacter(character, false, NormalVariant).font;
    65     if (baseFont && (static_cast<int32_t>(clusterLength) == normalizedLength || baseFont->canRenderCombiningCharacterSequence(characters, length)))
     122    if (baseFont
     123        && (static_cast<int32_t>(clusterLength) == normalizedLength || baseFont->canRenderCombiningCharacterSequence(characters, length))
     124        && (!isEmoji || baseFont->platformData().isColorBitmapFont()))
    66125        return baseFont;
    67126
     
    71130            continue;
    72131
    73         if (fallbackFont->canRenderCombiningCharacterSequence(characters, length))
     132        if (fallbackFont->canRenderCombiningCharacterSequence(characters, length) && (!isEmoji || fallbackFont->platformData().isColorBitmapFont()))
    74133            return fallbackFont;
    75134    }
    76135
    77     if (auto systemFallback = FontCache::singleton().systemFallbackForCharacters(m_fontDescription, baseFont, false, characters, length)) {
    78         if (systemFallback->canRenderCombiningCharacterSequence(characters, length))
     136    if (auto systemFallback = FontCache::singleton().systemFallbackForCharacters(m_fontDescription, baseFont, IsForPlatformFont::No, isEmoji ? FontCache::PreferColoredFont::Yes : FontCache::PreferColoredFont::No, characters, length)) {
     137        if (systemFallback->canRenderCombiningCharacterSequence(characters, length) && (!isEmoji || systemFallback->platformData().isColorBitmapFont()))
    79138            return systemFallback.get();
    80139    }
  • trunk/Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp

    r239461 r239822  
    13551355}
    13561356
    1357 RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font* originalFontData, bool isPlatformFont, const UChar* characters, unsigned length)
     1357RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font* originalFontData, IsForPlatformFont isForPlatformFont, PreferColoredFont, const UChar* characters, unsigned length)
    13581358{
    13591359#if PLATFORM(IOS_FAMILY)
     
    13841384
    13851385    bool syntheticBold, syntheticOblique;
    1386     std::tie(syntheticBold, syntheticOblique) = computeNecessarySynthesis(substituteFont, description, isPlatformFont).boldObliquePair();
     1386    std::tie(syntheticBold, syntheticOblique) = computeNecessarySynthesis(substituteFont, description, isForPlatformFont == IsForPlatformFont::Yes).boldObliquePair();
    13871387
    13881388    FontPlatformData alternateFont(substituteFont, platformData.size(), syntheticBold, syntheticOblique, platformData.orientation(), platformData.widthVariant(), platformData.textRenderingMode());
  • trunk/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp

    r239768 r239822  
    119119}
    120120
    121 RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font*, bool, const UChar* characters, unsigned length)
     121RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font*, IsForPlatformFont, PreferColoredFont preferColoredFont, const UChar* characters, unsigned length)
    122122{
    123123    FcUniquePtr<FcCharSet> fontConfigCharSet(FcCharSetCreate());
     
    133133
    134134    FcPatternAddBool(pattern.get(), FC_SCALABLE, FcTrue);
     135    if (preferColoredFont == PreferColoredFont::Yes)
     136        FcPatternAddBool(pattern.get(), FC_COLOR, FcTrue);
    135137
    136138    if (!configurePatternForFontDescription(pattern.get(), description))
  • trunk/Source/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp

    r239554 r239822  
    3333#include <fontconfig/fcfreetype.h>
    3434#include <ft2build.h>
     35#include FT_FREETYPE_H
    3536#include FT_TRUETYPE_TABLES_H
    3637#include <hb-ft.h>
     
    118119
    119120    buildScaledFont(fontFace);
     121
     122#ifdef FT_HAS_COLOR
     123    CairoFtFaceLocker cairoFtFaceLocker(m_scaledFont.get());
     124    if (FT_Face ftFace = cairoFtFaceLocker.ftFace())
     125        m_isColorBitmapFont = FT_HAS_COLOR(ftFace);
     126#endif
    120127}
    121128
  • trunk/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp

    r239427 r239822  
    189189}
    190190
    191 }
     191bool Font::variantCapsSupportsCharacterForSynthesis(FontVariantCaps fontVariantCaps, UChar32) const
     192{
     193    switch (fontVariantCaps) {
     194    case FontVariantCaps::Small:
     195    case FontVariantCaps::Petite:
     196    case FontVariantCaps::AllSmall:
     197    case FontVariantCaps::AllPetite:
     198        return false;
     199    default:
     200        // Synthesis only supports the variant-caps values listed above.
     201        return true;
     202    }
     203}
     204
     205bool Font::platformSupportsCodePoint(UChar32 character) const
     206{
     207    CairoFtFaceLocker cairoFtFaceLocker(m_platformData.scaledFont());
     208    if (FT_Face face = cairoFtFaceLocker.ftFace())
     209        return !!FcFreeTypeCharIndex(face, character);
     210
     211    return false;
     212}
     213
     214}
  • trunk/Source/WebCore/platform/graphics/win/FontCacheWin.cpp

    r239092 r239822  
    212212}
    213213
    214 RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font* originalFontData, bool, const UChar* characters, unsigned length)
     214RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& description, const Font* originalFontData, IsForPlatformFont, PreferColoredFont, const UChar* characters, unsigned length)
    215215{
    216216    UChar character = characters[0];
  • trunk/Source/WebCore/platform/text/CharacterProperties.h

    r213616 r239822  
    7777}
    7878
     79inline bool isEmojiKeycapBase(UChar32 character)
     80{
     81    return (character >= '0' && character <= '9') || character == '#' || character == '*';
    7982}
     83
     84inline bool isEmojiRegionalIndicator(UChar32 character)
     85{
     86    return character >= 0x1F1E6 && character <= 0x1F1FF;
     87}
     88
     89inline bool isEmojiWithPresentationByDefault(UChar32 character)
     90{
     91#if U_ICU_VERSION_MAJOR_NUM >= 57
     92    return u_hasBinaryProperty(character, UCHAR_EMOJI_PRESENTATION);
     93#else
     94    UNUSED_PARAM(character);
     95    return false;
     96#endif
     97}
     98
     99inline bool isEmojiModifierBase(UChar32 character)
     100{
     101#if U_ICU_VERSION_MAJOR_NUM >= 57
     102    return u_hasBinaryProperty(character, UCHAR_EMOJI_MODIFIER_BASE);
     103#else
     104    UNUSED_PARAM(character);
     105    return false;
     106#endif
     107}
     108
     109}
Note: See TracChangeset for help on using the changeset viewer.