Repository: fonttools/fonttools

Issue:
feaLib does not sort name table
Although the name table is sorted when it is compiled, if it is written out without being compiled (such as to TTX) then the entries will not be in the order expected by the spec.

In practice, I suspect this is only really an issue in the feaLib test suite, where there are [several](https://github.com/fonttools/fonttools/blob/5a0dc4bc8dfaa0c7da146cf902395f748b3cebe5/Tests/feaLib/data/spec8d.ttx#L5) [cases](https://github.com/fonttools/fonttools/blob/main/Tests/feaLib/data/spec8c.ttx#L11) where the expected TTX has name entires in an order that is not valid per the spec.

This has come up for me because I am reusing the (very nice!) feaLib test suite for the development of a new feature compiler, and am running into these differences.

This is not a huge problem for me; I have a mechanism for indicating that certain diffs are 'acceptable', so I can work around this reasonably easily. I do think that it would be nice if the TTX in these cases did reflect the expected order in the compiled table.


Discussion:

Resolving patch:
diff --git a/Lib/fontTools/feaLib/builder.py b/Lib/fontTools/feaLib/builder.py
--- a/Lib/fontTools/feaLib/builder.py
+++ b/Lib/fontTools/feaLib/builder.py
@@ -446,6 +446,7 @@ def build_name(self):
                         assert self.cv_parameters_ids_[tag] is not None
                     nameID = self.cv_parameters_ids_[tag]
             table.setName(string, nameID, platformID, platEncID, langID)
+        table.names.sort()
 
     def build_OS_2(self):
         if not self.os2_:


Test patch:
diff --git a/Tests/feaLib/data/name.ttx b/Tests/feaLib/data/name.ttx
--- a/Tests/feaLib/data/name.ttx
+++ b/Tests/feaLib/data/name.ttx
@@ -2,6 +2,15 @@
 <ttFont>
 
   <name>
+    <namerecord nameID="8" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Test8
+    </namerecord>
+    <namerecord nameID="10" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Test10
+    </namerecord>
+    <namerecord nameID="11" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Test11
+    </namerecord>
     <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
       Test1
     </namerecord>
@@ -23,18 +32,9 @@
     <namerecord nameID="7" platformID="3" platEncID="1" langID="0x409">
       Test7
     </namerecord>
-    <namerecord nameID="8" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      Test8
-    </namerecord>
     <namerecord nameID="9" platformID="3" platEncID="1" langID="0x409">
       Test9
     </namerecord>
-    <namerecord nameID="10" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      Test10
-    </namerecord>
-    <namerecord nameID="11" platformID="1" platEncID="0" langID="0x0" unicode="True">
-      Test11
-    </namerecord>
   </name>
 
 </ttFont>
diff --git a/Tests/feaLib/data/spec8b.ttx b/Tests/feaLib/data/spec8b.ttx
--- a/Tests/feaLib/data/spec8b.ttx
+++ b/Tests/feaLib/data/spec8b.ttx
@@ -2,15 +2,15 @@
 <ttFont>
 
   <name>
-    <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
-      Win MinionPro Size Name
-    </namerecord>
     <namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
       Mac MinionPro Size Name
     </namerecord>
     <namerecord nameID="256" platformID="1" platEncID="0" langID="0x5" unicode="True">
       Mac MinionPro Size Name
     </namerecord>
+    <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
+      Win MinionPro Size Name
+    </namerecord>
   </name>
 
   <GPOS>
@@ -37,7 +37,7 @@
           <FeatureParamsSize>
             <DesignSize value="10.0"/>
             <SubfamilyID value="3"/>
-            <SubfamilyNameID value="256"/>  <!-- Win MinionPro Size Name -->
+            <SubfamilyNameID value="256"/>  <!-- Mac MinionPro Size Name -->
             <RangeStart value="8.0"/>
             <RangeEnd value="13.9"/>
           </FeatureParamsSize>
diff --git a/Tests/feaLib/data/spec8c.ttx b/Tests/feaLib/data/spec8c.ttx
--- a/Tests/feaLib/data/spec8c.ttx
+++ b/Tests/feaLib/data/spec8c.ttx
@@ -2,18 +2,18 @@
 <ttFont>
 
   <name>
-    <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
-      Feature description for MS Platform, script Unicode, language English
-    </namerecord>
-    <namerecord nameID="256" platformID="3" platEncID="1" langID="0x411">
-      Feature description for MS Platform, script Unicode, language Japanese
-    </namerecord>
     <namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
       Feature description for Apple Platform, script Roman, language unspecified
     </namerecord>
     <namerecord nameID="256" platformID="1" platEncID="1" langID="0xc" unicode="True">
       Feature description for Apple Platform, script Japanese, language Japanese
     </namerecord>
+    <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
+      Feature description for MS Platform, script Unicode, language English
+    </namerecord>
+    <namerecord nameID="256" platformID="3" platEncID="1" langID="0x411">
+      Feature description for MS Platform, script Unicode, language Japanese
+    </namerecord>
   </name>
 
   <GSUB>
@@ -39,7 +39,7 @@
         <Feature>
           <FeatureParamsStylisticSet>
             <Version value="0"/>
-            <UINameID value="256"/>  <!-- Feature description for MS Platform, script Unicode, language English -->
+            <UINameID value="256"/>  <!-- Feature description for Apple Platform, script Roman, language unspecified -->
           </FeatureParamsStylisticSet>
           <!-- LookupCount=1 -->
           <LookupListIndex index="0" value="0"/>
diff --git a/Tests/feaLib/data/spec8d.ttx b/Tests/feaLib/data/spec8d.ttx
--- a/Tests/feaLib/data/spec8d.ttx
+++ b/Tests/feaLib/data/spec8d.ttx
@@ -2,34 +2,34 @@
 <ttFont>
 
   <name>
-    <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
-      uilabel simple a
-    </namerecord>
     <namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
       uilabel simple a
     </namerecord>
-    <namerecord nameID="257" platformID="3" platEncID="1" langID="0x409">
-      tool tip simple a
-    </namerecord>
     <namerecord nameID="257" platformID="1" platEncID="0" langID="0x0" unicode="True">
       tool tip simple a
     </namerecord>
-    <namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
-      sample text simple a
-    </namerecord>
     <namerecord nameID="258" platformID="1" platEncID="0" langID="0x0" unicode="True">
       sample text simple a
     </namerecord>
-    <namerecord nameID="259" platformID="3" platEncID="1" langID="0x409">
-      param1 text simple a
-    </namerecord>
     <namerecord nameID="259" platformID="1" platEncID="0" langID="0x0" unicode="True">
       param1 text simple a
     </namerecord>
-    <namerecord nameID="260" platformID="3" platEncID="1" langID="0x409">
+    <namerecord nameID="260" platformID="1" platEncID="0" langID="0x0" unicode="True">
       param2 text simple a
     </namerecord>
-    <namerecord nameID="260" platformID="1" platEncID="0" langID="0x0" unicode="True">
+    <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
+      uilabel simple a
+    </namerecord>
+    <namerecord nameID="257" platformID="3" platEncID="1" langID="0x409">
+      tool tip simple a
+    </namerecord>
+    <namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
+      sample text simple a
+    </namerecord>
+    <namerecord nameID="259" platformID="3" platEncID="1" langID="0x409">
+      param1 text simple a
+    </namerecord>
+    <namerecord nameID="260" platformID="3" platEncID="1" langID="0x409">
       param2 text simple a
     </namerecord>
   </name>
diff --git a/Tests/feaLib/data/spec9e.ttx b/Tests/feaLib/data/spec9e.ttx
--- a/Tests/feaLib/data/spec9e.ttx
+++ b/Tests/feaLib/data/spec9e.ttx
@@ -2,10 +2,10 @@
 <ttFont>
 
   <name>
-    <namerecord nameID="9" platformID="3" platEncID="1" langID="0x409">
+    <namerecord nameID="9" platformID="1" platEncID="0" langID="0x0" unicode="True">
       Joachim Müller-Lancé
     </namerecord>
-    <namerecord nameID="9" platformID="1" platEncID="0" langID="0x0" unicode="True">
+    <namerecord nameID="9" platformID="3" platEncID="1" langID="0x409">
       Joachim Müller-Lancé
     </namerecord>
   </name>