From 706858646a102c22631e02610e21f929aeabd6e0 Mon Sep 17 00:00:00 2001 From: Sascha Brawer Date: Sat, 11 Feb 2017 16:48:27 +0100 Subject: [PATCH] Preserve ordering of glyph alternates when round-tripping through TTX Also fixes a bug where glyph alternates in MTI feature files were wrongly sorted by glyph name. After this change, the output is using the same ordering as in the input MTI feature file. Fixes https://github.com/fonttools/fonttools/issues/833. --- Lib/fontTools/feaLib/builder.py | 2 + Lib/fontTools/ttLib/tables/otTables.py | 4 +- Tests/mtiLib/data/mti/gsubalternate.ttx.GSUB | 124 +++++++++---------- Tests/ttLib/tables/otTables_test.py | 16 +-- 4 files changed, 74 insertions(+), 72 deletions(-) diff --git a/Lib/fontTools/feaLib/builder.py b/Lib/fontTools/feaLib/builder.py index 7f7250fd3..7bed9a180 100644 --- a/Lib/fontTools/feaLib/builder.py +++ b/Lib/fontTools/feaLib/builder.py @@ -159,6 +159,8 @@ class Builder(object): alternates.setdefault(glyph, set()).update(alts) single = {glyph: list(repl)[0] for glyph, repl in alternates.items() if len(repl) == 1} + # TODO: Figure out the glyph alternate ordering used by makeotf. + # https://github.com/fonttools/fonttools/issues/836 multi = {glyph: sorted(repl, key=self.font.getGlyphID) for glyph, repl in alternates.items() if len(repl) > 1} diff --git a/Lib/fontTools/ttLib/tables/otTables.py b/Lib/fontTools/ttLib/tables/otTables.py index 5bebae809..c995b744a 100644 --- a/Lib/fontTools/ttLib/tables/otTables.py +++ b/Lib/fontTools/ttLib/tables/otTables.py @@ -536,7 +536,7 @@ class AlternateSubst(FormatSwitchingBaseTable): cov.glyphs = [ item[1] for item in items] alternates = [] setList = [ item[-1] for item in items] - for set in setList: + for set in setList: alts = AlternateSet() alts.Alternate = set alternates.append(alts) @@ -553,7 +553,7 @@ class AlternateSubst(FormatSwitchingBaseTable): for glyphName, alternates in items: xmlWriter.begintag("AlternateSet", glyph=glyphName) xmlWriter.newline() - for alt in sorted(alternates): + for alt in alternates: xmlWriter.simpletag("Alternate", glyph=alt) xmlWriter.newline() xmlWriter.endtag("AlternateSet") diff --git a/Tests/mtiLib/data/mti/gsubalternate.ttx.GSUB b/Tests/mtiLib/data/mti/gsubalternate.ttx.GSUB index 80c035d3d..41843252b 100644 --- a/Tests/mtiLib/data/mti/gsubalternate.ttx.GSUB +++ b/Tests/mtiLib/data/mti/gsubalternate.ttx.GSUB @@ -9,34 +9,34 @@ - - - - - + - + + + + + - - - - - + - + + + + + - - - - - + - + + + + + @@ -47,77 +47,77 @@ - - - - - + - + + + + + - - - - - + + + + + + - - - - - - + - + + + + + - - - - - + - + + + + + - - - - - + - + + + + + - - - - - - + - + + + + + + - - - - - - + - + + + + + + diff --git a/Tests/ttLib/tables/otTables_test.py b/Tests/ttLib/tables/otTables_test.py index 30dc441ae..dc61e8cfb 100644 --- a/Tests/ttLib/tables/otTables_test.py +++ b/Tests/ttLib/tables/otTables_test.py @@ -308,13 +308,13 @@ class AlternateSubstTest(unittest.TestCase): rawTable = { "Coverage": makeCoverage(["G", "Z"]), "AlternateSet": [ - self.makeAlternateSet("G.alt1 G.alt2"), + self.makeAlternateSet("G.alt2 G.alt1"), self.makeAlternateSet("Z.fina") ] } table.postRead(rawTable, self.font) self.assertEqual(table.alternates, { - "G": ["G.alt1", "G.alt2"], + "G": ["G.alt2", "G.alt1"], "Z": ["Z.fina"] }) @@ -325,25 +325,25 @@ class AlternateSubstTest(unittest.TestCase): def test_preWrite_format1(self): table = otTables.AlternateSubst() - table.alternates = {"G": ["G.alt1", "G.alt2"], "Z": ["Z.fina"]} + table.alternates = {"G": ["G.alt2", "G.alt1"], "Z": ["Z.fina"]} rawTable = table.preWrite(self.font) self.assertEqual(table.Format, 1) self.assertEqual(rawTable["Coverage"].glyphs, ["G", "Z"]) [g, z] = rawTable["AlternateSet"] self.assertIsInstance(g, otTables.AlternateSet) - self.assertEqual(g.Alternate, ["G.alt1", "G.alt2"]) + self.assertEqual(g.Alternate, ["G.alt2", "G.alt1"]) self.assertIsInstance(z, otTables.AlternateSet) self.assertEqual(z.Alternate, ["Z.fina"]) def test_toXML2(self): writer = XMLWriter(StringIO()) table = otTables.AlternateSubst() - table.alternates = {"G": ["G.alt1", "G.alt2"], "Z": ["Z.fina"]} + table.alternates = {"G": ["G.alt2", "G.alt1"], "Z": ["Z.fina"]} table.toXML2(writer, self.font) self.assertEqual(writer.file.getvalue().splitlines()[1:], [ '', - ' ', ' ', + ' ', '', '', ' ', @@ -354,15 +354,15 @@ class AlternateSubstTest(unittest.TestCase): table = otTables.AlternateSubst() for name, attrs, content in parseXML( '' - ' ' ' ' + ' ' '' '' ' ' ''): table.fromXML(name, attrs, content, self.font) self.assertEqual(table.alternates, { - "G": ["G.alt1", "G.alt2"], + "G": ["G.alt2", "G.alt1"], "Z": ["Z.fina"] })