Merge pull request #1523 from justvanrossum/cmap_update2

[cmap,VORG,COLR,otTables] misc idiomatic updates
This commit is contained in:
Just van Rossum 2019-03-04 21:54:46 +01:00 committed by GitHub
commit a360252709
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 34 deletions

View File

@ -6,7 +6,6 @@ from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import * from fontTools.misc.py23 import *
from fontTools.misc.textTools import safeEval from fontTools.misc.textTools import safeEval
from . import DefaultTable from . import DefaultTable
import operator
import struct import struct
@ -44,12 +43,13 @@ class table_C_O_L_R_(DefaultTable.DefaultTable):
self.ColorLayers = colorLayerLists = {} self.ColorLayers = colorLayerLists = {}
try: try:
names = list(map(operator.getitem, [glyphOrder]*numBaseGlyphRecords, gids)) names = [glyphOrder[gid] for gid in gids]
except IndexError: except IndexError:
getGlyphName = self.getGlyphName getGlyphName = self.getGlyphName
names = list(map(getGlyphName, gids )) names = map(getGlyphName, gids)
list(map(operator.setitem, [colorLayerLists]*numBaseGlyphRecords, names, layerLists)) for name, layerList in zip(names, layerLists):
colorLayerLists[name] = layerList
def compile(self, ttFont): def compile(self, ttFont):
ordered = [] ordered = []
@ -112,7 +112,7 @@ class table_C_O_L_R_(DefaultTable.DefaultTable):
layer = LayerRecord() layer = LayerRecord()
layer.fromXML(element[0], element[1], element[2], ttFont) layer.fromXML(element[0], element[1], element[2], ttFont)
layers.append (layer) layers.append (layer)
operator.setitem(self, glyphName, layers) self[glyphName] = layers
elif "value" in attrs: elif "value" in attrs:
setattr(self, name, safeEval(attrs["value"])) setattr(self, name, safeEval(attrs["value"]))

View File

@ -30,25 +30,25 @@ class table_V_O_R_G_(DefaultTable.DefaultTable):
self.VOriginRecords = vOrig = {} self.VOriginRecords = vOrig = {}
glyphOrder = ttFont.getGlyphOrder() glyphOrder = ttFont.getGlyphOrder()
try: try:
names = map(operator.getitem, [glyphOrder]*self.numVertOriginYMetrics, gids) names = [glyphOrder[gid] for gid in gids]
except IndexError: except IndexError:
getGlyphName = self.getGlyphName getGlyphName = self.getGlyphName
names = map(getGlyphName, gids) names = map(getGlyphName, gids)
list(map(operator.setitem, [vOrig]*self.numVertOriginYMetrics, names, vids)) for name, vid in zip(names, vids):
vOrig[name] = vid
def compile(self, ttFont): def compile(self, ttFont):
vorgs = list(self.VOriginRecords.values()) vorgs = list(self.VOriginRecords.values())
names = list(self.VOriginRecords.keys()) names = list(self.VOriginRecords.keys())
nameMap = ttFont.getReverseGlyphMap() nameMap = ttFont.getReverseGlyphMap()
lenRecords = len(vorgs)
try: try:
gids = map(operator.getitem, [nameMap]*lenRecords, names) gids = [nameMap[name] for name in names]
except KeyError: except KeyError:
nameMap = ttFont.getReverseGlyphMap(rebuild=True) nameMap = ttFont.getReverseGlyphMap(rebuild=True)
gids = map(operator.getitem, [nameMap]*lenRecords, names) gids = [nameMap[name] for name in names]
vOriginTable = list(zip(gids, vorgs)) vOriginTable = list(zip(gids, vorgs))
self.numVertOriginYMetrics = lenRecords self.numVertOriginYMetrics = len(vorgs)
vOriginTable.sort() # must be in ascending GID order vOriginTable.sort() # must be in ascending GID order
dataList = [struct.pack(">Hh", rec[0], rec[1]) for rec in vOriginTable] dataList = [struct.pack(">Hh", rec[0], rec[1]) for rec in vOriginTable]
header = struct.pack(">HHhH", self.majorVersion, self.minorVersion, self.defaultVertOriginY, self.numVertOriginYMetrics) header = struct.pack(">HHhH", self.majorVersion, self.minorVersion, self.defaultVertOriginY, self.numVertOriginYMetrics)

View File

@ -8,7 +8,6 @@ from . import DefaultTable
import sys import sys
import struct import struct
import array import array
import operator
import logging import logging
@ -442,13 +441,12 @@ class cmap_format_2(CmapSubtable):
charCodes = [item[0] for item in items] charCodes = [item[0] for item in items]
names = [item[1] for item in items] names = [item[1] for item in items]
nameMap = ttFont.getReverseGlyphMap() nameMap = ttFont.getReverseGlyphMap()
lenCharCodes = len(charCodes)
try: try:
gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names)) gids = [nameMap[name] for name in names]
except KeyError: except KeyError:
nameMap = ttFont.getReverseGlyphMap(rebuild=True) nameMap = ttFont.getReverseGlyphMap(rebuild=True)
try: try:
gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names)) gids = [nameMap[name] for name in names]
except KeyError: except KeyError:
# allow virtual GIDs in format 2 tables # allow virtual GIDs in format 2 tables
gids = [] gids = []
@ -458,7 +456,7 @@ class cmap_format_2(CmapSubtable):
except KeyError: except KeyError:
try: try:
if (name[:3] == 'gid'): if (name[:3] == 'gid'):
gid = eval(name[3:]) gid = int(name[3:])
else: else:
gid = ttFont.getGlyphID(name) gid = ttFont.getGlyphID(name)
except: except:
@ -744,20 +742,19 @@ class cmap_format_4(CmapSubtable):
return struct.pack(">HHH", self.format, self.length, self.language) + self.data return struct.pack(">HHH", self.format, self.length, self.language) + self.data
charCodes = list(self.cmap.keys()) charCodes = list(self.cmap.keys())
lenCharCodes = len(charCodes) if not charCodes:
if lenCharCodes == 0:
startCode = [0xffff] startCode = [0xffff]
endCode = [0xffff] endCode = [0xffff]
else: else:
charCodes.sort() charCodes.sort()
names = list(map(operator.getitem, [self.cmap]*lenCharCodes, charCodes)) names = [self.cmap[code] for code in charCodes]
nameMap = ttFont.getReverseGlyphMap() nameMap = ttFont.getReverseGlyphMap()
try: try:
gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names)) gids = [nameMap[name] for name in names]
except KeyError: except KeyError:
nameMap = ttFont.getReverseGlyphMap(rebuild=True) nameMap = ttFont.getReverseGlyphMap(rebuild=True)
try: try:
gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names)) gids = [nameMap[name] for name in names]
except KeyError: except KeyError:
# allow virtual GIDs in format 4 tables # allow virtual GIDs in format 4 tables
gids = [] gids = []
@ -767,7 +764,7 @@ class cmap_format_4(CmapSubtable):
except KeyError: except KeyError:
try: try:
if (name[:3] == 'gid'): if (name[:3] == 'gid'):
gid = eval(name[3:]) gid = int(name[3:])
else: else:
gid = ttFont.getGlyphID(name) gid = ttFont.getGlyphID(name)
except: except:
@ -775,7 +772,8 @@ class cmap_format_4(CmapSubtable):
gids.append(gid) gids.append(gid)
cmap = {} # code:glyphID mapping cmap = {} # code:glyphID mapping
list(map(operator.setitem, [cmap]*len(charCodes), charCodes, gids)) for code, gid in zip(charCodes, gids):
cmap[code] = gid
# Build startCode and endCode lists. # Build startCode and endCode lists.
# Split the char codes in ranges of consecutive char codes, then split # Split the char codes in ranges of consecutive char codes, then split
@ -955,15 +953,14 @@ class cmap_format_12_or_13(CmapSubtable):
if self.data: if self.data:
return struct.pack(">HHLLL", self.format, self.reserved, self.length, self.language, self.nGroups) + self.data return struct.pack(">HHLLL", self.format, self.reserved, self.length, self.language, self.nGroups) + self.data
charCodes = list(self.cmap.keys()) charCodes = list(self.cmap.keys())
lenCharCodes = len(charCodes)
names = list(self.cmap.values()) names = list(self.cmap.values())
nameMap = ttFont.getReverseGlyphMap() nameMap = ttFont.getReverseGlyphMap()
try: try:
gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names)) gids = [nameMap[name] for name in names]
except KeyError: except KeyError:
nameMap = ttFont.getReverseGlyphMap(rebuild=True) nameMap = ttFont.getReverseGlyphMap(rebuild=True)
try: try:
gids = list(map(operator.getitem, [nameMap]*lenCharCodes, names)) gids = [nameMap[name] for name in names]
except KeyError: except KeyError:
# allow virtual GIDs in format 12 tables # allow virtual GIDs in format 12 tables
gids = [] gids = []
@ -973,7 +970,7 @@ class cmap_format_12_or_13(CmapSubtable):
except KeyError: except KeyError:
try: try:
if (name[:3] == 'gid'): if (name[:3] == 'gid'):
gid = eval(name[3:]) gid = int(name[3:])
else: else:
gid = ttFont.getGlyphID(name) gid = ttFont.getGlyphID(name)
except: except:
@ -982,7 +979,8 @@ class cmap_format_12_or_13(CmapSubtable):
gids.append(gid) gids.append(gid)
cmap = {} # code:glyphID mapping cmap = {} # code:glyphID mapping
list(map(operator.setitem, [cmap]*len(charCodes), charCodes, gids)) for code, gid in zip(charCodes, gids):
cmap[code] = gid
charCodes.sort() charCodes.sort()
index = 0 index = 0

View File

@ -9,7 +9,6 @@ from __future__ import print_function, division, absolute_import, unicode_litera
from fontTools.misc.py23 import * from fontTools.misc.py23 import *
from fontTools.misc.textTools import pad, safeEval from fontTools.misc.textTools import pad, safeEval
from .otBase import BaseTable, FormatSwitchingBaseTable, ValueRecord from .otBase import BaseTable, FormatSwitchingBaseTable, ValueRecord
import operator
import logging import logging
import struct import struct
@ -698,18 +697,19 @@ class SingleSubst(FormatSwitchingBaseTable):
def postRead(self, rawTable, font): def postRead(self, rawTable, font):
mapping = {} mapping = {}
input = _getGlyphsFromCoverageTable(rawTable["Coverage"]) input = _getGlyphsFromCoverageTable(rawTable["Coverage"])
lenMapping = len(input)
if self.Format == 1: if self.Format == 1:
delta = rawTable["DeltaGlyphID"] delta = rawTable["DeltaGlyphID"]
inputGIDS = [ font.getGlyphID(name) for name in input ] inputGIDS = [ font.getGlyphID(name) for name in input ]
outGIDS = [ (glyphID + delta) % 65536 for glyphID in inputGIDS ] outGIDS = [ (glyphID + delta) % 65536 for glyphID in inputGIDS ]
outNames = [ font.getGlyphName(glyphID) for glyphID in outGIDS ] outNames = [ font.getGlyphName(glyphID) for glyphID in outGIDS ]
list(map(operator.setitem, [mapping]*lenMapping, input, outNames)) for inp, out in zip(input, outNames):
mapping[inp] = out
elif self.Format == 2: elif self.Format == 2:
assert len(input) == rawTable["GlyphCount"], \ assert len(input) == rawTable["GlyphCount"], \
"invalid SingleSubstFormat2 table" "invalid SingleSubstFormat2 table"
subst = rawTable["Substitute"] subst = rawTable["Substitute"]
list(map(operator.setitem, [mapping]*lenMapping, input, subst)) for inp, sub in zip(input, subst):
mapping[inp] = sub
else: else:
assert 0, "unknown format: %s" % self.Format assert 0, "unknown format: %s" % self.Format
self.mapping = mapping self.mapping = mapping

View File

@ -51,6 +51,47 @@ class CmapSubtableTest(unittest.TestCase):
self.assertEqual(subtable.getEncoding("ascii"), "ascii") self.assertEqual(subtable.getEncoding("ascii"), "ascii")
self.assertEqual(subtable.getEncoding(default="xyz"), "xyz") self.assertEqual(subtable.getEncoding(default="xyz"), "xyz")
def test_compile_2(self):
subtable = self.makeSubtable(2, 1, 2, 0)
subtable.cmap = {c: "cid%05d" % c for c in range(32, 8192)}
font = ttLib.TTFont()
font.setGlyphOrder([".notdef"] + list(subtable.cmap.values()))
data = subtable.compile(font)
subtable2 = CmapSubtable.newSubtable(2)
subtable2.decompile(data, font)
self.assertEqual(subtable2.cmap, subtable.cmap)
def test_compile_2_rebuild_rev_glyph_order(self):
for fmt in [2, 4, 12]:
subtable = self.makeSubtable(fmt, 1, 2, 0)
subtable.cmap = {c: "cid%05d" % c for c in range(32, 8192)}
font = ttLib.TTFont()
font.setGlyphOrder([".notdef"] + list(subtable.cmap.values()))
font._reverseGlyphOrderDict = {} # force first KeyError branch in subtable.compile()
data = subtable.compile(font)
subtable2 = CmapSubtable.newSubtable(fmt)
subtable2.decompile(data, font)
self.assertEqual(subtable2.cmap, subtable.cmap, str(fmt))
def test_compile_2_gids(self):
for fmt in [2, 4, 12]:
subtable = self.makeSubtable(fmt, 1, 3, 0)
subtable.cmap = {0x0041:'gid001', 0x0042:'gid002'}
font = ttLib.TTFont()
font.setGlyphOrder([".notdef"])
data = subtable.compile(font)
def test_compile_decompile_4_empty(self):
subtable = self.makeSubtable(4, 3, 1, 0)
subtable.cmap = {}
font = ttLib.TTFont()
font.setGlyphOrder([])
data = subtable.compile(font)
subtable2 = CmapSubtable.newSubtable(4)
subtable2.decompile(data, font)
self.assertEqual(subtable2.cmap, {})
def test_decompile_4(self): def test_decompile_4(self):
subtable = CmapSubtable.newSubtable(4) subtable = CmapSubtable.newSubtable(4)
font = ttLib.TTFont() font = ttLib.TTFont()