Home | History | Annotate | Download | only in tables
      1 from __future__ import print_function, division, absolute_import
      2 from fontTools.misc.py23 import *
      3 from fontTools.misc import sstruct
      4 from fontTools.misc.textTools import safeEval
      5 from .otBase import BaseTTXConverter
      6 from . import DefaultTable
      7 from . import grUtils
      8 import struct
      9 
     10 Feat_hdr_format='''
     11     >
     12     version:    16.16F
     13 '''
     14 
     15 class table_F__e_a_t(DefaultTable.DefaultTable):
     16 
     17     def __init__(self, tag=None):
     18         DefaultTable.DefaultTable.__init__(self, tag)
     19         self.features = {}
     20 
     21     def decompile(self, data, ttFont):
     22         (_, data) = sstruct.unpack2(Feat_hdr_format, data, self)
     23         numFeats, = struct.unpack('>H', data[:2])
     24         data = data[8:]
     25         allfeats = []
     26         maxsetting = 0
     27         for i in range(numFeats):
     28             if self.version >= 2.0:
     29                 (fid, nums, _, offset, flags, lid) = struct.unpack(">LHHLHH",
     30                                                             data[16*i:16*(i+1)])
     31                 offset = int((offset - 12 - 16 * numFeats) / 4)
     32             else:
     33                 (fid, nums, offset, flags, lid) = struct.unpack(">HHLHH",
     34                                                             data[12*i:12*(i+1)])
     35                 offset = int((offset - 12 - 12 * numFeats) / 4)
     36             allfeats.append((fid, nums, offset, flags, lid))
     37             maxsetting = max(maxsetting, offset + nums)
     38         data = data[16*numFeats:]
     39         allsettings = []
     40         for i in range(maxsetting):
     41             if len(data) >= 4 * (i + 1):
     42                 (val, lid) = struct.unpack(">HH", data[4*i:4*(i+1)])
     43                 allsettings.append((val, lid))
     44         for i,f in enumerate(allfeats):
     45             (fid, nums, offset, flags, lid) = f
     46             fobj = Feature()
     47             fobj.flags = flags
     48             fobj.label = lid
     49             self.features[grUtils.num2tag(fid)] = fobj
     50             fobj.settings = {}
     51             fobj.default = None
     52             fobj.index = i
     53             for i in range(offset, offset + nums):
     54                 if i >= len(allsettings): continue
     55                 (vid, vlid) = allsettings[i]
     56                 fobj.settings[vid] = vlid
     57                 if fobj.default is None:
     58                     fobj.default = vid
     59 
     60     def compile(self, ttFont):
     61         fdat = b""
     62         vdat = b""
     63         offset = 0
     64         for f, v in sorted(self.features.items(), key=lambda x:x[1].index):
     65             fnum = grUtils.tag2num(f)
     66             if self.version >= 2.0:
     67                 fdat += struct.pack(">LHHLHH", grUtils.tag2num(f), len(v.settings),
     68                     0, offset * 4 + 12 + 16 * len(self.features), v.flags, v.label)
     69             elif fnum > 65535:      # self healing for alphabetic ids
     70                 self.version = 2.0
     71                 return self.compile(ttFont)
     72             else:
     73                 fdat += struct.pack(">HHLHH", grUtils.tag2num(f), len(v.settings),
     74                     offset * 4 + 12 + 12 * len(self.features), v.flags, v.label)
     75             for s, l in sorted(v.settings.items(), key=lambda x:(-1, x[1]) if x[0] == v.default else x):
     76                 vdat += struct.pack(">HH", s, l)
     77             offset += len(v.settings)
     78         hdr = sstruct.pack(Feat_hdr_format, self)
     79         return hdr + struct.pack('>HHL', len(self.features), 0, 0) + fdat + vdat
     80 
     81     def toXML(self, writer, ttFont):
     82         writer.simpletag('version', version=self.version)
     83         writer.newline()
     84         for f, v in sorted(self.features.items(), key=lambda x:x[1].index):
     85             writer.begintag('feature', fid=f, label=v.label, flags=v.flags,
     86                             default=(v.default if v.default else 0))
     87             writer.newline()
     88             for s, l in sorted(v.settings.items()):
     89                 writer.simpletag('setting', value=s, label=l)
     90                 writer.newline()
     91             writer.endtag('feature')
     92             writer.newline()
     93 
     94     def fromXML(self, name, attrs, content, ttFont):
     95         if name == 'version':
     96             self.version = float(safeEval(attrs['version']))
     97         elif name == 'feature':
     98             fid = attrs['fid']
     99             fobj = Feature()
    100             fobj.flags = int(safeEval(attrs['flags']))
    101             fobj.label = int(safeEval(attrs['label']))
    102             fobj.default = int(safeEval(attrs.get('default','0')))
    103             fobj.index = len(self.features)
    104             self.features[fid] = fobj
    105             fobj.settings = {}
    106             for element in content:
    107                 if not isinstance(element, tuple): continue
    108                 tag, a, c = element
    109                 if tag == 'setting':
    110                     fobj.settings[int(safeEval(a['value']))] = int(safeEval(a['label']))
    111 
    112 class Feature(object):
    113     pass
    114 
    115