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