summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeigo Nonaka <nona@google.com>2016-02-25 17:07:42 +0900
committerSeigo Nonaka <nona@google.com>2016-02-26 11:26:30 +0900
commit0036da164e3b25f1ac29c840c1fe15b03dc6677f (patch)
treedfc0752fe5b816e262695b5a5a693dcec89bf3cf
parent94d5525508b60407c9224fbd279a9f6932d5fb6c (diff)
downloadandroid_frameworks_minikin-0036da164e3b25f1ac29c840c1fe15b03dc6677f.tar.gz
android_frameworks_minikin-0036da164e3b25f1ac29c840c1fe15b03dc6677f.tar.bz2
android_frameworks_minikin-0036da164e3b25f1ac29c840c1fe15b03dc6677f.zip
Use color font if skin tone is specified.
If skin tone is specified, the base emoji should be emoji style even if it is text presentation default emoji. This patch also removes wrong test case which expects default emoji presentation but it is controlled by family order in /etc/fonts.xml and there is no special logic for default presentation in minikin. Thus the default presentation unit test should not be in minikin. Bug: 27342346 Change-Id: I74a2b2feab4d559535049e368cfd833063cce81c
-rw-r--r--libs/minikin/FontCollection.cpp10
-rw-r--r--libs/minikin/GraphemeBreak.cpp43
-rw-r--r--libs/minikin/MinikinInternal.cpp42
-rw-r--r--libs/minikin/MinikinInternal.h6
-rw-r--r--tests/FontCollectionItemizeTest.cpp110
-rw-r--r--tests/data/ColorEmojiFont.ttfbin948 -> 1020 bytes
-rw-r--r--tests/data/ColorEmojiFont.ttx16
-rw-r--r--tests/data/TextEmojiFont.ttfbin940 -> 964 bytes
-rw-r--r--tests/data/TextEmojiFont.ttx6
-rw-r--r--tests/data/emoji.xml6
10 files changed, 116 insertions, 123 deletions
diff --git a/libs/minikin/FontCollection.cpp b/libs/minikin/FontCollection.cpp
index dd905a3..4541af8 100644
--- a/libs/minikin/FontCollection.cpp
+++ b/libs/minikin/FontCollection.cpp
@@ -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) {
diff --git a/libs/minikin/GraphemeBreak.cpp b/libs/minikin/GraphemeBreak.cpp
index 4141091..ef323d5 100644
--- a/libs/minikin/GraphemeBreak.cpp
+++ b/libs/minikin/GraphemeBreak.cpp
@@ -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
diff --git a/libs/minikin/MinikinInternal.cpp b/libs/minikin/MinikinInternal.cpp
index c2aa01a..7fa7ce9 100644
--- a/libs/minikin/MinikinInternal.cpp
+++ b/libs/minikin/MinikinInternal.cpp
@@ -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;
+ }
+}
+
}
diff --git a/libs/minikin/MinikinInternal.h b/libs/minikin/MinikinInternal.h
index 34a95bb..3d68691 100644
--- a/libs/minikin/MinikinInternal.h
+++ b/libs/minikin/MinikinInternal.h
@@ -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
diff --git a/tests/FontCollectionItemizeTest.cpp b/tests/FontCollectionItemizeTest.cpp
index 446efc6..031f3f9 100644
--- a/tests/FontCollectionItemizeTest.cpp
+++ b/tests/FontCollectionItemizeTest.cpp
@@ -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]));
+}
diff --git a/tests/data/ColorEmojiFont.ttf b/tests/data/ColorEmojiFont.ttf
index dd72eea..e0b34a1 100644
--- a/tests/data/ColorEmojiFont.ttf
+++ b/tests/data/ColorEmojiFont.ttf
Binary files differ
diff --git a/tests/data/ColorEmojiFont.ttx b/tests/data/ColorEmojiFont.ttx
index b077339..58b3d83 100644
--- a/tests/data/ColorEmojiFont.ttx
+++ b/tests/data/ColorEmojiFont.ttx
@@ -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>
diff --git a/tests/data/TextEmojiFont.ttf b/tests/data/TextEmojiFont.ttf
index 21013a0..21b6801 100644
--- a/tests/data/TextEmojiFont.ttf
+++ b/tests/data/TextEmojiFont.ttf
Binary files differ
diff --git a/tests/data/TextEmojiFont.ttx b/tests/data/TextEmojiFont.ttx
index 35e7d98..83cc9bc 100644
--- a/tests/data/TextEmojiFont.ttx
+++ b/tests/data/TextEmojiFont.ttx
@@ -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>
diff --git a/tests/data/emoji.xml b/tests/data/emoji.xml
index a908b46..796a0f1 100644
--- a/tests/data/emoji.xml
+++ b/tests/data/emoji.xml
@@ -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>