[Cocoa] LastResort in the font family list causes emoji with joiners to be rendered...
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Jul 2018 01:36:43 +0000 (01:36 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Jul 2018 01:36:43 +0000 (01:36 +0000)
commitae43e1e0161e8c5684fb4df10235d7f9a0ce95e2
tree8d6fb8c62b8ecbaeeb982cefdb1ec6107be15ef3
parent83978083d3db8b95e9be171511e0e1a09a990083
[Cocoa] LastResort in the font family list causes emoji with joiners to be rendered as multiple .notdef characters
https://bugs.webkit.org/show_bug.cgi?id=187209
<rdar://problem/40920785>

Reviewed by Darin Adler.

Source/WebCore:

Inside our complex text codepath, we perform our own font fallback, which
includes a function that asks "can this font support this grapheme cluster?"
Because of the mechanics of how fonts work, the implementation of this
function is "Does the font's cmap table support every character of the
cluster?" We were using Font::glyphForCharacter() to determine this; however,
this function maps certain control characters to the zero width space
character (with the intention that these control characters shouldn't be
visible in the fast text codepath). That replacement, however, was causing
us to get false negatives, because Apple Color Emoji doesn't support zero
width space. Therefore, Apple Color Emoji was looking like it didn't support
emoji combining sequences.

The best solution to this would be to get Font::glyphForCharacter() to stop
performing these replacements (see https://bugs.webkit.org/show_bug.cgi?id=187166).
However, that is too risky of a change to be making right now. Instead,
a more localized solution is to implement a version of "Does the font's cmap
table support every character of the cluster" that doesn't perform the
substitutions. This patch does exactly that, and uses a bit vector to cache
the results. In order to not have a giant bit vector, we take the old code
path if we know the substitutions won't affect us (and uses ASSERT()s to
validate this) so the bit vector only holds at maximum 3 words of storage.

Test: fast/text/emoji-with-joiner.html

* platform/graphics/Font.cpp:
(WebCore::codePointSupportIndex):
(WebCore::createAndFillGlyphPage):
(WebCore::Font::platformSupportsCodePoint const):
(WebCore::Font::supportsCodePoint const):
(WebCore::Font::canRenderCombiningCharacterSequence const):
* platform/graphics/Font.h:
* platform/graphics/cocoa/FontCocoa.mm:
(WebCore::Font::platformSupportsCodePoint const):

Source/WTF:

* wtf/unicode/CharacterNames.h:

LayoutTests:

* fast/text/emoji-with-joiner-expected.txt: Added.
* fast/text/emoji-with-joiner.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@233413 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/fast/text/emoji-with-joiner-expected.txt [new file with mode: 0644]
LayoutTests/fast/text/emoji-with-joiner.html [new file with mode: 0644]
Source/WTF/ChangeLog
Source/WTF/wtf/unicode/CharacterNames.h
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/Font.cpp
Source/WebCore/platform/graphics/Font.h
Source/WebCore/platform/graphics/cocoa/FontCocoa.mm