Source/WTF/wtf/unicode/CharacterNames.h

@@const UChar zeroWidthJoiner = 0x200D;
100100const UChar zeroWidthNoBreakSpace = 0xFEFF;
101101const UChar zeroWidthNonJoiner = 0x200C;
102102const UChar zeroWidthSpace = 0x200B;
 103const UChar combiningEnclosingKeycap = 0x20E3;
103104
104105} // namespace Unicode
105106} // namespace WTF

@@using WTF::Unicode::zeroWidthJoiner;
166167using WTF::Unicode::zeroWidthNoBreakSpace;
167168using WTF::Unicode::zeroWidthNonJoiner;
168169using WTF::Unicode::zeroWidthSpace;
 170using WTF::Unicode::combiningEnclosingKeycap;

Source/WebCore/platform/graphics/ComplexTextController.cpp

@@static bool advanceByCombiningCharacterSequence(const UChar*& iterator, const UC
286286 // Consume marks.
287287 bool sawEmojiGroupCandidate = isEmojiGroupCandidate(baseCharacter);
288288 bool sawJoiner = false;
 289 bool sawRegionalIndicator = isEmojiRegionalIndicator(baseCharacter);
289290 while (iterator < end) {
290291 UChar32 nextCharacter;
291292 unsigned markLength = 0;

@@static bool advanceByCombiningCharacterSequence(const UChar*& iterator, const UC
296297 if (isVariationSelector(nextCharacter) || isEmojiFitzpatrickModifier(nextCharacter))
297298 shouldContinue = true;
298299
 300 if (sawRegionalIndicator && isEmojiRegionalIndicator(nextCharacter)) {
 301 shouldContinue = true;
 302 sawRegionalIndicator = false;
 303 }
 304
299305 if (sawJoiner && isEmojiGroupCandidate(nextCharacter))
300306 shouldContinue = true;
301307

Source/WebCore/platform/graphics/Font.cpp

@@RefPtr<Font> Font::systemFallbackFontForCharacter(UChar32 character, const FontD
566566
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, false, &codeUnit, 1);
570570 }
571571
572572 auto key = CharacterFallbackMapKey(description.locale(), character, isForPlatformFont);

@@RefPtr<Font> Font::systemFallbackFontForCharacter(UChar32 character, const FontD
586586 codeUnitsLength = 2;
587587 }
588588
589  fallbackFont = FontCache::singleton().systemFallbackForCharacters(description, this, isForPlatformFont, codeUnits, codeUnitsLength).get();
 589 fallbackFont = FontCache::singleton().systemFallbackForCharacters(description, this, isForPlatformFont, false, codeUnits, codeUnitsLength).get();
590590 if (fallbackFont)
591591 fallbackFont->m_isUsedInSystemFallbackCache = true;
592592 }

@@void Font::removeFromSystemFallbackCache()
612612 }
613613}
614614
615 #if !PLATFORM(COCOA)
 615#if !PLATFORM(COCOA) && !USE(FREETYPE)
616616bool Font::variantCapsSupportsCharacterForSynthesis(FontVariantCaps fontVariantCaps, UChar32) const
617617{
618618 switch (fontVariantCaps) {

Source/WebCore/platform/graphics/FontCache.h

@@public:
190190 WEBCORE_EXPORT static FontCache& singleton();
191191
192192 // These methods are implemented by the platform.
193  RefPtr<Font> systemFallbackForCharacters(const FontDescription&, const Font* originalFontData, bool isPlatformFont, const UChar* characters, unsigned length);
 193 RefPtr<Font> systemFallbackForCharacters(const FontDescription&, const Font* originalFontData, bool isPlatformFont, bool coloredFont, const UChar* characters, unsigned length);
194194 Vector<String> systemFontFamilies();
195195 void platformInit();
196196

Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp

2929
3030#if USE(CAIRO)
3131
 32#include "CharacterProperties.h"
3233#include "FontCache.h"
3334#include "SurrogatePairAwareTextIterator.h"
3435#include <unicode/normlzr.h>

@@bool FontCascade::canExpandAroundIdeographsInComplexText()
4546 return false;
4647}
4748
 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
 100 return false;
 101}
 102
48103const Font* FontCascade::fontForCombiningCharacterSequence(const UChar* characters, size_t length) const
49104{
50105 UErrorCode error = U_ZERO_ERROR;

@@const Font* FontCascade::fontForCombiningCharacterSequence(const UChar* characte
61116 if (!iterator.consume(character, clusterLength))
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
68127 for (unsigned i = 0; !fallbackRangesAt(i).isNull(); ++i) {

@@const Font* FontCascade::fontForCombiningCharacterSequence(const UChar* characte
70129 if (!fallbackFont || fallbackFont == baseFont)
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, false, isEmoji, characters, length)) {
 137 if (systemFallback->canRenderCombiningCharacterSequence(characters, length) && (!isEmoji || systemFallback->platformData().isColorBitmapFont()))
79138 return systemFallback.get();
80139 }
81140

Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp

@@static RetainPtr<CTFontRef> lookupFallbackFont(CTFontRef font, FontSelectionValu
13541354 return result;
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, bool isPlatformFont, bool, const UChar* characters, unsigned length)
13581358{
13591359#if PLATFORM(IOS_FAMILY)
13601360 if (length && requiresCustomFallbackFont(*characters)) {

Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp

@@static void getFontPropertiesFromPattern(FcPattern* pattern, const FontDescripti
118118 }
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*, bool, bool coloredFont, const UChar* characters, unsigned length)
122122{
123123 FcUniquePtr<FcCharSet> fontConfigCharSet(FcCharSetCreate());
124124 UTF16UChar32Iterator iterator(characters, length);

@@RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& descr
132132 FcPatternAddCharSet(pattern.get(), FC_CHARSET, fontConfigCharSet.get());
133133
134134 FcPatternAddBool(pattern.get(), FC_SCALABLE, FcTrue);
 135 if (coloredFont)
 136 FcPatternAddBool(pattern.get(), FC_COLOR, FcTrue);
135137
136138 if (!configurePatternForFontDescription(pattern.get(), description))
137139 return nullptr;

Source/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp

3232#include <cairo-ft.h>
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>
3738#include <hb-ot.h>

@@FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, FcPattern* patte
117118 m_fixedWidth = fixedWidth;
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
122129FontPlatformData::FontPlatformData(const FontPlatformData& other)

Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp

@@float Font::platformWidthForGlyph(Glyph glyph) const
188188 return width ? width : m_spaceWidth;
189189}
190190
 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
191214}

Source/WebCore/platform/graphics/win/FontCacheWin.cpp

@@static HFONT createMLangFont(IMLangFontLinkType* langFontLink, HDC hdc, DWORD co
211211 return hfont;
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, bool, bool, const UChar* characters, unsigned length)
215215{
216216 UChar character = characters[0];
217217 RefPtr<Font> fontData;

Source/WebCore/platform/text/CharacterProperties.h

@@inline bool isVariationSelector(UChar32 character)
7676 return character >= 0xFE00 && character <= 0xFE0F;
7777}
7878
 79inline bool isEmojiKeycapBase(UChar32 character)
 80{
 81 return (character >= '0' && character <= '9') || character == '#' || character == '*';
 82}
 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
79109}