[_k_e_r_n] fix order of format/coverage bytes

In OT kern subtable header, the format is the high byte of 'coverage'
bit mask (bits 8-15), and the low byte (bits 0-7) is the actual coverage
bits.

In AAT kern, it's the opposite: the coverage flags are the high byte,
whereas the subtable format is the low byte.

Also adjusted the test data, and set coverage to 1 for OT kern subtable
(which means the usual horizontal kerning).
This commit is contained in:
Cosimo Lupo 2017-11-04 10:56:07 +00:00
parent 5d16828031
commit d715575794
2 changed files with 35 additions and 24 deletions

View File

@ -37,15 +37,14 @@ class table__k_e_r_n(DefaultTable.DefaultTable):
for i in range(nTables):
if self.version == 1.0:
# Apple
length, coverage = struct.unpack(">LH", data[:6])
length, coverage, subtableFormat = struct.unpack(">LBB", data[:6])
else:
# in OpenType spec the "version" field refers to the common
# subtable header; the actual subtable format is stored in
# the last 8 mask bits of "coverage" field.
# Since this "version" is always 0 (and is not present in the
# later AAT extensions), we simply ignore it here
_, length, coverage = struct.unpack(">HHH", data[:6])
subtableFormat = coverage & 0xff
_, length, subtableFormat, coverage = struct.unpack(">HHBB", data[:6])
if subtableFormat not in kern_classes:
subtable = KernTable_format_unkown(subtableFormat)
else:
@ -103,7 +102,8 @@ class KernTable_format_0(object):
def decompile(self, data, ttFont):
if not self.apple:
version, length, coverage = struct.unpack(">HHH", data[:6])
version, length, subtableFormat, coverage = struct.unpack(
">HHBB", data[:6])
if version != 0:
from fontTools.ttLib import TTLibError
raise TTLibError(
@ -112,9 +112,10 @@ class KernTable_format_0(object):
# Should we also assert length == len(data)?
data = data[6:]
else:
length, coverage, tupleIndex = struct.unpack(">LHH", data[:8])
length, coverage, subtableFormat, tupleIndex = struct.unpack(
">LBBH", data[:8])
data = data[8:]
assert self.format == coverage & 0xFF, "unsupported format"
assert self.format == subtableFormat, "unsupported format"
self.coverage = coverage
self.tupleIndex = tupleIndex
@ -168,13 +169,12 @@ class KernTable_format_0(object):
for left, right, value in kernTable:
data = data + struct.pack(">HHh", left, right, value)
# ensure mask bits 8-15 (subtable format) are set to 0
self.coverage &= ~0xFF
if not self.apple:
version = 0
length = len(data) + 6
header = struct.pack(">HHH", version, length, self.coverage)
header = struct.pack(
">HHBB", version, length, self.format, self.coverage)
else:
if self.tupleIndex is None:
# sensible default when compiling a TTX from an old fonttools
@ -183,7 +183,8 @@ class KernTable_format_0(object):
log.warning("'tupleIndex' is None; default to 0")
self.tupleIndex = 0
length = len(data) + 8
header = struct.pack(">LHH", length, self.coverage, self.tupleIndex)
header = struct.pack(
">LBBH", length, self.coverage, self.format, self.tupleIndex)
return header + data
def toXML(self, writer, ttFont):

View File

@ -13,7 +13,8 @@ KERN_VER_0_FMT_0_DATA = deHexStr(
'0001 ' # 2: nTables=1
'0000 ' # 4: version=0 (bogus field, unused)
'0020 ' # 6: length=32
'0000 ' # 8: coverage=0
'00 ' # 8: format=0
'01 ' # 9: coverage=1
'0003 ' # 10: nPairs=3
'000C ' # 12: searchRange=12
'0001 ' # 14: entrySelector=1
@ -26,7 +27,7 @@ assert len(KERN_VER_0_FMT_0_DATA) == 36
KERN_VER_0_FMT_0_XML = [
'<version value="0"/>',
'<kernsubtable coverage="0" format="0">',
'<kernsubtable coverage="1" format="0">',
' <pair l="E" r="M" v="-40"/>',
' <pair l="E" r="c" v="40"/>',
' <pair l="F" r="o" v="-50"/>',
@ -37,7 +38,8 @@ KERN_VER_1_FMT_0_DATA = deHexStr(
'0001 0000 ' # 0: version=1
'0000 0001 ' # 4: nTables=1
'0000 0022 ' # 8: length=34
'0000 ' # 12: coverage=0
'00 ' # 12: coverage=0
'00 ' # 13: format=0
'0000 ' # 14: tupleIndex=0
'0003 ' # 16: nPairs=3
'000C ' # 18: searchRange=12
@ -63,11 +65,13 @@ KERN_VER_0_FMT_UNKNOWN_DATA = deHexStr(
'0002 ' # 2: nTables=2
'0000 ' # 4: version=0
'000A ' # 6: length=10
'0004 ' # 8: coverage=4 (format 4 doesn't exist)
'04 ' # 8: format=4 (format 4 doesn't exist)
'01 ' # 9: coverage=1
'1234 5678 ' # 10: garbage...
'0000 ' # 14: version=0
'000A ' # 16: length=10
'0005 ' # 18: coverage=5 (format 5 doesn't exist)
'05 ' # 18: format=5 (format 5 doesn't exist)
'01 ' # 18: coverage=1
'9ABC DEF0 ' # 20: garbage...
)
assert len(KERN_VER_0_FMT_UNKNOWN_DATA) == 24
@ -76,11 +80,13 @@ KERN_VER_1_FMT_UNKNOWN_DATA = deHexStr(
'0001 0000 ' # 0: version=1
'0000 0002 ' # 4: nTables=2
'0000 000C ' # 8: length=12
'0004 ' # 12: coverage=4 (format 4 doesn't exist)
'00 ' # 12: coverage=0
'04 ' # 13: format=4 (format 4 doesn't exist)
'0000 ' # 14: tupleIndex=0
'1234 5678' # 16: garbage...
'0000 000C ' # 20: length=12
'0005 ' # 18: coverage=5 (format 5 doesn't exist)
'00 ' # 18: coverage=0
'05 ' # 19: format=5 (format 5 doesn't exist)
'0000 ' # 20: tupleIndex=0
'9ABC DEF0 ' # 22: garbage...
)
@ -113,7 +119,9 @@ class KernTableTest(object):
st = kern.kernTables[0]
assert st.apple is (version == 1.0)
assert st.format == 0
assert st.coverage == 0
# horizontal kerning in OT kern is coverage 0x01, while in
# AAT kern it's the default (0)
assert st.coverage == (0 if st.apple else 1)
assert st.tupleIndex == (0 if st.apple else None)
assert len(st.kernTable) == 3
assert st.kernTable == {
@ -136,7 +144,7 @@ class KernTableTest(object):
apple = version == 1.0
st = KernTable_format_0(apple)
kern.kernTables = [st]
st.coverage = 0
st.coverage = (0 if apple else 1)
st.tupleIndex = 0 if apple else None
st.kernTable = {
('E', 'M'): -40,
@ -165,7 +173,7 @@ class KernTableTest(object):
st = kern.kernTables[0]
assert st.apple is (version == 1.0)
assert st.format == 0
assert st.coverage == 0
assert st.coverage == (0 if st.apple else 1)
assert st.tupleIndex == (0 if st.apple else None)
assert len(st.kernTable) == 3
assert st.kernTable == {
@ -188,7 +196,7 @@ class KernTableTest(object):
apple = version == 1.0
st = KernTable_format_0(apple)
kern.kernTables = [st]
st.coverage = 0
st.coverage = 0 if apple else 1
st.tupleIndex = 0 if apple else None
st.kernTable = {
('E', 'M'): -40,
@ -238,13 +246,15 @@ class KernTableTest(object):
kern.kernTables = []
for unknown_fmt, kern_data in zip((4, 5), ("1234 5678", "9ABC DEF0")):
coverage = unknown_fmt
if version > 0:
coverage = 0
header_fmt = deHexStr(
"%08X %04X %04X" % (st_length, coverage, 0))
"%08X %02X %02X %04X" % (
st_length, coverage, unknown_fmt, 0))
else:
coverage = 1
header_fmt = deHexStr(
"%04X %04X %04X" % (0, st_length, coverage))
"%04X %04X %02X %02X" % (0, st_length, unknown_fmt, coverage))
st = KernTable_format_unkown(unknown_fmt)
st.data = header_fmt + deHexStr(kern_data)
kern.kernTables.append(st)