<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[245457] releases/WebKitGTK/webkit-2.24/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/245457">245457</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2019-05-17 04:25:37 -0700 (Fri, 17 May 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/245393">r245393</a> - [FreeType] Some character sequences with a variation selector are not rendered
https://bugs.webkit.org/show_bug.cgi?id=197838

Reviewed by Michael Catanzaro.

We get the invalid glyph instead. See http://mts.io/2015/04/21/unicode-symbol-render-text-emoji/. In the table at
the end the Emoji and Text columns are not correctly rendered. It happens also when copying an emoji from
GtkEmojiChooser and pasting in WebKit text field, because GTK appends U+FE0F to all emojis to force the emoji
style. We need to take into account the variation selector when checking if a font can render a combining
sequence, using FT_Face_GetCharVariantIndex to get the right glyph in case of variation character present.

* platform/graphics/Font.cpp:
(WebCore::Font::platformSupportsCodePoint const): Add optional variation parameter.
(WebCore::Font::canRenderCombiningCharacterSequence const): Take into account variation selector characters
* platform/graphics/Font.h:
* platform/graphics/cairo/FontCairoHarfbuzzNG.cpp:
(WebCore::FontCascade::fontForCombiningCharacterSequence const): Check variation selectors 0xFE0E and 0xFE0F to
decide whether to use the emoji or text style.
* platform/graphics/cocoa/FontCocoa.mm:
(WebCore::Font::platformSupportsCodePoint const): Return false when a variation character is passed so that
characters are checked individually.
* platform/graphics/freetype/SimpleFontDataFreeType.cpp:
(WebCore::Font::platformSupportsCodePoint const): Use FT_Face_GetCharVariantIndex when a variation character is
passed.
* platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp:
(WebCore::harfBuzzFontFunctions): Do not return true when FT_Face_GetCharVariantIndex returns 0.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit224SourceWebCoreChangeLog">releases/WebKitGTK/webkit-2.24/Source/WebCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicsFontcpp">releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/Font.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicsFonth">releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/Font.h</a></li>
<li><a href="#releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicscairoFontCairoHarfbuzzNGcpp">releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicscocoaFontCocoamm">releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm</a></li>
<li><a href="#releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicsfreetypeSimpleFontDataFreeTypecpp">releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicsharfbuzzComplexTextControllerHarfBuzzcpp">releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit224SourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/ChangeLog (245456 => 245457)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.24/Source/WebCore/ChangeLog  2019-05-17 11:25:32 UTC (rev 245456)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/ChangeLog     2019-05-17 11:25:37 UTC (rev 245457)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2019-05-16  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [FreeType] Some character sequences with a variation selector are not rendered
+        https://bugs.webkit.org/show_bug.cgi?id=197838
+
+        Reviewed by Michael Catanzaro.
+
+        We get the invalid glyph instead. See http://mts.io/2015/04/21/unicode-symbol-render-text-emoji/. In the table at
+        the end the Emoji and Text columns are not correctly rendered. It happens also when copying an emoji from
+        GtkEmojiChooser and pasting in WebKit text field, because GTK appends U+FE0F to all emojis to force the emoji
+        style. We need to take into account the variation selector when checking if a font can render a combining
+        sequence, using FT_Face_GetCharVariantIndex to get the right glyph in case of variation character present.
+
+        * platform/graphics/Font.cpp:
+        (WebCore::Font::platformSupportsCodePoint const): Add optional variation parameter.
+        (WebCore::Font::canRenderCombiningCharacterSequence const): Take into account variation selector characters
+        * platform/graphics/Font.h:
+        * platform/graphics/cairo/FontCairoHarfbuzzNG.cpp:
+        (WebCore::FontCascade::fontForCombiningCharacterSequence const): Check variation selectors 0xFE0E and 0xFE0F to
+        decide whether to use the emoji or text style.
+        * platform/graphics/cocoa/FontCocoa.mm:
+        (WebCore::Font::platformSupportsCodePoint const): Return false when a variation character is passed so that
+        characters are checked individually.
+        * platform/graphics/freetype/SimpleFontDataFreeType.cpp:
+        (WebCore::Font::platformSupportsCodePoint const): Use FT_Face_GetCharVariantIndex when a variation character is
+        passed.
+        * platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp:
+        (WebCore::harfBuzzFontFunctions): Do not return true when FT_Face_GetCharVariantIndex returns 0.
+
</ins><span class="cx"> 2019-03-16  Darin Adler  <darin@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Improve normalization code, including moving from unorm.h to unorm2.h
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicsFontcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/Font.cpp (245456 => 245457)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/Font.cpp 2019-05-17 11:25:32 UTC (rev 245456)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/Font.cpp    2019-05-17 11:25:37 UTC (rev 245457)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx"> #include <pal/spi/cocoa/CoreTextSPI.h>
</span><span class="cx"> #endif
</span><ins>+#include "CharacterProperties.h"
</ins><span class="cx"> #include "FontCache.h"
</span><span class="cx"> #include "FontCascade.h"
</span><span class="cx"> #include "OpenTypeMathData.h"
</span><span class="lines">@@ -641,9 +642,9 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Font::platformSupportsCodePoint(UChar32 character) const
</del><ins>+bool Font::platformSupportsCodePoint(UChar32 character, Optional<UChar32> variation) const
</ins><span class="cx"> {
</span><del>-    return glyphForCharacter(character);
</del><ins>+    return variation ? false : glyphForCharacter(character);
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -671,7 +672,23 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx"> 
</span><del>-    for (UChar32 codePoint : StringView(characters, length).codePoints()) {
</del><ins>+    auto codePoints = StringView(characters, length).codePoints();
+    auto it = codePoints.begin();
+    auto end = codePoints.end();
+    while (it != end) {
+        auto codePoint = *it;
+        ++it;
+
+        if (it != end && isVariationSelector(*it)) {
+            if (!platformSupportsCodePoint(codePoint, *it)) {
+                // Try the characters individually.
+                if (!supportsCodePoint(codePoint) || !supportsCodePoint(*it))
+                    return false;
+            }
+            ++it;
+            continue;
+        }
+
</ins><span class="cx">         if (!supportsCodePoint(codePoint))
</span><span class="cx">             return false;
</span><span class="cx">     }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicsFonth"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/Font.h (245456 => 245457)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/Font.h   2019-05-17 11:25:32 UTC (rev 245456)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/Font.h      2019-05-17 11:25:37 UTC (rev 245457)
</span><span class="lines">@@ -175,7 +175,7 @@
</span><span class="cx">     GlyphData glyphDataForCharacter(UChar32) const;
</span><span class="cx">     Glyph glyphForCharacter(UChar32) const;
</span><span class="cx">     bool supportsCodePoint(UChar32) const;
</span><del>-    bool platformSupportsCodePoint(UChar32) const;
</del><ins>+    bool platformSupportsCodePoint(UChar32, Optional<UChar32> variation = WTF::nullopt) const;
</ins><span class="cx"> 
</span><span class="cx">     RefPtr<Font> systemFallbackFontForCharacter(UChar32, const FontDescription&, IsForPlatformFont) const;
</span><span class="cx"> 
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicscairoFontCairoHarfbuzzNGcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp (245456 => 245457)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp    2019-05-17 11:25:32 UTC (rev 245456)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp       2019-05-17 11:25:37 UTC (rev 245457)
</span><span class="lines">@@ -115,11 +115,18 @@
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><span class="cx">     bool isEmoji = characterSequenceIsEmoji(iterator, character, clusterLength);
</span><ins>+    bool preferColoredFont = isEmoji;
+    // U+FE0E forces text style.
+    // U+FE0F forces emoji style.
+    if (characters[length - 1] == 0xFE0E)
+        preferColoredFont = false;
+    else if (characters[length - 1] == 0xFE0F)
+        preferColoredFont = true;
</ins><span class="cx"> 
</span><span class="cx">     const Font* baseFont = glyphDataForCharacter(character, false, NormalVariant).font;
</span><span class="cx">     if (baseFont
</span><span class="cx">         && (clusterLength == length || baseFont->canRenderCombiningCharacterSequence(characters, length))
</span><del>-        && (!isEmoji || baseFont->platformData().isColorBitmapFont()))
</del><ins>+        && (!preferColoredFont || baseFont->platformData().isColorBitmapFont()))
</ins><span class="cx">         return baseFont;
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = 0; !fallbackRangesAt(i).isNull(); ++i) {
</span><span class="lines">@@ -127,13 +134,17 @@
</span><span class="cx">         if (!fallbackFont || fallbackFont == baseFont)
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        if (fallbackFont->canRenderCombiningCharacterSequence(characters, length) && (!isEmoji || fallbackFont->platformData().isColorBitmapFont()))
</del><ins>+        if (fallbackFont->canRenderCombiningCharacterSequence(characters, length) && (!preferColoredFont || fallbackFont->platformData().isColorBitmapFont()))
</ins><span class="cx">             return fallbackFont;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (auto systemFallback = FontCache::singleton().systemFallbackForCharacters(m_fontDescription, baseFont, IsForPlatformFont::No, isEmoji ? FontCache::PreferColoredFont::Yes : FontCache::PreferColoredFont::No, characters, length)) {
-        if (systemFallback->canRenderCombiningCharacterSequence(characters, length) && (!isEmoji || systemFallback->platformData().isColorBitmapFont()))
</del><ins>+    if (auto systemFallback = FontCache::singleton().systemFallbackForCharacters(m_fontDescription, baseFont, IsForPlatformFont::No, preferColoredFont ? FontCache::PreferColoredFont::Yes : FontCache::PreferColoredFont::No, characters, length)) {
+        if (systemFallback->canRenderCombiningCharacterSequence(characters, length) && (!preferColoredFont || systemFallback->platformData().isColorBitmapFont()))
</ins><span class="cx">             return systemFallback.get();
</span><ins>+
+        // In case of emoji, if fallback font is colored try again without the variation selector character.
+        if (isEmoji && characters[length - 1] == 0xFE0F && systemFallback->platformData().isColorBitmapFont() && systemFallback->canRenderCombiningCharacterSequence(characters, length - 1))
+            return systemFallback.get();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return baseFont;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicscocoaFontCocoamm"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm (245456 => 245457)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm       2019-05-17 11:25:32 UTC (rev 245456)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm  2019-05-17 11:25:37 UTC (rev 245457)
</span><span class="lines">@@ -613,8 +613,11 @@
</span><span class="cx">     return adoptCF(CGPathCreateMutableCopy(result.get()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Font::platformSupportsCodePoint(UChar32 character) const
</del><ins>+bool Font::platformSupportsCodePoint(UChar32 character, Optional<UChar32> variation) const
</ins><span class="cx"> {
</span><ins>+    if (variation)
+        return false;
+
</ins><span class="cx">     UniChar codeUnits[2];
</span><span class="cx">     CGGlyph glyphs[2];
</span><span class="cx">     CFIndex count = 0;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicsfreetypeSimpleFontDataFreeTypecpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp (245456 => 245457)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp      2019-05-17 11:25:32 UTC (rev 245456)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp 2019-05-17 11:25:37 UTC (rev 245457)
</span><span class="lines">@@ -201,11 +201,11 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Font::platformSupportsCodePoint(UChar32 character) const
</del><ins>+bool Font::platformSupportsCodePoint(UChar32 character, Optional<UChar32> variation) const
</ins><span class="cx"> {
</span><span class="cx">     CairoFtFaceLocker cairoFtFaceLocker(m_platformData.scaledFont());
</span><span class="cx">     if (FT_Face face = cairoFtFaceLocker.ftFace())
</span><del>-        return !!FcFreeTypeCharIndex(face, character);
</del><ins>+        return variation ? !!FT_Face_GetCharVariantIndex(face, character, variation.value()) : !!FcFreeTypeCharIndex(face, character);
</ins><span class="cx"> 
</span><span class="cx">     return false;
</span><span class="cx"> }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit224SourceWebCoreplatformgraphicsharfbuzzComplexTextControllerHarfBuzzcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp (245456 => 245457)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp       2019-05-17 11:25:32 UTC (rev 245456)
+++ releases/WebKitGTK/webkit-2.24/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp  2019-05-17 11:25:37 UTC (rev 245457)
</span><span class="lines">@@ -78,7 +78,7 @@
</span><span class="cx">             CairoFtFaceLocker cairoFtFaceLocker(scaledFont);
</span><span class="cx">             if (FT_Face ftFace = cairoFtFaceLocker.ftFace()) {
</span><span class="cx">                 *glyph = FT_Face_GetCharVariantIndex(ftFace, unicode, variation);
</span><del>-                return true;
</del><ins>+                return !!*glyph;
</ins><span class="cx">             }
</span><span class="cx">             return false;
</span><span class="cx">             }, nullptr, nullptr);
</span></span></pre>
</div>
</div>

</body>
</html>