diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2014-03-28 17:41:01 -0700 |
---|---|---|
committer | Behdad Esfahbod <behdad@behdad.org> | 2014-03-28 17:41:01 -0700 |
commit | 8fec68796d90d217a7e869215810b5179cc28c16 (patch) | |
tree | 7b65c57427c04991499d258b65952437a7cb79ca | |
parent | d0903e3bb3f0c313532a46d99423ae6f9c327aa5 (diff) | |
download | fonttools-8fec68796d90d217a7e869215810b5179cc28c16.tar.gz |
[merge] Map duplicate glyphs using synthesized GSUB 'locl' tables
-rw-r--r-- | Lib/fontTools/merge.py | 81 |
1 files changed, 75 insertions, 6 deletions
diff --git a/Lib/fontTools/merge.py b/Lib/fontTools/merge.py index 5534cc55..5f51ad60 100644 --- a/Lib/fontTools/merge.py +++ b/Lib/fontTools/merge.py @@ -350,21 +350,30 @@ ttLib.getTableClass('cvt ').mergeMap = lambda self, lst: first(lst) @_add_method(ttLib.getTableClass('cmap')) def merge(self, m, tables): # TODO Handle format=14. - cmapTables = [t for table in tables for t in table.tables + cmapTables = [(t,fontIdx) for fontIdx,table in enumerate(tables) for t in table.tables if t.isUnicode()] # TODO Better handle format-4 and format-12 coexisting in same font. # TODO Insert both a format-4 and format-12 if needed. module = ttLib.getTableModule('cmap') - assert all(t.format in [4, 12] for t in cmapTables) - format = max(t.format for t in cmapTables) + assert all(t.format in [4, 12] for t,_ in cmapTables) + format = max(t.format for t,_ in cmapTables) cmapTable = module.cmap_classes[format](format) cmapTable.cmap = {} cmapTable.platformID = 3 - cmapTable.platEncID = max(t.platEncID for t in cmapTables) + cmapTable.platEncID = max(t.platEncID for t,_ in cmapTables) cmapTable.language = 0 - for table in cmapTables: + cmap = cmapTable.cmap + for table,fontIdx in cmapTables: # TODO handle duplicates. - cmapTable.cmap.update(table.cmap) + for uni,gid in table.cmap.items(): + oldgid = cmap.get(uni, None) + if oldgid is None: + cmap[uni] = gid + elif oldgid != gid: + # Char previously mapped to oldgid, now to gid. + # Record, to fix up in GSUB 'locl' later. + assert m.duplicateGlyphsPerFont[fontIdx].get(oldgid, gid) == gid + m.duplicateGlyphsPerFont[fontIdx][oldgid] = gid self.tableVersion = 0 self.tables = [cmapTable] self.numSubTables = len(self.tables) @@ -434,6 +443,58 @@ ttLib.getTableClass('MATH').mergeMap = \ 'table': mergeObjects, } +@_add_method(ttLib.getTableClass('GSUB')) +def merge(self, m, tables): + + assert len(tables) == len(m.duplicateGlyphsPerFont) + for i,(table,dups) in enumerate(zip(tables, m.duplicateGlyphsPerFont)): + if not dups: continue + assert (table is not None and table is not NotImplemented), "Have duplicates to resolve for font %d but no GSUB" % (i + 1) + lookupMap = {id(v):v for v in table.table.LookupList.Lookup} + featureMap = {id(v):v for v in table.table.FeatureList.FeatureRecord} + synthFeature = None + synthLookup = None + for script in table.table.ScriptList.ScriptRecord: + if script.ScriptTag == 'DFLT': continue # XXX + for langsys in [script.Script.DefaultLangSys] + [l.LangSys for l in script.Script.LangSysRecord]: + feature = [featureMap[v] for v in langsys.FeatureIndex if featureMap[v].FeatureTag == 'locl'] + assert len(feature) <= 1 + if feature: + feature = feature[0] + else: + if not synthFeature: + synthFeature = otTables.FeatureRecord() + synthFeature.FeatureTag = 'locl' + f = synthFeature.Feature = otTables.Feature() + f.FeatureParams = None + f.LookupCount = 0 + f.LookupListIndex = [] + langsys.FeatureIndex.append(id(synthFeature)) + featureMap[id(synthFeature)] = synthFeature + langsys.FeatureIndex.sort(key=lambda v: featureMap[v].FeatureTag) + table.table.FeatureList.FeatureRecord.append(synthFeature) + table.table.FeatureList.FeatureCount += 1 + feature = synthFeature + + if not synthLookup: + subtable = otTables.SingleSubst() + subtable.mapping = dups + synthLookup = otTables.Lookup() + synthLookup.LookupFlag = 0 + synthLookup.LookupType = 1 + synthLookup.SubTableCount = 1 + synthLookup.SubTable = [subtable] + table.table.LookupList.Lookup.append(synthLookup) + table.table.LookupList.LookupCount += 1 + + feature.Feature.LookupListIndex[:0] = [id(synthLookup)] + feature.Feature.LookupCount += 1 + + + DefaultTable.merge(self, m, tables) + return self + + @_add_method(otTables.SingleSubst, otTables.MultipleSubst, @@ -669,6 +730,8 @@ class Merger(object): for font in fonts: self._preMerge(font) + self.duplicateGlyphsPerFont = [{} for f in fonts] + allTags = reduce(set.union, (list(font.keys()) for font in fonts), set()) allTags.remove('GlyphOrder') allTags.remove('cmap') @@ -689,6 +752,8 @@ class Merger(object): self.log("Dropped '%s'." % tag) self.log.lapse("merge '%s'" % tag) + del self.duplicateGlyphsPerFont + self._postMerge(mega) return mega @@ -731,6 +796,8 @@ class Merger(object): def _preMerge(self, font): + # Map indices to references + GDEF = font.get('GDEF') GSUB = font.get('GSUB') GPOS = font.get('GPOS') @@ -754,6 +821,8 @@ class Merger(object): def _postMerge(self, font): + # Map references back to indices + GDEF = font.get('GDEF') GSUB = font.get('GSUB') GPOS = font.get('GPOS') |