Source code for fontTools.ttLib.tables.F__e_a_t

from fontTools.misc import sstruct
from fontTools.misc.fixedTools import floatToFixedToStr
from fontTools.misc.textTools import safeEval
from . import DefaultTable
from . import grUtils
import struct

Feat_hdr_format = """
    >
    version:    16.16F
"""


[docs] class table_F__e_a_t(DefaultTable.DefaultTable): """The ``Feat`` table is used exclusively by the Graphite shaping engine to store features and possible settings specified in GDL. Graphite features determine what rules are applied to transform a glyph stream. Not to be confused with ``feat``, or the OpenType Layout tables ``GSUB``/``GPOS``.""" def __init__(self, tag=None): DefaultTable.DefaultTable.__init__(self, tag) self.features = {}
[docs] def decompile(self, data, ttFont): (_, data) = sstruct.unpack2(Feat_hdr_format, data, self) self.version = float(floatToFixedToStr(self.version, precisionBits=16)) (numFeats,) = struct.unpack(">H", data[:2]) data = data[8:] allfeats = [] maxsetting = 0 for i in range(numFeats): if self.version >= 2.0: (fid, nums, _, offset, flags, lid) = struct.unpack( ">LHHLHH", data[16 * i : 16 * (i + 1)] ) offset = int((offset - 12 - 16 * numFeats) / 4) else: (fid, nums, offset, flags, lid) = struct.unpack( ">HHLHH", data[12 * i : 12 * (i + 1)] ) offset = int((offset - 12 - 12 * 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 i, f in enumerate(allfeats): (fid, nums, offset, flags, lid) = f fobj = Feature() fobj.flags = flags fobj.label = lid self.features[grUtils.num2tag(fid)] = fobj fobj.settings = {} fobj.default = None fobj.index = i for i in range(offset, offset + nums): if i >= len(allsettings): continue (vid, vlid) = allsettings[i] fobj.settings[vid] = vlid if fobj.default is None: fobj.default = vid
[docs] def compile(self, ttFont): fdat = b"" vdat = b"" offset = 0 for f, v in sorted(self.features.items(), key=lambda x: x[1].index): fnum = grUtils.tag2num(f) if self.version >= 2.0: fdat += struct.pack( ">LHHLHH", grUtils.tag2num(f), len(v.settings), 0, offset * 4 + 12 + 16 * len(self.features), v.flags, v.label, ) elif fnum > 65535: # self healing for alphabetic ids self.version = 2.0 return self.compile(ttFont) else: fdat += struct.pack( ">HHLHH", grUtils.tag2num(f), len(v.settings), offset * 4 + 12 + 12 * len(self.features), v.flags, v.label, ) for s, l in sorted( v.settings.items(), key=lambda x: (-1, x[1]) if x[0] == v.default else x ): 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
[docs] def toXML(self, writer, ttFont): writer.simpletag("version", version=self.version) writer.newline() for f, v in sorted(self.features.items(), key=lambda x: x[1].index): writer.begintag( "feature", fid=f, label=v.label, flags=v.flags, default=(v.default if v.default else 0), ) writer.newline() for s, l in sorted(v.settings.items()): writer.simpletag("setting", value=s, label=l) writer.newline() writer.endtag("feature") writer.newline()
[docs] 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"])) fobj.default = int(safeEval(attrs.get("default", "0"))) fobj.index = len(self.features) 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"]))
[docs] class Feature(object): pass