diff --git a/include/minikin/FontFamily.h b/include/minikin/FontFamily.h index fc05e3b219688e9dbce1f70ddb85bd96d3a5f3eb..776bcc41beb9c8a38ed9e05702bcc670f6d8eeb8 100644 --- a/include/minikin/FontFamily.h +++ b/include/minikin/FontFamily.h @@ -48,6 +48,7 @@ public: operator bool() const { return mBits != 0; } bool isUnsupported() const { return mBits == kUnsupportedLanguage; } + bool hasEmojiFlag() const { return isUnsupported() ? false : (mBits & kEmojiFlag); } std::string getString() const; @@ -61,9 +62,10 @@ private: static const uint32_t kUnsupportedLanguage = 0xFFFFFFFFu; static const uint32_t kBaseLangMask = 0xFFFFFFu; - static const uint32_t kScriptMask = (1u << 26) - (1u << 24); static const uint32_t kHansFlag = 1u << 24; static const uint32_t kHantFlag = 1u << 25; + static const uint32_t kEmojiFlag = 1u << 26; + static const uint32_t kScriptMask = kHansFlag | kHantFlag | kEmojiFlag; uint32_t mBits; }; diff --git a/libs/minikin/FontCollection.cpp b/libs/minikin/FontCollection.cpp index ea702226af283f4fb2a19c18af68442cf3cd9460..d089e8b0d90c9fd06c1fdd6d56da95967b42a226 100644 --- a/libs/minikin/FontCollection.cpp +++ b/libs/minikin/FontCollection.cpp @@ -106,7 +106,15 @@ FontCollection::~FontCollection() { // 2. If a font matches both language and script, it gets a score of 4. // 3. If a font matches just language, it gets a score of 2. // 4. Matching the "compact" or "elegant" variant adds one to the score. -// 5. Highest score wins, with ties resolved to the first font. +// 5. If there is a variation selector and a font supports the complete variation sequence, we add +// 12 to the score. +// 6. If there is a color variation selector (U+FE0F), we add 6 to the score if the font is an emoji +// font. This additional score of 6 is only given if the base character is supported in the font, +// but not the whole variation sequence. +// 7. If there is a text variation selector (U+FE0E), we add 6 to the score if the font is not an +// emoji font. This additional score of 6 is only given if the base character is supported in the +// font, but not the whole variation sequence. +// 8. Highest score wins, with ties resolved to the first font. FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs, FontLanguage lang, int variant) const { if (ch >= mMaxChar) { @@ -131,27 +139,29 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs, int bestScore = -1; for (size_t i = range.start; i < range.end; i++) { FontFamily* family = familyVec[i]; - if (vs == 0 ? family->getCoverage()->get(ch) : family->hasVariationSelector(ch, vs)) { - // First font family in collection always matches - if (mFamilies[0] == family) { + const bool hasVSGlyph = (vs != 0) && family->hasVariationSelector(ch, vs); + if (hasVSGlyph || family->getCoverage()->get(ch)) { + if ((vs == 0 || hasVSGlyph) && mFamilies[0] == family) { + // If the first font family in collection supports the given character or sequence, + // always use it. return family; } int score = lang.match(family->lang()) * 2; if (family->variant() == 0 || family->variant() == variant) { score++; } + if (hasVSGlyph) { + score += 12; + } else if (((vs == 0xFE0F) && family->lang().hasEmojiFlag()) || + ((vs == 0xFE0E) && !family->lang().hasEmojiFlag())) { + score += 6; + } if (score > bestScore) { bestScore = score; bestFamily = family; } } } - if (bestFamily == nullptr && vs != 0) { - // If no fonts support the codepoint and variation selector pair, - // fallback to select a font family that supports just the base - // character, ignoring the variation selector. - return getFamilyForChar(ch, 0, lang, variant); - } if (bestFamily == nullptr && !mFamilyVec.empty()) { UErrorCode errorCode = U_ZERO_ERROR; const UNormalizer2* normalizer = unorm2_getNFDInstance(&errorCode); diff --git a/libs/minikin/FontFamily.cpp b/libs/minikin/FontFamily.cpp index 1ff5a6bce4b7b6a5fa79c9427b8ab2f1e52728f6..5adff57b6ec713220c088998b99c93ceae743dfc 100644 --- a/libs/minikin/FontFamily.cpp +++ b/libs/minikin/FontFamily.cpp @@ -62,11 +62,15 @@ FontLanguage::FontLanguage(const char* buf, size_t size) { uint16_t c = buf[next]; if (c == '-' || c == '_') break; } - if (next - i == 4 && buf[i] == 'H' && buf[i+1] == 'a' && buf[i+2] == 'n') { - if (buf[i+3] == 's') { - bits |= kHansFlag; - } else if (buf[i+3] == 't') { - bits |= kHantFlag; + if (next - i == 4) { + if (buf[i] == 'H' && buf[i+1] == 'a' && buf[i+2] == 'n') { + if (buf[i+3] == 's') { + bits |= kHansFlag; + } else if (buf[i+3] == 't') { + bits |= kHantFlag; + } + } else if (buf[i] == 'Q' && buf[i+1] == 'a' && buf[i+2] == 'a'&& buf[i+3] == 'e') { + bits |= kEmojiFlag; } } // TODO: this might be a good place to infer script from country (zh_TW -> Hant), @@ -96,10 +100,17 @@ std::string FontLanguage::getString() const { buf[i++] = 'd'; } buf[i++] = '-'; - buf[i++] = 'H'; - buf[i++] = 'a'; - buf[i++] = 'n'; - buf[i++] = (mBits & kHansFlag) ? 's' : 't'; + if (mBits & kEmojiFlag) { + buf[i++] = 'Q'; + buf[i++] = 'a'; + buf[i++] = 'a'; + buf[i++] = 'e'; + } else { + buf[i++] = 'H'; + buf[i++] = 'a'; + buf[i++] = 'n'; + buf[i++] = (mBits & kHansFlag) ? 's' : 't'; + } } return std::string(buf, i); } diff --git a/tests/FontCollectionItemizeTest.cpp b/tests/FontCollectionItemizeTest.cpp index 47f5259c73392a76ed276440a75d016f2d74df3e..a7da4269a69cc8ca13615919950e5a2277307053 100644 --- a/tests/FontCollectionItemizeTest.cpp +++ b/tests/FontCollectionItemizeTest.cpp @@ -25,9 +25,9 @@ using android::FontFamily; using android::FontLanguage; using android::FontStyle; -const char kItemizeFontXml[] = "/data/minikin/test/data/itemize.xml"; #define kTestFontDir "/data/minikin/test/data/" +const char kItemizeFontXml[] = kTestFontDir "itemize.xml"; const char kEmojiFont[] = kTestFontDir "Emoji.ttf"; const char kJAFont[] = kTestFontDir "Ja.ttf"; const char kKOFont[] = kTestFontDir "Ko.ttf"; @@ -38,6 +38,12 @@ const char kLatinItalicFont[] = kTestFontDir "Italic.ttf"; const char kZH_HansFont[] = kTestFontDir "ZhHans.ttf"; const char kZH_HantFont[] = kTestFontDir "ZhHant.ttf"; +const char kEmojiXmlFile[] = kTestFontDir "emoji.xml"; +const char kNoGlyphFont[] = kTestFontDir "NoGlyphFont.ttf"; +const char kColorEmojiFont[] = kTestFontDir "ColorEmojiFont.ttf"; +const char kTextEmojiFont[] = kTestFontDir "TextEmojiFont.ttf"; +const char kMixedEmojiFont[] = kTestFontDir "ColorTextMixedEmojiFont.ttf"; + // Utility function for calling itemize function. void itemize(FontCollection* collection, const char* str, FontStyle style, std::vector* result) { @@ -52,6 +58,7 @@ void itemize(FontCollection* collection, const char* str, FontStyle style, // Utility function to obtain font path associated with run. const std::string& getFontPath(const FontCollection::Run& run) { + EXPECT_NE(nullptr, run.fakedFont.font); return ((MinikinFontForTest*)run.fakedFont.font)->fontPath(); } @@ -425,6 +432,21 @@ TEST(FontCollectionItemizeTest, itemize_variationSelector) { EXPECT_EQ(0, runs[0].start); EXPECT_EQ(1, runs[0].end); EXPECT_TRUE(runs[0].fakedFont.font == nullptr || kLatinFont == getFontPath(runs[0])); + + // First font family (Regular.ttf) supports U+203C but doesn't support U+203C U+FE0F. + // Emoji.ttf font supports supports U+203C U+FE0F. Emoji.ttf should be selected. + itemize(collection.get(), "U+203C U+FE0F", kZH_HantStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kEmojiFont, getFontPath(runs[0])); + + // First font family (Regular.ttf) supports U+203C U+FE0E. + itemize(collection.get(), "U+203C U+FE0E", kZH_HantStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kLatinFont, getFontPath(runs[0])); } TEST(FontCollectionItemizeTest, itemize_variationSelectorSupplement) { @@ -643,3 +665,240 @@ TEST(FontCollectionItemizeTest, itemize_vs_sequence_but_no_base_char) { family1->Unref(); family2->Unref(); } + +TEST(FontCollectionItemizeTest, itemize_emojiSelection) { + std::unique_ptr collection = getFontCollection(kTestFontDir, kEmojiXmlFile); + std::vector 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(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) { + std::unique_ptr collection = getFontCollection(kTestFontDir, kEmojiXmlFile); + std::vector 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 U+FE0E", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kTextEmojiFont, getFontPath(runs[0])); + + // U+00A9 is a text default emoji which is only available in ColorEmojiFont.ttf. + // ColorEmojiFont.ttf should be selected. + itemize(collection.get(), "U+00AE U+FE0E", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + // Text emoji is specified but it is not available. Use color emoji instead. + 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 U+FE0E", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kTextEmojiFont, getFontPath(runs[0])); + + // U+2049 is a text default emoji which is not available either TextEmojiFont.ttf or + // ColorEmojiFont.ttf. No font should be selected. + itemize(collection.get(), "U+2049 U+FE0E", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, 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 TextEmojifFont. + // TextEmojiFont.ttf sohuld be selected. + itemize(collection.get(), "U+231A U+FE0E", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, 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 U+FE0E", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + // Text emoji is specified but it is not available. Use color emoji instead. + EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0])); + + // U+23E9 is a emoji default emoji which is available in both TextEmojiFont.ttf and + // ColorEmojiFont.ttf. TextEmojiFont.ttf should be selected even if U+23E9 is emoji default + // emoji since U+FE0E is appended. + itemize(collection.get(), "U+23E9 U+FE0E", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kTextEmojiFont, getFontPath(runs[0])); + + // U+23EA is a emoji default emoji but which is not available in either TextEmojiFont.ttf or + // ColorEmojiFont.ttf. No font should be selected. + itemize(collection.get(), "U+23EA U+FE0E", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_TRUE(runs[0].fakedFont.font == NULL || kNoGlyphFont == getFontPath(runs[0])); + + // U+26FA U+FE0E is specified but ColorTextMixedEmojiFont has a variation sequence U+26F9 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()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kMixedEmojiFont, getFontPath(runs[0])); +} + +TEST(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) { + std::unique_ptr collection = getFontCollection(kTestFontDir, kEmojiXmlFile); + std::vector runs; + + const FontStyle kDefaultFontStyle; + + // U+00A9 is a text default emoji which is available only in TextEmojiFont.ttf. + // TextEmojiFont.ttf shoudl be selected. + itemize(collection.get(), "U+00A9 U+FE0F", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + // Color emoji is specified but it is not available. Use text representaion instead. + EXPECT_EQ(kTextEmojiFont, getFontPath(runs[0])); + + // U+00AE is a text default emoji which is available only in ColorEmojiFont.ttf. + // ColorEmojiFont.ttf should be selected. + itemize(collection.get(), "U+00AE U+FE0F", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, 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. ColorEmojiFont.ttf should be selected even if U+203C is a text default + // emoji since U+FF0F is appended. + itemize(collection.get(), "U+203C U+FE0F", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kColorEmojiFont, 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 U+FE0F", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, 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 U+FE0F", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + // Color emoji is specified but it is not available. Use text representation instead. + 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 U+FE0F", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, 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.ttf should be selected. + itemize(collection.get(), "U+23E9 U+FE0F", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0])); + + // U+23EA is a emoji default emoji which is not available in either TextEmojiFont.ttf or + // ColorEmojiFont.ttf. No font should be selected. + itemize(collection.get(), "U+23EA U+FE0F", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_TRUE(runs[0].fakedFont.font == NULL || kNoGlyphFont == getFontPath(runs[0])); + + // U+26F9 U+FE0F is specified but ColorTextMixedEmojiFont has a variation sequence U+26F9 U+FE0F + // in its cmap, so ColorTextMixedEmojiFont should be selected instaed of ColorEmojiFont. + itemize(collection.get(), "U+26F9 U+FE0F", kDefaultFontStyle, &runs); + ASSERT_EQ(1U, runs.size()); + EXPECT_EQ(0, runs[0].start); + EXPECT_EQ(2, runs[0].end); + EXPECT_EQ(kMixedEmojiFont, getFontPath(runs[0])); +} + diff --git a/tests/FontFamilyTest.cpp b/tests/FontFamilyTest.cpp index 78f286c0ca682094bdd4c47659cbc3d67b161b61..d46245cd1fdc97cf40c7c329370008272c8ae320 100644 --- a/tests/FontFamilyTest.cpp +++ b/tests/FontFamilyTest.cpp @@ -70,6 +70,19 @@ TEST(FontLanguagesTest, repeatedLanguageTests) { EXPECT_EQ(english, langs[0]); } +TEST(FontLanguagesTest, undEmojiTests) { + FontLanguage emoji("und-Qaae", 8); + EXPECT_TRUE(emoji.hasEmojiFlag()); + + FontLanguage und("und", 3); + EXPECT_FALSE(und.hasEmojiFlag()); + EXPECT_FALSE(emoji == und); + + FontLanguage undExample("und-example", 10); + EXPECT_FALSE(undExample.hasEmojiFlag()); + EXPECT_FALSE(emoji == undExample); +} + // The test font has following glyphs. // U+82A6 // U+82A6 U+FE00 (VS1) diff --git a/tests/data/ColorEmojiFont.ttf b/tests/data/ColorEmojiFont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..dd72eea6d58a44e8a320acf90732f8ee9c421c44 Binary files /dev/null and b/tests/data/ColorEmojiFont.ttf differ diff --git a/tests/data/ColorEmojiFont.ttx b/tests/data/ColorEmojiFont.ttx new file mode 100644 index 0000000000000000000000000000000000000000..b077339e6a3e5c463ea30d70c9141385f2096572 --- /dev/null +++ b/tests/data/ColorEmojiFont.ttx @@ -0,0 +1,250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ColorEmojiFont Test + + + Regular + + + ColorEmojiFont Test + + + ColorEmojiFontTest-Regular + + + ColorEmojiFont Test + + + Regular + + + ColorEmojiFont Test + + + ColorEmojiFontTest-Regular + + + + + + + + + + + + + + + + diff --git a/tests/data/ColorTextMixedEmojiFont.ttf b/tests/data/ColorTextMixedEmojiFont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..57ee330b79f66be79c74b7f18e323a178620df58 Binary files /dev/null and b/tests/data/ColorTextMixedEmojiFont.ttf differ diff --git a/tests/data/ColorTextMixedEmojiFont.ttx b/tests/data/ColorTextMixedEmojiFont.ttx new file mode 100644 index 0000000000000000000000000000000000000000..461210bfd882d4750d5b8595de598142c1f2c225 --- /dev/null +++ b/tests/data/ColorTextMixedEmojiFont.ttx @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ColorTextMixedEmojiFont Test + + + Regular + + + ColorTextMixedEmojiFont Test + + + ColorTextMixedEmojiFontTest-Regular + + + ColorTextMixedEmojiFont Test + + + Regular + + + ColorTextMixedEmojiFont Test + + + ColorTextMixedEmojiFontTest-Regular + + + + + + + + + + + + + + + + diff --git a/tests/data/Emoji.ttf b/tests/data/Emoji.ttf index 5476d678c8cbf55e2c376c69a9c3a952a0710bda..a3413b3e08f96ab5b2a0b5cffd1cc249026ffd40 100644 Binary files a/tests/data/Emoji.ttf and b/tests/data/Emoji.ttf differ diff --git a/tests/data/Emoji.ttx b/tests/data/Emoji.ttx index ac5468c0615b6eb74b9857acf5a2ee27a61cd704..3318c594ae1edd070cd5ab939692e55df68ece30 100644 --- a/tests/data/Emoji.ttx +++ b/tests/data/Emoji.ttx @@ -23,6 +23,7 @@ + @@ -145,6 +146,7 @@ + @@ -156,6 +158,9 @@ + + + @@ -186,6 +191,9 @@ + + + diff --git a/tests/data/NoGlyphFont.ttf b/tests/data/NoGlyphFont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0243f820408af7cd33497de3b01c19e43ab71e67 Binary files /dev/null and b/tests/data/NoGlyphFont.ttf differ diff --git a/tests/data/NoGlyphFont.ttx b/tests/data/NoGlyphFont.ttx new file mode 100644 index 0000000000000000000000000000000000000000..72c9f292f05eefa14e3195b1a50c12eeccc5b92b --- /dev/null +++ b/tests/data/NoGlyphFont.ttx @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EmptyFont Test + + + Regular + + + EmptyFont Test + + + EmptyFontTest-Regular + + + EmptyFont Test + + + Regular + + + EmptyFont Test + + + EmptyFontTest-Regular + + + + + + + + + + + + + + + + diff --git a/tests/data/Regular.ttf b/tests/data/Regular.ttf index ff0c5eaba84388f496690f36f7c56060113dcb41..ab638f58de03bb8514e197653aee37795765ad39 100644 Binary files a/tests/data/Regular.ttf and b/tests/data/Regular.ttf differ diff --git a/tests/data/Regular.ttx b/tests/data/Regular.ttx index 9918fc510b4a79bac8f071f45d0d0247cf37e1bf..a5f3ebac2653e2f4467e6683e3119d2222accac4 100644 --- a/tests/data/Regular.ttx +++ b/tests/data/Regular.ttx @@ -27,6 +27,7 @@ + @@ -153,6 +154,7 @@ + @@ -167,7 +169,11 @@ + + + + @@ -210,6 +216,9 @@ + + + diff --git a/tests/data/TextEmojiFont.ttf b/tests/data/TextEmojiFont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..21013a0fa73cebdf661eb0daa2054890c3d1f7eb Binary files /dev/null and b/tests/data/TextEmojiFont.ttf differ diff --git a/tests/data/TextEmojiFont.ttx b/tests/data/TextEmojiFont.ttx new file mode 100644 index 0000000000000000000000000000000000000000..35e7d9837b234a42ba7381aab3bf360c361aaf18 --- /dev/null +++ b/tests/data/TextEmojiFont.ttx @@ -0,0 +1,250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TextEmojiFont Test + + + Regular + + + TextEmojiFont Test + + + TextEmojiFontTest-Regular + + + TextEmojiFont Test + + + Regular + + + TextEmojiFont Test + + + TextEmojiFontTest-Regular + + + + + + + + + + + + + + + + diff --git a/tests/data/emoji.xml b/tests/data/emoji.xml new file mode 100644 index 0000000000000000000000000000000000000000..05b2f84a1a42e20888fea7eeedfbe92d9679b0ab --- /dev/null +++ b/tests/data/emoji.xml @@ -0,0 +1,31 @@ + + + + + + NoGlyphFont.ttf + + + ColorEmojiFont.ttf + + + TextEmojiFont.ttf + + + ColorTextMixedEmojiFont.ttf + +