Add FontConfig.Font.getPostScriptName API

Bug: 184003133
Bug: 185508395
Test: atest FontManagerTest#fontManager_PostScriptName
Change-Id: Ie44e0d500c61b37035a0b39039891da13cd6a5ce
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index f0b7595..1d308df 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -4,6 +4,7 @@
 import copy
 import glob
 from os import path
+import re
 import sys
 from xml.etree import ElementTree
 
@@ -199,8 +200,9 @@
 
 
 class FontRecord(object):
-    def __init__(self, name, scripts, variant, weight, style, fallback_for, font):
+    def __init__(self, name, psName, scripts, variant, weight, style, fallback_for, font):
         self.name = name
+        self.psName = psName
         self.scripts = scripts
         self.variant = variant
         self.weight = weight
@@ -236,6 +238,7 @@
             assert variant in {None, 'elegant', 'compact'}, (
                 'Unexpected value for variant: %s' % variant)
 
+    trim_re = re.compile(r"^[ \n\r\t]*(.+)[ \n\r\t]*$")
     for family in families:
         name = family.get('name')
         variant = family.get('variant')
@@ -251,6 +254,10 @@
             assert child.tag == 'font', (
                 'Unknown tag <%s>' % child.tag)
             font_file = child.text.rstrip()
+
+            m = trim_re.match(font_file)
+            font_file = m.group(1)
+
             weight = int(child.get('weight'))
             assert weight % 100 == 0, (
                 'Font weight "%d" is not a multiple of 100.' % weight)
@@ -270,11 +277,12 @@
             if index:
                 index = int(index)
 
-            if not path.exists(path.join(_fonts_dir, font_file)):
+            if not path.exists(path.join(_fonts_dir, m.group(1))):
                 continue # Missing font is a valid case. Just ignore the missing font files.
 
             record = FontRecord(
                 name,
+                child.get('postScriptName'),
                 frozenset(scripts),
                 variant,
                 weight,
@@ -664,6 +672,37 @@
                 break
             assert_font_supports_none_of_chars(record.font, cjk_punctuation, name)
 
+def getPostScriptName(font):
+  font_file, index = font
+  font_path = path.join(_fonts_dir, font_file)
+  if index is not None:
+      # Use the first font file in the collection for resolving post script name.
+      ttf = ttLib.TTFont(font_path, fontNumber=0)
+  else:
+      ttf = ttLib.TTFont(font_path)
+
+  nameTable = ttf['name']
+  for name in nameTable.names:
+      if (name.nameID == 6 and name.platformID == 3 and name.platEncID == 1
+          and name.langID == 0x0409):
+          return str(name)
+
+def check_canonical_name():
+    for record in _all_fonts:
+        file_name, index = record.font
+
+        psName = getPostScriptName(record.font)
+        if record.psName:
+            # If fonts element has postScriptName attribute, it should match with the PostScript
+            # name in the name table.
+            assert psName == record.psName, ('postScriptName attribute %s should match with %s' % (
+                record.psName, psName))
+        else:
+            # If fonts element doesn't have postScriptName attribute, the file name should match
+            # with the PostScript name in the name table.
+            assert psName == file_name[:-4], ('file name %s should match with %s' % (
+                file_name, psName))
+
 
 def main():
     global _fonts_dir
@@ -682,6 +721,8 @@
 
     check_cjk_punctuation()
 
+    check_canonical_name()
+
     check_emoji = sys.argv[2]
     if check_emoji == 'true':
         ucd_path = sys.argv[3]