Extract flag font from NotoColorEmoji

Bug: 188926991
Bug: 188779144
Test: m fontchain_lint
Change-Id: Ie807e31abb407f5b58665d4d2941bc75186d5c42
Merged-In: Ie807e31abb407f5b58665d4d2941bc75186d5c42
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index 45b63e0..652622d 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -304,11 +304,6 @@
         forwardDelete(state, 0);
         state.assertEquals("|");
 
-        // Regional indicator symbol + COMBINING ENCLOSING KEYCAP
-        state.setByString("| U+1F1FA U+20E3");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
         // COMBINING ENCLOSING KEYCAP + emoji modifier
         state.setByString("| '1' U+20E3 U+1F3FB");
         forwardDelete(state, 0);
@@ -408,11 +403,6 @@
         // forwardDelete(state, 0);
         // state.assertEquals("|");
 
-        // Regional indicator symbol + emoji modifier
-        state.setByString("| U+1F1FA U+1F3FB");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
         // Emoji modifier + regional indicator symbol
         state.setByString("| U+1F466 U+1F3FB U+1F1FA");
         forwardDelete(state, 0);
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index d757a8c..4ae0fc4 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -1331,6 +1331,9 @@
     <family lang="und-Zsye">
         <font weight="400" style="normal">NotoColorEmoji.ttf</font>
     </family>
+    <family lang="und-Zsye">
+        <font weight="400" style="normal">NotoColorEmojiFlags.ttf</font>
+    </family>
     <family lang="und-Zsym">
         <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted2.ttf</font>
     </family>
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index 1266cce..e181c62 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -117,13 +117,14 @@
     reverse_cmap = {glyph: code for code, glyph in emoji_map.items() if not contains_pua(code) }
 
     # Add variation sequences
-    vs_dict = get_variation_sequences_cmap(font).uvsDict
-    for vs in vs_dict:
-        for base, glyph in vs_dict[vs]:
-            if glyph is None:
-                emoji_map[(base, vs)] = emoji_map[base]
-            else:
-                emoji_map[(base, vs)] = glyph
+    vs_cmap = get_variation_sequences_cmap(font)
+    if vs_cmap:
+        for vs in vs_cmap.uvsDict:
+            for base, glyph in vs_cmap.uvsDict[vs]:
+                if glyph is None:
+                    emoji_map[(base, vs)] = emoji_map[base]
+                else:
+                    emoji_map[(base, vs)] = glyph
 
     # Add GSUB rules
     ttfont = open_font(font)
@@ -310,17 +311,12 @@
 
 
 def check_emoji_coverage(all_emoji, equivalent_emoji):
-    emoji_font = get_emoji_font()
-    check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji)
+    emoji_fonts = get_emoji_fonts()
+    check_emoji_font_coverage(emoji_fonts, all_emoji, equivalent_emoji)
 
 
-def get_emoji_font():
-    emoji_fonts = [
-        record.font for record in _all_fonts
-        if 'Zsye' in record.scripts]
-    assert len(emoji_fonts) == 1, 'There are %d emoji fonts.' % len(emoji_fonts)
-    return emoji_fonts[0]
-
+def get_emoji_fonts():
+    return [ record.font for record in _all_fonts if 'Zsye' in record.scripts ]
 
 def is_pua(x):
     return 0xE000 <= x <= 0xF8FF or 0xF0000 <= x <= 0xFFFFD or 0x100000 <= x <= 0x10FFFD
@@ -331,58 +327,71 @@
   else:
     return is_pua(sequence)
 
+def get_psname(ttf):
+    return str(next(x for x in ttf['name'].names
+        if x.platformID == 3 and x.platEncID == 1 and x.nameID == 6))
 
 def check_emoji_compat():
-    ttf = open_font(get_emoji_font())
-    meta = ttf['meta']
-    assert meta, 'Compat font must have meta table'
-    assert 'Emji' in meta.data, 'meta table should have \'Emji\' data.'
+    for emoji_font in get_emoji_fonts():
+        ttf = open_font(emoji_font)
+        psname = get_psname(ttf)
 
-def check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji):
-    coverage = get_emoji_map(emoji_font)
+        # If the font file is NotoColorEmoji, it must be Compat font.
+        if psname == 'NotoColorEmoji':
+            meta = ttf['meta']
+            assert meta, 'Compat font must have meta table'
+            assert 'Emji' in meta.data, 'meta table should have \'Emji\' data.'
+
+def check_emoji_font_coverage(emoji_fonts, all_emoji, equivalent_emoji):
+    coverages = []
+    for emoji_font in emoji_fonts:
+        coverages.append(get_emoji_map(emoji_font))
 
     errors = []
 
     for sequence in all_emoji:
-        if not sequence in coverage:
-          errors.append('%s is not supported in the emoji font.' % printable(sequence))
+        if all([sequence not in coverage for coverage in coverages]):
+            errors.append('%s is not supported in the emoji font.' % printable(sequence))
 
-    for sequence in coverage:
-        if sequence in {0x0000, 0x000D, 0x0020}:
-            # The font needs to support a few extra characters, which is OK
-            continue
+    for coverage in coverages:
+        for sequence in coverage:
+            if sequence in {0x0000, 0x000D, 0x0020}:
+                # The font needs to support a few extra characters, which is OK
+                continue
 
-        if contains_pua(sequence):
-            # The font needs to have some PUA for EmojiCompat library.
-            continue
+            if contains_pua(sequence):
+                # The font needs to have some PUA for EmojiCompat library.
+                continue
 
-        if sequence not in all_emoji:
-          errors.append('%s support unexpected in the emoji font.' % printable(sequence))
+            if sequence not in all_emoji:
+                errors.append('%s support unexpected in the emoji font.' % printable(sequence))
 
     for first, second in equivalent_emoji.items():
-        if first not in coverage or second not in coverage:
-            continue  # sequence will be reported missing
-        if coverage[first] != coverage[second]:
-            errors.append('%s and %s should map to the same glyph.' % (
-                printable(first),
-                printable(second)))
+        for coverage in coverages:
+            if first not in coverage or second not in coverage:
+                continue  # sequence will be reported missing
+            if coverage[first] != coverage[second]:
+                errors.append('%s and %s should map to the same glyph.' % (
+                    printable(first),
+                    printable(second)))
 
-    for glyph in set(coverage.values()):
-        maps_to_glyph = [
-            seq for seq in coverage if coverage[seq] == glyph and not contains_pua(seq) ]
-        if len(maps_to_glyph) > 1:
-            # There are more than one sequences mapping to the same glyph. We
-            # need to make sure they were expected to be equivalent.
-            equivalent_seqs = set()
-            for seq in maps_to_glyph:
-                equivalent_seq = seq
-                while equivalent_seq in equivalent_emoji:
-                    equivalent_seq = equivalent_emoji[equivalent_seq]
-                equivalent_seqs.add(equivalent_seq)
-            if len(equivalent_seqs) != 1:
-                errors.append('The sequences %s should not result in the same glyph %s' % (
-                    printable(equivalent_seqs),
-                    glyph))
+    for coverage in coverages:
+        for glyph in set(coverage.values()):
+            maps_to_glyph = [
+                seq for seq in coverage if coverage[seq] == glyph and not contains_pua(seq) ]
+            if len(maps_to_glyph) > 1:
+                # There are more than one sequences mapping to the same glyph. We
+                # need to make sure they were expected to be equivalent.
+                equivalent_seqs = set()
+                for seq in maps_to_glyph:
+                    equivalent_seq = seq
+                    while equivalent_seq in equivalent_emoji:
+                        equivalent_seq = equivalent_emoji[equivalent_seq]
+                    equivalent_seqs.add(equivalent_seq)
+                if len(equivalent_seqs) != 1:
+                    errors.append('The sequences %s should not result in the same glyph %s' % (
+                        printable(equivalent_seqs),
+                        glyph))
 
     assert not errors, '%d emoji font errors:\n%s\n%d emoji font coverage errors' % (len(errors), '\n'.join(errors), len(errors))