From 56bda7e82a59b3fcaa828960deeb2a766f8afdfe Mon Sep 17 00:00:00 2001 From: Seigo Nonaka Date: Mon, 11 Jul 2016 17:28:44 +0900 Subject: [PATCH] Lookup glyph from color emoji font before and after ZWJ. Unicode recommends that the zwj sequences should be emoji presentation even if they don't have the proper U+FE0F. Thus always lookup the glyph for the code point before and after zwj as if they have a U+FE0F variation selector. Bug: 30056627 Change-Id: I03958a92337eaba4a8dd9c5be824b2665aa4a103 --- .../flutter/libs/minikin/FontCollection.cpp | 18 +++++++++++------- .../tests/FontCollectionItemizeTest.cpp | 12 +++++++++--- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/engine/src/flutter/libs/minikin/FontCollection.cpp b/engine/src/flutter/libs/minikin/FontCollection.cpp index 33418ab1b5..e665615d93 100644 --- a/engine/src/flutter/libs/minikin/FontCollection.cpp +++ b/engine/src/flutter/libs/minikin/FontCollection.cpp @@ -335,18 +335,15 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs, } const uint32_t NBSP = 0xa0; -const uint32_t ZWJ = 0x200c; -const uint32_t ZWNJ = 0x200d; +const uint32_t ZWJ = 0x200d; +const uint32_t ZWNJ = 0x200c; const uint32_t HYPHEN = 0x2010; const uint32_t NB_HYPHEN = 0x2011; -const uint32_t FEMALE_SIGN = 0x2640; -const uint32_t MALE_SIGN = 0x2642; -const uint32_t STAFF_OF_AESCULAPIUS = 0x2695; // Characters where we want to continue using existing font run instead of // recomputing the best match in the fallback list. static const uint32_t stickyWhitelist[] = { '!', ',', '-', '.', ':', ';', '?', NBSP, ZWJ, ZWNJ, - HYPHEN, NB_HYPHEN, FEMALE_SIGN, MALE_SIGN, STAFF_OF_AESCULAPIUS }; + HYPHEN, NB_HYPHEN }; static bool isStickyWhitelisted(uint32_t c) { for (size_t i = 0; i < sizeof(stickyWhitelist) / sizeof(stickyWhitelist[0]); i++) { @@ -432,8 +429,15 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty } if (!shouldContinueRun) { - FontFamily* family = getFamilyForChar(ch, isVariationSelector(nextCh) ? nextCh : 0, + FontFamily* family; + if ((prevCh == ZWJ || nextCh == ZWJ) && isEmoji(ch)) { + // Treat emoji before and after ZWJ as emoji presentation. + family = getFamilyForChar(ch, EMOJI_STYLE_VS, langListId, variant); + } else { + family = getFamilyForChar(ch, isVariationSelector(nextCh) ? nextCh : 0, langListId, variant); + } + if (utf16Pos == 0 || family != lastFamily) { size_t start = utf16Pos; // Workaround for combining marks and emoji modifiers until we implement diff --git a/engine/src/flutter/tests/FontCollectionItemizeTest.cpp b/engine/src/flutter/tests/FontCollectionItemizeTest.cpp index 468b4a28fa..85d223ceaf 100644 --- a/engine/src/flutter/tests/FontCollectionItemizeTest.cpp +++ b/engine/src/flutter/tests/FontCollectionItemizeTest.cpp @@ -1223,7 +1223,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) { EXPECT_EQ(2, runs[0].end); EXPECT_EQ(kNoGlyphFont, getFontPath(runs[0])); - // U+26FA U+FE0E is specified but ColorTextMixedEmojiFont has a variation sequence U+26F9 U+FE0F + // U+26FA U+FE0E is specified but ColorTextMixedEmojiFont has a variation sequence U+26FA U+FE0F // in its cmap, so ColorTextMixedEmojiFont should be selected instaed of ColorEmojiFont. itemize(collection.get(), "U+26FA U+FE0E", kDefaultFontStyle, &runs); ASSERT_EQ(1U, runs.size()); @@ -1305,9 +1305,9 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) { EXPECT_EQ(2, runs[0].end); EXPECT_EQ(kNoGlyphFont, getFontPath(runs[0])); - // U+26F9 U+FE0F is specified but ColorTextMixedEmojiFont has a variation sequence U+26F9 U+FE0F + // U+26F8 U+FE0F is specified but ColorTextMixedEmojiFont has a variation sequence U+26F8 U+FE0F // in its cmap, so ColorTextMixedEmojiFont should be selected instaed of ColorEmojiFont. - itemize(collection.get(), "U+26F9 U+FE0F", kDefaultFontStyle, &runs); + itemize(collection.get(), "U+26F8 U+FE0F", kDefaultFontStyle, &runs); ASSERT_EQ(1U, runs.size()); EXPECT_EQ(0, runs[0].start); EXPECT_EQ(2, runs[0].end); @@ -1396,4 +1396,10 @@ TEST_F(FontCollectionItemizeTest, itemize_genderBalancedEmoji) { EXPECT_EQ(0, runs[0].start); EXPECT_EQ(4, runs[0].end); EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0])); + + itemize(collection.get(), "U+26F9 U+200D U+2695", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(3, runs[0].end); + EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0])); }