1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "minikin/FontCollection.h"
18 
19 #include <memory>
20 
21 #include <gtest/gtest.h>
22 
23 #include "minikin/FontFamily.h"
24 #include "minikin/FontFileParser.h"
25 #include "minikin/LocaleList.h"
26 #include "minikin/MinikinPaint.h"
27 
28 #include "FontTestUtils.h"
29 #include "FreeTypeMinikinFontForTest.h"
30 #include "Locale.h"
31 #include "LocaleListCache.h"
32 #include "MinikinInternal.h"
33 #include "UnicodeUtils.h"
34 
35 namespace minikin {
36 
37 const char kItemizeFontXml[] = "itemize.xml";
38 const char kCherokeeFont[] = "Cherokee.ttf";
39 const char kEmojiFont[] = "Emoji.ttf";
40 const char kJAFont[] = "Ja.ttf";
41 const char kKOFont[] = "Ko.ttf";
42 const char kLatinBoldFont[] = "Bold.ttf";
43 const char kLatinBoldItalicFont[] = "BoldItalic.ttf";
44 const char kLatinFont[] = "Regular.ttf";
45 const char kLatinItalicFont[] = "Italic.ttf";
46 const char kZH_HansFont[] = "ZhHans.ttf";
47 const char kZH_HantFont[] = "ZhHant.ttf";
48 const char kAsciiFont[] = "Ascii.ttf";
49 
50 const char kEmojiXmlFile[] = "emoji.xml";
51 const char kNoGlyphFont[] = "NoGlyphFont.ttf";
52 const char kColorEmojiFont[] = "ColorEmojiFont.ttf";
53 const char kTextEmojiFont[] = "TextEmojiFont.ttf";
54 const char kMixedEmojiFont[] = "ColorTextMixedEmojiFont.ttf";
55 
56 const char kHasCmapFormat14Font[] = "NoCmapFormat14.ttf";
57 const char kNoCmapFormat14Font[] = "VariationSelectorTest-Regular.ttf";
58 
59 struct Run {
60     FakedFont fakedFont;
61     int start;
62     int end;
63 };
64 
65 // Utility functions for calling itemize function.
itemize(const std::shared_ptr<FontCollection> & collection,const char * str,FontStyle style,const std::string & localeList)66 std::vector<Run> itemize(const std::shared_ptr<FontCollection>& collection, const char* str,
67                          FontStyle style, const std::string& localeList) {
68     const size_t BUF_SIZE = 256;
69     uint16_t buf[BUF_SIZE];
70     size_t len;
71 
72     ParseUnicode(buf, BUF_SIZE, str, &len, NULL);
73     const uint32_t localeListId = registerLocaleList(localeList);
74     auto result = collection->itemize(U16StringPiece(buf, len), style, localeListId,
75                                       FamilyVariant::DEFAULT);
76 
77     // Check the same result has returned by calling with maxRun.
78     for (uint32_t runMax = 1; runMax <= result.size(); runMax++) {
79         auto resultWithRunMax = collection->itemize(U16StringPiece(buf, len), style, localeListId,
80                                                     FamilyVariant::DEFAULT, runMax);
81         EXPECT_EQ(runMax, resultWithRunMax.size());
82         for (uint32_t i = 0; i < runMax; ++i) {
83             EXPECT_EQ(result[i].start, resultWithRunMax[i].start);
84             EXPECT_EQ(result[i].end, resultWithRunMax[i].end);
85             EXPECT_EQ(result[i].familyMatch, resultWithRunMax[i].familyMatch);
86         }
87     }
88     std::vector<Run> runs;
89     for (const auto& r : result) {
90         runs.push_back(
91                 {collection->getBestFont(U16StringPiece(buf, len), r, style), r.start, r.end});
92     }
93     return runs;
94 }
95 
96 // Overloaded version for default font style.
itemize(const std::shared_ptr<FontCollection> & collection,const char * str,const std::string & localeList)97 std::vector<Run> itemize(const std::shared_ptr<FontCollection>& collection, const char* str,
98                          const std::string& localeList) {
99     return itemize(collection, str, FontStyle(), localeList);
100 }
101 
102 // Overloaded version for empty locale list id.
itemize(const std::shared_ptr<FontCollection> & collection,const char * str,FontStyle style)103 std::vector<Run> itemize(const std::shared_ptr<FontCollection>& collection, const char* str,
104                          FontStyle style) {
105     return itemize(collection, str, style, "");
106 }
107 
108 // Overloaded version for default font style and empty locale list id.
itemize(const std::shared_ptr<FontCollection> & collection,const char * str)109 std::vector<Run> itemize(const std::shared_ptr<FontCollection>& collection, const char* str) {
110     return itemize(collection, str, FontStyle(), "");
111 }
112 
113 // Utility function to obtain font path associated with run.
getFontName(const Run & run)114 std::string getFontName(const Run& run) {
115     EXPECT_NE(nullptr, run.fakedFont.font.get());
116     return getBasename(run.fakedFont.typeface()->GetFontPath());
117 }
118 
119 // Utility function to obtain LocaleList from string.
registerAndGetLocaleList(const std::string & locale_string)120 const LocaleList& registerAndGetLocaleList(const std::string& locale_string) {
121     return LocaleListCache::getById(LocaleListCache::getId(locale_string));
122 }
123 
TEST(FontCollectionItemizeTest,itemize_latin)124 TEST(FontCollectionItemizeTest, itemize_latin) {
125     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
126 
127     const FontStyle kRegularStyle = FontStyle();
128     const FontStyle kItalicStyle = FontStyle(FontStyle::Slant::ITALIC);
129     const FontStyle kBoldStyle = FontStyle(FontStyle::Weight::BOLD);
130     const FontStyle kBoldItalicStyle = FontStyle(FontStyle::Weight::BOLD, FontStyle::Slant::ITALIC);
131 
132     auto runs = itemize(collection, "'a' 'b' 'c' 'd' 'e'", kRegularStyle);
133     ASSERT_EQ(1U, runs.size());
134     EXPECT_EQ(0, runs[0].start);
135     EXPECT_EQ(5, runs[0].end);
136     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
137     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
138     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
139 
140     runs = itemize(collection, "'a' 'b' 'c' 'd' 'e'", kItalicStyle);
141     ASSERT_EQ(1U, runs.size());
142     EXPECT_EQ(0, runs[0].start);
143     EXPECT_EQ(5, runs[0].end);
144     EXPECT_EQ(kLatinItalicFont, getFontName(runs[0]));
145     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
146     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
147 
148     runs = itemize(collection, "'a' 'b' 'c' 'd' 'e'", kBoldStyle);
149     ASSERT_EQ(1U, runs.size());
150     EXPECT_EQ(0, runs[0].start);
151     EXPECT_EQ(5, runs[0].end);
152     EXPECT_EQ(kLatinBoldFont, getFontName(runs[0]));
153     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
154     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
155 
156     runs = itemize(collection, "'a' 'b' 'c' 'd' 'e'", kBoldItalicStyle);
157     ASSERT_EQ(1U, runs.size());
158     EXPECT_EQ(0, runs[0].start);
159     EXPECT_EQ(5, runs[0].end);
160     EXPECT_EQ(kLatinBoldItalicFont, getFontName(runs[0]));
161     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
162     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
163 
164     // Continue if the specific characters (e.g. hyphen, comma, etc.) is
165     // followed.
166     runs = itemize(collection, "'a' ',' '-' 'd' '!'", kRegularStyle);
167     ASSERT_EQ(1U, runs.size());
168     EXPECT_EQ(0, runs[0].start);
169     EXPECT_EQ(5, runs[0].end);
170     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
171     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
172     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
173 
174     runs = itemize(collection, "'a' ',' '-' 'd' '!'", kRegularStyle);
175     ASSERT_EQ(1U, runs.size());
176     EXPECT_EQ(0, runs[0].start);
177     EXPECT_EQ(5, runs[0].end);
178     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
179     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
180     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
181 
182     // U+0301 (COMBINING ACUTE ACCENT) must be in the same run with preceding
183     // chars if the font supports it.
184     runs = itemize(collection, "'a' U+0301", kRegularStyle);
185     ASSERT_EQ(1U, runs.size());
186     EXPECT_EQ(0, runs[0].start);
187     EXPECT_EQ(2, runs[0].end);
188     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
189     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
190     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
191 }
192 
TEST(FontCollectionItemizeTest,itemize_combining)193 TEST(FontCollectionItemizeTest, itemize_combining) {
194     // The regular font and the Cherokee font both support U+0301 (COMBINING ACUTE ACCENT). Since
195     // it's a combining mark, it should come from whatever font the base character comes from.
196     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
197 
198     auto runs = itemize(collection, "'a' U+0301");
199     ASSERT_EQ(1U, runs.size());
200     EXPECT_EQ(0, runs[0].start);
201     EXPECT_EQ(2, runs[0].end);
202     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
203 
204     // CHEROKEE LETTER A, COMBINING ACUTE ACCENT
205     runs = itemize(collection, "U+13A0 U+0301");
206     ASSERT_EQ(1U, runs.size());
207     EXPECT_EQ(0, runs[0].start);
208     EXPECT_EQ(2, runs[0].end);
209     EXPECT_EQ(kCherokeeFont, getFontName(runs[0]));
210 
211     // CHEROKEE LETTER A, COMBINING ACUTE ACCENT, COMBINING ACUTE ACCENT
212     runs = itemize(collection, "U+13A0 U+0301 U+0301");
213     ASSERT_EQ(1U, runs.size());
214     EXPECT_EQ(0, runs[0].start);
215     EXPECT_EQ(3, runs[0].end);
216     EXPECT_EQ(kCherokeeFont, getFontName(runs[0]));
217 
218     runs = itemize(collection, "U+0301");
219     ASSERT_EQ(1U, runs.size());
220     EXPECT_EQ(0, runs[0].start);
221     EXPECT_EQ(1, runs[0].end);
222     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
223 
224     // COMBINING ACUTE ACCENT, CHEROKEE LETTER A, COMBINING ACUTE ACCENT
225     runs = itemize(collection, "U+0301 U+13A0 U+0301");
226     ASSERT_EQ(2U, runs.size());
227     EXPECT_EQ(0, runs[0].start);
228     EXPECT_EQ(1, runs[0].end);
229     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
230     EXPECT_EQ(1, runs[1].start);
231     EXPECT_EQ(3, runs[1].end);
232     EXPECT_EQ(kCherokeeFont, getFontName(runs[1]));
233 }
234 
TEST(FontCollectionItemizeTest,itemize_emoji)235 TEST(FontCollectionItemizeTest, itemize_emoji) {
236     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
237 
238     auto runs = itemize(collection, "U+1F469 U+1F467");
239     ASSERT_EQ(1U, runs.size());
240     EXPECT_EQ(0, runs[0].start);
241     EXPECT_EQ(4, runs[0].end);
242     EXPECT_EQ(kEmojiFont, getFontName(runs[0]));
243     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
244     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
245 
246     // U+20E3(COMBINING ENCLOSING KEYCAP) must be in the same run with preceding
247     // character if the font supports.
248     runs = itemize(collection, "'0' U+20E3");
249     ASSERT_EQ(1U, runs.size());
250     EXPECT_EQ(0, runs[0].start);
251     EXPECT_EQ(2, runs[0].end);
252     EXPECT_EQ(kEmojiFont, getFontName(runs[0]));
253     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
254     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
255 
256     runs = itemize(collection, "U+1F470 U+20E3");
257     ASSERT_EQ(1U, runs.size());
258     EXPECT_EQ(0, runs[0].start);
259     EXPECT_EQ(3, runs[0].end);
260     EXPECT_EQ(kEmojiFont, getFontName(runs[0]));
261     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
262     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
263 
264     runs = itemize(collection, "U+242EE U+1F470 U+20E3");
265     ASSERT_EQ(2U, runs.size());
266     EXPECT_EQ(0, runs[0].start);
267     EXPECT_EQ(2, runs[0].end);
268     EXPECT_EQ(kJAFont, getFontName(runs[0]));
269     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
270     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
271 
272     EXPECT_EQ(2, runs[1].start);
273     EXPECT_EQ(5, runs[1].end);
274     EXPECT_EQ(kEmojiFont, getFontName(runs[1]));
275     EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold());
276     EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic());
277 
278     // Currently there is no fonts which has a glyph for 'a' + U+20E3, so they
279     // are splitted into two.
280     runs = itemize(collection, "'a' U+20E3");
281     ASSERT_EQ(2U, runs.size());
282     EXPECT_EQ(0, runs[0].start);
283     EXPECT_EQ(1, runs[0].end);
284     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
285     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
286     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
287 
288     EXPECT_EQ(1, runs[1].start);
289     EXPECT_EQ(2, runs[1].end);
290     EXPECT_EQ(kEmojiFont, getFontName(runs[1]));
291     EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold());
292     EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic());
293 }
294 
TEST(FontCollectionItemizeTest,itemize_non_latin)295 TEST(FontCollectionItemizeTest, itemize_non_latin) {
296     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
297 
298     // All Japanese Hiragana characters.
299     auto runs = itemize(collection, "U+3042 U+3044 U+3046 U+3048 U+304A", "ja-JP");
300     ASSERT_EQ(1U, runs.size());
301     EXPECT_EQ(0, runs[0].start);
302     EXPECT_EQ(5, runs[0].end);
303     EXPECT_EQ(kJAFont, getFontName(runs[0]));
304     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
305     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
306 
307     // All Korean Hangul characters.
308     runs = itemize(collection, "U+B300 U+D55C U+BBFC U+AD6D", "en-US");
309     ASSERT_EQ(1U, runs.size());
310     EXPECT_EQ(0, runs[0].start);
311     EXPECT_EQ(4, runs[0].end);
312     EXPECT_EQ(kKOFont, getFontName(runs[0]));
313     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
314     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
315 
316     // All Han characters ja, zh-Hans font having.
317     // Japanese font should be selected if the specified language is Japanese.
318     runs = itemize(collection, "U+81ED U+82B1 U+5FCD", "ja-JP");
319     ASSERT_EQ(1U, runs.size());
320     EXPECT_EQ(0, runs[0].start);
321     EXPECT_EQ(3, runs[0].end);
322     EXPECT_EQ(kJAFont, getFontName(runs[0]));
323     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
324     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
325 
326     // Simplified Chinese font should be selected if the specified language is Simplified
327     // Chinese.
328     runs = itemize(collection, "U+81ED U+82B1 U+5FCD", "zh-Hans");
329     ASSERT_EQ(1U, runs.size());
330     EXPECT_EQ(0, runs[0].start);
331     EXPECT_EQ(3, runs[0].end);
332     EXPECT_EQ(kZH_HansFont, getFontName(runs[0]));
333     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
334     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
335 
336     // Fallbacks to other fonts if there is no glyph in the specified language's
337     // font. There is no character U+4F60 in Japanese.
338     runs = itemize(collection, "U+81ED U+4F60 U+5FCD", "ja-JP");
339     ASSERT_EQ(3U, runs.size());
340     EXPECT_EQ(0, runs[0].start);
341     EXPECT_EQ(1, runs[0].end);
342     EXPECT_EQ(kJAFont, getFontName(runs[0]));
343     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
344     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
345 
346     EXPECT_EQ(1, runs[1].start);
347     EXPECT_EQ(2, runs[1].end);
348     EXPECT_EQ(kZH_HansFont, getFontName(runs[1]));
349     EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold());
350     EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic());
351 
352     EXPECT_EQ(2, runs[2].start);
353     EXPECT_EQ(3, runs[2].end);
354     EXPECT_EQ(kJAFont, getFontName(runs[2]));
355     EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeBold());
356     EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeItalic());
357 
358     // Tone mark.
359     runs = itemize(collection, "U+4444 U+302D", "");
360     ASSERT_EQ(1U, runs.size());
361     EXPECT_EQ(0, runs[0].start);
362     EXPECT_EQ(2, runs[0].end);
363     EXPECT_EQ(kZH_HansFont, getFontName(runs[0]));
364     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
365     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
366 
367     // Both zh-Hant and ja fonts support U+242EE, but zh-Hans doesn't.
368     // Here, ja and zh-Hant font should have the same score but ja should be selected since it is
369     // listed before zh-Hant.
370     runs = itemize(collection, "U+242EE", "zh-Hans");
371     ASSERT_EQ(1U, runs.size());
372     EXPECT_EQ(0, runs[0].start);
373     EXPECT_EQ(2, runs[0].end);
374     EXPECT_EQ(kJAFont, getFontName(runs[0]));
375     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
376     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
377 }
378 
TEST(FontCollectionItemizeTest,itemize_mixed)379 TEST(FontCollectionItemizeTest, itemize_mixed) {
380     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
381 
382     auto runs = itemize(collection, "'a' U+4F60 'b' U+4F60 'c'", "en-US");
383     ASSERT_EQ(5U, runs.size());
384     EXPECT_EQ(0, runs[0].start);
385     EXPECT_EQ(1, runs[0].end);
386     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
387     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
388     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
389 
390     EXPECT_EQ(1, runs[1].start);
391     EXPECT_EQ(2, runs[1].end);
392     EXPECT_EQ(kZH_HansFont, getFontName(runs[1]));
393     EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeBold());
394     EXPECT_FALSE(runs[1].fakedFont.fakery.isFakeItalic());
395 
396     EXPECT_EQ(2, runs[2].start);
397     EXPECT_EQ(3, runs[2].end);
398     EXPECT_EQ(kLatinFont, getFontName(runs[2]));
399     EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeBold());
400     EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeItalic());
401 
402     EXPECT_EQ(3, runs[3].start);
403     EXPECT_EQ(4, runs[3].end);
404     EXPECT_EQ(kZH_HansFont, getFontName(runs[3]));
405     EXPECT_FALSE(runs[3].fakedFont.fakery.isFakeBold());
406     EXPECT_FALSE(runs[3].fakedFont.fakery.isFakeItalic());
407 
408     EXPECT_EQ(4, runs[4].start);
409     EXPECT_EQ(5, runs[4].end);
410     EXPECT_EQ(kLatinFont, getFontName(runs[4]));
411     EXPECT_FALSE(runs[4].fakedFont.fakery.isFakeBold());
412     EXPECT_FALSE(runs[4].fakedFont.fakery.isFakeItalic());
413 }
414 
TEST(FontCollectionItemizeTest,itemize_variationSelector)415 TEST(FontCollectionItemizeTest, itemize_variationSelector) {
416     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
417 
418     // A glyph for U+4FAE is provided by both Japanese font and Simplified
419     // Chinese font. Also a glyph for U+242EE is provided by both Japanese and
420     // Traditional Chinese font.  To avoid effects of device default locale,
421     // explicitly specify the locale.
422 
423     // U+4FAE is available in both zh_Hans and ja font, but U+4FAE,U+FE00 is
424     // only available in ja font.
425     auto runs = itemize(collection, "U+4FAE", "zh-Hans");
426     ASSERT_EQ(1U, runs.size());
427     EXPECT_EQ(0, runs[0].start);
428     EXPECT_EQ(1, runs[0].end);
429     EXPECT_EQ(kZH_HansFont, getFontName(runs[0]));
430 
431     runs = itemize(collection, "U+4FAE U+FE00", "zh-Hans");
432     ASSERT_EQ(1U, runs.size());
433     EXPECT_EQ(0, runs[0].start);
434     EXPECT_EQ(2, runs[0].end);
435     EXPECT_EQ(kJAFont, getFontName(runs[0]));
436 
437     runs = itemize(collection, "U+4FAE U+4FAE U+FE00", "zh-Hans");
438     ASSERT_EQ(2U, runs.size());
439     EXPECT_EQ(0, runs[0].start);
440     EXPECT_EQ(1, runs[0].end);
441     EXPECT_EQ(kZH_HansFont, getFontName(runs[0]));
442     EXPECT_EQ(1, runs[1].start);
443     EXPECT_EQ(3, runs[1].end);
444     EXPECT_EQ(kJAFont, getFontName(runs[1]));
445 
446     runs = itemize(collection, "U+4FAE U+4FAE U+FE00 U+4FAE", "zh-Hans");
447     ASSERT_EQ(3U, runs.size());
448     EXPECT_EQ(0, runs[0].start);
449     EXPECT_EQ(1, runs[0].end);
450     EXPECT_EQ(kZH_HansFont, getFontName(runs[0]));
451     EXPECT_EQ(1, runs[1].start);
452     EXPECT_EQ(3, runs[1].end);
453     EXPECT_EQ(kJAFont, getFontName(runs[1]));
454     EXPECT_EQ(3, runs[2].start);
455     EXPECT_EQ(4, runs[2].end);
456     EXPECT_EQ(kZH_HansFont, getFontName(runs[2]));
457 
458     // Validation selector after validation selector.
459     runs = itemize(collection, "U+4FAE U+FE00 U+FE00", "zh-Hans");
460     ASSERT_EQ(1U, runs.size());
461     EXPECT_EQ(0, runs[0].start);
462     EXPECT_EQ(3, runs[0].end);
463     EXPECT_EQ(kJAFont, getFontName(runs[0]));
464 
465     // No font supports U+242EE U+FE0E.
466     runs = itemize(collection, "U+4FAE U+FE0E", "zh-Hans");
467     ASSERT_EQ(1U, runs.size());
468     EXPECT_EQ(0, runs[0].start);
469     EXPECT_EQ(2, runs[0].end);
470     EXPECT_EQ(kZH_HansFont, getFontName(runs[0]));
471 
472     // Surrogate pairs handling.
473     // U+242EE is available in ja font and zh_Hant font.
474     // U+242EE U+FE00 is available only in ja font.
475     runs = itemize(collection, "U+242EE", "zh-Hant");
476     ASSERT_EQ(1U, runs.size());
477     EXPECT_EQ(0, runs[0].start);
478     EXPECT_EQ(2, runs[0].end);
479     EXPECT_EQ(kZH_HantFont, getFontName(runs[0]));
480 
481     runs = itemize(collection, "U+242EE U+FE00", "zh-Hant");
482     ASSERT_EQ(1U, runs.size());
483     EXPECT_EQ(0, runs[0].start);
484     EXPECT_EQ(3, runs[0].end);
485     EXPECT_EQ(kJAFont, getFontName(runs[0]));
486 
487     runs = itemize(collection, "U+242EE U+242EE U+FE00", "zh-Hant");
488     ASSERT_EQ(2U, runs.size());
489     EXPECT_EQ(0, runs[0].start);
490     EXPECT_EQ(2, runs[0].end);
491     EXPECT_EQ(kZH_HantFont, getFontName(runs[0]));
492     EXPECT_EQ(2, runs[1].start);
493     EXPECT_EQ(5, runs[1].end);
494     EXPECT_EQ(kJAFont, getFontName(runs[1]));
495 
496     runs = itemize(collection, "U+242EE U+242EE U+FE00 U+242EE", "zh-Hant");
497     ASSERT_EQ(3U, runs.size());
498     EXPECT_EQ(0, runs[0].start);
499     EXPECT_EQ(2, runs[0].end);
500     EXPECT_EQ(kZH_HantFont, getFontName(runs[0]));
501     EXPECT_EQ(2, runs[1].start);
502     EXPECT_EQ(5, runs[1].end);
503     EXPECT_EQ(kJAFont, getFontName(runs[1]));
504     EXPECT_EQ(5, runs[2].start);
505     EXPECT_EQ(7, runs[2].end);
506     EXPECT_EQ(kZH_HantFont, getFontName(runs[2]));
507 
508     // Validation selector after validation selector.
509     runs = itemize(collection, "U+242EE U+FE00 U+FE00", "zh-Hans");
510     ASSERT_EQ(1U, runs.size());
511     EXPECT_EQ(0, runs[0].start);
512     EXPECT_EQ(4, runs[0].end);
513     EXPECT_EQ(kJAFont, getFontName(runs[0]));
514 
515     // No font supports U+242EE U+FE0E
516     runs = itemize(collection, "U+242EE U+FE0E", "zh-Hant");
517     ASSERT_EQ(1U, runs.size());
518     EXPECT_EQ(0, runs[0].start);
519     EXPECT_EQ(3, runs[0].end);
520     EXPECT_EQ(kZH_HantFont, getFontName(runs[0]));
521 
522     // Isolated variation selector supplement.
523     runs = itemize(collection, "U+FE00", "");
524     ASSERT_EQ(1U, runs.size());
525     EXPECT_EQ(0, runs[0].start);
526     EXPECT_EQ(1, runs[0].end);
527     EXPECT_TRUE(runs[0].fakedFont.font.get() == nullptr || kLatinFont == getFontName(runs[0]));
528 
529     runs = itemize(collection, "U+FE00", "zh-Hant");
530     ASSERT_EQ(1U, runs.size());
531     EXPECT_EQ(0, runs[0].start);
532     EXPECT_EQ(1, runs[0].end);
533     EXPECT_TRUE(runs[0].fakedFont.font.get() == nullptr || kLatinFont == getFontName(runs[0]));
534 
535     // First font family (Regular.ttf) supports U+203C but doesn't support U+203C U+FE0F.
536     // Emoji.ttf font supports U+203C U+FE0F.  Emoji.ttf should be selected.
537     runs = itemize(collection, "U+203C U+FE0F", "zh-Hant");
538     ASSERT_EQ(1U, runs.size());
539     EXPECT_EQ(0, runs[0].start);
540     EXPECT_EQ(2, runs[0].end);
541     EXPECT_EQ(kEmojiFont, getFontName(runs[0]));
542 
543     // First font family (Regular.ttf) supports U+203C U+FE0E.
544     runs = itemize(collection, "U+203C U+FE0E", "zh-Hant");
545     ASSERT_EQ(1U, runs.size());
546     EXPECT_EQ(0, runs[0].start);
547     EXPECT_EQ(2, runs[0].end);
548     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
549 }
550 
TEST(FontCollectionItemizeTest,itemize_variationSelectorSupplement)551 TEST(FontCollectionItemizeTest, itemize_variationSelectorSupplement) {
552     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
553 
554     // A glyph for U+845B is provided by both Japanese font and Simplified
555     // Chinese font. Also a glyph for U+242EE is provided by both Japanese and
556     // Traditional Chinese font.  To avoid effects of device default locale,
557     // explicitly specify the locale.
558 
559     // U+845B is available in both zh_Hans and ja font, but U+845B,U+E0100 is
560     // only available in ja font.
561     auto runs = itemize(collection, "U+845B", "zh-Hans");
562     ASSERT_EQ(1U, runs.size());
563     EXPECT_EQ(0, runs[0].start);
564     EXPECT_EQ(1, runs[0].end);
565     EXPECT_EQ(kZH_HansFont, getFontName(runs[0]));
566 
567     runs = itemize(collection, "U+845B U+E0100", "zh-Hans");
568     ASSERT_EQ(1U, runs.size());
569     EXPECT_EQ(0, runs[0].start);
570     EXPECT_EQ(3, runs[0].end);
571     EXPECT_EQ(kJAFont, getFontName(runs[0]));
572 
573     runs = itemize(collection, "U+845B U+845B U+E0100", "zh-Hans");
574     ASSERT_EQ(2U, runs.size());
575     EXPECT_EQ(0, runs[0].start);
576     EXPECT_EQ(1, runs[0].end);
577     EXPECT_EQ(kZH_HansFont, getFontName(runs[0]));
578     EXPECT_EQ(1, runs[1].start);
579     EXPECT_EQ(4, runs[1].end);
580     EXPECT_EQ(kJAFont, getFontName(runs[1]));
581 
582     runs = itemize(collection, "U+845B U+845B U+E0100 U+845B", "zh-Hans");
583     ASSERT_EQ(3U, runs.size());
584     EXPECT_EQ(0, runs[0].start);
585     EXPECT_EQ(1, runs[0].end);
586     EXPECT_EQ(kZH_HansFont, getFontName(runs[0]));
587     EXPECT_EQ(1, runs[1].start);
588     EXPECT_EQ(4, runs[1].end);
589     EXPECT_EQ(kJAFont, getFontName(runs[1]));
590     EXPECT_EQ(4, runs[2].start);
591     EXPECT_EQ(5, runs[2].end);
592     EXPECT_EQ(kZH_HansFont, getFontName(runs[2]));
593 
594     // Validation selector after validation selector.
595     runs = itemize(collection, "U+845B U+E0100 U+E0100", "zh-Hans");
596     ASSERT_EQ(1U, runs.size());
597     EXPECT_EQ(0, runs[0].start);
598     EXPECT_EQ(5, runs[0].end);
599     EXPECT_EQ(kJAFont, getFontName(runs[0]));
600 
601     // No font supports U+845B U+E01E0.
602     runs = itemize(collection, "U+845B U+E01E0", "zh-Hans");
603     ASSERT_EQ(1U, runs.size());
604     EXPECT_EQ(0, runs[0].start);
605     EXPECT_EQ(3, runs[0].end);
606     EXPECT_EQ(kZH_HansFont, getFontName(runs[0]));
607 
608     // Isolated variation selector supplement
609     // Surrogate pairs handling.
610     // U+242EE is available in ja font and zh_Hant font.
611     // U+242EE U+E0100 is available only in ja font.
612     runs = itemize(collection, "U+242EE", "zh-Hant");
613     ASSERT_EQ(1U, runs.size());
614     EXPECT_EQ(0, runs[0].start);
615     EXPECT_EQ(2, runs[0].end);
616     EXPECT_EQ(kZH_HantFont, getFontName(runs[0]));
617 
618     runs = itemize(collection, "U+242EE U+E0101", "zh-Hant");
619     ASSERT_EQ(1U, runs.size());
620     EXPECT_EQ(0, runs[0].start);
621     EXPECT_EQ(4, runs[0].end);
622     EXPECT_EQ(kJAFont, getFontName(runs[0]));
623 
624     runs = itemize(collection, "U+242EE U+242EE U+E0101", "zh-Hant");
625     ASSERT_EQ(2U, runs.size());
626     EXPECT_EQ(0, runs[0].start);
627     EXPECT_EQ(2, runs[0].end);
628     EXPECT_EQ(kZH_HantFont, getFontName(runs[0]));
629     EXPECT_EQ(2, runs[1].start);
630     EXPECT_EQ(6, runs[1].end);
631     EXPECT_EQ(kJAFont, getFontName(runs[1]));
632 
633     runs = itemize(collection, "U+242EE U+242EE U+E0101 U+242EE", "zh-Hant");
634     ASSERT_EQ(3U, runs.size());
635     EXPECT_EQ(0, runs[0].start);
636     EXPECT_EQ(2, runs[0].end);
637     EXPECT_EQ(kZH_HantFont, getFontName(runs[0]));
638     EXPECT_EQ(2, runs[1].start);
639     EXPECT_EQ(6, runs[1].end);
640     EXPECT_EQ(kJAFont, getFontName(runs[1]));
641     EXPECT_EQ(6, runs[2].start);
642     EXPECT_EQ(8, runs[2].end);
643     EXPECT_EQ(kZH_HantFont, getFontName(runs[2]));
644 
645     // Validation selector after validation selector.
646     runs = itemize(collection, "U+242EE U+E0100 U+E0100", "zh-Hant");
647     ASSERT_EQ(1U, runs.size());
648     EXPECT_EQ(0, runs[0].start);
649     EXPECT_EQ(6, runs[0].end);
650     EXPECT_EQ(kJAFont, getFontName(runs[0]));
651 
652     // No font supports U+242EE U+E01E0.
653     runs = itemize(collection, "U+242EE U+E01E0", "zh-Hant");
654     ASSERT_EQ(1U, runs.size());
655     EXPECT_EQ(0, runs[0].start);
656     EXPECT_EQ(4, runs[0].end);
657     EXPECT_EQ(kZH_HantFont, getFontName(runs[0]));
658 
659     // Isolated variation selector supplement.
660     runs = itemize(collection, "U+E0100", "");
661     ASSERT_EQ(1U, runs.size());
662     EXPECT_EQ(0, runs[0].start);
663     EXPECT_EQ(2, runs[0].end);
664     EXPECT_TRUE(runs[0].fakedFont.font.get() == nullptr || kLatinFont == getFontName(runs[0]));
665 
666     runs = itemize(collection, "U+E0100", "zh-Hant");
667     ASSERT_EQ(1U, runs.size());
668     EXPECT_EQ(0, runs[0].start);
669     EXPECT_EQ(2, runs[0].end);
670     EXPECT_TRUE(runs[0].fakedFont.font.get() == nullptr || kLatinFont == getFontName(runs[0]));
671 }
672 
TEST(FontCollectionItemizeTest,itemize_no_crash)673 TEST(FontCollectionItemizeTest, itemize_no_crash) {
674     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
675 
676     // Broken Surrogate pairs. Check only not crashing.
677     auto runs = itemize(collection, "'a' U+D83D 'a'");
678     runs = itemize(collection, "'a' U+DC69 'a'");
679     runs = itemize(collection, "'a' U+D83D U+D83D 'a'");
680     runs = itemize(collection, "'a' U+DC69 U+DC69 'a'");
681 
682     // Isolated variation selector. Check only not crashing.
683     runs = itemize(collection, "U+FE00 U+FE00");
684     runs = itemize(collection, "U+E0100 U+E0100");
685     runs = itemize(collection, "U+FE00 U+E0100");
686     runs = itemize(collection, "U+E0100 U+FE00");
687 
688     // Tone mark only. Check only not crashing.
689     runs = itemize(collection, "U+302D");
690     runs = itemize(collection, "U+302D U+302D");
691 
692     // Tone mark and variation selector mixed. Check only not crashing.
693     runs = itemize(collection, "U+FE00 U+302D U+E0100");
694 }
695 
TEST(FontCollectionItemizeTest,itemize_fakery)696 TEST(FontCollectionItemizeTest, itemize_fakery) {
697     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
698 
699     FontStyle kBoldStyle(FontStyle::Weight::BOLD);
700     FontStyle kItalicStyle(FontStyle::Slant::ITALIC);
701     FontStyle kBoldItalicStyle(FontStyle::Weight::BOLD, FontStyle::Slant::ITALIC);
702 
703     // Currently there is no italic or bold font for Japanese. FontFakery has
704     // the differences between desired and actual font style.
705 
706     // All Japanese Hiragana characters.
707     auto runs = itemize(collection, "U+3042 U+3044 U+3046 U+3048 U+304A", kBoldStyle, "ja-JP");
708     ASSERT_EQ(1U, runs.size());
709     EXPECT_EQ(0, runs[0].start);
710     EXPECT_EQ(5, runs[0].end);
711     EXPECT_EQ(kJAFont, getFontName(runs[0]));
712     EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeBold());
713     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
714 
715     // All Japanese Hiragana characters.
716     runs = itemize(collection, "U+3042 U+3044 U+3046 U+3048 U+304A", kItalicStyle, "ja-JP");
717     ASSERT_EQ(1U, runs.size());
718     EXPECT_EQ(0, runs[0].start);
719     EXPECT_EQ(5, runs[0].end);
720     EXPECT_EQ(kJAFont, getFontName(runs[0]));
721     EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
722     EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeItalic());
723 
724     // All Japanese Hiragana characters.
725     runs = itemize(collection, "U+3042 U+3044 U+3046 U+3048 U+304A", kBoldItalicStyle, "ja-JP");
726     ASSERT_EQ(1U, runs.size());
727     EXPECT_EQ(0, runs[0].start);
728     EXPECT_EQ(5, runs[0].end);
729     EXPECT_EQ(kJAFont, getFontName(runs[0]));
730     EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeBold());
731     EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeItalic());
732 }
733 
TEST(FontCollectionItemizeTest,itemize_vs_sequence_but_no_base_char)734 TEST(FontCollectionItemizeTest, itemize_vs_sequence_but_no_base_char) {
735     // kVSTestFont supports U+717D U+FE02 but doesn't support U+717D.
736     // kVSTestFont should be selected for U+717D U+FE02 even if it does not support the base code
737     // point.
738     const std::string kVSTestFont = "VariationSelectorTest-Regular.ttf";
739 
740     std::vector<std::shared_ptr<FontFamily>> families;
741     families.push_back(buildFontFamily(kLatinFont));
742     families.push_back(buildFontFamily(kVSTestFont));
743 
744     std::shared_ptr<FontCollection> collection(FontCollection::create(families));
745 
746     auto runs = itemize(collection, "U+717D U+FE02");
747     ASSERT_EQ(1U, runs.size());
748     EXPECT_EQ(0, runs[0].start);
749     EXPECT_EQ(2, runs[0].end);
750     EXPECT_EQ(kVSTestFont, getFontName(runs[0]));
751 }
752 
TEST(FontCollectionItemizeTest,itemize_format_chars)753 TEST(FontCollectionItemizeTest, itemize_format_chars) {
754     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
755 
756     auto runs = itemize(collection, "'a' U+061C 'b'");
757     ASSERT_EQ(1U, runs.size());
758     EXPECT_EQ(0, runs[0].start);
759     EXPECT_EQ(3, runs[0].end);
760     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
761 
762     runs = itemize(collection, "'a' U+200D 'b'");
763     ASSERT_EQ(1U, runs.size());
764     EXPECT_EQ(0, runs[0].start);
765     EXPECT_EQ(3, runs[0].end);
766     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
767 
768     runs = itemize(collection, "U+3042 U+061C U+3042");
769     ASSERT_EQ(1U, runs.size());
770     EXPECT_EQ(0, runs[0].start);
771     EXPECT_EQ(3, runs[0].end);
772     EXPECT_EQ(kJAFont, getFontName(runs[0]));
773 
774     runs = itemize(collection, "U+061C 'b'");
775     ASSERT_EQ(1U, runs.size());
776     EXPECT_EQ(0, runs[0].start);
777     EXPECT_EQ(2, runs[0].end);
778     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
779 
780     runs = itemize(collection, "U+061C U+3042");
781     ASSERT_EQ(1U, runs.size());
782     EXPECT_EQ(0, runs[0].start);
783     EXPECT_EQ(2, runs[0].end);
784     EXPECT_EQ(kJAFont, getFontName(runs[0]));
785 
786     runs = itemize(collection, "U+061C");
787     ASSERT_EQ(1U, runs.size());
788     EXPECT_EQ(0, runs[0].start);
789     EXPECT_EQ(1, runs[0].end);
790     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
791 
792     runs = itemize(collection, "U+061C U+061C U+061C");
793     ASSERT_EQ(1U, runs.size());
794     EXPECT_EQ(0, runs[0].start);
795     EXPECT_EQ(3, runs[0].end);
796     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
797 
798     runs = itemize(collection, "U+200D U+20E3");
799     ASSERT_EQ(1U, runs.size());
800     EXPECT_EQ(0, runs[0].start);
801     EXPECT_EQ(2, runs[0].end);
802     EXPECT_EQ(kEmojiFont, getFontName(runs[0]));
803 
804     runs = itemize(collection, "U+200D");
805     ASSERT_EQ(1U, runs.size());
806     EXPECT_EQ(0, runs[0].start);
807     EXPECT_EQ(1, runs[0].end);
808     EXPECT_EQ(kLatinFont, getFontName(runs[0]));
809 
810     runs = itemize(collection, "U+20E3");
811     ASSERT_EQ(1U, runs.size());
812     EXPECT_EQ(0, runs[0].start);
813     EXPECT_EQ(1, runs[0].end);
814     EXPECT_EQ(kEmojiFont, getFontName(runs[0]));
815 }
816 
TEST(FontCollectionItemizeTest,itemize_LocaleScore)817 TEST(FontCollectionItemizeTest, itemize_LocaleScore) {
818     struct TestCase {
819         std::string userPreferredLocale;
820         std::vector<std::string> fontLocales;
821         int selectedFontIndex;
822     } testCases[] = {
823             // Font can specify empty locale.
824             {"und", {"", ""}, 0},
825             {"und", {"", "en-Latn"}, 0},
826             {"en-Latn", {"", ""}, 0},
827             {"en-Latn", {"", "en-Latn"}, 1},
828 
829             // Single user preferred locale.
830             // Exact match case
831             {"en-Latn", {"en-Latn", "ja-Jpan"}, 0},
832             {"ja-Jpan", {"en-Latn", "ja-Jpan"}, 1},
833             {"en-Latn", {"en-Latn", "nl-Latn", "es-Latn"}, 0},
834             {"nl-Latn", {"en-Latn", "nl-Latn", "es-Latn"}, 1},
835             {"es-Latn", {"en-Latn", "nl-Latn", "es-Latn"}, 2},
836             {"es-Latn", {"en-Latn", "en-Latn", "nl-Latn"}, 0},
837 
838             // Exact script match case
839             {"en-Latn", {"nl-Latn", "e-Latn"}, 0},
840             {"en-Arab", {"nl-Latn", "ar-Arab"}, 1},
841             {"en-Latn", {"be-Latn", "ar-Arab", "d-Beng"}, 0},
842             {"en-Arab", {"be-Latn", "ar-Arab", "d-Beng"}, 1},
843             {"en-Beng", {"be-Latn", "ar-Arab", "d-Beng"}, 2},
844             {"en-Beng", {"be-Latn", "ar-Beng", "d-Beng"}, 1},
845             {"zh-Hant", {"zh-Hant", "zh-Hans"}, 0},
846             {"zh-Hans", {"zh-Hant", "zh-Hans"}, 1},
847 
848             // Subscript match case, e.g. Jpan supports Hira.
849             {"en-Hira", {"ja-Jpan"}, 0},
850             {"zh-Hani", {"zh-Hans", "zh-Hant"}, 0},
851             {"zh-Hani", {"zh-Hant", "zh-Hans"}, 0},
852             {"en-Hira", {"zh-Hant", "ja-Jpan", "ja-Jpan"}, 1},
853 
854             // Language match case
855             {"ja-Latn", {"zh-Latn", "ja-Latn"}, 1},
856             {"zh-Latn", {"zh-Latn", "ja-Latn"}, 0},
857             {"ja-Latn", {"zh-Latn", "ja-Latn"}, 1},
858             {"ja-Latn", {"zh-Latn", "ja-Latn", "ja-Latn"}, 1},
859 
860             // Mixed case
861             // Script/subscript match is strongest.
862             {"ja-Jpan", {"en-Latn", "ja-Latn", "en-Jpan"}, 2},
863             {"ja-Hira", {"en-Latn", "ja-Latn", "en-Jpan"}, 2},
864             {"ja-Hira", {"en-Latn", "ja-Latn", "en-Jpan", "en-Jpan"}, 2},
865 
866             // Language match only happens if the script matches.
867             {"ja-Hira", {"en-Latn", "ja-Latn"}, 0},
868             {"ja-Hira", {"en-Jpan", "ja-Jpan"}, 1},
869 
870             // Multiple locales.
871             // Even if all fonts have the same score, use the 2nd locale for better selection.
872             {"en-Latn,ja-Jpan", {"zh-Hant", "zh-Hans", "ja-Jpan"}, 2},
873             {"en-Latn,nl-Latn", {"es-Latn", "be-Latn", "nl-Latn"}, 2},
874             {"en-Latn,br-Latn,nl-Latn", {"es-Latn", "be-Latn", "nl-Latn"}, 2},
875             {"en-Latn,br-Latn,nl-Latn", {"es-Latn", "be-Latn", "nl-Latn", "nl-Latn"}, 2},
876 
877             // Script score.
878             {"en-Latn,ja-Jpan", {"en-Arab", "en-Jpan"}, 1},
879             {"en-Latn,ja-Jpan", {"en-Arab", "en-Jpan", "en-Jpan"}, 1},
880 
881             // Language match case
882             {"en-Latn,ja-Latn", {"bd-Latn", "ja-Latn"}, 1},
883             {"en-Latn,ja-Latn", {"bd-Latn", "ja-Latn", "ja-Latn"}, 1},
884 
885             // Language match only happens if the script matches.
886             {"en-Latn,ar-Arab", {"en-Beng", "ar-Arab"}, 1},
887 
888             // Multiple locales in the font settings.
889             {"ko-Jamo", {"ja-Jpan", "ko-Kore", "ko-Kore,ko-Jamo"}, 2},
890             {"en-Latn", {"ja-Jpan", "en-Latn,ja-Jpan"}, 1},
891             {"en-Latn", {"ja-Jpan", "ja-Jpan,en-Latn"}, 1},
892             {"en-Latn", {"ja-Jpan,zh-Hant", "en-Latn,ja-Jpan", "en-Latn"}, 1},
893             {"en-Latn", {"zh-Hant,ja-Jpan", "ja-Jpan,en-Latn", "en-Latn"}, 1},
894 
895             // Kore = Hang + Hani, etc.
896             {"ko-Kore", {"ko-Hang", "ko-Jamo,ko-Hani", "ko-Hang,ko-Hani"}, 2},
897             {"ja-Hrkt", {"ja-Hira", "ja-Kana", "ja-Hira,ja-Kana"}, 2},
898             {"ja-Jpan", {"ja-Hira", "ja-Kana", "ja-Hani", "ja-Hira,ja-Kana,ja-Hani"}, 3},
899             {"zh-Hanb", {"zh-Hant", "zh-Bopo", "zh-Hant,zh-Bopo"}, 2},
900             {"zh-Hanb", {"ja-Hanb", "zh-Hant,zh-Bopo"}, 1},
901 
902             // Language match with unified subscript bits.
903             {"zh-Hanb", {"zh-Hant", "zh-Bopo", "ja-Hant,ja-Bopo", "zh-Hant,zh-Bopo"}, 3},
904             {"zh-Hanb", {"zh-Hant", "zh-Bopo", "ja-Hant,zh-Bopo", "zh-Hant,zh-Bopo"}, 3},
905 
906             // Two elements subtag matching: language and subtag or language or script.
907             {"ja-Kana-u-em-emoji", {"zh-Hant", "ja-Kana"}, 1},
908             {"ja-Kana-u-em-emoji", {"zh-Hant", "ja-Kana", "ja-Zsye"}, 2},
909             {"ja-Zsym-u-em-emoji", {"ja-Kana", "ja-Zsym", "ja-Zsye"}, 2},
910 
911             // One element subtag matching: subtag only or script only.
912             {"en-Latn-u-em-emoji", {"ja-Latn", "ja-Zsye"}, 1},
913             {"en-Zsym-u-em-emoji", {"ja-Zsym", "ja-Zsye"}, 1},
914             {"en-Zsye-u-em-text", {"ja-Zsym", "ja-Zsye"}, 0},
915 
916             // Multiple locale list with subtags.
917             {"en-Latn,ja-Jpan-u-em-text", {"en-Latn", "en-Zsye", "en-Zsym"}, 0},
918             {"en-Latn,en-Zsye,ja-Jpan-u-em-text", {"zh", "en-Zsye", "en-Zsym"}, 1},
919     };
920 
921     for (auto testCase : testCases) {
922         std::string fontLocaleStr = "{";
923         for (size_t i = 0; i < testCase.fontLocales.size(); ++i) {
924             if (i != 0) {
925                 fontLocaleStr += ", ";
926             }
927             fontLocaleStr += "\"" + testCase.fontLocales[i] + "\"";
928         }
929         fontLocaleStr += "}";
930         SCOPED_TRACE("Test of user preferred locale: \"" + testCase.userPreferredLocale +
931                      "\" with font locale: " + fontLocaleStr);
932 
933         std::vector<std::shared_ptr<FontFamily>> families;
934 
935         // Prepare first font which doesn't supports U+9AA8
936         auto firstFamilyMinikinFont =
937                 std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath(kNoGlyphFont));
938         std::vector<std::shared_ptr<Font>> fonts;
939         fonts.push_back(Font::Builder(firstFamilyMinikinFont).build());
940         auto firstFamily =
941                 FontFamily::create(registerLocaleList("und"), FamilyVariant::DEFAULT,
942                                    std::move(fonts), false /* isCustomFallback */,
943                                    false /* isDefaultFallback */, VariationFamilyType::None);
944         families.push_back(firstFamily);
945 
946         // Prepare font families
947         // Each font family is associated with a specified locale. All font families except for
948         // the first font support U+9AA8.
949         std::unordered_map<MinikinFont*, int> fontLocaleIdxMap;
950 
951         for (size_t i = 0; i < testCase.fontLocales.size(); ++i) {
952             auto minikinFont =
953                     std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath(kJAFont));
954             std::vector<std::shared_ptr<Font>> fonts;
955             fonts.push_back(Font::Builder(minikinFont).build());
956             auto family = FontFamily::create(
957                     registerLocaleList(testCase.fontLocales[i]), FamilyVariant::DEFAULT,
958                     std::move(fonts), false /* isCustomFallback */, false /* isDefaultFallback */,
959                     VariationFamilyType::None);
960             families.push_back(family);
961             fontLocaleIdxMap.insert(std::make_pair(minikinFont.get(), i));
962         }
963         std::shared_ptr<FontCollection> collection(FontCollection::create(families));
964         // Do itemize
965         auto runs = itemize(collection, "U+9AA8", testCase.userPreferredLocale);
966         ASSERT_EQ(1U, runs.size());
967         ASSERT_NE(nullptr, runs[0].fakedFont.font.get());
968 
969         // First family doesn't support U+9AA8 and others support it, so the first font should not
970         // be selected.
971         EXPECT_NE(firstFamilyMinikinFont.get(), runs[0].fakedFont.typeface().get());
972 
973         // Lookup used font family by MinikinFont*.
974         const int usedLocaleIndex = fontLocaleIdxMap[runs[0].fakedFont.typeface().get()];
975         EXPECT_EQ(testCase.selectedFontIndex, usedLocaleIndex);
976     }
977 }
978 
TEST(FontCollectionItemizeTest,itemize_LocaleAndCoverage)979 TEST(FontCollectionItemizeTest, itemize_LocaleAndCoverage) {
980     struct TestCase {
981         std::string testString;
982         std::string requestedLocales;
983         std::string expectedFont;
984     } testCases[] = {
985             // Following test cases verify that following rules in font fallback chain.
986             // - If the first font in the collection supports the given character or variation
987             // sequence,
988             //   it should be selected.
989             // - If the font doesn't support the given character, variation sequence or its base
990             //   character, it should not be selected.
991             // - If two or more fonts match the requested locales, the font matches with the highest
992             //   priority locale should be selected.
993             // - If two or more fonts get the same score, the font listed earlier in the XML file
994             //   (here, kItemizeFontXml) should be selected.
995 
996             // Regardless of locale, the first font is always selected if it covers the code point.
997             {"'a'", "", kLatinFont},
998             {"'a'", "en-Latn", kLatinFont},
999             {"'a'", "ja-Jpan", kLatinFont},
1000             {"'a'", "ja-Jpan,en-Latn", kLatinFont},
1001             {"'a'", "zh-Hans,zh-Hant,en-Latn,ja-Jpan,fr-Latn", kLatinFont},
1002 
1003             // U+81ED is supported by both the ja font and zh-Hans font.
1004             {"U+81ED", "", kZH_HansFont},         // zh-Hans font is listed before ja font.
1005             {"U+81ED", "en-Latn", kZH_HansFont},  // zh-Hans font is listed before ja font.
1006             {"U+81ED", "ja-Jpan", kJAFont},
1007             {"U+81ED", "zh-Hans", kZH_HansFont},
1008 
1009             {"U+81ED", "ja-Jpan,en-Latn", kJAFont},
1010             {"U+81ED", "en-Latn,ja-Jpan", kJAFont},
1011             {"U+81ED", "en-Latn,zh-Hans", kZH_HansFont},
1012             {"U+81ED", "zh-Hans,en-Latn", kZH_HansFont},
1013             {"U+81ED", "ja-Jpan,zh-Hans", kJAFont},
1014             {"U+81ED", "zh-Hans,ja-Jpan", kZH_HansFont},
1015 
1016             {"U+81ED", "en-Latn,zh-Hans,ja-Jpan", kZH_HansFont},
1017             {"U+81ED", "en-Latn,ja-Jpan,zh-Hans", kJAFont},
1018             {"U+81ED", "en-Latn,zh-Hans,ja-Jpan", kZH_HansFont},
1019             {"U+81ED", "ja-Jpan,en-Latn,zh-Hans", kJAFont},
1020             {"U+81ED", "ja-Jpan,zh-Hans,en-Latn", kJAFont},
1021             {"U+81ED", "zh-Hans,en-Latn,ja-Jpan", kZH_HansFont},
1022             {"U+81ED", "zh-Hans,ja-Jpan,en-Latn", kZH_HansFont},
1023 
1024             // U+304A is only supported by ja font.
1025             {"U+304A", "", kJAFont},
1026             {"U+304A", "ja-Jpan", kJAFont},
1027             {"U+304A", "zh-Hant", kJAFont},
1028             {"U+304A", "zh-Hans", kJAFont},
1029 
1030             {"U+304A", "ja-Jpan,zh-Hant", kJAFont},
1031             {"U+304A", "zh-Hant,ja-Jpan", kJAFont},
1032             {"U+304A", "zh-Hans,zh-Hant", kJAFont},
1033             {"U+304A", "zh-Hant,zh-Hans", kJAFont},
1034             {"U+304A", "zh-Hans,ja-Jpan", kJAFont},
1035             {"U+304A", "ja-Jpan,zh-Hans", kJAFont},
1036 
1037             {"U+304A", "zh-Hans,ja-Jpan,zh-Hant", kJAFont},
1038             {"U+304A", "zh-Hans,zh-Hant,ja-Jpan", kJAFont},
1039             {"U+304A", "ja-Jpan,zh-Hans,zh-Hant", kJAFont},
1040             {"U+304A", "ja-Jpan,zh-Hant,zh-Hans", kJAFont},
1041             {"U+304A", "zh-Hant,zh-Hans,ja-Jpan", kJAFont},
1042             {"U+304A", "zh-Hant,ja-Jpan,zh-Hans", kJAFont},
1043 
1044             // U+242EE is supported by both ja font and zh-Hant fonts but not by zh-Hans font.
1045             {"U+242EE", "", kJAFont},  // ja font is listed before zh-Hant font.
1046             {"U+242EE", "ja-Jpan", kJAFont},
1047             {"U+242EE", "zh-Hans", kJAFont},
1048             {"U+242EE", "zh-Hant", kZH_HantFont},
1049 
1050             {"U+242EE", "ja-Jpan,zh-Hant", kJAFont},
1051             {"U+242EE", "zh-Hant,ja-Jpan", kZH_HantFont},
1052             {"U+242EE", "zh-Hans,zh-Hant", kZH_HantFont},
1053             {"U+242EE", "zh-Hant,zh-Hans", kZH_HantFont},
1054             {"U+242EE", "zh-Hans,ja-Jpan", kJAFont},
1055             {"U+242EE", "ja-Jpan,zh-Hans", kJAFont},
1056 
1057             {"U+242EE", "zh-Hans,ja-Jpan,zh-Hant", kJAFont},
1058             {"U+242EE", "zh-Hans,zh-Hant,ja-Jpan", kZH_HantFont},
1059             {"U+242EE", "ja-Jpan,zh-Hans,zh-Hant", kJAFont},
1060             {"U+242EE", "ja-Jpan,zh-Hant,zh-Hans", kJAFont},
1061             {"U+242EE", "zh-Hant,zh-Hans,ja-Jpan", kZH_HantFont},
1062             {"U+242EE", "zh-Hant,ja-Jpan,zh-Hans", kZH_HantFont},
1063 
1064             // U+9AA8 is supported by all ja-Jpan, zh-Hans, zh-Hant fonts.
1065             {"U+9AA8", "", kZH_HansFont},  // zh-Hans font is listed before ja and zh-Hant fonts.
1066             {"U+9AA8", "ja-Jpan", kJAFont},
1067             {"U+9AA8", "zh-Hans", kZH_HansFont},
1068             {"U+9AA8", "zh-Hant", kZH_HantFont},
1069 
1070             {"U+9AA8", "ja-Jpan,zh-Hant", kJAFont},
1071             {"U+9AA8", "zh-Hant,ja-Jpan", kZH_HantFont},
1072             {"U+9AA8", "zh-Hans,zh-Hant", kZH_HansFont},
1073             {"U+9AA8", "zh-Hant,zh-Hans", kZH_HantFont},
1074             {"U+9AA8", "zh-Hans,ja-Jpan", kZH_HansFont},
1075             {"U+9AA8", "ja-Jpan,zh-Hans", kJAFont},
1076 
1077             {"U+9AA8", "zh-Hans,ja-Jpan,zh-Hant", kZH_HansFont},
1078             {"U+9AA8", "zh-Hans,zh-Hant,ja-Jpan", kZH_HansFont},
1079             {"U+9AA8", "ja-Jpan,zh-Hans,zh-Hant", kJAFont},
1080             {"U+9AA8", "ja-Jpan,zh-Hant,zh-Hans", kJAFont},
1081             {"U+9AA8", "zh-Hant,zh-Hans,ja-Jpan", kZH_HantFont},
1082             {"U+9AA8", "zh-Hant,ja-Jpan,zh-Hans", kZH_HantFont},
1083 
1084             // U+242EE U+FE00 is supported by ja font but not by zh-Hans or zh-Hant fonts.
1085             {"U+242EE U+FE00", "", kJAFont},
1086             {"U+242EE U+FE00", "ja-Jpan", kJAFont},
1087             {"U+242EE U+FE00", "zh-Hant", kJAFont},
1088             {"U+242EE U+FE00", "zh-Hans", kJAFont},
1089 
1090             {"U+242EE U+FE00", "ja-Jpan,zh-Hant", kJAFont},
1091             {"U+242EE U+FE00", "zh-Hant,ja-Jpan", kJAFont},
1092             {"U+242EE U+FE00", "zh-Hans,zh-Hant", kJAFont},
1093             {"U+242EE U+FE00", "zh-Hant,zh-Hans", kJAFont},
1094             {"U+242EE U+FE00", "zh-Hans,ja-Jpan", kJAFont},
1095             {"U+242EE U+FE00", "ja-Jpan,zh-Hans", kJAFont},
1096 
1097             {"U+242EE U+FE00", "zh-Hans,ja-Jpan,zh-Hant", kJAFont},
1098             {"U+242EE U+FE00", "zh-Hans,zh-Hant,ja-Jpan", kJAFont},
1099             {"U+242EE U+FE00", "ja-Jpan,zh-Hans,zh-Hant", kJAFont},
1100             {"U+242EE U+FE00", "ja-Jpan,zh-Hant,zh-Hans", kJAFont},
1101             {"U+242EE U+FE00", "zh-Hant,zh-Hans,ja-Jpan", kJAFont},
1102             {"U+242EE U+FE00", "zh-Hant,ja-Jpan,zh-Hans", kJAFont},
1103 
1104             // U+3402 U+E0100 is supported by both zh-Hans and zh-Hant but not by ja font.
1105             {"U+3402 U+E0100", "", kZH_HansFont},  // zh-Hans font is listed before zh-Hant font.
1106             {"U+3402 U+E0100", "ja-Jpan",
1107              kZH_HansFont},  // zh-Hans font is listed before zh-Hant font.
1108             {"U+3402 U+E0100", "zh-Hant", kZH_HantFont},
1109             {"U+3402 U+E0100", "zh-Hans", kZH_HansFont},
1110 
1111             {"U+3402 U+E0100", "ja-Jpan,zh-Hant", kZH_HantFont},
1112             {"U+3402 U+E0100", "zh-Hant,ja-Jpan", kZH_HantFont},
1113             {"U+3402 U+E0100", "zh-Hans,zh-Hant", kZH_HansFont},
1114             {"U+3402 U+E0100", "zh-Hant,zh-Hans", kZH_HantFont},
1115             {"U+3402 U+E0100", "zh-Hans,ja-Jpan", kZH_HansFont},
1116             {"U+3402 U+E0100", "ja-Jpan,zh-Hans", kZH_HansFont},
1117 
1118             {"U+3402 U+E0100", "zh-Hans,ja-Jpan,zh-Hant", kZH_HansFont},
1119             {"U+3402 U+E0100", "zh-Hans,zh-Hant,ja-Jpan", kZH_HansFont},
1120             {"U+3402 U+E0100", "ja-Jpan,zh-Hans,zh-Hant", kZH_HansFont},
1121             {"U+3402 U+E0100", "ja-Jpan,zh-Hant,zh-Hans", kZH_HantFont},
1122             {"U+3402 U+E0100", "zh-Hant,zh-Hans,ja-Jpan", kZH_HantFont},
1123             {"U+3402 U+E0100", "zh-Hant,ja-Jpan,zh-Hans", kZH_HantFont},
1124 
1125             // No font supports U+4444 U+FE00 but only zh-Hans supports its base character U+4444.
1126             {"U+4444 U+FE00", "", kZH_HansFont},
1127             {"U+4444 U+FE00", "ja-Jpan", kZH_HansFont},
1128             {"U+4444 U+FE00", "zh-Hant", kZH_HansFont},
1129             {"U+4444 U+FE00", "zh-Hans", kZH_HansFont},
1130 
1131             {"U+4444 U+FE00", "ja-Jpan,zh-Hant", kZH_HansFont},
1132             {"U+4444 U+FE00", "zh-Hant,ja-Jpan", kZH_HansFont},
1133             {"U+4444 U+FE00", "zh-Hans,zh-Hant", kZH_HansFont},
1134             {"U+4444 U+FE00", "zh-Hant,zh-Hans", kZH_HansFont},
1135             {"U+4444 U+FE00", "zh-Hans,ja-Jpan", kZH_HansFont},
1136             {"U+4444 U+FE00", "ja-Jpan,zh-Hans", kZH_HansFont},
1137 
1138             {"U+4444 U+FE00", "zh-Hans,ja-Jpan,zh-Hant", kZH_HansFont},
1139             {"U+4444 U+FE00", "zh-Hans,zh-Hant,ja-Jpan", kZH_HansFont},
1140             {"U+4444 U+FE00", "ja-Jpan,zh-Hans,zh-Hant", kZH_HansFont},
1141             {"U+4444 U+FE00", "ja-Jpan,zh-Hant,zh-Hans", kZH_HansFont},
1142             {"U+4444 U+FE00", "zh-Hant,zh-Hans,ja-Jpan", kZH_HansFont},
1143             {"U+4444 U+FE00", "zh-Hant,ja-Jpan,zh-Hans", kZH_HansFont},
1144 
1145             // No font supports U+81ED U+E0100 but ja and zh-Hans support its base character U+81ED.
1146             // zh-Hans font is listed before ja font.
1147             {"U+81ED U+E0100", "", kZH_HansFont},
1148             {"U+81ED U+E0100", "ja-Jpan", kJAFont},
1149             {"U+81ED U+E0100", "zh-Hant", kZH_HansFont},
1150             {"U+81ED U+E0100", "zh-Hans", kZH_HansFont},
1151 
1152             {"U+81ED U+E0100", "ja-Jpan,zh-Hant", kJAFont},
1153             {"U+81ED U+E0100", "zh-Hant,ja-Jpan", kJAFont},
1154             {"U+81ED U+E0100", "zh-Hans,zh-Hant", kZH_HansFont},
1155             {"U+81ED U+E0100", "zh-Hant,zh-Hans", kZH_HansFont},
1156             {"U+81ED U+E0100", "zh-Hans,ja-Jpan", kZH_HansFont},
1157             {"U+81ED U+E0100", "ja-Jpan,zh-Hans", kJAFont},
1158 
1159             {"U+81ED U+E0100", "zh-Hans,ja-Jpan,zh-Hant", kZH_HansFont},
1160             {"U+81ED U+E0100", "zh-Hans,zh-Hant,ja-Jpan", kZH_HansFont},
1161             {"U+81ED U+E0100", "ja-Jpan,zh-Hans,zh-Hant", kJAFont},
1162             {"U+81ED U+E0100", "ja-Jpan,zh-Hant,zh-Hans", kJAFont},
1163             {"U+81ED U+E0100", "zh-Hant,zh-Hans,ja-Jpan", kZH_HansFont},
1164             {"U+81ED U+E0100", "zh-Hant,ja-Jpan,zh-Hans", kJAFont},
1165 
1166             // No font supports U+9AA8 U+E0100 but all zh-Hans zh-hant ja fonts support its base
1167             // character U+9AA8.
1168             // zh-Hans font is listed before ja and zh-Hant fonts.
1169             {"U+9AA8 U+E0100", "", kZH_HansFont},
1170             {"U+9AA8 U+E0100", "ja-Jpan", kJAFont},
1171             {"U+9AA8 U+E0100", "zh-Hans", kZH_HansFont},
1172             {"U+9AA8 U+E0100", "zh-Hant", kZH_HantFont},
1173 
1174             {"U+9AA8 U+E0100", "ja-Jpan,zh-Hant", kJAFont},
1175             {"U+9AA8 U+E0100", "zh-Hant,ja-Jpan", kZH_HantFont},
1176             {"U+9AA8 U+E0100", "zh-Hans,zh-Hant", kZH_HansFont},
1177             {"U+9AA8 U+E0100", "zh-Hant,zh-Hans", kZH_HantFont},
1178             {"U+9AA8 U+E0100", "zh-Hans,ja-Jpan", kZH_HansFont},
1179             {"U+9AA8 U+E0100", "ja-Jpan,zh-Hans", kJAFont},
1180 
1181             {"U+9AA8 U+E0100", "zh-Hans,ja-Jpan,zh-Hant", kZH_HansFont},
1182             {"U+9AA8 U+E0100", "zh-Hans,zh-Hant,ja-Jpan", kZH_HansFont},
1183             {"U+9AA8 U+E0100", "ja-Jpan,zh-Hans,zh-Hant", kJAFont},
1184             {"U+9AA8 U+E0100", "ja-Jpan,zh-Hant,zh-Hans", kJAFont},
1185             {"U+9AA8 U+E0100", "zh-Hant,zh-Hans,ja-Jpan", kZH_HantFont},
1186             {"U+9AA8 U+E0100", "zh-Hant,ja-Jpan,zh-Hans", kZH_HantFont},
1187 
1188             // All zh-Hans,zh-Hant,ja fonts support U+35A8 U+E0100 and its base character U+35A8.
1189             // zh-Hans font is listed before ja and zh-Hant fonts.
1190             {"U+35A8", "", kZH_HansFont},
1191             {"U+35A8", "ja-Jpan", kJAFont},
1192             {"U+35A8", "zh-Hans", kZH_HansFont},
1193             {"U+35A8", "zh-Hant", kZH_HantFont},
1194 
1195             {"U+35A8", "ja-Jpan,zh-Hant", kJAFont},
1196             {"U+35A8", "zh-Hant,ja-Jpan", kZH_HantFont},
1197             {"U+35A8", "zh-Hans,zh-Hant", kZH_HansFont},
1198             {"U+35A8", "zh-Hant,zh-Hans", kZH_HantFont},
1199             {"U+35A8", "zh-Hans,ja-Jpan", kZH_HansFont},
1200             {"U+35A8", "ja-Jpan,zh-Hans", kJAFont},
1201 
1202             {"U+35A8", "zh-Hans,ja-Jpan,zh-Hant", kZH_HansFont},
1203             {"U+35A8", "zh-Hans,zh-Hant,ja-Jpan", kZH_HansFont},
1204             {"U+35A8", "ja-Jpan,zh-Hans,zh-Hant", kJAFont},
1205             {"U+35A8", "ja-Jpan,zh-Hant,zh-Hans", kJAFont},
1206             {"U+35A8", "zh-Hant,zh-Hans,ja-Jpan", kZH_HantFont},
1207             {"U+35A8", "zh-Hant,ja-Jpan,zh-Hans", kZH_HantFont},
1208 
1209             // All zh-Hans,zh-Hant,ja fonts support U+35B6 U+E0100, but zh-Hant and ja fonts support
1210             // its
1211             // base character U+35B6.
1212             // ja font is listed before zh-Hant font.
1213             {"U+35B6", "", kJAFont},
1214             {"U+35B6", "ja-Jpan", kJAFont},
1215             {"U+35B6", "zh-Hant", kZH_HantFont},
1216             {"U+35B6", "zh-Hans", kJAFont},
1217 
1218             {"U+35B6", "ja-Jpan,zh-Hant", kJAFont},
1219             {"U+35B6", "zh-Hant,ja-Jpan", kZH_HantFont},
1220             {"U+35B6", "zh-Hans,zh-Hant", kZH_HantFont},
1221             {"U+35B6", "zh-Hant,zh-Hans", kZH_HantFont},
1222             {"U+35B6", "zh-Hans,ja-Jpan", kJAFont},
1223             {"U+35B6", "ja-Jpan,zh-Hans", kJAFont},
1224 
1225             {"U+35B6", "zh-Hans,ja-Jpan,zh-Hant", kJAFont},
1226             {"U+35B6", "zh-Hans,zh-Hant,ja-Jpan", kZH_HantFont},
1227             {"U+35B6", "ja-Jpan,zh-Hans,zh-Hant", kJAFont},
1228             {"U+35B6", "ja-Jpan,zh-Hant,zh-Hans", kJAFont},
1229             {"U+35B6", "zh-Hant,zh-Hans,ja-Jpan", kZH_HantFont},
1230             {"U+35B6", "zh-Hant,ja-Jpan,zh-Hans", kZH_HantFont},
1231 
1232             // All zh-Hans,zh-Hant,ja fonts support U+35C5 U+E0100, but only ja font supports its
1233             // base
1234             // character U+35C5.
1235             {"U+35C5", "", kJAFont},
1236             {"U+35C5", "ja-Jpan", kJAFont},
1237             {"U+35C5", "zh-Hant", kJAFont},
1238             {"U+35C5", "zh-Hans", kJAFont},
1239 
1240             {"U+35C5", "ja-Jpan,zh-Hant", kJAFont},
1241             {"U+35C5", "zh-Hant,ja-Jpan", kJAFont},
1242             {"U+35C5", "zh-Hans,zh-Hant", kJAFont},
1243             {"U+35C5", "zh-Hant,zh-Hans", kJAFont},
1244             {"U+35C5", "zh-Hans,ja-Jpan", kJAFont},
1245             {"U+35C5", "ja-Jpan,zh-Hans", kJAFont},
1246 
1247             {"U+35C5", "zh-Hans,ja-Jpan,zh-Hant", kJAFont},
1248             {"U+35C5", "zh-Hans,zh-Hant,ja-Jpan", kJAFont},
1249             {"U+35C5", "ja-Jpan,zh-Hans,zh-Hant", kJAFont},
1250             {"U+35C5", "ja-Jpan,zh-Hant,zh-Hans", kJAFont},
1251             {"U+35C5", "zh-Hant,zh-Hans,ja-Jpan", kJAFont},
1252             {"U+35C5", "zh-Hant,ja-Jpan,zh-Hans", kJAFont},
1253 
1254             // None of ja-Jpan, zh-Hant, zh-Hans font supports U+1F469. Emoji font supports it.
1255             {"U+1F469", "", kEmojiFont},
1256             {"U+1F469", "ja-Jpan", kEmojiFont},
1257             {"U+1F469", "zh-Hant", kEmojiFont},
1258             {"U+1F469", "zh-Hans", kEmojiFont},
1259 
1260             {"U+1F469", "ja-Jpan,zh-Hant", kEmojiFont},
1261             {"U+1F469", "zh-Hant,ja-Jpan", kEmojiFont},
1262             {"U+1F469", "zh-Hans,zh-Hant", kEmojiFont},
1263             {"U+1F469", "zh-Hant,zh-Hans", kEmojiFont},
1264             {"U+1F469", "zh-Hans,ja-Jpan", kEmojiFont},
1265             {"U+1F469", "ja-Jpan,zh-Hans", kEmojiFont},
1266 
1267             {"U+1F469", "zh-Hans,ja-Jpan,zh-Hant", kEmojiFont},
1268             {"U+1F469", "zh-Hans,zh-Hant,ja-Jpan", kEmojiFont},
1269             {"U+1F469", "ja-Jpan,zh-Hans,zh-Hant", kEmojiFont},
1270             {"U+1F469", "ja-Jpan,zh-Hant,zh-Hans", kEmojiFont},
1271             {"U+1F469", "zh-Hant,zh-Hans,ja-Jpan", kEmojiFont},
1272             {"U+1F469", "zh-Hant,ja-Jpan,zh-Hans", kEmojiFont},
1273     };
1274 
1275     auto collection = buildFontCollectionFromXml(kItemizeFontXml);
1276 
1277     for (const auto& testCase : testCases) {
1278         SCOPED_TRACE("Test for \"" + testCase.testString + "\" with locales " +
1279                      testCase.requestedLocales);
1280 
1281         auto runs = itemize(collection, testCase.testString.c_str(), testCase.requestedLocales);
1282         ASSERT_EQ(1U, runs.size());
1283         EXPECT_EQ(testCase.expectedFont, getFontName(runs[0]));
1284     }
1285 }
1286 
TEST(FontCollectionItemizeTest,itemize_emojiSelection_withFE0E)1287 TEST(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
1288     auto collection = buildFontCollectionFromXml(kEmojiXmlFile);
1289 
1290     // U+00A9 is a text default emoji which is only available in TextEmojiFont.ttf.
1291     // TextEmojiFont.ttf should be selected.
1292     auto runs = itemize(collection, "U+00A9 U+FE0E");
1293     ASSERT_EQ(1U, runs.size());
1294     EXPECT_EQ(0, runs[0].start);
1295     EXPECT_EQ(2, runs[0].end);
1296     EXPECT_EQ(kTextEmojiFont, getFontName(runs[0]));
1297 
1298     // U+00A9 is a text default emoji which is only available in ColorEmojiFont.ttf.
1299     // ColorEmojiFont.ttf should be selected.
1300     runs = itemize(collection, "U+00AE U+FE0E");
1301     ASSERT_EQ(1U, runs.size());
1302     EXPECT_EQ(0, runs[0].start);
1303     EXPECT_EQ(2, runs[0].end);
1304     // Text emoji is specified but it is not available. Use color emoji instead.
1305     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1306 
1307     // U+203C is a text default emoji which is available in both TextEmojiFont.ttf and
1308     // ColorEmojiFont.ttf. TextEmojiFont.ttf should be selected.
1309     runs = itemize(collection, "U+203C U+FE0E");
1310     ASSERT_EQ(1U, runs.size());
1311     EXPECT_EQ(0, runs[0].start);
1312     EXPECT_EQ(2, runs[0].end);
1313     EXPECT_EQ(kTextEmojiFont, getFontName(runs[0]));
1314 
1315     // U+2049 is a text default emoji which is not available either TextEmojiFont.ttf or
1316     // ColorEmojiFont.ttf. No font should be selected.
1317     runs = itemize(collection, "U+2049 U+FE0E");
1318     ASSERT_EQ(1U, runs.size());
1319     EXPECT_EQ(0, runs[0].start);
1320     EXPECT_EQ(2, runs[0].end);
1321     EXPECT_EQ(kNoGlyphFont, getFontName(runs[0]));
1322 
1323     // U+231A is a emoji default emoji which is available only in TextEmojifFont.
1324     // TextEmojiFont.ttf sohuld be selected.
1325     runs = itemize(collection, "U+231A U+FE0E");
1326     ASSERT_EQ(1U, runs.size());
1327     EXPECT_EQ(0, runs[0].start);
1328     EXPECT_EQ(2, runs[0].end);
1329     EXPECT_EQ(kTextEmojiFont, getFontName(runs[0]));
1330 
1331     // U+231B is a emoji default emoji which is available only in ColorEmojiFont.ttf.
1332     // ColorEmojiFont.ttf should be selected.
1333     runs = itemize(collection, "U+231B U+FE0E");
1334     ASSERT_EQ(1U, runs.size());
1335     EXPECT_EQ(0, runs[0].start);
1336     EXPECT_EQ(2, runs[0].end);
1337     // Text emoji is specified but it is not available. Use color emoji instead.
1338     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1339 
1340     // U+23E9 is a emoji default emoji which is available in both TextEmojiFont.ttf and
1341     // ColorEmojiFont.ttf. TextEmojiFont.ttf should be selected even if U+23E9 is emoji default
1342     // emoji since U+FE0E is appended.
1343     runs = itemize(collection, "U+23E9 U+FE0E");
1344     ASSERT_EQ(1U, runs.size());
1345     EXPECT_EQ(0, runs[0].start);
1346     EXPECT_EQ(2, runs[0].end);
1347     EXPECT_EQ(kTextEmojiFont, getFontName(runs[0]));
1348 
1349     // U+23EA is a emoji default emoji but which is not available in either TextEmojiFont.ttf or
1350     // ColorEmojiFont.ttf. No font should be selected.
1351     runs = itemize(collection, "U+23EA U+FE0E");
1352     ASSERT_EQ(1U, runs.size());
1353     EXPECT_EQ(0, runs[0].start);
1354     EXPECT_EQ(2, runs[0].end);
1355     EXPECT_EQ(kNoGlyphFont, getFontName(runs[0]));
1356 
1357     // U+26FA U+FE0E is specified but ColorTextMixedEmojiFont has a variation sequence U+26F9 U+FE0F
1358     // in its cmap, so ColorTextMixedEmojiFont should be selected instaed of ColorEmojiFont.
1359     runs = itemize(collection, "U+26FA U+FE0E");
1360     ASSERT_EQ(1U, runs.size());
1361     EXPECT_EQ(0, runs[0].start);
1362     EXPECT_EQ(2, runs[0].end);
1363     EXPECT_EQ(kMixedEmojiFont, getFontName(runs[0]));
1364 }
1365 
TEST(FontCollectionItemizeTest,itemize_emojiSelection_withFE0F)1366 TEST(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
1367     auto collection = buildFontCollectionFromXml(kEmojiXmlFile);
1368 
1369     // U+00A9 is a text default emoji which is available only in TextEmojiFont.ttf.
1370     // TextEmojiFont.ttf shoudl be selected.
1371     auto runs = itemize(collection, "U+00A9 U+FE0F");
1372     ASSERT_EQ(1U, runs.size());
1373     EXPECT_EQ(0, runs[0].start);
1374     EXPECT_EQ(2, runs[0].end);
1375     // Color emoji is specified but it is not available. Use text representaion instead.
1376     EXPECT_EQ(kTextEmojiFont, getFontName(runs[0]));
1377 
1378     // U+00AE is a text default emoji which is available only in ColorEmojiFont.ttf.
1379     // ColorEmojiFont.ttf should be selected.
1380     runs = itemize(collection, "U+00AE U+FE0F");
1381     ASSERT_EQ(1U, runs.size());
1382     EXPECT_EQ(0, runs[0].start);
1383     EXPECT_EQ(2, runs[0].end);
1384     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1385 
1386     // U+203C is a text default emoji which is available in both TextEmojiFont.ttf and
1387     // ColorEmojiFont.ttf. ColorEmojiFont.ttf should be selected even if U+203C is a text default
1388     // emoji since U+FF0F is appended.
1389     runs = itemize(collection, "U+203C U+FE0F");
1390     ASSERT_EQ(1U, runs.size());
1391     EXPECT_EQ(0, runs[0].start);
1392     EXPECT_EQ(2, runs[0].end);
1393     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1394 
1395     // U+2049 is a text default emoji which is not available in either TextEmojiFont.ttf or
1396     // ColorEmojiFont.ttf. No font should be selected.
1397     runs = itemize(collection, "U+2049 U+FE0F");
1398     ASSERT_EQ(1U, runs.size());
1399     EXPECT_EQ(0, runs[0].start);
1400     EXPECT_EQ(2, runs[0].end);
1401     EXPECT_EQ(kNoGlyphFont, getFontName(runs[0]));
1402 
1403     // U+231A is a emoji default emoji which is available only in TextEmojiFont.ttf.
1404     // TextEmojiFont.ttf should be selected.
1405     runs = itemize(collection, "U+231A U+FE0F");
1406     ASSERT_EQ(1U, runs.size());
1407     EXPECT_EQ(0, runs[0].start);
1408     EXPECT_EQ(2, runs[0].end);
1409     // Color emoji is specified but it is not available. Use text representation instead.
1410     EXPECT_EQ(kTextEmojiFont, getFontName(runs[0]));
1411 
1412     // U+231B is a emoji default emoji which is available only in ColorEmojiFont.ttf.
1413     // ColorEmojiFont.ttf should be selected.
1414     runs = itemize(collection, "U+231B U+FE0F");
1415     ASSERT_EQ(1U, runs.size());
1416     EXPECT_EQ(0, runs[0].start);
1417     EXPECT_EQ(2, runs[0].end);
1418     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1419 
1420     // U+23E9 is a emoji default emoji which is available in both TextEmojiFont.ttf and
1421     // ColorEmojiFont.ttf. ColorEmojiFont.ttf should be selected.
1422     runs = itemize(collection, "U+23E9 U+FE0F");
1423     ASSERT_EQ(1U, runs.size());
1424     EXPECT_EQ(0, runs[0].start);
1425     EXPECT_EQ(2, runs[0].end);
1426     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1427 
1428     // U+23EA is a emoji default emoji which is not available in either TextEmojiFont.ttf or
1429     // ColorEmojiFont.ttf. No font should be selected.
1430     runs = itemize(collection, "U+23EA U+FE0F");
1431     ASSERT_EQ(1U, runs.size());
1432     EXPECT_EQ(0, runs[0].start);
1433     EXPECT_EQ(2, runs[0].end);
1434     EXPECT_EQ(kNoGlyphFont, getFontName(runs[0]));
1435 
1436     // U+26F9 U+FE0F is specified but ColorTextMixedEmojiFont has a variation sequence U+26F9 U+FE0F
1437     // in its cmap, so ColorTextMixedEmojiFont should be selected instaed of ColorEmojiFont.
1438     runs = itemize(collection, "U+26F9 U+FE0F");
1439     ASSERT_EQ(1U, runs.size());
1440     EXPECT_EQ(0, runs[0].start);
1441     EXPECT_EQ(2, runs[0].end);
1442     EXPECT_EQ(kMixedEmojiFont, getFontName(runs[0]));
1443 }
1444 
TEST(FontCollectionItemizeTest,itemize_emojiSelection_with_skinTone)1445 TEST(FontCollectionItemizeTest, itemize_emojiSelection_with_skinTone) {
1446     auto collection = buildFontCollectionFromXml(kEmojiXmlFile);
1447 
1448     // TextEmoji font is selected since it is listed before ColorEmoji font.
1449     auto runs = itemize(collection, "U+261D");
1450     ASSERT_EQ(1U, runs.size());
1451     EXPECT_EQ(0, runs[0].start);
1452     EXPECT_EQ(1, runs[0].end);
1453     EXPECT_EQ(kTextEmojiFont, getFontName(runs[0]));
1454 
1455     // If skin tone is specified, it should be colored.
1456     runs = itemize(collection, "U+261D U+1F3FD");
1457     ASSERT_EQ(1U, runs.size());
1458     EXPECT_EQ(0, runs[0].start);
1459     EXPECT_EQ(3, runs[0].end);
1460     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1461 
1462     // Still color font is selected if an emoji variation selector is specified.
1463     runs = itemize(collection, "U+261D U+FE0F U+1F3FD");
1464     ASSERT_EQ(1U, runs.size());
1465     EXPECT_EQ(0, runs[0].start);
1466     EXPECT_EQ(4, runs[0].end);
1467     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1468 
1469     // Text font should be selected if a text variation selector is specified and skin tone is
1470     // rendered by itself.
1471     runs = itemize(collection, "U+261D U+FE0E U+1F3FD");
1472     ASSERT_EQ(2U, runs.size());
1473     EXPECT_EQ(0, runs[0].start);
1474     EXPECT_EQ(2, runs[0].end);
1475     EXPECT_EQ(kTextEmojiFont, getFontName(runs[0]));
1476     EXPECT_EQ(2, runs[1].start);
1477     EXPECT_EQ(4, runs[1].end);
1478     EXPECT_EQ(kColorEmojiFont, getFontName(runs[1]));
1479 }
1480 
TEST(FontCollectionItemizeTest,itemize_PrivateUseArea)1481 TEST(FontCollectionItemizeTest, itemize_PrivateUseArea) {
1482     auto collection = buildFontCollectionFromXml(kEmojiXmlFile);
1483 
1484     // Should not set nullptr to the result run. (Issue 26808815)
1485     auto runs = itemize(collection, "U+FEE10");
1486     ASSERT_EQ(1U, runs.size());
1487     EXPECT_EQ(0, runs[0].start);
1488     EXPECT_EQ(2, runs[0].end);
1489     EXPECT_EQ(kNoGlyphFont, getFontName(runs[0]));
1490 
1491     runs = itemize(collection, "U+FEE40 U+FE4C5");
1492     ASSERT_EQ(1U, runs.size());
1493     EXPECT_EQ(0, runs[0].start);
1494     EXPECT_EQ(4, runs[0].end);
1495     EXPECT_EQ(kNoGlyphFont, getFontName(runs[0]));
1496 }
1497 
TEST(FontCollectionItemizeTest,itemize_genderBalancedEmoji)1498 TEST(FontCollectionItemizeTest, itemize_genderBalancedEmoji) {
1499     auto collection = buildFontCollectionFromXml(kEmojiXmlFile);
1500 
1501     auto runs = itemize(collection, "U+1F469 U+200D U+1F373");
1502     ASSERT_EQ(1U, runs.size());
1503     EXPECT_EQ(0, runs[0].start);
1504     EXPECT_EQ(5, runs[0].end);
1505     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1506 
1507     runs = itemize(collection, "U+1F469 U+200D U+2695 U+FE0F");
1508     ASSERT_EQ(1U, runs.size());
1509     EXPECT_EQ(0, runs[0].start);
1510     EXPECT_EQ(5, runs[0].end);
1511     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1512 
1513     runs = itemize(collection, "U+1F469 U+200D U+2695");
1514     ASSERT_EQ(1U, runs.size());
1515     EXPECT_EQ(0, runs[0].start);
1516     EXPECT_EQ(4, runs[0].end);
1517     EXPECT_EQ(kColorEmojiFont, getFontName(runs[0]));
1518 }
1519 
1520 // For b/29585939
TEST(FontCollectionItemizeTest,itemizeShouldKeepOrderForVS)1521 TEST(FontCollectionItemizeTest, itemizeShouldKeepOrderForVS) {
1522     std::shared_ptr<FontFamily> dummyFamily = buildFontFamily(kNoGlyphFont);
1523     std::shared_ptr<FontFamily> familyA = buildFontFamily(kZH_HansFont);
1524     std::shared_ptr<FontFamily> familyB = buildFontFamily(kZH_HansFont);
1525 
1526     std::vector<std::shared_ptr<FontFamily>> families = {dummyFamily, familyA, familyB};
1527     std::vector<std::shared_ptr<FontFamily>> reversedFamilies = {dummyFamily, familyB, familyA};
1528 
1529     std::shared_ptr<FontCollection> collection(FontCollection::create(families));
1530     std::shared_ptr<FontCollection> reversedCollection(FontCollection::create(reversedFamilies));
1531 
1532     // Both fontA/fontB support U+35A8 but don't support U+35A8 U+E0100. The first font should be
1533     // selected.
1534     auto runs = itemize(collection, "U+35A8 U+E0100");
1535     EXPECT_EQ(familyA->getFont(0), runs[0].fakedFont.font.get());
1536 
1537     runs = itemize(reversedCollection, "U+35A8 U+E0100");
1538     EXPECT_EQ(familyB->getFont(0), runs[0].fakedFont.font.get());
1539 }
1540 
1541 // For b/29585939
TEST(FontCollectionItemizeTest,itemizeShouldKeepOrderForVS2)1542 TEST(FontCollectionItemizeTest, itemizeShouldKeepOrderForVS2) {
1543     std::shared_ptr<FontFamily> dummyFamily = buildFontFamily(kNoGlyphFont);
1544     std::shared_ptr<FontFamily> hasCmapFormat14Family = buildFontFamily(kHasCmapFormat14Font);
1545     std::shared_ptr<FontFamily> noCmapFormat14Family = buildFontFamily(kNoCmapFormat14Font);
1546 
1547     std::vector<std::shared_ptr<FontFamily>> families = {dummyFamily, hasCmapFormat14Family,
1548                                                          noCmapFormat14Family};
1549     std::vector<std::shared_ptr<FontFamily>> reversedFamilies = {dummyFamily, noCmapFormat14Family,
1550                                                                  hasCmapFormat14Family};
1551 
1552     std::shared_ptr<FontCollection> collection(FontCollection::create(families));
1553     std::shared_ptr<FontCollection> reversedCollection(FontCollection::create(reversedFamilies));
1554 
1555     // Both hasCmapFormat14Font/noCmapFormat14Font support U+5380 but don't support U+5380 U+E0100.
1556     // The first font should be selected.
1557     auto runs = itemize(collection, "U+5380 U+E0100");
1558     EXPECT_EQ(hasCmapFormat14Family->getFont(0), runs[0].fakedFont.font.get());
1559 
1560     runs = itemize(reversedCollection, "U+5380 U+E0100");
1561     EXPECT_EQ(noCmapFormat14Family->getFont(0), runs[0].fakedFont.font.get());
1562 }
1563 
TEST(FontCollectionItemizeTest,colorEmojiSelectionTest)1564 TEST(FontCollectionItemizeTest, colorEmojiSelectionTest) {
1565     auto dummyFamily = buildFontFamily(kNoGlyphFont);
1566     auto textEmojiFamily = buildFontFamily(kTextEmojiFont, "ja-JP");
1567     auto colorEmojiFamily = buildFontFamily(kColorEmojiFont, "und-Zsye");
1568 
1569     std::vector<std::shared_ptr<FontFamily>> families = {dummyFamily, textEmojiFamily,
1570                                                          colorEmojiFamily};
1571     auto collection = FontCollection::create(families);
1572     // Both textEmojiFamily and colorEmojiFamily supports U+203C and U+23E9.
1573     // U+203C is text default emoji, and U+23E9 is color default emoji.
1574     auto runs = itemize(collection, "U+203C", "en-US,en-Zsym");
1575     EXPECT_EQ(textEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1576     runs = itemize(collection, "U+23E9", "en-US,en-Zsym");
1577     EXPECT_EQ(textEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1578 
1579     runs = itemize(collection, "U+203C", "en-US,en-Zsye");
1580     EXPECT_EQ(colorEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1581     runs = itemize(collection, "U+23E9", "en-US,en-Zsye");
1582     EXPECT_EQ(colorEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1583 
1584     runs = itemize(collection, "U+203C", "ja-Zsym-JP");
1585     EXPECT_EQ(textEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1586     runs = itemize(collection, "U+23E9", "ja-Zsym-JP");
1587     EXPECT_EQ(textEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1588 
1589     runs = itemize(collection, "U+203C", "ja-Zsye-JP");
1590     EXPECT_EQ(colorEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1591     runs = itemize(collection, "U+23E9", "ja-Zsye-JP");
1592     EXPECT_EQ(colorEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1593 
1594     runs = itemize(collection, "U+203C", "ja-JP-u-em-text");
1595     EXPECT_EQ(textEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1596     runs = itemize(collection, "U+23E9", "ja-JP-u-em-text");
1597     EXPECT_EQ(textEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1598 
1599     runs = itemize(collection, "U+203C", "ja-JP-u-em-emoji");
1600     EXPECT_EQ(colorEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1601     runs = itemize(collection, "U+23E9", "ja-JP-u-em-emoji");
1602     EXPECT_EQ(colorEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1603 
1604     runs = itemize(collection, "U+203C", "ja-JP,und-Zsym");
1605     EXPECT_EQ(textEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1606     runs = itemize(collection, "U+23E9", "ja-JP,und-Zsym");
1607     EXPECT_EQ(textEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1608 
1609     runs = itemize(collection, "U+203C", "ja-JP,und-Zsye");
1610     EXPECT_EQ(colorEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1611     runs = itemize(collection, "U+23E9", "ja-JP,und-Zsye");
1612     EXPECT_EQ(colorEmojiFamily->getFont(0), runs[0].fakedFont.font.get());
1613 }
1614 
TEST(FontCollectionItemizeTest,customFallbackTest)1615 TEST(FontCollectionItemizeTest, customFallbackTest) {
1616     auto firstFamily = buildFontFamily(kNoGlyphFont);
1617     auto customFallbackFamily = buildFontFamily(kAsciiFont, "", true /* isCustomFallback */);
1618     auto languageFamily = buildFontFamily(kAsciiFont, "ja-JP");
1619 
1620     std::vector<std::shared_ptr<FontFamily>> families = {firstFamily, customFallbackFamily,
1621                                                          languageFamily};
1622 
1623     auto collection = FontCollection::create(families);
1624 
1625     auto runs = itemize(collection, "'a'", "");
1626     EXPECT_EQ(customFallbackFamily->getFont(0), runs[0].fakedFont.font.get());
1627     runs = itemize(collection, "'a'", "en-US");
1628     EXPECT_EQ(customFallbackFamily->getFont(0), runs[0].fakedFont.font.get());
1629     runs = itemize(collection, "'a'", "ja-JP");
1630     EXPECT_EQ(customFallbackFamily->getFont(0), runs[0].fakedFont.font.get());
1631 }
1632 
1633 struct ItemizeResult {
1634     int start;
1635     int end;
1636     std::string psName;
1637 };
1638 
itemizeEmojiAndFontPostScriptNames(const std::string & txt)1639 std::vector<ItemizeResult> itemizeEmojiAndFontPostScriptNames(const std::string& txt) {
1640     auto firstFamily = buildFontFamily(kAsciiFont);
1641     auto OverrideEmojiFamily = buildFontFamily("OverrideEmoji.ttf", "und-Zsye");
1642     auto emojiBaseFamily = buildFontFamily("EmojiBase.ttf", "und-Zsye");
1643 
1644     std::vector<std::shared_ptr<FontFamily>> families = {firstFamily, OverrideEmojiFamily,
1645                                                          emojiBaseFamily};
1646 
1647     auto collection = FontCollection::create(families);
1648     auto runs = itemize(collection, txt.c_str());
1649 
1650     std::vector<ItemizeResult> out;
1651     for (const auto& run : runs) {
1652         auto psName = FontFileParser(run.fakedFont.hbFont()).getPostScriptName().value();
1653         out.push_back({run.start, run.end, psName});
1654     }
1655     return out;
1656 }
1657 
itemizeEmojiAndFontPostScriptName(const std::string & txt)1658 std::string itemizeEmojiAndFontPostScriptName(const std::string& txt) {
1659     auto results = itemizeEmojiAndFontPostScriptNames(txt);
1660     EXPECT_EQ(1u, results.size());
1661     return results[0].psName;
1662 }
1663 
TEST(FontCollectionItemizeTest,emojiFallback)1664 TEST(FontCollectionItemizeTest, emojiFallback) {
1665     // OverrideEmojiFont supports U+1F9B0, U+1F3FB and U+1F9B0 U+1F3FB sequence.
1666     // Use Override font.
1667     EXPECT_EQ("OverrideEmojiFont", itemizeEmojiAndFontPostScriptName("U+1F9B0"));
1668     EXPECT_EQ("OverrideEmojiFont", itemizeEmojiAndFontPostScriptName("U+1F9B0 U+1F3FB"));
1669     EXPECT_EQ("OverrideEmojiFont", itemizeEmojiAndFontPostScriptName("U+1F9B0 U+FE0F U+1F3FB"));
1670 
1671     // OverrideEmojiFont doesn't suppot U+1F9B6 and U+1F3FC.
1672     EXPECT_EQ("EmojiBaseFont", itemizeEmojiAndFontPostScriptName("U+1F9B6"));
1673     EXPECT_EQ("EmojiBaseFont", itemizeEmojiAndFontPostScriptName("U+1F9B6 U+1F3FC"));
1674     EXPECT_EQ("EmojiBaseFont", itemizeEmojiAndFontPostScriptName("U+1F9B6 U+FE0F U+1F3FC"));
1675 
1676     // OverrideEmojiFont support U+1F9B1, U+1F3FB but doesn't support the sequence U+1F9B1 U+1F3FB.
1677     EXPECT_EQ("OverrideEmojiFont", itemizeEmojiAndFontPostScriptName("U+1F9B1"));
1678     EXPECT_EQ("OverrideEmojiFont", itemizeEmojiAndFontPostScriptName("U+1F3FB"));
1679     EXPECT_EQ("EmojiBaseFont", itemizeEmojiAndFontPostScriptName("U+1F9B1 U+1F3FB"));
1680     EXPECT_EQ("EmojiBaseFont", itemizeEmojiAndFontPostScriptName("U+1F9B1 U+FE0F U+1F3FB"));
1681 
1682     // Find the longest sequence if two sequences are supported.
1683     EXPECT_EQ("OverrideEmojiFont", itemizeEmojiAndFontPostScriptName("U+1F9B2 U+200D U+1F9B3"));
1684     EXPECT_EQ("EmojiBaseFont",
1685               itemizeEmojiAndFontPostScriptName("U+1F9B2 U+200D U+1F9B3 U+200D U+1F9B4"));
1686 }
1687 
TEST(FontCollectionItemizeTest,customEmojiFallback)1688 TEST(FontCollectionItemizeTest, customEmojiFallback) {
1689     auto results = itemizeEmojiAndFontPostScriptNames("U+1F9B6 U+1F9B0");
1690     EXPECT_EQ(0, results[0].start);
1691     EXPECT_EQ(2, results[0].end);
1692     EXPECT_EQ("EmojiBaseFont", results[0].psName);
1693 
1694     EXPECT_EQ(2, results[1].start);
1695     EXPECT_EQ(4, results[1].end);
1696     EXPECT_EQ("OverrideEmojiFont", results[1].psName);
1697 
1698     results = itemizeEmojiAndFontPostScriptNames("U+1F9B0 U+1F9B6");
1699     EXPECT_EQ(0, results[0].start);
1700     EXPECT_EQ(2, results[0].end);
1701     EXPECT_EQ("OverrideEmojiFont", results[0].psName);
1702 
1703     EXPECT_EQ(2, results[1].start);
1704     EXPECT_EQ(4, results[1].end);
1705     EXPECT_EQ("EmojiBaseFont", results[1].psName);
1706 }
1707 
TEST(FontCollectionItemizeTest,customEmojiFallback_modifier)1708 TEST(FontCollectionItemizeTest, customEmojiFallback_modifier) {
1709     auto results = itemizeEmojiAndFontPostScriptNames("U+1F9B0 U+1F3FC U+1F9B0 U+1F3FB");
1710     EXPECT_EQ(0, results[0].start);
1711     EXPECT_EQ(4, results[0].end);
1712     EXPECT_EQ("EmojiBaseFont", results[0].psName);
1713 
1714     EXPECT_EQ(4, results[1].start);
1715     EXPECT_EQ(8, results[1].end);
1716     EXPECT_EQ("OverrideEmojiFont", results[1].psName);
1717 
1718     results = itemizeEmojiAndFontPostScriptNames("U+1F9B0 U+1F3FB U+1F9B0 U+1F3FC");
1719     EXPECT_EQ(0, results[0].start);
1720     EXPECT_EQ(4, results[0].end);
1721     EXPECT_EQ("OverrideEmojiFont", results[0].psName);
1722 
1723     EXPECT_EQ(4, results[1].start);
1724     EXPECT_EQ(8, results[1].end);
1725     EXPECT_EQ("EmojiBaseFont", results[1].psName);
1726 }
1727 
TEST(FontCollectionItemizeTest,customEmojiFallback_zwj)1728 TEST(FontCollectionItemizeTest, customEmojiFallback_zwj) {
1729     auto results = itemizeEmojiAndFontPostScriptNames(
1730             "U+1F9B4 U+200D U+1F9B3 U+200D U+1F9B4 "
1731             "U+1F9B3 U+200D U+1F9B3 U+200D U+1F9B4 ");
1732     EXPECT_EQ(0, results[0].start);
1733     EXPECT_EQ(8, results[0].end);
1734     EXPECT_EQ("EmojiBaseFont", results[0].psName);
1735 
1736     EXPECT_EQ(8, results[1].start);
1737     EXPECT_EQ(16, results[1].end);
1738     EXPECT_EQ("OverrideEmojiFont", results[1].psName);
1739 
1740     results = itemizeEmojiAndFontPostScriptNames(
1741             "U+1F9B3 U+200D U+1F9B3 U+200D U+1F9B4 "
1742             "U+1F9B4 U+200D U+1F9B3 U+200D U+1F9B4 ");
1743     EXPECT_EQ(0, results[0].start);
1744     EXPECT_EQ(8, results[0].end);
1745     EXPECT_EQ("OverrideEmojiFont", results[0].psName);
1746 
1747     EXPECT_EQ(8, results[1].start);
1748     EXPECT_EQ(16, results[1].end);
1749     EXPECT_EQ("EmojiBaseFont", results[1].psName);
1750 }
1751 
TEST(FontCollectionItemizeTest,customEmojiFallback_tagSequence)1752 TEST(FontCollectionItemizeTest, customEmojiFallback_tagSequence) {
1753     auto results = itemizeEmojiAndFontPostScriptNames(
1754             "U+1F9BA U+E0003 U+E0004 U+E007F "
1755             "U+1F9BA U+E0001 U+E0002 U+E007F");
1756     EXPECT_EQ(0, results[0].start);
1757     EXPECT_EQ(8, results[0].end);
1758     EXPECT_EQ("EmojiBaseFont", results[0].psName);
1759 
1760     EXPECT_EQ(8, results[1].start);
1761     EXPECT_EQ(16, results[1].end);
1762     EXPECT_EQ("OverrideEmojiFont", results[1].psName);
1763 
1764     results = itemizeEmojiAndFontPostScriptNames(
1765             "U+1F9BA U+E0001 U+E0002 U+E007F "
1766             "U+1F9BA U+E0003 U+E0004 U+E007F");
1767     EXPECT_EQ(0, results[0].start);
1768     EXPECT_EQ(8, results[0].end);
1769     EXPECT_EQ("OverrideEmojiFont", results[0].psName);
1770 
1771     EXPECT_EQ(8, results[1].start);
1772     EXPECT_EQ(16, results[1].end);
1773     EXPECT_EQ("EmojiBaseFont", results[1].psName);
1774 }
1775 
TEST(FontCollectionItemizeTest,emojiFlagFallback)1776 TEST(FontCollectionItemizeTest, emojiFlagFallback) {
1777     // If the OverrideEmojiFont supports U+1F1E6 U+1F1E6, use that font.
1778     EXPECT_EQ("OverrideEmojiFont", itemizeEmojiAndFontPostScriptName("U+1F1E6 U+1F1E6"));
1779 
1780     // Even if the OverrideEmojiFont directs to .notdef (i.e. Tofu glyph) for the sequence, use it.
1781     EXPECT_EQ("OverrideEmojiFont", itemizeEmojiAndFontPostScriptName("U+1F1E6 U+1F1E7"));
1782 }
1783 
1784 }  // namespace minikin
1785