[_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:
parent
5d16828031
commit
d715575794
@ -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):
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user