Source code for fontTools.ttLib.tables.G__l_a_t

from fontTools.misc import sstruct
from fontTools.misc.fixedTools import floatToFixedToStr
from fontTools.misc.textTools import safeEval

# from itertools import *
from functools import partial
from . import DefaultTable
from . import grUtils
import struct


Glat_format_0 = """
    >        # big endian
    version: 16.16F
"""

Glat_format_3 = """
    >
    version: 16.16F
    compression:L    # compression scheme or reserved 
"""

Glat_format_1_entry = """
    >
    attNum:     B    # Attribute number of first attribute
    num:        B    # Number of attributes in this run
"""
Glat_format_23_entry = """
    >
    attNum:     H    # Attribute number of first attribute
    num:        H    # Number of attributes in this run
"""

Glat_format_3_octabox_metrics = """
    >
    subboxBitmap:   H    # Which subboxes exist on 4x4 grid
    diagNegMin:     B    # Defines minimum negatively-sloped diagonal (si)
    diagNegMax:     B    # Defines maximum negatively-sloped diagonal (sa)
    diagPosMin:     B    # Defines minimum positively-sloped diagonal (di)
    diagPosMax:     B    # Defines maximum positively-sloped diagonal (da)
"""

Glat_format_3_subbox_entry = """
    >
    left:           B    # xi
    right:          B    # xa
    bottom:         B    # yi
    top:            B    # ya
    diagNegMin:     B    # Defines minimum negatively-sloped diagonal (si)
    diagNegMax:     B    # Defines maximum negatively-sloped diagonal (sa)
    diagPosMin:     B    # Defines minimum positively-sloped diagonal (di)
    diagPosMax:     B    # Defines maximum positively-sloped diagonal (da)
"""


class _Object:
    pass


class _Dict(dict):
    pass


[docs] class table_G__l_a_t(DefaultTable.DefaultTable): """ Support Graphite Glat tables """ def __init__(self, tag=None): DefaultTable.DefaultTable.__init__(self, tag) self.scheme = 0
[docs] def decompile(self, data, ttFont): sstruct.unpack2(Glat_format_0, data, self) self.version = float(floatToFixedToStr(self.version, precisionBits=16)) if self.version <= 1.9: decoder = partial(self.decompileAttributes12, fmt=Glat_format_1_entry) elif self.version <= 2.9: decoder = partial(self.decompileAttributes12, fmt=Glat_format_23_entry) elif self.version >= 3.0: (data, self.scheme) = grUtils.decompress(data) sstruct.unpack2(Glat_format_3, data, self) self.hasOctaboxes = (self.compression & 1) == 1 decoder = self.decompileAttributes3 gloc = ttFont["Gloc"] self.attributes = {} count = 0 for s, e in zip(gloc, gloc[1:]): self.attributes[ttFont.getGlyphName(count)] = decoder(data[s:e]) count += 1
[docs] def decompileAttributes12(self, data, fmt): attributes = _Dict() while len(data) > 3: e, data = sstruct.unpack2(fmt, data, _Object()) keys = range(e.attNum, e.attNum + e.num) if len(data) >= 2 * e.num: vals = struct.unpack_from((">%dh" % e.num), data) attributes.update(zip(keys, vals)) data = data[2 * e.num :] return attributes
[docs] def decompileAttributes3(self, data): if self.hasOctaboxes: o, data = sstruct.unpack2(Glat_format_3_octabox_metrics, data, _Object()) numsub = bin(o.subboxBitmap).count("1") o.subboxes = [] for b in range(numsub): if len(data) >= 8: subbox, data = sstruct.unpack2( Glat_format_3_subbox_entry, data, _Object() ) o.subboxes.append(subbox) attrs = self.decompileAttributes12(data, Glat_format_23_entry) if self.hasOctaboxes: attrs.octabox = o return attrs
[docs] def compile(self, ttFont): data = sstruct.pack(Glat_format_0, self) if self.version <= 1.9: encoder = partial(self.compileAttributes12, fmt=Glat_format_1_entry) elif self.version <= 2.9: encoder = partial(self.compileAttributes12, fmt=Glat_format_1_entry) elif self.version >= 3.0: self.compression = (self.scheme << 27) + (1 if self.hasOctaboxes else 0) data = sstruct.pack(Glat_format_3, self) encoder = self.compileAttributes3 glocs = [] for n in range(len(self.attributes)): glocs.append(len(data)) data += encoder(self.attributes[ttFont.getGlyphName(n)]) glocs.append(len(data)) ttFont["Gloc"].set(glocs) if self.version >= 3.0: data = grUtils.compress(self.scheme, data) return data
[docs] def compileAttributes12(self, attrs, fmt): data = b"" for e in grUtils.entries(attrs): data += sstruct.pack(fmt, {"attNum": e[0], "num": e[1]}) + struct.pack( (">%dh" % len(e[2])), *e[2] ) return data
[docs] def compileAttributes3(self, attrs): if self.hasOctaboxes: o = attrs.octabox data = sstruct.pack(Glat_format_3_octabox_metrics, o) numsub = bin(o.subboxBitmap).count("1") for b in range(numsub): data += sstruct.pack(Glat_format_3_subbox_entry, o.subboxes[b]) else: data = "" return data + self.compileAttributes12(attrs, Glat_format_23_entry)
[docs] def toXML(self, writer, ttFont): writer.simpletag("version", version=self.version, compressionScheme=self.scheme) writer.newline() for n, a in sorted( self.attributes.items(), key=lambda x: ttFont.getGlyphID(x[0]) ): writer.begintag("glyph", name=n) writer.newline() if hasattr(a, "octabox"): o = a.octabox formatstring, names, fixes = sstruct.getformat( Glat_format_3_octabox_metrics ) vals = {} for k in names: if k == "subboxBitmap": continue vals[k] = "{:.3f}%".format(getattr(o, k) * 100.0 / 255) vals["bitmap"] = "{:0X}".format(o.subboxBitmap) writer.begintag("octaboxes", **vals) writer.newline() formatstring, names, fixes = sstruct.getformat( Glat_format_3_subbox_entry ) for s in o.subboxes: vals = {} for k in names: vals[k] = "{:.3f}%".format(getattr(s, k) * 100.0 / 255) writer.simpletag("octabox", **vals) writer.newline() writer.endtag("octaboxes") writer.newline() for k, v in sorted(a.items()): writer.simpletag("attribute", index=k, value=v) writer.newline() writer.endtag("glyph") writer.newline()
[docs] def fromXML(self, name, attrs, content, ttFont): if name == "version": self.version = float(safeEval(attrs["version"])) self.scheme = int(safeEval(attrs["compressionScheme"])) if name != "glyph": return if not hasattr(self, "attributes"): self.attributes = {} gname = attrs["name"] attributes = _Dict() for element in content: if not isinstance(element, tuple): continue tag, attrs, subcontent = element if tag == "attribute": k = int(safeEval(attrs["index"])) v = int(safeEval(attrs["value"])) attributes[k] = v elif tag == "octaboxes": self.hasOctaboxes = True o = _Object() o.subboxBitmap = int(attrs["bitmap"], 16) o.subboxes = [] del attrs["bitmap"] for k, v in attrs.items(): setattr(o, k, int(float(v[:-1]) * 255.0 / 100.0 + 0.5)) for element in subcontent: if not isinstance(element, tuple): continue (tag, attrs, subcontent) = element so = _Object() for k, v in attrs.items(): setattr(so, k, int(float(v[:-1]) * 255.0 / 100.0 + 0.5)) o.subboxes.append(so) attributes.octabox = o self.attributes[gname] = attributes