mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This is 2nd attempt of I8df992a6851021903478972601a9a5c9424b100c. The main purpose of this CL is expanding FontLanguage to be able to save full script tag. Previously, FontLangauge kept only limited script tags. With this CL, FontLanguage keeps all script tags. This CL contains the following changes: - FontLanguage changes: -- Moved to private directory not to be instantiated outside of Minikin. -- Removed bool(), bits(), FontLanguage(uint32_t) methods which are no longer used. -- Change the FontLanguage internal data structure. -- Introduces script match logic. - FontLanguages changes: -- Moved to private directory not to be instantiated outside of Minikin. -- This is now std::vector<FontLanguage> - FontLanguageListCache changes: -- Now FontLanguageListCache::getId through FontStyle::registerLanguageList is the only way to instantiate the FontLanguage. -- Normalize input to be BCP47 compliant identifier by ICU. Bug: 26168983 Change-Id: I431b3f361a7635497c05b85e8ecbeb48d9aef63e
919 lines
38 KiB
C++
919 lines
38 KiB
C++
/*
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "FontLanguage.h"
|
|
#include "FontTestUtils.h"
|
|
#include "ICUTestBase.h"
|
|
#include "MinikinFontForTest.h"
|
|
#include "UnicodeUtils.h"
|
|
|
|
using android::FontCollection;
|
|
using android::FontFamily;
|
|
using android::FontLanguage;
|
|
using android::FontStyle;
|
|
|
|
const char kItemizeFontXml[] = kTestFontDir "itemize.xml";
|
|
const char kEmojiFont[] = kTestFontDir "Emoji.ttf";
|
|
const char kJAFont[] = kTestFontDir "Ja.ttf";
|
|
const char kKOFont[] = kTestFontDir "Ko.ttf";
|
|
const char kLatinBoldFont[] = kTestFontDir "Bold.ttf";
|
|
const char kLatinBoldItalicFont[] = kTestFontDir "BoldItalic.ttf";
|
|
const char kLatinFont[] = kTestFontDir "Regular.ttf";
|
|
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";
|
|
|
|
typedef ICUTestBase FontCollectionItemizeTest;
|
|
|
|
// Utility function for calling itemize function.
|
|
void itemize(FontCollection* collection, const char* str, FontStyle style,
|
|
std::vector<FontCollection::Run>* result) {
|
|
const size_t BUF_SIZE = 256;
|
|
uint16_t buf[BUF_SIZE];
|
|
size_t len;
|
|
|
|
result->clear();
|
|
ParseUnicode(buf, BUF_SIZE, str, &len, NULL);
|
|
collection->itemize(buf, len, style, result);
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
|
|
TEST_F(FontCollectionItemizeTest, itemize_latin) {
|
|
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kItemizeFontXml);
|
|
std::vector<FontCollection::Run> runs;
|
|
|
|
const FontStyle kRegularStyle = FontStyle();
|
|
const FontStyle kItalicStyle = FontStyle(4, true);
|
|
const FontStyle kBoldStyle = FontStyle(7, false);
|
|
const FontStyle kBoldItalicStyle = FontStyle(7, true);
|
|
|
|
itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kRegularStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kLatinFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kItalicStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kLatinItalicFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kBoldStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kLatinBoldFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kBoldItalicStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kLatinBoldItalicFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
// Continue if the specific characters (e.g. hyphen, comma, etc.) is
|
|
// followed.
|
|
itemize(collection.get(), "'a' ',' '-' 'd' '!'", kRegularStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kLatinFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
itemize(collection.get(), "'a' ',' '-' 'd' '!'", kRegularStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kLatinFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
// U+0301(COMBINING ACUTE ACCENT) must be in the same run with preceding
|
|
// chars if the font supports it.
|
|
itemize(collection.get(), "'a' U+0301", kRegularStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kLatinFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
}
|
|
|
|
TEST_F(FontCollectionItemizeTest, itemize_emoji) {
|
|
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kItemizeFontXml);
|
|
std::vector<FontCollection::Run> runs;
|
|
|
|
itemize(collection.get(), "U+1F469 U+1F467", FontStyle(), &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(4, runs[0].end);
|
|
EXPECT_EQ(kEmojiFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
// U+20E3(COMBINING ENCLOSING KEYCAP) must be in the same run with preceding
|
|
// character if the font supports.
|
|
itemize(collection.get(), "'0' U+20E3", FontStyle(), &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kEmojiFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
itemize(collection.get(), "U+1F470 U+20E3", FontStyle(), &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(3, runs[0].end);
|
|
EXPECT_EQ(kEmojiFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
itemize(collection.get(), "U+242EE U+1F470 U+20E3", FontStyle(), &runs);
|
|
ASSERT_EQ(2U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
EXPECT_EQ(2, runs[1].start);
|
|
EXPECT_EQ(5, runs[1].end);
|
|
EXPECT_EQ(kEmojiFont, getFontPath(runs[1]));
|
|
EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic());
|
|
|
|
// Currently there is no fonts which has a glyph for 'a' + U+20E3, so they
|
|
// are splitted into two.
|
|
itemize(collection.get(), "'a' U+20E3", FontStyle(), &runs);
|
|
ASSERT_EQ(2U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(1, runs[0].end);
|
|
EXPECT_EQ(kLatinFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
EXPECT_EQ(1, runs[1].start);
|
|
EXPECT_EQ(2, runs[1].end);
|
|
EXPECT_EQ(kEmojiFont, getFontPath(runs[1]));
|
|
EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic());
|
|
}
|
|
|
|
TEST_F(FontCollectionItemizeTest, itemize_non_latin) {
|
|
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kItemizeFontXml);
|
|
std::vector<FontCollection::Run> runs;
|
|
|
|
FontStyle kJAStyle = FontStyle(FontStyle::registerLanguageList("ja_JP"));
|
|
FontStyle kUSStyle = FontStyle(FontStyle::registerLanguageList("en_US"));
|
|
FontStyle kZH_HansStyle = FontStyle(FontStyle::registerLanguageList("zh_Hans"));
|
|
|
|
// All Japanese Hiragana characters.
|
|
itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kUSStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
// All Korean Hangul characters.
|
|
itemize(collection.get(), "U+B300 U+D55C U+BBFC U+AD6D", kUSStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(4, runs[0].end);
|
|
EXPECT_EQ(kKOFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
// All Han characters ja, zh-Hans font having.
|
|
// Japanese font should be selected if the specified language is Japanese.
|
|
itemize(collection.get(), "U+81ED U+82B1 U+5FCD", kJAStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(3, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
// Simplified Chinese font should be selected if the specified language is Simplified
|
|
// Chinese.
|
|
itemize(collection.get(), "U+81ED U+82B1 U+5FCD", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(3, runs[0].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
// Fallbacks to other fonts if there is no glyph in the specified language's
|
|
// font. There is no character U+4F60 in Japanese.
|
|
itemize(collection.get(), "U+81ED U+4F60 U+5FCD", kJAStyle, &runs);
|
|
ASSERT_EQ(3U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(1, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
EXPECT_EQ(1, runs[1].start);
|
|
EXPECT_EQ(2, runs[1].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[1]));
|
|
EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic());
|
|
|
|
EXPECT_EQ(2, runs[2].start);
|
|
EXPECT_EQ(3, runs[2].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[2]));
|
|
EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeItalic());
|
|
|
|
// Tone mark.
|
|
itemize(collection.get(), "U+4444 U+302D", FontStyle(), &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
// Both zh-Hant and ja fonts support U+242EE, but zh-Hans doesn't.
|
|
// Here, ja and zh-Hant font should have the same score but ja should be selected since it is
|
|
// listed before zh-Hant.
|
|
itemize(collection.get(), "U+242EE", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
}
|
|
|
|
TEST_F(FontCollectionItemizeTest, itemize_mixed) {
|
|
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kItemizeFontXml);
|
|
std::vector<FontCollection::Run> runs;
|
|
|
|
FontStyle kUSStyle = FontStyle(FontStyle::registerLanguageList("en_US"));
|
|
|
|
itemize(collection.get(), "'a' U+4F60 'b' U+4F60 'c'", kUSStyle, &runs);
|
|
ASSERT_EQ(5U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(1, runs[0].end);
|
|
EXPECT_EQ(kLatinFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
EXPECT_EQ(1, runs[1].start);
|
|
EXPECT_EQ(2, runs[1].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[1]));
|
|
EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic());
|
|
|
|
EXPECT_EQ(2, runs[2].start);
|
|
EXPECT_EQ(3, runs[2].end);
|
|
EXPECT_EQ(kLatinFont, getFontPath(runs[2]));
|
|
EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeItalic());
|
|
|
|
EXPECT_EQ(3, runs[3].start);
|
|
EXPECT_EQ(4, runs[3].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[3]));
|
|
EXPECT_FALSE(runs[3].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[3].fakedFont.fakery.isFakeItalic());
|
|
|
|
EXPECT_EQ(4, runs[4].start);
|
|
EXPECT_EQ(5, runs[4].end);
|
|
EXPECT_EQ(kLatinFont, getFontPath(runs[4]));
|
|
EXPECT_FALSE(runs[4].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[4].fakedFont.fakery.isFakeItalic());
|
|
}
|
|
|
|
TEST_F(FontCollectionItemizeTest, itemize_variationSelector) {
|
|
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kItemizeFontXml);
|
|
std::vector<FontCollection::Run> runs;
|
|
|
|
// A glyph for U+4FAE is provided by both Japanese font and Simplified
|
|
// Chinese font. Also a glyph for U+242EE is provided by both Japanese and
|
|
// Traditional Chinese font. To avoid effects of device default locale,
|
|
// explicitly specify the locale.
|
|
FontStyle kZH_HansStyle = FontStyle(FontStyle::registerLanguageList("zh_Hans"));
|
|
FontStyle kZH_HantStyle = FontStyle(FontStyle::registerLanguageList("zh_Hant"));
|
|
|
|
// U+4FAE is available in both zh_Hans and ja font, but U+4FAE,U+FE00 is
|
|
// only available in ja font.
|
|
itemize(collection.get(), "U+4FAE", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(1, runs[0].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
|
|
|
|
itemize(collection.get(), "U+4FAE U+FE00", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
|
|
itemize(collection.get(), "U+4FAE U+4FAE U+FE00", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(2U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(1, runs[0].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
|
|
EXPECT_EQ(1, runs[1].start);
|
|
EXPECT_EQ(3, runs[1].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
|
|
|
|
itemize(collection.get(), "U+4FAE U+4FAE U+FE00 U+4FAE", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(3U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(1, runs[0].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
|
|
EXPECT_EQ(1, runs[1].start);
|
|
EXPECT_EQ(3, runs[1].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
|
|
EXPECT_EQ(3, runs[2].start);
|
|
EXPECT_EQ(4, runs[2].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[2]));
|
|
|
|
// Validation selector after validation selector.
|
|
itemize(collection.get(), "U+4FAE U+FE00 U+FE00", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(3, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
|
|
|
|
// No font supports U+242EE U+FE0E.
|
|
itemize(collection.get(), "U+4FAE U+FE0E", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
|
|
|
|
// Surrogate pairs handling.
|
|
// U+242EE is available in ja font and zh_Hant font.
|
|
// U+242EE U+FE00 is available only in ja font.
|
|
itemize(collection.get(), "U+242EE", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
|
|
|
|
itemize(collection.get(), "U+242EE U+FE00", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(3, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
|
|
itemize(collection.get(), "U+242EE U+242EE U+FE00", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(2U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
|
|
EXPECT_EQ(2, runs[1].start);
|
|
EXPECT_EQ(5, runs[1].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
|
|
|
|
itemize(collection.get(), "U+242EE U+242EE U+FE00 U+242EE", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(3U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
|
|
EXPECT_EQ(2, runs[1].start);
|
|
EXPECT_EQ(5, runs[1].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
|
|
EXPECT_EQ(5, runs[2].start);
|
|
EXPECT_EQ(7, runs[2].end);
|
|
EXPECT_EQ(kZH_HantFont, getFontPath(runs[2]));
|
|
|
|
// Validation selector after validation selector.
|
|
itemize(collection.get(), "U+242EE U+FE00 U+FE00", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(4, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
|
|
// No font supports U+242EE U+FE0E
|
|
itemize(collection.get(), "U+242EE U+FE0E", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(3, runs[0].end);
|
|
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
|
|
|
|
// Isolated variation selector supplement.
|
|
itemize(collection.get(), "U+FE00", FontStyle(), &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(1, runs[0].end);
|
|
EXPECT_TRUE(runs[0].fakedFont.font == nullptr || kLatinFont == getFontPath(runs[0]));
|
|
|
|
itemize(collection.get(), "U+FE00", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
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_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) {
|
|
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kItemizeFontXml);
|
|
std::vector<FontCollection::Run> runs;
|
|
|
|
// A glyph for U+845B is provided by both Japanese font and Simplified
|
|
// Chinese font. Also a glyph for U+242EE is provided by both Japanese and
|
|
// Traditional Chinese font. To avoid effects of device default locale,
|
|
// explicitly specify the locale.
|
|
FontStyle kZH_HansStyle = FontStyle(FontStyle::registerLanguageList("zh_Hans"));
|
|
FontStyle kZH_HantStyle = FontStyle(FontStyle::registerLanguageList("zh_Hant"));
|
|
|
|
// U+845B is available in both zh_Hans and ja font, but U+845B,U+E0100 is
|
|
// only available in ja font.
|
|
itemize(collection.get(), "U+845B", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(1, runs[0].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
|
|
|
|
itemize(collection.get(), "U+845B U+E0100", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(3, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
|
|
itemize(collection.get(), "U+845B U+845B U+E0100", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(2U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(1, runs[0].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
|
|
EXPECT_EQ(1, runs[1].start);
|
|
EXPECT_EQ(4, runs[1].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
|
|
|
|
itemize(collection.get(), "U+845B U+845B U+E0100 U+845B", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(3U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(1, runs[0].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
|
|
EXPECT_EQ(1, runs[1].start);
|
|
EXPECT_EQ(4, runs[1].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
|
|
EXPECT_EQ(4, runs[2].start);
|
|
EXPECT_EQ(5, runs[2].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[2]));
|
|
|
|
// Validation selector after validation selector.
|
|
itemize(collection.get(), "U+845B U+E0100 U+E0100", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
|
|
// No font supports U+845B U+E01E0.
|
|
itemize(collection.get(), "U+845B U+E01E0", kZH_HansStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(3, runs[0].end);
|
|
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
|
|
|
|
// Isolated variation selector supplement
|
|
// Surrogate pairs handling.
|
|
// U+242EE is available in ja font and zh_Hant font.
|
|
// U+242EE U+E0100 is available only in ja font.
|
|
itemize(collection.get(), "U+242EE", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
|
|
|
|
itemize(collection.get(), "U+242EE U+E0101", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(4, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
|
|
itemize(collection.get(), "U+242EE U+242EE U+E0101", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(2U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
|
|
EXPECT_EQ(2, runs[1].start);
|
|
EXPECT_EQ(6, runs[1].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
|
|
|
|
itemize(collection.get(), "U+242EE U+242EE U+E0101 U+242EE", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(3U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
|
|
EXPECT_EQ(2, runs[1].start);
|
|
EXPECT_EQ(6, runs[1].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
|
|
EXPECT_EQ(6, runs[2].start);
|
|
EXPECT_EQ(8, runs[2].end);
|
|
EXPECT_EQ(kZH_HantFont, getFontPath(runs[2]));
|
|
|
|
// Validation selector after validation selector.
|
|
itemize(collection.get(), "U+242EE U+E0100 U+E0100", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(6, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
|
|
// No font supports U+242EE U+E01E0.
|
|
itemize(collection.get(), "U+242EE U+E01E0", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(4, runs[0].end);
|
|
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
|
|
|
|
// Isolated variation selector supplement.
|
|
itemize(collection.get(), "U+E0100", FontStyle(), &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_TRUE(runs[0].fakedFont.font == nullptr || kLatinFont == getFontPath(runs[0]));
|
|
|
|
itemize(collection.get(), "U+E0100", kZH_HantStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_TRUE(runs[0].fakedFont.font == nullptr || kLatinFont == getFontPath(runs[0]));
|
|
}
|
|
|
|
TEST_F(FontCollectionItemizeTest, itemize_no_crash) {
|
|
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kItemizeFontXml);
|
|
std::vector<FontCollection::Run> runs;
|
|
|
|
// Broken Surrogate pairs. Check only not crashing.
|
|
itemize(collection.get(), "'a' U+D83D 'a'", FontStyle(), &runs);
|
|
itemize(collection.get(), "'a' U+DC69 'a'", FontStyle(), &runs);
|
|
itemize(collection.get(), "'a' U+D83D U+D83D 'a'", FontStyle(), &runs);
|
|
itemize(collection.get(), "'a' U+DC69 U+DC69 'a'", FontStyle(), &runs);
|
|
|
|
// Isolated variation selector. Check only not crashing.
|
|
itemize(collection.get(), "U+FE00 U+FE00", FontStyle(), &runs);
|
|
itemize(collection.get(), "U+E0100 U+E0100", FontStyle(), &runs);
|
|
itemize(collection.get(), "U+FE00 U+E0100", FontStyle(), &runs);
|
|
itemize(collection.get(), "U+E0100 U+FE00", FontStyle(), &runs);
|
|
|
|
// Tone mark only. Check only not crashing.
|
|
itemize(collection.get(), "U+302D", FontStyle(), &runs);
|
|
itemize(collection.get(), "U+302D U+302D", FontStyle(), &runs);
|
|
|
|
// Tone mark and variation selector mixed. Check only not crashing.
|
|
itemize(collection.get(), "U+FE00 U+302D U+E0100", FontStyle(), &runs);
|
|
}
|
|
|
|
TEST_F(FontCollectionItemizeTest, itemize_fakery) {
|
|
std::unique_ptr<FontCollection> collection = getFontCollection(kTestFontDir, kItemizeFontXml);
|
|
std::vector<FontCollection::Run> runs;
|
|
|
|
FontStyle kJABoldStyle = FontStyle(FontStyle::registerLanguageList("ja_JP"), 0, 7, false);
|
|
FontStyle kJAItalicStyle = FontStyle(FontStyle::registerLanguageList("ja_JP"), 0, 5, true);
|
|
FontStyle kJABoldItalicStyle =
|
|
FontStyle(FontStyle::registerLanguageList("ja_JP"), 0, 7, true);
|
|
|
|
// Currently there is no italic or bold font for Japanese. FontFakery has
|
|
// the differences between desired and actual font style.
|
|
|
|
// All Japanese Hiragana characters.
|
|
itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kJABoldStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
// All Japanese Hiragana characters.
|
|
itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kJAItalicStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
|
|
// All Japanese Hiragana characters.
|
|
itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kJABoldItalicStyle, &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(5, runs[0].end);
|
|
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
|
|
EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeBold());
|
|
EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeItalic());
|
|
}
|
|
|
|
TEST_F(FontCollectionItemizeTest, itemize_vs_sequence_but_no_base_char) {
|
|
// kVSTestFont supports U+717D U+FE02 but doesn't support U+717D.
|
|
// kVSTestFont should be selected for U+717D U+FE02 even if it does not support the base code
|
|
// point.
|
|
const std::string kVSTestFont = kTestFontDir "VarioationSelectorTest-Regular.ttf";
|
|
|
|
std::vector<android::FontFamily*> families;
|
|
FontFamily* family1 = new FontFamily(android::VARIANT_DEFAULT);
|
|
family1->addFont(new MinikinFontForTest(kLatinFont));
|
|
families.push_back(family1);
|
|
|
|
FontFamily* family2 = new FontFamily(android::VARIANT_DEFAULT);
|
|
family2->addFont(new MinikinFontForTest(kVSTestFont));
|
|
families.push_back(family2);
|
|
|
|
FontCollection collection(families);
|
|
|
|
std::vector<FontCollection::Run> runs;
|
|
|
|
itemize(&collection, "U+717D U+FE02", FontStyle(), &runs);
|
|
ASSERT_EQ(1U, runs.size());
|
|
EXPECT_EQ(0, runs[0].start);
|
|
EXPECT_EQ(2, runs[0].end);
|
|
EXPECT_EQ(kVSTestFont, getFontPath(runs[0]));
|
|
|
|
family1->Unref();
|
|
family2->Unref();
|
|
}
|
|
|
|
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;
|
|
|
|
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_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
|
|
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 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]));
|
|
}
|
|
|