diff options
Diffstat (limited to 'Lib/fontTools/varLib/merger.py')
-rw-r--r-- | Lib/fontTools/varLib/merger.py | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/Lib/fontTools/varLib/merger.py b/Lib/fontTools/varLib/merger.py index b4b17059..cd16ace4 100644 --- a/Lib/fontTools/varLib/merger.py +++ b/Lib/fontTools/varLib/merger.py @@ -2,6 +2,8 @@ Merge OpenType Layout tables (GDEF / GPOS / GSUB). """ from __future__ import print_function, division, absolute_import +import copy +from operator import ior from fontTools.misc.py23 import * from fontTools.misc.fixedTools import otRound from fontTools.misc import classifyTools @@ -12,6 +14,7 @@ from fontTools.varLib import builder, models, varStore from fontTools.varLib.models import nonNone, allNone, allEqual, allEqualTo from fontTools.varLib.varStore import VarStoreInstancer from functools import reduce +from fontTools.otlLib.builder import buildSinglePos class Merger(object): @@ -455,7 +458,7 @@ def _PairPosFormat2_align_matrices(self, lst, font, transparent=False): exemplarGlyph = next(iter(classSet)) klass = classDef2.get(exemplarGlyph, 0) rec2 = oldClass2Records[klass] - class2Records.append(rec2) + class2Records.append(copy.deepcopy(rec2)) class1Records.append(rec1new) new_matrices.append(class1Records) matrices = new_matrices @@ -726,6 +729,30 @@ def _Lookup_PairPos_subtables_canonicalize(lst, font): return lst +def _Lookup_SinglePos_subtables_flatten(lst, font, min_inclusive_rec_format): + glyphs, _ = _merge_GlyphOrders(font, + [v.Coverage.glyphs for v in lst], None) + num_glyphs = len(glyphs) + new = ot.SinglePos() + new.Format = 2 + new.ValueFormat = min_inclusive_rec_format + new.Coverage = ot.Coverage() + new.Coverage.glyphs = glyphs + new.ValueCount = num_glyphs + new.Value = [None] * num_glyphs + for singlePos in lst: + if singlePos.Format == 1: + val_rec = singlePos.Value + for gname in singlePos.Coverage.glyphs: + i = glyphs.index(gname) + new.Value[i] = copy.deepcopy(val_rec) + elif singlePos.Format == 2: + for j, gname in enumerate(singlePos.Coverage.glyphs): + val_rec = singlePos.Value[j] + i = glyphs.index(gname) + new.Value[i] = copy.deepcopy(val_rec) + return [new] + @AligningMerger.merger(ot.Lookup) def merge(merger, self, lst): subtables = merger.lookup_subtables = [l.SubTable for l in lst] @@ -745,12 +772,28 @@ def merge(merger, self, lst): isPairPos = self.SubTable and isinstance(self.SubTable[0], ot.PairPos) if isPairPos: - # AFDKO and feaLib sometimes generate two Format1 subtables instead of one. # Merge those before continuing. # https://github.com/fonttools/fonttools/issues/719 self.SubTable = _Lookup_PairPos_subtables_canonicalize(self.SubTable, merger.font) subtables = merger.lookup_subtables = [_Lookup_PairPos_subtables_canonicalize(st, merger.font) for st in subtables] + else: + isSinglePos = self.SubTable and isinstance(self.SubTable[0], ot.SinglePos) + if isSinglePos: + numSubtables = [len(st) for st in subtables] + if not all([nums == numSubtables[0] for nums in numSubtables]): + # Flatten list of SinglePos subtables to single Format 2 subtable, + # with all value records set to the rec format type. + # We use buildSinglePos() to optimize the lookup after merging. + valueFormatList = [t.ValueFormat for st in subtables for t in st] + # Find the minimum value record that can accomodate all the singlePos subtables. + mirf = reduce(ior, valueFormatList) + self.SubTable = _Lookup_SinglePos_subtables_flatten(self.SubTable, merger.font, mirf) + subtables = merger.lookup_subtables = [ + _Lookup_SinglePos_subtables_flatten(st, merger.font, mirf) for st in subtables] + flattened = True + else: + flattened = False merger.mergeLists(self.SubTable, subtables) self.SubTableCount = len(self.SubTable) @@ -768,6 +811,16 @@ def merge(merger, self, lst): self.SubTable.pop(-1) self.SubTableCount -= 1 + elif isSinglePos and flattened: + singlePosTable = self.SubTable[0] + glyphs = singlePosTable.Coverage.glyphs + # We know that singlePosTable is Format 2, as this is set + # in _Lookup_SinglePos_subtables_flatten. + singlePosMapping = { + gname: valRecord + for gname, valRecord in zip(glyphs, singlePosTable.Value) + } + self.SubTable = buildSinglePos(singlePosMapping, merger.font.getReverseGlyphMap()) merger.mergeObjects(self, lst, exclude=['SubTable', 'SubTableCount']) del merger.lookup_subtables |