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