Handle all Graphite tables now

This commit is contained in:
Martin Hosken 2017-09-13 23:39:39 +07:00 committed by Sascha Brawer
parent bb162e00b9
commit 860a8e0522
5 changed files with 206 additions and 17 deletions

View File

@ -0,0 +1,92 @@
from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval
from .otBase import BaseTTXConverter
from . import DefaultTable
from . import grUtils
import struct
Feat_hdr_format='''
>
version: 16.16F
'''
class table_F__e_a_t(DefaultTable.DefaultTable):
def __init__(self, tag=None):
DefaultTable.DefaultTable.__init__(self, tag)
self.features = {}
def decompile(self, data, ttFont):
(_, data) = sstruct.unpack2(Feat_hdr_format, data, self)
numFeats, = struct.unpack('>H', data[:2])
data = data[8:]
allfeats = []
maxsetting = 0
for i in range(numFeats):
(fid, nums, _, offset, flags, lid) = struct.unpack(">LHHLHH", data[16*i:16*(i+1)])
offset = int((offset - 12 - 16 * numFeats) / 4)
allfeats.append((fid, nums, offset, flags, lid))
maxsetting = max(maxsetting, offset + nums)
data = data[16*numFeats:]
allsettings = []
for i in range(maxsetting):
if len(data) >= 4 * (i + 1):
(val, lid) = struct.unpack(">HH", data[4*i:4*(i+1)])
allsettings.append((val, lid))
for f in allfeats:
(fid, nums, offset, flags, lid) = f
fobj = Feature()
fobj.flags = flags
fobj.label = lid
self.features[grUtils.num2tag(fid)] = fobj
fobj.settings = {}
for i in range(offset, offset + nums):
if i >= len(allsettings): continue
(vid, vlid) = allsettings[i]
fobj.settings[vid] = vlid
def compile(self, ttFont):
fdat = ""
vdat = ""
offset = 0
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)
for s, l in sorted(v.settings.items()):
vdat += struct.pack(">HH", s, l)
offset += len(v.settings)
hdr = sstruct.pack(Feat_hdr_format, self)
return hdr + struct.pack('>HHL', len(self.features), 0, 0) + fdat + vdat
def toXML(self, writer, ttFont):
writer.simpletag('version', version=self.version)
writer.newline()
for f, v in sorted(self.features.items()):
writer.begintag('feature', fid=f, label=v.label, flags=v.flags)
writer.newline()
for s, l in sorted(v.settings.items()):
writer.simpletag('setting', value=s, label=l)
writer.newline()
writer.endtag('feature')
writer.newline()
def fromXML(self, name, attrs, content, ttFont):
if name == 'version':
self.version = float(safeEval(attrs['version']))
elif name == 'feature':
fid = attrs['fid']
fobj = Feature()
fobj.flags = int(safeEval(attrs['flags']))
fobj.label = int(safeEval(attrs['label']))
self.features[fid] = fobj
fobj.settings = {}
for element in content:
if not isinstance(element, tuple): continue
tag, a, c = element
if tag == 'setting':
fobj.settings[int(safeEval(a['value']))] = int(safeEval(a['label']))
class Feature(object):
pass

View File

@ -278,20 +278,6 @@ def content_string(contents):
res += element
return res.strip()
def bininfo(num, size=1):
if num == 0:
return struct.pack(">4H", 0, 0, 0, 0)
srange = 1;
select = 0
while srange <= num:
srange *= 2
select += 1
select -= 1
srange /= 2
srange *= size
shift = num * size - srange
return struct.pack(">4H", num, srange, select, shift)
class _Object() :
pass
@ -423,7 +409,7 @@ class Silf(object):
data += struct.pack(">H", self.lbGID)
self.passOffset = len(data)
data1 = bininfo(numPseudo, 6)
data1 = grUtils.bininfo(numPseudo, 6)
currpos = hdroffset + len(data) + 4 * (self.numPasses + 1)
self.pseudosOffset = currpos + len(data1)
for u, p in sorted(self.pMap.items()):
@ -582,7 +568,7 @@ class Classes(object):
data += struct.pack((">%dH" % len(l)), *l)
for l in self.nonLinear:
oClasses.append(len(data) + offset)
data += bininfo(len(l.lookups))
data += grUtils.bininfo(len(l.lookups))
data += "".join([struct.pack(">HH", *x) for x in l.lookups])
oClasses.append(len(data) + offset)
self.numClass = len(oClasses) - 1
@ -731,7 +717,7 @@ class Pass(object):
self.oDebug = 0
# now generate output
data = sstruct.pack(Silf_pass_format, self)
data += bininfo(len(passRanges), 6)
data += grUtils.bininfo(len(passRanges), 6)
data += "".join(struct.pack(">3H", *p) for p in passRanges)
data += struct.pack((">%dH" % len(oRuleMap)), *oRuleMap)
flatrules = reduce(lambda a,x: a+x, self.rules, [])

View File

@ -0,0 +1,75 @@
from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval
from . import DefaultTable
from . import grUtils
import struct
Sill_hdr = '''
>
version: 16.16F
'''
class table_S__i_l_l(DefaultTable.DefaultTable):
def __init__(self, tag=None):
DefaultTable.DefaultTable.__init__(self, tag)
self.langs = {}
def decompile(self, data, ttFont):
(_, data) = sstruct.unpack2(Sill_hdr, data, self)
numLangs, = struct.unpack('>H', data[:2])
data = data[8:]
maxsetting = 0
langinfo = []
for i in range(numLangs):
(langcode, numSettings, offset) = struct.unpack(">4sHH", data[i * 8:(i+1) * 8])
offset = int(offset / 8) - (numLangs + 1)
langinfo.append((langcode, numsettings, offset))
maxsetting = max(maxsetting, offset + numsettings)
data[numLangs * 8:]
finfo = []
for i in range(maxsetting):
(fid, val, _) = struct.unpack(">LHH", data[i * 8:(i+1) * 8])
finfo.append((fid, val))
self.langs = {}
for c, n, o in langinfo:
self.langs[c] = []
for i in range(o, o+n):
self.langs[c].append(finfo[i])
def compile(self, ttFont):
ldat = ""
fdat = ""
offset = 0
for c, inf in sorted(self.langs.items()):
ldat += struct.pack(">4sHH", c, len(inf), 8 * (offset + len(self.langs) + 1))
for fid, val in inf:
fdat += struct.pack(">LHH", fid, val, 0)
offset += len(inf)
return sstruct.pack(Sill_hdr, self) + grUtils.bininfo(len(self.langs)) + ldat + fdat
def toXML(self, writer, ttFont):
writer.simpletag('version', version=self.version)
writer.newline()
for c, inf in sorted(self.langs.items()):
writer.begintag('lang', name=c)
writer.newline()
for fid, val in inf:
writer.simpletag('feature', fid=grUtils.num2tag(fid), val=val)
writer.newline()
writer.endtag('lang')
writer.newline()
def fromXML(self, name, attrs, content, ttFont):
if name == 'version':
self.version = float(safeEval(attrs['version']))
elif name == 'lang':
c = attrs['name']
self.langs[c] = []
for element in content:
if not isinstance(element, tuple): continue
tag, a, subcontent = element
if tag == 'feature':
self.langs[c].append((grUtils.tag2num(attrs['fid']), int(safeEval(attrs['val']))))

View File

@ -50,3 +50,29 @@ def entries(attributes, sameval = False):
g = _entries(sorted(attributes.iteritems(), key=lambda x:int(x[0])), sameval)
return g
def bininfo(num, size=1):
if num == 0:
return struct.pack(">4H", 0, 0, 0, 0)
srange = 1;
select = 0
while srange <= num:
srange *= 2
select += 1
select -= 1
srange /= 2
srange *= size
shift = num * size - srange
return struct.pack(">4H", num, srange, select, shift)
def num2tag(n):
if n < 0x200000:
return str(n)
else:
return struct.unpack('4s', struct.pack('>L', n))[0]
def tag2num(n):
try:
return int(n)
except ValueError:
return struct.unpack('>L', n)[0]

View File

@ -1325,6 +1325,16 @@ otData = [
]),
#
# Feat
#
('Feat', [
('Version', 'Version', None, None, 'Version of the feat table-initially set to 0x00010000.'),
('FeatureNames', 'FeatureNames', None, None, 'The feature names.'),
]),
#
# lcar
#