Fix Silf v2 support

This commit is contained in:
Martin Hosken 2017-09-14 15:17:02 +07:00 committed by Sascha Brawer
parent a997fae488
commit e29a41bbe3
4 changed files with 50 additions and 21 deletions

View File

@ -25,7 +25,8 @@ class table_F__e_a_t(DefaultTable.DefaultTable):
allfeats = [] allfeats = []
maxsetting = 0 maxsetting = 0
for i in range(numFeats): for i in range(numFeats):
(fid, nums, _, offset, flags, lid) = struct.unpack(">LHHLHH", data[16*i:16*(i+1)]) (fid, nums, _, offset, flags, lid) = struct.unpack(">LHHLHH",
data[16*i:16*(i+1)])
offset = int((offset - 12 - 16 * numFeats) / 4) offset = int((offset - 12 - 16 * numFeats) / 4)
allfeats.append((fid, nums, offset, flags, lid)) allfeats.append((fid, nums, offset, flags, lid))
maxsetting = max(maxsetting, offset + nums) maxsetting = max(maxsetting, offset + nums)
@ -52,7 +53,8 @@ class table_F__e_a_t(DefaultTable.DefaultTable):
vdat = "" vdat = ""
offset = 0 offset = 0
for f, v in sorted(self.features.items()): for f, v in sorted(self.features.items()):
fdat += struct.pack(">LHHLHH", grUtils.tag2num(f), len(v.settings), 0, offset * 4 + 12 + 16 * len(self.features), v.flags, v.label) fdat += struct.pack(">LHHLHH", grUtils.tag2num(f), len(v.settings),
0, offset * 4 + 12 + 16 * len(self.features), v.flags, v.label)
for s, l in sorted(v.settings.items()): for s, l in sorted(v.settings.items()):
vdat += struct.pack(">HH", s, l) vdat += struct.pack(">HH", s, l)
offset += len(v.settings) offset += len(v.settings)

View File

@ -12,6 +12,11 @@ import struct, operator, warnings, re
Silf_hdr_format = ''' Silf_hdr_format = '''
> >
version: 16.16F version: 16.16F
'''
Silf_hdr_format_3 = '''
>
version: 16.16F
compilerVersion: L compilerVersion: L
numSilf: H numSilf: H
x x
@ -304,12 +309,19 @@ class table_S__i_l_f(DefaultTable.DefaultTable):
sstruct.unpack2(Silf_hdr_format, data, self) sstruct.unpack2(Silf_hdr_format, data, self)
if self.version >= 5.0: if self.version >= 5.0:
(data, self.scheme) = grUtils.decompress(data) (data, self.scheme) = grUtils.decompress(data)
sstruct.unpack2(Silf_hdr_format, data, self) sstruct.unpack2(Silf_hdr_format_3, data, self)
base = sstruct.calcsize(Silf_hdr_format_3)
elif self.version < 3.0:
self.numSilf = struct.unpack('>H', data[4:6])
self.scheme = 0
self.compilerVersion = 0
base = 8
else: else:
self.scheme = 0 self.scheme = 0
sstruct.unpack2(Silf_hdr_format_3, data, self)
base = sstruct.calcsize(Silf_hdr_format_3)
silfoffsets = struct.unpack_from(('>%dL' % self.numSilf), silfoffsets = struct.unpack_from(('>%dL' % self.numSilf), data[base:])
data[sstruct.calcsize(Silf_hdr_format):])
for offset in silfoffsets: for offset in silfoffsets:
s = Silf() s = Silf()
self.silfs.append(s) self.silfs.append(s)
@ -317,7 +329,11 @@ class table_S__i_l_f(DefaultTable.DefaultTable):
def compile(self, ttFont): def compile(self, ttFont):
self.numSilf = len(self.silfs) self.numSilf = len(self.silfs)
if self.version < 3.0:
hdr = sstruct.pack(Silf_hdr_format, self) hdr = sstruct.pack(Silf_hdr_format, self)
hdr += struct.pack(">HH", self.numSilf, 0)
else:
hdr = sstruct.pack(Silf_hdr_format_3, self)
offset = len(hdr) + 4 * self.numSilf offset = len(hdr) + 4 * self.numSilf
data = "" data = ""
for s in self.silfs: for s in self.silfs:
@ -330,6 +346,8 @@ class table_S__i_l_f(DefaultTable.DefaultTable):
return hdr+data return hdr+data
def toXML(self, writer, ttFont): def toXML(self, writer, ttFont):
writer.comment('Attributes starting with _ are informative only')
writer.newline()
writer.simpletag('version', version=self.version, writer.simpletag('version', version=self.version,
compilerVersion=self.compilerVersion, compressionScheme=self.scheme) compilerVersion=self.compilerVersion, compressionScheme=self.scheme)
writer.newline() writer.newline()
@ -385,7 +403,10 @@ class Silf(object):
data = data[6 + 4 * self.numPasses:] data = data[6 + 4 * self.numPasses:]
(numPseudo,) = struct.unpack(">H", data[:2]) (numPseudo,) = struct.unpack(">H", data[:2])
for i in range(numPseudo): for i in range(numPseudo):
if version >= 3.0:
pseudo = sstruct.unpack(Silf_pseudomap_format, data[8+6*i:14+6*i], _Object()) pseudo = sstruct.unpack(Silf_pseudomap_format, data[8+6*i:14+6*i], _Object())
else:
pseudo = struct.unpack('>HH', data[8+4*i:12+4*i], _Object())
self.pMap[pseudo.unicode] = ttFont.getGlyphName(pseudo.nPseudo) self.pMap[pseudo.unicode] = ttFont.getGlyphName(pseudo.nPseudo)
data = data[8 + 6 * numPseudo:] data = data[8 + 6 * numPseudo:]
currpos = (sstruct.calcsize(Silf_part1_format) currpos = (sstruct.calcsize(Silf_part1_format)
@ -429,7 +450,8 @@ class Silf(object):
currpos = hdroffset + len(data) + 4 * (self.numPasses + 1) currpos = hdroffset + len(data) + 4 * (self.numPasses + 1)
self.pseudosOffset = currpos + len(data1) self.pseudosOffset = currpos + len(data1)
for u, p in sorted(self.pMap.items()): for u, p in sorted(self.pMap.items()):
data1 += struct.pack(">LH", u, ttFont.getGlyphID(p)) data1 += struct.pack((">LH" if version >= 3.0 else ">HH"),
u, ttFont.getGlyphID(p))
data1 += self.classes.compile(ttFont, version) data1 += self.classes.compile(ttFont, version)
currpos += len(data1) currpos += len(data1)
data2 = "" data2 = ""
@ -492,7 +514,7 @@ class Silf(object):
writer.begintag('passes') writer.begintag('passes')
writer.newline() writer.newline()
for i, p in enumerate(self.passes): for i, p in enumerate(self.passes):
writer.begintag('pass', index=i) writer.begintag('pass', _index=i)
writer.newline() writer.newline()
p.toXML(writer, ttFont, version) p.toXML(writer, ttFont, version)
writer.endtag('pass') writer.endtag('pass')
@ -582,7 +604,10 @@ class Classes(object):
def compile(self, ttFont, version=2.0): def compile(self, ttFont, version=2.0):
data = "" data = ""
oClasses = [] oClasses = []
if version >= 4.0:
offset = 8 + 4 * (len(self.linear) + len(self.nonLinear)) offset = 8 + 4 * (len(self.linear) + len(self.nonLinear))
else:
offset = 6 + 2 * (len(self.linear) + len(self.nonLinear))
for l in self.linear: for l in self.linear:
oClasses.append(len(data) + offset) oClasses.append(len(data) + offset)
gs = map(ttFont.getGlyphID, l) gs = map(ttFont.getGlyphID, l)
@ -596,8 +621,8 @@ class Classes(object):
self.numClass = len(oClasses) - 1 self.numClass = len(oClasses) - 1
self.numLinear = len(self.linear) self.numLinear = len(self.linear)
return sstruct.pack(Silf_classmap_format, self) + \ return sstruct.pack(Silf_classmap_format, self) + \
struct.pack((">%dL" % len(oClasses)), *oClasses) + \ struct.pack(((">%dL" if version >= 4.0 else ">%dH") % len(oClasses)),
data *oClasses) + data
def toXML(self, writer, ttFont, version=2.0): def toXML(self, writer, ttFont, version=2.0):
writer.begintag('classes') writer.begintag('classes')
@ -605,7 +630,7 @@ class Classes(object):
writer.begintag('linearClasses') writer.begintag('linearClasses')
writer.newline() writer.newline()
for i,l in enumerate(self.linear): for i,l in enumerate(self.linear):
writer.begintag('linear', index=i) writer.begintag('linear', _index=i)
writer.newline() writer.newline()
wrapline(writer, l) wrapline(writer, l)
writer.endtag('linear') writer.endtag('linear')
@ -615,7 +640,7 @@ class Classes(object):
writer.begintag('nonLinearClasses') writer.begintag('nonLinearClasses')
writer.newline() writer.newline()
for i, l in enumerate(self.nonLinear): for i, l in enumerate(self.nonLinear):
writer.begintag('nonLinear', index=i + self.numLinear) writer.begintag('nonLinear', _index=i + self.numLinear)
writer.newline() writer.newline()
for inp, ind in l.items(): for inp, ind in l.items():
writer.simpletag('map', glyph=inp, index=ind) writer.simpletag('map', glyph=inp, index=ind)
@ -794,7 +819,7 @@ class Pass(object):
writer.endtag('starts') writer.endtag('starts')
writer.newline() writer.newline()
for i, s in enumerate(self.stateTrans): for i, s in enumerate(self.stateTrans):
writer.begintag('row', i=i) writer.begintag('row', _i=i)
# no newlines here # no newlines here
writer.write(" ".join(map(str, s))) writer.write(" ".join(map(str, s)))
writer.endtag('row') writer.endtag('row')

View File

@ -24,12 +24,13 @@ class table_S__i_l_l(DefaultTable.DefaultTable):
maxsetting = 0 maxsetting = 0
langinfo = [] langinfo = []
for i in range(numLangs): for i in range(numLangs):
(langcode, numSettings, offset) = struct.unpack(">4sHH", (langcode, numsettings, offset) = struct.unpack(">4sHH",
data[i * 8:(i+1) * 8]) data[i * 8:(i+1) * 8])
offset = int(offset / 8) - (numLangs + 1) offset = int(offset / 8) - (numLangs + 1)
langcode = langcode.replace('\000', '')
langinfo.append((langcode, numsettings, offset)) langinfo.append((langcode, numsettings, offset))
maxsetting = max(maxsetting, offset + numsettings) maxsetting = max(maxsetting, offset + numsettings)
data[numLangs * 8:] data = data[numLangs * 8:]
finfo = [] finfo = []
for i in range(maxsetting): for i in range(maxsetting):
(fid, val, _) = struct.unpack(">LHH", data[i * 8:(i+1) * 8]) (fid, val, _) = struct.unpack(">LHH", data[i * 8:(i+1) * 8])
@ -45,7 +46,7 @@ class table_S__i_l_l(DefaultTable.DefaultTable):
fdat = "" fdat = ""
offset = 0 offset = 0
for c, inf in sorted(self.langs.items()): for c, inf in sorted(self.langs.items()):
ldat += struct.pack(">4sHH", c, len(inf), 8 * (offset + len(self.langs) + 1)) ldat += struct.pack(">4sHH", c.encode('utf8'), len(inf), 8 * (offset + len(self.langs) + 1))
for fid, val in inf: for fid, val in inf:
fdat += struct.pack(">LHH", fid, val, 0) fdat += struct.pack(">LHH", fid, val, 0)
offset += len(inf) offset += len(inf)
@ -74,5 +75,5 @@ class table_S__i_l_l(DefaultTable.DefaultTable):
if not isinstance(element, tuple): continue if not isinstance(element, tuple): continue
tag, a, subcontent = element tag, a, subcontent = element
if tag == 'feature': if tag == 'feature':
self.langs[c].append((grUtils.tag2num(attrs['fid']), self.langs[c].append((grUtils.tag2num(a['fid']),
int(safeEval(attrs['val'])))) int(safeEval(a['val']))))

View File

@ -68,11 +68,12 @@ def num2tag(n):
if n < 0x200000: if n < 0x200000:
return str(n) return str(n)
else: else:
return struct.unpack('4s', struct.pack('>L', n))[0] return struct.unpack('4s', struct.pack('>L', n))[0].replace('\000', '')
def tag2num(n): def tag2num(n):
try: try:
return int(n) return int(n)
except ValueError: except ValueError:
n = (n+" ")[:4]
return struct.unpack('>L', n)[0] return struct.unpack('>L', n)[0]