Use color font if skin tone is specified. am: 0036da164e

am: 77270a5074

* commit '77270a5074698777e820306ebfb6a3469f3ac952':
  Use color font if skin tone is specified.
This commit is contained in:
Seigo Nonaka 2016-02-26 03:23:39 +00:00 committed by android-build-merger
commit ff75f198a3
10 changed files with 116 additions and 123 deletions

View File

@ -379,11 +379,13 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
langListId, variant);
if (utf16Pos == 0 || family != lastFamily) {
size_t start = utf16Pos;
// Workaround for Emoji keycap until we implement per-cluster font
// selection: if keycap is found in a different font that also
// supports previous char, attach previous char to the new run.
// Workaround for Emoji keycap and emoji modifier until we implement per-cluster
// font selection: if a keycap or an emoji modifier is found in a different font
// that also supports previous char, attach previous char to the new run.
// Bug 7557244.
if (ch == KEYCAP && utf16Pos != 0 && family && family->getCoverage()->get(prevCh)) {
if (utf16Pos != 0 &&
(ch == KEYCAP || (isEmojiModifier(ch) && isEmojiBase(prevCh))) &&
family && family->getCoverage()->get(prevCh)) {
const size_t prevChLength = U16_LENGTH(prevCh);
run->end -= prevChLength;
if (run->start == run->end) {

View File

@ -19,6 +19,7 @@
#include <unicode/utf16.h>
#include <minikin/GraphemeBreak.h>
#include "MinikinInternal.h"
namespace android {
@ -77,48 +78,6 @@ bool isZwjEmoji(uint32_t c) {
|| c == 0x1F5E8); // LEFT SPEECH BUBBLE
}
// Based on Modifiers from http://www.unicode.org/L2/L2016/16011-data-file.txt
bool isEmojiModifier(uint32_t c) {
return (0x1F3FB <= c && c <= 0x1F3FF);
}
// Based on Emoji_Modifier_Base from
// http://www.unicode.org/Public/emoji/3.0/emoji-data.txt
bool isEmojiBase(uint32_t c) {
if (0x261D <= c && c <= 0x270D) {
return (c == 0x261D || c == 0x26F9 || (0x270A <= c && c <= 0x270D));
} else if (0x1F385 <= c && c <= 0x1F93E) {
return (c == 0x1F385
|| (0x1F3C3 <= c || c <= 0x1F3C4)
|| (0x1F3CA <= c || c <= 0x1F3CB)
|| (0x1F442 <= c || c <= 0x1F443)
|| (0x1F446 <= c || c <= 0x1F450)
|| (0x1F466 <= c || c <= 0x1F469)
|| c == 0x1F46E
|| (0x1F470 <= c || c <= 0x1F478)
|| c == 0x1F47C
|| (0x1F481 <= c || c <= 0x1F483)
|| (0x1F485 <= c || c <= 0x1F487)
|| c == 0x1F4AA
|| c == 0x1F575
|| c == 0x1F57A
|| c == 0x1F590
|| (0x1F595 <= c || c <= 0x1F596)
|| (0x1F645 <= c || c <= 0x1F647)
|| (0x1F64B <= c || c <= 0x1F64F)
|| c == 0x1F6A3
|| (0x1F6B4 <= c || c <= 0x1F6B6)
|| c == 0x1F6C0
|| (0x1F918 <= c || c <= 0x1F91E)
|| c == 0x1F926
|| c == 0x1F930
|| (0x1F933 <= c || c <= 0x1F939)
|| (0x1F93B <= c || c <= 0x1F93E));
} else {
return false;
}
}
bool GraphemeBreak::isGraphemeBreak(const uint16_t* buf, size_t start, size_t count,
size_t offset) {
// This implementation closely follows Unicode Standard Annex #29 on

View File

@ -30,4 +30,46 @@ void assertMinikinLocked() {
#endif
}
// Based on Modifiers from http://www.unicode.org/L2/L2016/16011-data-file.txt
bool isEmojiModifier(uint32_t c) {
return (0x1F3FB <= c && c <= 0x1F3FF);
}
// Based on Emoji_Modifier_Base from
// http://www.unicode.org/Public/emoji/3.0/emoji-data.txt
bool isEmojiBase(uint32_t c) {
if (0x261D <= c && c <= 0x270D) {
return (c == 0x261D || c == 0x26F9 || (0x270A <= c && c <= 0x270D));
} else if (0x1F385 <= c && c <= 0x1F93E) {
return (c == 0x1F385
|| (0x1F3C3 <= c || c <= 0x1F3C4)
|| (0x1F3CA <= c || c <= 0x1F3CB)
|| (0x1F442 <= c || c <= 0x1F443)
|| (0x1F446 <= c || c <= 0x1F450)
|| (0x1F466 <= c || c <= 0x1F469)
|| c == 0x1F46E
|| (0x1F470 <= c || c <= 0x1F478)
|| c == 0x1F47C
|| (0x1F481 <= c || c <= 0x1F483)
|| (0x1F485 <= c || c <= 0x1F487)
|| c == 0x1F4AA
|| c == 0x1F575
|| c == 0x1F57A
|| c == 0x1F590
|| (0x1F595 <= c || c <= 0x1F596)
|| (0x1F645 <= c || c <= 0x1F647)
|| (0x1F64B <= c || c <= 0x1F64F)
|| c == 0x1F6A3
|| (0x1F6B4 <= c || c <= 0x1F6B6)
|| c == 0x1F6C0
|| (0x1F918 <= c || c <= 0x1F91E)
|| c == 0x1F926
|| c == 0x1F930
|| (0x1F933 <= c || c <= 0x1F939)
|| (0x1F93B <= c || c <= 0x1F93E));
} else {
return false;
}
}
}

View File

@ -32,6 +32,12 @@ extern Mutex gMinikinLock;
// Aborts if gMinikinLock is not acquired. Do nothing on the release build.
void assertMinikinLocked();
// Returns true if c is emoji modifier base.
bool isEmojiBase(uint32_t c);
// Returns true if c is emoji modifier.
bool isEmojiModifier(uint32_t c);
}
#endif // MINIKIN_INTERNAL_H

View File

@ -1119,78 +1119,6 @@ TEST_F(FontCollectionItemizeTest, itemize_LanguageAndCoverage) {
}
}
TEST_F(FontCollectionItemizeTest, itemize_emojiSelection) {
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kEmojiXmlFile);
std::vector<FontCollection::Run> runs;
const FontStyle kDefaultFontStyle;
// U+00A9 is a text default emoji which is only available in TextEmojiFont.ttf.
// TextEmojiFont.ttf should be selected.
itemize(collection.get(), "U+00A9", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_EQ(kTextEmojiFont, getFontPath(runs[0]));
// U+00AE is a text default emoji which is only available in ColorEmojiFont.ttf.
// ColorEmojiFont.ttf should be selected.
itemize(collection.get(), "U+00AE", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0]));
// U+203C is a text default emoji which is available in both TextEmojiFont.ttf and
// ColorEmojiFont.ttf. TextEmojiFont.ttf should be selected.
itemize(collection.get(), "U+203C", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
// TODO: use text font for text default emoji.
// EXPECT_EQ(kTextEmojiFont, getFontPath(runs[0]));
// U+2049 is a text default emoji which is not available in either TextEmojiFont.ttf or
// ColorEmojiFont.ttf. No font should be selected.
itemize(collection.get(), "U+2049", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_TRUE(runs[0].fakedFont.font == NULL || kNoGlyphFont == getFontPath(runs[0]));
// U+231A is a emoji default emoji which is available only in TextEmojiFont.ttf.
// TextEmojiFont.ttf should be selected.
itemize(collection.get(), "U+231A", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_EQ(kTextEmojiFont, getFontPath(runs[0]));
// U+231B is a emoji default emoji which is available only in ColorEmojiFont.ttf.
// ColorEmojiFont.ttf should be selected.
itemize(collection.get(), "U+231B", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0]));
// U+23E9 is a emoji default emoji which is available in both TextEmojiFont.ttf and
// ColorEmojiFont.ttf. ColorEmojiFont should be selected.
itemize(collection.get(), "U+23E9", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0]));
// U+23EA is a emoji default emoji which is not avaialble in either TextEmojiFont.ttf and
// ColorEmojiFont.ttf. No font should b e selected.
itemize(collection.get(), "U+23EA", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_TRUE(runs[0].fakedFont.font == NULL || kNoGlyphFont == getFontPath(runs[0]));
}
TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kEmojiXmlFile);
std::vector<FontCollection::Run> runs;
@ -1355,3 +1283,41 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
EXPECT_EQ(kMixedEmojiFont, getFontPath(runs[0]));
}
TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_with_skinTone) {
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kEmojiXmlFile);
std::vector<FontCollection::Run> runs;
const FontStyle kDefaultFontStyle;
// TextEmoji font is selected since it is listed before ColorEmoji font.
itemize(collection.get(), "U+261D", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_EQ(kTextEmojiFont, getFontPath(runs[0]));
// If skin tone is specified, it should be colored.
itemize(collection.get(), "U+261D U+1F3FD", 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]));
// Still color font is selected if an emoji variation selector is specified.
itemize(collection.get(), "U+261D U+FE0F U+1F3FD", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(4, runs[0].end);
EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0]));
// Text font should be selected if a text variation selector is specified and skin tone is
// rendered by itself.
itemize(collection.get(), "U+261D U+FE0E U+1F3FD", kDefaultFontStyle, &runs);
ASSERT_EQ(2U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
EXPECT_EQ(kTextEmojiFont, getFontPath(runs[0]));
EXPECT_EQ(2, runs[1].start);
EXPECT_EQ(4, runs[1].end);
EXPECT_EQ(kColorEmojiFont, getFontPath(runs[1]));
}

Binary file not shown.

View File

@ -27,6 +27,8 @@
<GlyphID id="7" name="Emoji7"/>
<GlyphID id="8" name="Emoji8"/>
<GlyphID id="9" name="Emoji9"/>
<GlyphID id="10" name="WHITE_UP_POINTING_INDEX" />
<GlyphID id="11" name="EMOJI_MODIFIER_FITZPATRICK_TYPE_4" />
</GlyphOrder>
<head>
@ -153,17 +155,21 @@
<mtx name="Emoji7" width="500" lsb="93"/>
<mtx name="Emoji8" width="500" lsb="93"/>
<mtx name="Emoji9" width="500" lsb="93"/>
<mtx name="WHITE_UP_POINTING_INDEX" width="500" lsb="93" />
<mtx name="EMOJI_MODIFIER_FITZPATRICK_TYPE_4" width="500" lsb="93" />
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="3" platEncID="10" language="0">
<cmap_format_12 format="12" reserved="0" length="7" nGroups="1" platformID="3" platEncID="10" language="0">
<map code="0x00AE" name="Emoji2" /> <!-- Text Default -->
<map code="0x203C" name="Emoji3" /> <!-- Text Default -->
<map code="0x231B" name="Emoji6" /> <!-- Emoji Default -->
<map code="0x23E9" name="Emoji7" /> <!-- Emoji Default -->
<map code="0x26F9" name="Emoji9" /> <!-- U+26F9 U+FE0F is in ColorTextMixedEmojiFont.ttf -->
</cmap_format_4>
<map code="0x261D" name="WHITE_UP_POINTING_INDEX" />
<map code="0x1F3FD" name="EMOJI_MODIFIER_FITZPATRICK_TYPE_4" />
</cmap_format_12>
</cmap>
<loca>
@ -206,6 +212,12 @@
<TTGlyph name="Emoji9" xMin="0" yMin="0" xMax="0" yMax="0">
<contour></contour><instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="WHITE_UP_POINTING_INDEX" xMin="0" yMin="0" xMax="0" yMax="0">
<contour></contour><instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="EMOJI_MODIFIER_FITZPATRICK_TYPE_4" xMin="0" yMin="0" xMax="0" yMax="0">
<contour></contour><instructions><assembly></assembly></instructions>
</TTGlyph>
</glyf>
<name>

Binary file not shown.

View File

@ -27,6 +27,7 @@
<GlyphID id="7" name="Emoji7"/>
<GlyphID id="8" name="Emoji8"/>
<GlyphID id="9" name="Emoji9"/>
<GlyphID id="10" name="WHITE_UP_POINTING_INDEX" />
</GlyphOrder>
<head>
@ -153,6 +154,7 @@
<mtx name="Emoji7" width="500" lsb="93"/>
<mtx name="Emoji8" width="500" lsb="93"/>
<mtx name="Emoji9" width="500" lsb="93"/>
<mtx name="WHITE_UP_POINTING_INDEX" width="500" lsb="93"/>
</hmtx>
<cmap>
@ -163,6 +165,7 @@
<map code="0x231A" name="Emoji5" /> <!-- Emoji Default -->
<map code="0x23E9" name="Emoji7" /> <!-- Emoji Default -->
<map code="0x26FA" name="Emoji9" /> <!-- U+26FA U+FE0E is in ColorTextMixedEmojiFont.ttf -->
<map code="0x261D" name="WHITE_UP_POINTING_INDEX" />
</cmap_format_4>
</cmap>
@ -206,6 +209,9 @@
<TTGlyph name="Emoji9" xMin="0" yMin="0" xMax="0" yMax="0">
<contour></contour><instructions><assembly></assembly></instructions>
</TTGlyph>
<TTGlyph name="WHITE_UP_POINTING_INDEX" xMin="0" yMin="0" xMax="0" yMax="0">
<contour></contour><instructions><assembly></assembly></instructions>
</TTGlyph>
</glyf>
<name>

View File

@ -19,12 +19,12 @@
<family>
<font weight="400" style="normal">NoGlyphFont.ttf</font>
</family>
<family lang="und-Zsye">
<font weight="400" style="normal">ColorEmojiFont.ttf</font>
</family>
<family>
<font weight="400" style="normal">TextEmojiFont.ttf</font>
</family>
<family lang="und-Zsye">
<font weight="400" style="normal">ColorEmojiFont.ttf</font>
</family>
<family>
<font weight="400" style="normal">ColorTextMixedEmojiFont.ttf</font>
</family>