[ttLib] cmap format 14 cleanup (#1437)
* cleanup cmap format 14 TTX format by removing redundant attributes * don't output the name attr for a default mapping, instead of a glyph named 'None' * still accept 'None' as an indicator glyph name, for bw compatibility * swap order of TTX attrs uv and uvs * make sure (unicode, glyphName) pairs are always tuples in uvsDict.
This commit is contained in:
parent
855378477f
commit
6f7c0f1d09
@ -1135,7 +1135,7 @@ class cmap_format_14(CmapSubtable):
|
||||
startOffset += 5
|
||||
uv = cvtToUVS(uv)
|
||||
glyphName = self.ttFont.getGlyphName(gid)
|
||||
localUVList.append( [uv, glyphName] )
|
||||
localUVList.append((uv, glyphName))
|
||||
try:
|
||||
uvsDict[varUVS].extend(localUVList)
|
||||
except KeyError:
|
||||
@ -1147,9 +1147,6 @@ class cmap_format_14(CmapSubtable):
|
||||
writer.begintag(self.__class__.__name__, [
|
||||
("platformID", self.platformID),
|
||||
("platEncID", self.platEncID),
|
||||
("format", self.format),
|
||||
("length", self.length),
|
||||
("numVarSelectorRecords", self.numVarSelectorRecords),
|
||||
])
|
||||
writer.newline()
|
||||
uvsDict = self.uvsDict
|
||||
@ -1158,18 +1155,15 @@ class cmap_format_14(CmapSubtable):
|
||||
uvList = uvsDict[uvs]
|
||||
uvList.sort(key=lambda item: (item[1] is not None, item[0], item[1]))
|
||||
for uv, gname in uvList:
|
||||
if gname is None:
|
||||
gname = "None"
|
||||
# I use the arg rather than th keyword syntax in order to preserve the attribute order.
|
||||
writer.simpletag("map", [ ("uvs",hex(uvs)), ("uv",hex(uv)), ("name", gname)] )
|
||||
attrs = [("uv", hex(uv)), ("uvs", hex(uvs))]
|
||||
if gname is not None:
|
||||
attrs.append(("name", gname))
|
||||
writer.simpletag("map", attrs)
|
||||
writer.newline()
|
||||
writer.endtag(self.__class__.__name__)
|
||||
writer.newline()
|
||||
|
||||
def fromXML(self, name, attrs, content, ttFont):
|
||||
self.format = safeEval(attrs["format"])
|
||||
self.length = safeEval(attrs["length"])
|
||||
self.numVarSelectorRecords = safeEval(attrs["numVarSelectorRecords"])
|
||||
self.language = 0xFF # provide a value so that CmapSubtable.__lt__() won't fail
|
||||
if not hasattr(self, "cmap"):
|
||||
self.cmap = {} # so that clients that expect this to exist in a cmap table won't fail.
|
||||
@ -1177,6 +1171,11 @@ class cmap_format_14(CmapSubtable):
|
||||
self.uvsDict = {}
|
||||
uvsDict = self.uvsDict
|
||||
|
||||
# For backwards compatibility reasons we accept "None" as an indicator
|
||||
# for "default mapping", unless the font actually has a glyph named
|
||||
# "None".
|
||||
_hasGlyphNamedNone = None
|
||||
|
||||
for element in content:
|
||||
if not isinstance(element, tuple):
|
||||
continue
|
||||
@ -1185,13 +1184,16 @@ class cmap_format_14(CmapSubtable):
|
||||
continue
|
||||
uvs = safeEval(attrs["uvs"])
|
||||
uv = safeEval(attrs["uv"])
|
||||
gname = attrs["name"]
|
||||
gname = attrs.get("name")
|
||||
if gname == "None":
|
||||
if _hasGlyphNamedNone is None:
|
||||
_hasGlyphNamedNone = "None" in ttFont.getGlyphOrder()
|
||||
if not _hasGlyphNamedNone:
|
||||
gname = None
|
||||
try:
|
||||
uvsDict[uvs].append( [uv, gname])
|
||||
uvsDict[uvs].append((uv, gname))
|
||||
except KeyError:
|
||||
uvsDict[uvs] = [ [uv, gname] ]
|
||||
uvsDict[uvs] = [(uv, gname)]
|
||||
|
||||
def compile(self, ttFont):
|
||||
if self.data:
|
||||
|
@ -7,9 +7,9 @@
|
||||
<map code="0x20" name="space"/><!-- SPACE -->
|
||||
<map code="0x30" name="zero"/><!-- DIGIT ZERO -->
|
||||
</cmap_format_4>
|
||||
<cmap_format_14 platformID="0" platEncID="5" format="14" length="49" numVarSelectorRecords="2">
|
||||
<map uvs="0xfe00" uv="0x30" name="zero.slash"/>
|
||||
<map uvs="0xfe01" uv="0x30" name="None"/>
|
||||
<cmap_format_14 platformID="0" platEncID="5">
|
||||
<map uv="0x30" uvs="0xfe00" name="zero.slash"/>
|
||||
<map uv="0x30" uvs="0xfe01"/>
|
||||
</cmap_format_14>
|
||||
<cmap_format_4 platformID="3" platEncID="1" language="0">
|
||||
<map code="0x20" name="space"/><!-- SPACE -->
|
||||
|
@ -11,6 +11,7 @@ from fontTools.ttLib.tables._c_m_a_p import CmapSubtable, table__c_m_a_p
|
||||
CURR_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
|
||||
DATA_DIR = os.path.join(CURR_DIR, 'data')
|
||||
CMAP_FORMAT_14_TTX = os.path.join(DATA_DIR, "_c_m_a_p_format_14.ttx")
|
||||
CMAP_FORMAT_14_BW_COMPAT_TTX = os.path.join(DATA_DIR, "_c_m_a_p_format_14_bw_compat.ttx")
|
||||
|
||||
def strip_VariableItems(string):
|
||||
# ttlib changes with the fontTools version
|
||||
@ -99,8 +100,8 @@ class CmapSubtableTest(unittest.TestCase):
|
||||
subtable = self.makeSubtable(14, 0, 5, 0)
|
||||
subtable.cmap = {} # dummy
|
||||
subtable.uvsDict = {
|
||||
0xFE00: [[0x0030, "zero.slash"]],
|
||||
0xFE01: [(0x0030, None)], # yes, tuple here, list above, to match decompile
|
||||
0xFE00: [(0x0030, "zero.slash")],
|
||||
0xFE01: [(0x0030, None)],
|
||||
}
|
||||
fb = FontBuilder(1024, isTTF=True)
|
||||
font = fb.font
|
||||
@ -122,6 +123,9 @@ class CmapSubtableTest(unittest.TestCase):
|
||||
with open(CMAP_FORMAT_14_TTX) as f:
|
||||
expected = strip_VariableItems(f.read())
|
||||
self.assertEqual(ttx, expected)
|
||||
with open(CMAP_FORMAT_14_BW_COMPAT_TTX) as f:
|
||||
font.importXML(f)
|
||||
self.assertEqual(font["cmap"].getcmap(0, 5).uvsDict, subtable.uvsDict)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
<cmap>
|
||||
<tableVersion version="0"/>
|
||||
<cmap_format_14 platformID="0" platEncID="5" format="14" length="49" numVarSelectorRecords="2">
|
||||
<map uvs="0xfe00" uv="0x30" name="zero.slash"/>
|
||||
<map uvs="0xfe01" uv="0x30" name="None"/>
|
||||
<cmap_format_14 platformID="0" platEncID="5">
|
||||
<map uv="0x30" uvs="0xfe00" name="zero.slash"/>
|
||||
<map uv="0x30" uvs="0xfe01"/>
|
||||
</cmap_format_14>
|
||||
</cmap>
|
||||
|
||||
|
12
Tests/ttLib/tables/data/_c_m_a_p_format_14_bw_compat.ttx
Normal file
12
Tests/ttLib/tables/data/_c_m_a_p_format_14_bw_compat.ttx
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.35">
|
||||
|
||||
<cmap>
|
||||
<tableVersion version="0"/>
|
||||
<cmap_format_14 platformID="0" platEncID="5">
|
||||
<map uvs="0xfe00" uv="0x30" name="zero.slash"/>
|
||||
<map uvs="0xfe01" uv="0x30" name="None"/><!-- testing whether the old format that uses name="None" is still accepted -->
|
||||
</cmap_format_14>
|
||||
</cmap>
|
||||
|
||||
</ttFont>
|
@ -3,14 +3,14 @@
|
||||
|
||||
<cmap>
|
||||
<tableVersion version="0"/>
|
||||
<cmap_format_14 platformID="0" platEncID="5" format="14" length="47" numVarSelectorRecords="1">
|
||||
<map uvs="0xe0100" uv="0x4e00" name="None"/>
|
||||
<map uvs="0xe0100" uv="0x4e03" name="None"/>
|
||||
<map uvs="0xe0100" uv="0x4e04" name="None"/>
|
||||
<map uvs="0xe0100" uv="0x4e05" name="None"/>
|
||||
<map uvs="0xe0100" uv="0x4e06" name="None"/>
|
||||
<map uvs="0xe0100" uv="0x4e10" name="g25"/>
|
||||
<map uvs="0xe0100" uv="0x4e11" name="g26"/>
|
||||
<cmap_format_14 platformID="0" platEncID="5">
|
||||
<map uv="0x4e00" uvs="0xe0100"/>
|
||||
<map uv="0x4e03" uvs="0xe0100"/>
|
||||
<map uv="0x4e04" uvs="0xe0100"/>
|
||||
<map uv="0x4e05" uvs="0xe0100"/>
|
||||
<map uv="0x4e06" uvs="0xe0100"/>
|
||||
<map uv="0x4e10" uvs="0xe0100" name="g25"/>
|
||||
<map uv="0x4e11" uvs="0xe0100" name="g26"/>
|
||||
</cmap_format_14>
|
||||
<cmap_format_4 platformID="3" platEncID="1" language="0">
|
||||
<map code="0x4e00" name="g10"/><!-- CJK UNIFIED IDEOGRAPH-4E00 -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user