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