| 
							
								 | 
							
							"""cffLib: read/write Adobe CFF fonts
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							OpenType fonts with PostScript outlines embed a completely independent
 | 
						
						
						
						
							 | 
							
								 | 
							
							font file in Adobe's *Compact Font Format*. So dealing with OpenType fonts
 | 
						
						
						
						
							 | 
							
								 | 
							
							requires also dealing with CFF. This module allows you to read and write
 | 
						
						
						
						
							 | 
							
								 | 
							
							fonts written in the CFF format.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							In 2016, OpenType 1.8 introduced the `CFF2 <https://docs.microsoft.com/en-us/typography/opentype/spec/cff2>`_
 | 
						
						
						
						
							 | 
							
								 | 
							
							format which, along with other changes, extended the CFF format to deal with
 | 
						
						
						
						
							 | 
							
								 | 
							
							the demands of variable fonts. This module parses both original CFF and CFF2.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							"""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							from fontTools.misc import sstruct
 | 
						
						
						
						
							 | 
							
								 | 
							
							from fontTools.misc import psCharStrings
 | 
						
						
						
						
							 | 
							
								 | 
							
							from fontTools.misc.arrayTools import unionRect, intRect
 | 
						
						
						
						
							 | 
							
								 | 
							
							from fontTools.misc.textTools import (
 | 
						
						
						
						
							 | 
							
								 | 
							
							    bytechr,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    byteord,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    bytesjoin,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    tobytes,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    tostr,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    safeEval,
 | 
						
						
						
						
							 | 
							
								 | 
							
							)
 | 
						
						
						
						
							 | 
							
								 | 
							
							from fontTools.ttLib import TTFont
 | 
						
						
						
						
							 | 
							
								 | 
							
							from fontTools.ttLib.tables.otBase import OTTableWriter
 | 
						
						
						
						
							 | 
							
								 | 
							
							from fontTools.ttLib.tables.otBase import OTTableReader
 | 
						
						
						
						
							 | 
							
								 | 
							
							from fontTools.ttLib.tables import otTables as ot
 | 
						
						
						
						
							 | 
							
								 | 
							
							from io import BytesIO
 | 
						
						
						
						
							 | 
							
								 | 
							
							import struct
 | 
						
						
						
						
							 | 
							
								 | 
							
							import logging
 | 
						
						
						
						
							 | 
							
								 | 
							
							import re
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							# mute cffLib debug messages when running ttx in verbose mode
 | 
						
						
						
						
							 | 
							
								 | 
							
							DEBUG = logging.DEBUG - 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							log = logging.getLogger(__name__)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							cffHeaderFormat = """
 | 
						
						
						
						
							 | 
							
								 | 
							
								major:   B
 | 
						
						
						
						
							 | 
							
								 | 
							
								minor:   B
 | 
						
						
						
						
							 | 
							
								 | 
							
								hdrSize: B
 | 
						
						
						
						
							 | 
							
								 | 
							
							"""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							maxStackLimit = 513
 | 
						
						
						
						
							 | 
							
								 | 
							
							# maxstack operator has been deprecated. max stack is now always 513.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class CFFFontSet(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """A CFF font "file" can contain more than one font, although this is
 | 
						
						
						
						
							 | 
							
								 | 
							
							    extremely rare (and not allowed within OpenType fonts).
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    This class is the entry point for parsing a CFF table. To actually
 | 
						
						
						
						
							 | 
							
								 | 
							
							    manipulate the data inside the CFF font, you will want to access the
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ``CFFFontSet``'s :class:`TopDict` object. To do this, a ``CFFFontSet``
 | 
						
						
						
						
							 | 
							
								 | 
							
							    object can either be treated as a dictionary (with appropriate
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ``keys()`` and ``values()`` methods) mapping font names to :class:`TopDict`
 | 
						
						
						
						
							 | 
							
								 | 
							
							    objects, or as a list.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    .. code:: python
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            from fontTools import ttLib
 | 
						
						
						
						
							 | 
							
								 | 
							
							            tt = ttLib.TTFont("Tests/cffLib/data/LinLibertine_RBI.otf")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            tt["CFF "].cff
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # <fontTools.cffLib.CFFFontSet object at 0x101e24c90>
 | 
						
						
						
						
							 | 
							
								 | 
							
							            tt["CFF "].cff[0] # Here's your actual font data
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # <fontTools.cffLib.TopDict object at 0x1020f1fd0>
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def decompile(self, file, otFont, isCFF2=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """Parse a binary CFF file into an internal representation. ``file``
 | 
						
						
						
						
							 | 
							
								 | 
							
							        should be a file handle object. ``otFont`` is the top-level
 | 
						
						
						
						
							 | 
							
								 | 
							
							        :py:class:`fontTools.ttLib.ttFont.TTFont` object containing this CFF file.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        If ``isCFF2`` is passed and set to ``True`` or ``False``, then the
 | 
						
						
						
						
							 | 
							
								 | 
							
							        library makes an assertion that the CFF header is of the appropriate
 | 
						
						
						
						
							 | 
							
								 | 
							
							        version.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.otFont = otFont
 | 
						
						
						
						
							 | 
							
								 | 
							
							        sstruct.unpack(cffHeaderFormat, file.read(3), self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isCFF2 is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # called from ttLib: assert 'major' as read from file matches the
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # expected version
 | 
						
						
						
						
							 | 
							
								 | 
							
							            expected_major = 2 if isCFF2 else 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if self.major != expected_major:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                raise ValueError(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    "Invalid CFF 'major' version: expected %d, found %d"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    % (expected_major, self.major)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # use 'major' version from file to determine if isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            assert self.major in (1, 2), "Unknown CFF format"
 | 
						
						
						
						
							 | 
							
								 | 
							
							            isCFF2 = self.major == 2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.offSize = struct.unpack("B", file.read(1))[0]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            file.seek(self.hdrSize)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.fontNames = list(tostr(s) for s in Index(file, isCFF2=isCFF2))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.topDictIndex = TopDictIndex(file, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.strings = IndexedStrings(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:  # isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.topDictSize = struct.unpack(">H", file.read(2))[0]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            file.seek(self.hdrSize)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.fontNames = ["CFF2Font"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            cff2GetGlyphOrder = otFont.getGlyphOrder
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # in CFF2, offsetSize is the size of the TopDict data.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.topDictIndex = TopDictIndex(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                file, cff2GetGlyphOrder, self.topDictSize, isCFF2=isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            )
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.strings = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.GlobalSubrs = GlobalSubrsIndex(file, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.topDictIndex.strings = self.strings
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.topDictIndex.GlobalSubrs = self.GlobalSubrs
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __len__(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.fontNames)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def keys(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return list(self.fontNames)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def values(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.topDictIndex
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __getitem__(self, nameOrIndex):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """Return TopDict instance identified by name (str) or index (int
 | 
						
						
						
						
							 | 
							
								 | 
							
							        or any object that implements `__index__`).
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(nameOrIndex, "__index__"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            index = nameOrIndex.__index__()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif isinstance(nameOrIndex, str):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            name = nameOrIndex
 | 
						
						
						
						
							 | 
							
								 | 
							
							            try:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                index = self.fontNames.index(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            except ValueError:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                raise KeyError(nameOrIndex)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            raise TypeError(nameOrIndex)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.topDictIndex[index]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def compile(self, file, otFont, isCFF2=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """Write the object back into binary representation onto the given file.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ``file`` should be a file handle object. ``otFont`` is the top-level
 | 
						
						
						
						
							 | 
							
								 | 
							
							        :py:class:`fontTools.ttLib.ttFont.TTFont` object containing this CFF file.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        If ``isCFF2`` is passed and set to ``True`` or ``False``, then the
 | 
						
						
						
						
							 | 
							
								 | 
							
							        library makes an assertion that the CFF header is of the appropriate
 | 
						
						
						
						
							 | 
							
								 | 
							
							        version.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.otFont = otFont
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isCFF2 is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # called from ttLib: assert 'major' value matches expected version
 | 
						
						
						
						
							 | 
							
								 | 
							
							            expected_major = 2 if isCFF2 else 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if self.major != expected_major:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                raise ValueError(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    "Invalid CFF 'major' version: expected %d, found %d"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    % (expected_major, self.major)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # use current 'major' value to determine output format
 | 
						
						
						
						
							 | 
							
								 | 
							
							            assert self.major in (1, 2), "Unknown CFF format"
 | 
						
						
						
						
							 | 
							
								 | 
							
							            isCFF2 = self.major == 2
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if otFont.recalcBBoxes and not isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for topDict in self.topDictIndex:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                topDict.recalcFontBBox()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            strings = IndexedStrings()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            strings = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        writer = CFFWriter(isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        topCompiler = self.topDictIndex.getCompiler(strings, self, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.hdrSize = 5
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writer.add(sstruct.pack(cffHeaderFormat, self))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # Note: topDictSize will most likely change in CFFWriter.toFile().
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.topDictSize = topCompiler.getDataLength()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writer.add(struct.pack(">H", self.topDictSize))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.hdrSize = 4
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.offSize = 4  # will most likely change in CFFWriter.toFile().
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writer.add(sstruct.pack(cffHeaderFormat, self))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writer.add(struct.pack("B", self.offSize))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fontNames = Index()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for name in self.fontNames:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fontNames.append(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writer.add(fontNames.getCompiler(strings, self, isCFF2=isCFF2))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        writer.add(topCompiler)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writer.add(strings.getCompiler())
 | 
						
						
						
						
							 | 
							
								 | 
							
							        writer.add(self.GlobalSubrs.getCompiler(strings, self, isCFF2=isCFF2))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for topDict in self.topDictIndex:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if not hasattr(topDict, "charset") or topDict.charset is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charset = otFont.getGlyphOrder()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                topDict.charset = charset
 | 
						
						
						
						
							 | 
							
								 | 
							
							        children = topCompiler.getChildren(strings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for child in children:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writer.add(child)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        writer.toFile(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toXML(self, xmlWriter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """Write the object into XML representation onto the given
 | 
						
						
						
						
							 | 
							
								 | 
							
							        :class:`fontTools.misc.xmlWriter.XMLWriter`.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        .. code:: python
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                writer = xmlWriter.XMLWriter(sys.stdout)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                tt["CFF "].cff.toXML(writer)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.simpletag("major", value=self.major)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.simpletag("minor", value=self.minor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for fontName in self.fontNames:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.begintag("CFFFont", name=tostr(fontName))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            font = self[fontName]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            font.toXML(xmlWriter)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.endtag("CFFFont")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.begintag("GlobalSubrs")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.GlobalSubrs.toXML(xmlWriter)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.endtag("GlobalSubrs")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def fromXML(self, name, attrs, content, otFont=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """Reads data from the XML element into the ``CFFFontSet`` object."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.otFont = otFont
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # set defaults. These will be replaced if there are entries for them
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # in the XML file.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not hasattr(self, "major"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.major = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not hasattr(self, "minor"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.minor = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if name == "CFFFont":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if self.major == 1:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if not hasattr(self, "offSize"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    # this will be recalculated when the cff is compiled.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.offSize = 4
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if not hasattr(self, "hdrSize"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.hdrSize = 4
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if not hasattr(self, "GlobalSubrs"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.GlobalSubrs = GlobalSubrsIndex()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if not hasattr(self, "fontNames"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.fontNames = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.topDictIndex = TopDictIndex()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fontName = attrs["name"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.fontNames.append(fontName)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                topDict = TopDict(GlobalSubrs=self.GlobalSubrs)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                topDict.charset = None  # gets filled in later
 | 
						
						
						
						
							 | 
							
								 | 
							
							            elif self.major == 2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if not hasattr(self, "hdrSize"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.hdrSize = 5
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if not hasattr(self, "GlobalSubrs"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.GlobalSubrs = GlobalSubrsIndex()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if not hasattr(self, "fontNames"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.fontNames = ["CFF2Font"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                cff2GetGlyphOrder = self.otFont.getGlyphOrder
 | 
						
						
						
						
							 | 
							
								 | 
							
							                topDict = TopDict(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    GlobalSubrs=self.GlobalSubrs, cff2GetGlyphOrder=cff2GetGlyphOrder
 | 
						
						
						
						
							 | 
							
								 | 
							
							                )
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.topDictIndex = TopDictIndex(None, cff2GetGlyphOrder)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.topDictIndex.append(topDict)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for element in content:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if isinstance(element, str):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							                name, attrs, content = element
 | 
						
						
						
						
							 | 
							
								 | 
							
							                topDict.fromXML(name, attrs, content)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(topDict, "VarStore") and topDict.FDArray[0].vstore is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fdArray = topDict.FDArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for fontDict in fdArray:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if hasattr(fontDict, "Private"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        fontDict.Private.vstore = topDict.VarStore
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif name == "GlobalSubrs":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            subrCharStringClass = psCharStrings.T2CharString
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if not hasattr(self, "GlobalSubrs"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.GlobalSubrs = GlobalSubrsIndex()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for element in content:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if isinstance(element, str):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							                name, attrs, content = element
 | 
						
						
						
						
							 | 
							
								 | 
							
							                subr = subrCharStringClass()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                subr.fromXML(name, attrs, content)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.GlobalSubrs.append(subr)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif name == "major":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.major = int(attrs["value"])
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif name == "minor":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.minor = int(attrs["value"])
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def convertCFFToCFF2(self, otFont):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        from .CFFToCFF2 import _convertCFFToCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        _convertCFFToCFF2(self, otFont)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def convertCFF2ToCFF(self, otFont):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        from .CFF2ToCFF import _convertCFF2ToCFF
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        _convertCFF2ToCFF(self, otFont)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def desubroutinize(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        from .transforms import desubroutinize
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        desubroutinize(self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def remove_hints(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        from .transforms import remove_hints
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        remove_hints(self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def remove_unused_subroutines(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        from .transforms import remove_unused_subroutines
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        remove_unused_subroutines(self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class CFFWriter(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """Helper class for serializing CFF data to binary. Used by
 | 
						
						
						
						
							 | 
							
								 | 
							
							    :meth:`CFFFontSet.compile`."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, isCFF2):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.data = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.isCFF2 = isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def add(self, table):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.data.append(table)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toFile(self, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        lastPosList = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        count = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        while True:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            log.log(DEBUG, "CFFWriter.toFile() iteration: %d", count)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            count = count + 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							            pos = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            posList = [pos]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for item in self.data:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if hasattr(item, "getDataLength"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    endPos = pos + item.getDataLength()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if isinstance(item, TopDictIndexCompiler) and item.isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        self.topDictSize = item.getDataLength()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    endPos = pos + len(item)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if hasattr(item, "setPos"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    item.setPos(pos, endPos)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                pos = endPos
 | 
						
						
						
						
							 | 
							
								 | 
							
							                posList.append(pos)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if posList == lastPosList:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                break
 | 
						
						
						
						
							 | 
							
								 | 
							
							            lastPosList = posList
 | 
						
						
						
						
							 | 
							
								 | 
							
							        log.log(DEBUG, "CFFWriter.toFile() writing to file.")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        begin = file.tell()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.data[1] = struct.pack(">H", self.topDictSize)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.offSize = calcOffSize(lastPosList[-1])
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.data[1] = struct.pack("B", self.offSize)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        posList = [0]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for item in self.data:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(item, "toFile"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                item.toFile(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                file.write(item)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            posList.append(file.tell() - begin)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        assert posList == lastPosList
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def calcOffSize(largestOffset):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if largestOffset < 0x100:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offSize = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							    elif largestOffset < 0x10000:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offSize = 2
 | 
						
						
						
						
							 | 
							
								 | 
							
							    elif largestOffset < 0x1000000:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offSize = 3
 | 
						
						
						
						
							 | 
							
								 | 
							
							    else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offSize = 4
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return offSize
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class IndexCompiler(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """Base class for writing CFF `INDEX data <https://docs.microsoft.com/en-us/typography/opentype/spec/cff2#5-index-data>`_
 | 
						
						
						
						
							 | 
							
								 | 
							
							    to binary."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, items, strings, parent, isCFF2=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isCFF2 is None and hasattr(parent, "isCFF2"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            isCFF2 = parent.isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            assert isCFF2 is not None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.isCFF2 = isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.items = self.getItems(items, strings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent = parent
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getItems(self, items, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return items
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getOffsets(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # An empty INDEX contains only the count field.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            pos = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							            offsets = [pos]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for item in self.items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if hasattr(item, "getDataLength"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    pos = pos + item.getDataLength()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    pos = pos + len(item)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                offsets.append(pos)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            offsets = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return offsets
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getDataLength(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            countSize = 4
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            countSize = 2
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            lastOffset = self.getOffsets()[-1]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            offSize = calcOffSize(lastOffset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            dataLength = (
 | 
						
						
						
						
							 | 
							
								 | 
							
							                countSize
 | 
						
						
						
						
							 | 
							
								 | 
							
							                + 1  # count
 | 
						
						
						
						
							 | 
							
								 | 
							
							                + (len(self.items) + 1) * offSize  # offSize
 | 
						
						
						
						
							 | 
							
								 | 
							
							                + lastOffset  # the offsets
 | 
						
						
						
						
							 | 
							
								 | 
							
							                - 1  # size of object data
 | 
						
						
						
						
							 | 
							
								 | 
							
							            )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # count. For empty INDEX tables, this is the only entry.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            dataLength = countSize
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return dataLength
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toFile(self, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offsets = self.getOffsets()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writeCard32(file, len(self.items))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writeCard16(file, len(self.items))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # An empty INDEX contains only the count field.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            offSize = calcOffSize(offsets[-1])
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writeCard8(file, offSize)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            offSize = -offSize
 | 
						
						
						
						
							 | 
							
								 | 
							
							            pack = struct.pack
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for offset in offsets:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                binOffset = pack(">l", offset)[offSize:]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                assert len(binOffset) == -offSize
 | 
						
						
						
						
							 | 
							
								 | 
							
							                file.write(binOffset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for item in self.items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if hasattr(item, "toFile"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    item.toFile(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    data = tobytes(item, encoding="latin1")
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    file.write(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class IndexedStringsCompiler(IndexCompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getItems(self, items, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return items.strings
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class TopDictIndexCompiler(IndexCompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """Helper class for writing the TopDict to binary."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getItems(self, items, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        out = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for item in items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            out.append(item.getCompiler(strings, self))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return out
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getChildren(self, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        children = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for topDict in self.items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.extend(topDict.getChildren(strings))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return children
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getOffsets(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            offsets = [0, self.items[0].getDataLength()]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return offsets
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return super(TopDictIndexCompiler, self).getOffsets()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getDataLength(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            dataLength = self.items[0].getDataLength()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return dataLength
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return super(TopDictIndexCompiler, self).getDataLength()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toFile(self, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.items[0].toFile(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            super(TopDictIndexCompiler, self).toFile(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class FDArrayIndexCompiler(IndexCompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """Helper class for writing the
 | 
						
						
						
						
							 | 
							
								 | 
							
							    `Font DICT INDEX <https://docs.microsoft.com/en-us/typography/opentype/spec/cff2#10-font-dict-index-font-dicts-and-fdselect>`_
 | 
						
						
						
						
							 | 
							
								 | 
							
							    to binary."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getItems(self, items, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        out = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for item in items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            out.append(item.getCompiler(strings, self))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return out
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getChildren(self, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        children = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for fontDict in self.items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.extend(fontDict.getChildren(strings))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return children
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toFile(self, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offsets = self.getOffsets()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writeCard32(file, len(self.items))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            writeCard16(file, len(self.items))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offSize = calcOffSize(offsets[-1])
 | 
						
						
						
						
							 | 
							
								 | 
							
							        writeCard8(file, offSize)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offSize = -offSize
 | 
						
						
						
						
							 | 
							
								 | 
							
							        pack = struct.pack
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for offset in offsets:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            binOffset = pack(">l", offset)[offSize:]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            assert len(binOffset) == -offSize
 | 
						
						
						
						
							 | 
							
								 | 
							
							            file.write(binOffset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for item in self.items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(item, "toFile"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                item.toFile(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                file.write(item)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def setPos(self, pos, endPos):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent.rawDict["FDArray"] = pos
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class GlobalSubrsCompiler(IndexCompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """Helper class for writing the `global subroutine INDEX <https://docs.microsoft.com/en-us/typography/opentype/spec/cff2#9-local-and-global-subr-indexes>`_
 | 
						
						
						
						
							 | 
							
								 | 
							
							    to binary."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getItems(self, items, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        out = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for cs in items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            cs.compile(self.isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            out.append(cs.bytecode)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return out
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class SubrsCompiler(GlobalSubrsCompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """Helper class for writing the `local subroutine INDEX <https://docs.microsoft.com/en-us/typography/opentype/spec/cff2#9-local-and-global-subr-indexes>`_
 | 
						
						
						
						
							 | 
							
								 | 
							
							    to binary."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def setPos(self, pos, endPos):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offset = pos - self.parent.pos
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent.rawDict["Subrs"] = offset
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class CharStringsCompiler(GlobalSubrsCompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """Helper class for writing the `CharStrings INDEX <https://docs.microsoft.com/en-us/typography/opentype/spec/cff2#9-local-and-global-subr-indexes>`_
 | 
						
						
						
						
							 | 
							
								 | 
							
							    to binary."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getItems(self, items, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        out = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for cs in items:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            cs.compile(self.isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            out.append(cs.bytecode)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return out
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def setPos(self, pos, endPos):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent.rawDict["CharStrings"] = pos
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class Index(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """This class represents what the CFF spec calls an INDEX (an array of
 | 
						
						
						
						
							 | 
							
								 | 
							
							    variable-sized objects). `Index` items can be addressed and set using
 | 
						
						
						
						
							 | 
							
								 | 
							
							    Python list indexing."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    compilerClass = IndexCompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, file=None, isCFF2=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.items = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.offsets = offsets = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        name = self.__class__.__name__
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if file is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self._isCFF2 = isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        log.log(DEBUG, "loading %s at %s", name, file.tell())
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.file = file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            count = readCard32(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            count = readCard16(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if count == 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.items = [None] * count
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offSize = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        log.log(DEBUG, "    index count: %s offSize: %s", count, offSize)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        assert offSize <= 4, "offSize too large: %s" % offSize
 | 
						
						
						
						
							 | 
							
								 | 
							
							        pad = b"\0" * (4 - offSize)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for index in range(count + 1):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            chunk = file.read(offSize)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            chunk = pad + chunk
 | 
						
						
						
						
							 | 
							
								 | 
							
							            (offset,) = struct.unpack(">L", chunk)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            offsets.append(int(offset))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.offsetBase = file.tell() - 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.seek(self.offsetBase + offsets[-1])  # pretend we've read the whole lot
 | 
						
						
						
						
							 | 
							
								 | 
							
							        log.log(DEBUG, "    end of %s at %s", name, file.tell())
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __len__(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.items)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __getitem__(self, index):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        item = self.items[index]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if item is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return item
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offset = self.offsets[index] + self.offsetBase
 | 
						
						
						
						
							 | 
							
								 | 
							
							        size = self.offsets[index + 1] - self.offsets[index]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file = self.file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.seek(offset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data = file.read(size)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        assert len(data) == size
 | 
						
						
						
						
							 | 
							
								 | 
							
							        item = self.produceItem(index, data, file, offset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.items[index] = item
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return item
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __setitem__(self, index, item):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.items[index] = item
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def produceItem(self, index, data, file, offset):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return data
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def append(self, item):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """Add an item to an INDEX."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.items.append(item)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getCompiler(self, strings, parent, isCFF2=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.compilerClass(self, strings, parent, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def clear(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """Empty the INDEX."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							        del self.items[:]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class GlobalSubrsIndex(Index):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """This index contains all the global subroutines in the font. A global
 | 
						
						
						
						
							 | 
							
								 | 
							
							    subroutine is a set of ``CharString`` data which is accessible to any
 | 
						
						
						
						
							 | 
							
								 | 
							
							    glyph in the font, and are used to store repeated instructions - for
 | 
						
						
						
						
							 | 
							
								 | 
							
							    example, components may be encoded as global subroutines, but so could
 | 
						
						
						
						
							 | 
							
								 | 
							
							    hinting instructions.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    Remember that when interpreting a ``callgsubr`` instruction (or indeed
 | 
						
						
						
						
							 | 
							
								 | 
							
							    a ``callsubr`` instruction) that you will need to add the "subroutine
 | 
						
						
						
						
							 | 
							
								 | 
							
							    number bias" to number given:
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    .. code:: python
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            tt = ttLib.TTFont("Almendra-Bold.otf")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            u = tt["CFF "].cff[0].CharStrings["udieresis"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            u.decompile()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            u.toXML(XMLWriter(sys.stdout))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # <some stuff>
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # -64 callgsubr <-- Subroutine which implements the dieresis mark
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # <other stuff>
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            tt["CFF "].cff[0].GlobalSubrs[-64] # <-- WRONG
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # <T2CharString (bytecode) at 103451d10>
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            tt["CFF "].cff[0].GlobalSubrs[-64 + 107] # <-- RIGHT
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # <T2CharString (source) at 103451390>
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ("The bias applied depends on the number of subrs (gsubrs). If the number of
 | 
						
						
						
						
							 | 
							
								 | 
							
							    subrs (gsubrs) is less than 1240, the bias is 107. Otherwise if it is less
 | 
						
						
						
						
							 | 
							
								 | 
							
							    than 33900, it is 1131; otherwise it is 32768.",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    `Subroutine Operators <https://docs.microsoft.com/en-us/typography/opentype/otspec180/cff2charstr#section4.4>`)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    compilerClass = GlobalSubrsCompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							    subrClass = psCharStrings.T2CharString
 | 
						
						
						
						
							 | 
							
								 | 
							
							    charStringClass = psCharStrings.T2CharString
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        globalSubrs=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        private=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdSelect=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdArray=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCFF2=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        super(GlobalSubrsIndex, self).__init__(file, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.globalSubrs = globalSubrs
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.private = private
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if fdSelect:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.fdSelect = fdSelect
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if fdArray:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.fdArray = fdArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def produceItem(self, index, data, file, offset):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.private is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            private = self.private
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif hasattr(self, "fdArray") and self.fdArray is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(self, "fdSelect") and self.fdSelect is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fdIndex = self.fdSelect[index]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fdIndex = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            private = self.fdArray[fdIndex].Private
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            private = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.subrClass(data, private=private, globalSubrs=self.globalSubrs)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toXML(self, xmlWriter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """Write the subroutines index into XML representation onto the given
 | 
						
						
						
						
							 | 
							
								 | 
							
							        :class:`fontTools.misc.xmlWriter.XMLWriter`.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        .. code:: python
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                writer = xmlWriter.XMLWriter(sys.stdout)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                tt["CFF "].cff[0].GlobalSubrs.toXML(writer)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.comment(
 | 
						
						
						
						
							 | 
							
								 | 
							
							            "The 'index' attribute is only for humans; " "it is ignored when parsed."
 | 
						
						
						
						
							 | 
							
								 | 
							
							        )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for i in range(len(self)):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            subr = self[i]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if subr.needsDecompilation():
 | 
						
						
						
						
							 | 
							
								 | 
							
							                xmlWriter.begintag("CharString", index=i, raw=1)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                xmlWriter.begintag("CharString", index=i)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            subr.toXML(xmlWriter)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.endtag("CharString")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def fromXML(self, name, attrs, content):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if name != "CharString":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return
 | 
						
						
						
						
							 | 
							
								 | 
							
							        subr = self.subrClass()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        subr.fromXML(name, attrs, content)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.append(subr)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getItemAndSelector(self, index):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        sel = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(self, "fdSelect"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            sel = self.fdSelect[index]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self[index], sel
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class SubrsIndex(GlobalSubrsIndex):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """This index contains a glyph's local subroutines. A local subroutine is a
 | 
						
						
						
						
							 | 
							
								 | 
							
							    private set of ``CharString`` data which is accessible only to the glyph to
 | 
						
						
						
						
							 | 
							
								 | 
							
							    which the index is attached."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    compilerClass = SubrsCompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class TopDictIndex(Index):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """This index represents the array of ``TopDict`` structures in the font
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (again, usually only one entry is present). Hence the following calls are
 | 
						
						
						
						
							 | 
							
								 | 
							
							    equivalent:
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    .. code:: python
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            tt["CFF "].cff[0]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # <fontTools.cffLib.TopDict object at 0x102ed6e50>
 | 
						
						
						
						
							 | 
							
								 | 
							
							            tt["CFF "].cff.topDictIndex[0]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # <fontTools.cffLib.TopDict object at 0x102ed6e50>
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    compilerClass = TopDictIndexCompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, file=None, cff2GetGlyphOrder=None, topSize=0, isCFF2=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.cff2GetGlyphOrder = cff2GetGlyphOrder
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if file is not None and isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self._isCFF2 = isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.items = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							            name = self.__class__.__name__
 | 
						
						
						
						
							 | 
							
								 | 
							
							            log.log(DEBUG, "loading %s at %s", name, file.tell())
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.file = file
 | 
						
						
						
						
							 | 
							
								 | 
							
							            count = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.items = [None] * count
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.offsets = [0, topSize]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.offsetBase = file.tell()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # pretend we've read the whole lot
 | 
						
						
						
						
							 | 
							
								 | 
							
							            file.seek(self.offsetBase + topSize)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            log.log(DEBUG, "    end of %s at %s", name, file.tell())
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            super(TopDictIndex, self).__init__(file, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def produceItem(self, index, data, file, offset):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        top = TopDict(
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.strings,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            file,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            offset,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.GlobalSubrs,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.cff2GetGlyphOrder,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            isCFF2=self._isCFF2,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        top.decompile(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return top
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toXML(self, xmlWriter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for i in range(len(self)):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.begintag("FontDict", index=i)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self[i].toXML(xmlWriter)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.endtag("FontDict")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class FDArrayIndex(Index):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    compilerClass = FDArrayIndexCompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toXML(self, xmlWriter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for i in range(len(self)):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.begintag("FontDict", index=i)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self[i].toXML(xmlWriter)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.endtag("FontDict")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def produceItem(self, index, data, file, offset):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fontDict = FontDict(
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.strings,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            file,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            offset,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.GlobalSubrs,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            isCFF2=self._isCFF2,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            vstore=self.vstore,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fontDict.decompile(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return fontDict
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def fromXML(self, name, attrs, content):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if name != "FontDict":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fontDict = FontDict()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for element in content:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if isinstance(element, str):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            name, attrs, content = element
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fontDict.fromXML(name, attrs, content)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.append(fontDict)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class VarStoreData(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, file=None, otVarStore=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.file = file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.data = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.otVarStore = otVarStore
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.font = TTFont()  # dummy font for the decompile function.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def decompile(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.file:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # read data in from file. Assume position is correct.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            length = readCard16(self.file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # https://github.com/fonttools/fonttools/issues/3673
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if length == 65535:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.data = self.file.read()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.data = self.file.read(length)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            globalState = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							            reader = OTTableReader(self.data, globalState)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.otVarStore = ot.VarStore()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.otVarStore.decompile(reader, self.font)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.data = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def compile(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        writer = OTTableWriter()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.otVarStore.compile(writer, self.font)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # Note that this omits the initial Card16 length from the CFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # VarStore data block
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.data = writer.getAllData()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def writeXML(self, xmlWriter, name):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.otVarStore.toXML(xmlWriter, self.font)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.otVarStore = ot.VarStore()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for element in content:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if isinstance(element, tuple):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                name, attrs, content = element
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.otVarStore.fromXML(name, attrs, content, self.font)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                pass
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return None
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __len__(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getNumRegions(self, vsIndex):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if vsIndex is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            vsIndex = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							        varData = self.otVarStore.VarData[vsIndex]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        numRegions = varData.VarRegionCount
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return numRegions
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class FDSelect(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, file=None, numGlyphs=None, format=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if file:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # read data in from file
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.format = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if self.format == 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                from array import array
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.gidArray = array("B", file.read(numGlyphs)).tolist()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            elif self.format == 3:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                gidArray = [None] * numGlyphs
 | 
						
						
						
						
							 | 
							
								 | 
							
							                nRanges = readCard16(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fd = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							                prev = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for i in range(nRanges):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    first = readCard16(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if prev is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        for glyphID in range(prev, first):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            gidArray[glyphID] = fd
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    prev = first
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    fd = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if prev is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    first = readCard16(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    for glyphID in range(prev, first):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        gidArray[glyphID] = fd
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.gidArray = gidArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							            elif self.format == 4:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                gidArray = [None] * numGlyphs
 | 
						
						
						
						
							 | 
							
								 | 
							
							                nRanges = readCard32(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fd = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							                prev = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for i in range(nRanges):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    first = readCard32(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if prev is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        for glyphID in range(prev, first):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            gidArray[glyphID] = fd
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    prev = first
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    fd = readCard16(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if prev is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    first = readCard32(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    for glyphID in range(prev, first):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        gidArray[glyphID] = fd
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.gidArray = gidArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                assert False, "unsupported FDSelect format: %s" % format
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # reading from XML. Make empty gidArray, and leave format as passed in.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # format is None will result in the smallest representation being used.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.format = format
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.gidArray = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __len__(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.gidArray)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __getitem__(self, index):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.gidArray[index]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __setitem__(self, index, fdSelectValue):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.gidArray[index] = fdSelectValue
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def append(self, fdSelectValue):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.gidArray.append(fdSelectValue)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class CharStrings(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """The ``CharStrings`` in the font represent the instructions for drawing
 | 
						
						
						
						
							 | 
							
								 | 
							
							    each glyph. This object presents a dictionary interface to the font's
 | 
						
						
						
						
							 | 
							
								 | 
							
							    CharStrings, indexed by glyph name:
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    .. code:: python
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            tt["CFF "].cff[0].CharStrings["a"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # <T2CharString (bytecode) at 103451e90>
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    See :class:`fontTools.misc.psCharStrings.T1CharString` and
 | 
						
						
						
						
							 | 
							
								 | 
							
							    :class:`fontTools.misc.psCharStrings.T2CharString` for how to decompile,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    compile and interpret the glyph drawing instructions in the returned objects.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        charset,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        globalSubrs,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        private,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdSelect,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdArray,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCFF2=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        varStore=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.globalSubrs = globalSubrs
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.varStore = varStore
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if file is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.charStringsIndex = SubrsIndex(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                file, globalSubrs, private, fdSelect, fdArray, isCFF2=isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            )
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.charStrings = charStrings = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for i in range(len(charset)):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charStrings[charset[i]] = i
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # read from OTF file: charStrings.values() are indices into
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # charStringsIndex.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.charStringsAreIndexed = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.charStrings = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # read from ttx file: charStrings.values() are actual charstrings
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.charStringsAreIndexed = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.private = private
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if fdSelect is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.fdSelect = fdSelect
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if fdArray is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.fdArray = fdArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def keys(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return list(self.charStrings.keys())
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def values(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.charStringsAreIndexed:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self.charStringsIndex
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return list(self.charStrings.values())
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def has_key(self, name):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return name in self.charStrings
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    __contains__ = has_key
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __len__(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.charStrings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __getitem__(self, name):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        charString = self.charStrings[name]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.charStringsAreIndexed:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charString = self.charStringsIndex[charString]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return charString
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __setitem__(self, name, charString):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.charStringsAreIndexed:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            index = self.charStrings[name]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.charStringsIndex[index] = charString
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.charStrings[name] = charString
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getItemAndSelector(self, name):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.charStringsAreIndexed:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            index = self.charStrings[name]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self.charStringsIndex.getItemAndSelector(index)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(self, "fdArray"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if hasattr(self, "fdSelect"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    sel = self.charStrings[name].fdSelectIndex
 | 
						
						
						
						
							 | 
							
								 | 
							
							                else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    sel = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                sel = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self.charStrings[name], sel
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toXML(self, xmlWriter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        names = sorted(self.keys())
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for name in names:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charStr, fdSelectIndex = self.getItemAndSelector(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if charStr.needsDecompilation():
 | 
						
						
						
						
							 | 
							
								 | 
							
							                raw = [("raw", 1)]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                raw = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if fdSelectIndex is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                xmlWriter.begintag("CharString", [("name", name)] + raw)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                xmlWriter.begintag(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    "CharString",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    [("name", name), ("fdSelectIndex", fdSelectIndex)] + raw,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                )
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charStr.toXML(xmlWriter)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.endtag("CharString")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def fromXML(self, name, attrs, content):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for element in content:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if isinstance(element, str):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            name, attrs, content = element
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if name != "CharString":
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdID = -1
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(self, "fdArray"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                try:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    fdID = safeEval(attrs["fdSelectIndex"])
 | 
						
						
						
						
							 | 
							
								 | 
							
							                except KeyError:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    fdID = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							                private = self.fdArray[fdID].Private
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                private = self.private
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            glyphName = attrs["name"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charStringClass = psCharStrings.T2CharString
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charString = charStringClass(private=private, globalSubrs=self.globalSubrs)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charString.fromXML(name, attrs, content)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if fdID >= 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charString.fdSelectIndex = fdID
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self[glyphName] = charString
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def readCard8(file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return byteord(file.read(1))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def readCard16(file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (value,) = struct.unpack(">H", file.read(2))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def readCard32(file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (value,) = struct.unpack(">L", file.read(4))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def writeCard8(file, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    file.write(bytechr(value))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def writeCard16(file, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    file.write(struct.pack(">H", value))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def writeCard32(file, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    file.write(struct.pack(">L", value))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def packCard8(value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return bytechr(value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def packCard16(value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return struct.pack(">H", value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def packCard32(value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return struct.pack(">L", value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def buildOperatorDict(table):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    d = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for op, name, arg, default, conv in table:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        d[op] = (name, arg)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return d
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def buildOpcodeDict(table):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    d = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for op, name, arg, default, conv in table:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isinstance(op, tuple):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            op = bytechr(op[0]) + bytechr(op[1])
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            op = bytechr(op)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        d[name] = (op, arg)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return d
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def buildOrder(table):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    l = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for op, name, arg, default, conv in table:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        l.append(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return l
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def buildDefaults(table):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    d = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for op, name, arg, default, conv in table:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if default is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            d[name] = default
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return d
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def buildConverters(table):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    d = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for op, name, arg, default, conv in table:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        d[name] = conv
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return d
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class SimpleConverter(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not hasattr(parent, "file"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self._read(parent, value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file = parent.file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        pos = file.tell()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        try:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self._read(parent, value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        finally:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            file.seek(pos)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.simpletag(name, value=value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return attrs["value"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class ASCIIConverter(SimpleConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return tostr(value, encoding="ascii")
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return tobytes(value, encoding="ascii")
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.simpletag(name, value=tostr(value, encoding="ascii"))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return tobytes(attrs["value"], encoding=("ascii"))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class Latin1Converter(SimpleConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return tostr(value, encoding="latin1")
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return tobytes(value, encoding="latin1")
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value = tostr(value, encoding="latin1")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if name in ["Notice", "Copyright"]:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value = re.sub(r"[\r\n]\s+", " ", value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.simpletag(name, value=value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return tobytes(attrs["value"], encoding=("latin1"))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def parseNum(s):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    try:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value = int(s)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    except:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value = float(s)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def parseBlendList(s):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    valueList = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for element in s:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isinstance(element, str):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							        name, attrs, content = element
 | 
						
						
						
						
							 | 
							
								 | 
							
							        blendList = attrs["value"].split()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        blendList = [eval(val) for val in blendList]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        valueList.append(blendList)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if len(valueList) == 1:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        valueList = valueList[0]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return valueList
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class NumberConverter(SimpleConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isinstance(value, list):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.begintag(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.indent()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            blendValue = " ".join([str(val) for val in value])
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.simpletag(kBlendDictOpName, value=blendValue)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.dedent()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.endtag(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.simpletag(name, value=value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        valueString = attrs.get("value", None)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if valueString is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value = parseBlendList(content)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value = parseNum(attrs["value"])
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class ArrayConverter(SimpleConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if value and isinstance(value[0], list):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.begintag(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.indent()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for valueList in value:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                blendValue = " ".join([str(val) for val in valueList])
 | 
						
						
						
						
							 | 
							
								 | 
							
							                xmlWriter.simpletag(kBlendDictOpName, value=blendValue)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.dedent()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.endtag(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value = " ".join([str(val) for val in value])
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.simpletag(name, value=value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        valueString = attrs.get("value", None)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if valueString is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            valueList = parseBlendList(content)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            values = valueString.split()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            valueList = [parseNum(value) for value in values]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return valueList
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class TableConverter(SimpleConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.begintag(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value.toXML(xmlWriter)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.endtag(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ob = self.getClass()()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for element in content:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if isinstance(element, str):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            name, attrs, content = element
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ob.fromXML(name, attrs, content)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return ob
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class PrivateDictConverter(TableConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getClass(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return PrivateDict
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        size, offset = value
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file = parent.file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCFF2 = parent._isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        try:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            vstore = parent.vstore
 | 
						
						
						
						
							 | 
							
								 | 
							
							        except AttributeError:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            vstore = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        priv = PrivateDict(parent.strings, file, offset, isCFF2=isCFF2, vstore=vstore)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.seek(offset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data = file.read(size)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        assert len(data) == size
 | 
						
						
						
						
							 | 
							
								 | 
							
							        priv.decompile(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return priv
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return (0, 0)  # dummy value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class SubrsConverter(TableConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getClass(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return SubrsIndex
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file = parent.file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCFF2 = parent._isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.seek(parent.offset + value)  # Offset(self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return SubrsIndex(file, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return 0  # dummy value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class CharStringsConverter(TableConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file = parent.file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCFF2 = parent._isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        charset = parent.charset
 | 
						
						
						
						
							 | 
							
								 | 
							
							        varStore = getattr(parent, "VarStore", None)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        globalSubrs = parent.GlobalSubrs
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(parent, "FDArray"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdArray = parent.FDArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(parent, "FDSelect"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fdSelect = parent.FDSelect
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fdSelect = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							            private = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdSelect, fdArray = None, None
 | 
						
						
						
						
							 | 
							
								 | 
							
							            private = parent.Private
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.seek(value)  # Offset(0)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        charStrings = CharStrings(
 | 
						
						
						
						
							 | 
							
								 | 
							
							            file,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charset,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            globalSubrs,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            private,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdSelect,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdArray,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            isCFF2=isCFF2,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            varStore=varStore,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return charStrings
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return 0  # dummy value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(parent, "FDArray"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # if it is a CID-keyed font, then the private Dict is extracted from the
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # parent.FDArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdArray = parent.FDArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(parent, "FDSelect"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fdSelect = parent.FDSelect
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fdSelect = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							            private = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # if it is a name-keyed font, then the private dict is in the top dict,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # and
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # there is no fdArray.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            private, fdSelect, fdArray = parent.Private, None, None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        charStrings = CharStrings(
 | 
						
						
						
						
							 | 
							
								 | 
							
							            None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            parent.GlobalSubrs,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            private,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdSelect,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdArray,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            varStore=getattr(parent, "VarStore", None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							        )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        charStrings.fromXML(name, attrs, content)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return charStrings
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class CharsetConverter(SimpleConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCID = hasattr(parent, "ROS")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if value > 2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            numGlyphs = parent.numGlyphs
 | 
						
						
						
						
							 | 
							
								 | 
							
							            file = parent.file
 | 
						
						
						
						
							 | 
							
								 | 
							
							            file.seek(value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            log.log(DEBUG, "loading charset at %s", value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            format = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if format == 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charset = parseCharset0(numGlyphs, file, parent.strings, isCID)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            elif format == 1 or format == 2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charset = parseCharset(numGlyphs, file, parent.strings, isCID, format)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                raise NotImplementedError
 | 
						
						
						
						
							 | 
							
								 | 
							
							            assert len(charset) == numGlyphs
 | 
						
						
						
						
							 | 
							
								 | 
							
							            log.log(DEBUG, "    charset end at %s", file.tell())
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # make sure glyph names are unique
 | 
						
						
						
						
							 | 
							
								 | 
							
							            allNames = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							            newCharset = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for glyphName in charset:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if glyphName in allNames:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    # make up a new glyphName that's unique
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    n = allNames[glyphName]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    names = set(allNames) | set(charset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    while (glyphName + "." + str(n)) in names:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        n += 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    allNames[glyphName] = n + 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    glyphName = glyphName + "." + str(n)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                allNames[glyphName] = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							                newCharset.append(glyphName)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charset = newCharset
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:  # offset == 0 -> no charset data.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if isCID or "CharStrings" not in parent.rawDict:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # We get here only when processing fontDicts from the FDArray of
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # CFF-CID fonts. Only the real topDict references the charset.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                assert value == 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charset = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							            elif value == 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charset = cffISOAdobeStrings
 | 
						
						
						
						
							 | 
							
								 | 
							
							            elif value == 1:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charset = cffIExpertStrings
 | 
						
						
						
						
							 | 
							
								 | 
							
							            elif value == 2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charset = cffExpertSubsetStrings
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if charset and (len(charset) != parent.numGlyphs):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charset = charset[: parent.numGlyphs]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return charset
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return 0  # dummy value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # XXX only write charset when not in OT/TTX context, where we
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # dump charset as a separate "GlyphOrder" table.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # # xmlWriter.simpletag("charset")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.comment("charset is dumped separately as the 'GlyphOrder' element")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        pass
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class CharsetCompiler(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, strings, charset, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        assert charset[0] == ".notdef"
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCID = hasattr(parent.dictObj, "ROS")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data0 = packCharset0(charset, isCID, strings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data = packCharset(charset, isCID, strings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if len(data) < len(data0):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.data = data
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.data = data0
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent = parent
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def setPos(self, pos, endPos):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent.rawDict["charset"] = pos
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getDataLength(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toFile(self, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.write(self.data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def getStdCharSet(charset):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # check to see if we can use a predefined charset value.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    predefinedCharSetVal = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							    predefinedCharSets = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							        (cffISOAdobeStringCount, cffISOAdobeStrings, 0),
 | 
						
						
						
						
							 | 
							
								 | 
							
							        (cffExpertStringCount, cffIExpertStrings, 1),
 | 
						
						
						
						
							 | 
							
								 | 
							
							        (cffExpertSubsetStringCount, cffExpertSubsetStrings, 2),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    lcs = len(charset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for cnt, pcs, csv in predefinedCharSets:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if predefinedCharSetVal is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if lcs > cnt:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							        predefinedCharSetVal = csv
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for i in range(lcs):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if charset[i] != pcs[i]:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                predefinedCharSetVal = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							                break
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return predefinedCharSetVal
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def getCIDfromName(name, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return int(name[3:])
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def getSIDfromName(name, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return strings.getSID(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def packCharset0(charset, isCID, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    fmt = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data = [packCard8(fmt)]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if isCID:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        getNameID = getCIDfromName
 | 
						
						
						
						
							 | 
							
								 | 
							
							    else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        getNameID = getSIDfromName
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for name in charset[1:]:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data.append(packCard16(getNameID(name, strings)))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def packCharset(charset, isCID, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    fmt = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ranges = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							    first = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							    end = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if isCID:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        getNameID = getCIDfromName
 | 
						
						
						
						
							 | 
							
								 | 
							
							    else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        getNameID = getSIDfromName
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for name in charset[1:]:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        SID = getNameID(name, strings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if first is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            first = SID
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif end + 1 != SID:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            nLeft = end - first
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if nLeft > 255:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fmt = 2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ranges.append((first, nLeft))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            first = SID
 | 
						
						
						
						
							 | 
							
								 | 
							
							        end = SID
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if end:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        nLeft = end - first
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if nLeft > 255:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fmt = 2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ranges.append((first, nLeft))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data = [packCard8(fmt)]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if fmt == 1:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        nLeftFunc = packCard8
 | 
						
						
						
						
							 | 
							
								 | 
							
							    else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        nLeftFunc = packCard16
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for first, nLeft in ranges:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data.append(packCard16(first) + nLeftFunc(nLeft))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def parseCharset0(numGlyphs, file, strings, isCID):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    charset = [".notdef"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if isCID:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for i in range(numGlyphs - 1):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            CID = readCard16(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charset.append("cid" + str(CID).zfill(5))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for i in range(numGlyphs - 1):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            SID = readCard16(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charset.append(strings[SID])
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return charset
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def parseCharset(numGlyphs, file, strings, isCID, fmt):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    charset = [".notdef"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    count = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if fmt == 1:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        nLeftFunc = readCard8
 | 
						
						
						
						
							 | 
							
								 | 
							
							    else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        nLeftFunc = readCard16
 | 
						
						
						
						
							 | 
							
								 | 
							
							    while count < numGlyphs:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        first = readCard16(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        nLeft = nLeftFunc(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isCID:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for CID in range(first, first + nLeft + 1):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charset.append("cid" + str(CID).zfill(5))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for SID in range(first, first + nLeft + 1):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charset.append(strings[SID])
 | 
						
						
						
						
							 | 
							
								 | 
							
							        count = count + nLeft + 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return charset
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class EncodingCompiler(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, strings, encoding, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        assert not isinstance(encoding, str)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data0 = packEncoding0(parent.dictObj.charset, encoding, parent.strings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data1 = packEncoding1(parent.dictObj.charset, encoding, parent.strings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if len(data0) < len(data1):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.data = data0
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.data = data1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent = parent
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def setPos(self, pos, endPos):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent.rawDict["Encoding"] = pos
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getDataLength(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toFile(self, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.write(self.data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class EncodingConverter(SimpleConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if value == 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return "StandardEncoding"
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif value == 1:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return "ExpertEncoding"
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # custom encoding at offset `value`
 | 
						
						
						
						
							 | 
							
								 | 
							
							        assert value > 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file = parent.file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.seek(value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        log.log(DEBUG, "loading Encoding at %s", value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fmt = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        haveSupplement = bool(fmt & 0x80)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fmt = fmt & 0x7F
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if fmt == 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            encoding = parseEncoding0(parent.charset, file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif fmt == 1:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            encoding = parseEncoding1(parent.charset, file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            raise ValueError(f"Unknown Encoding format: {fmt}")
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if haveSupplement:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            parseEncodingSupplement(file, encoding, parent.strings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return encoding
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if value == "StandardEncoding":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif value == "ExpertEncoding":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return 0  # dummy value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if value in ("StandardEncoding", "ExpertEncoding"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.simpletag(name, name=value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.begintag(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for code in range(len(value)):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            glyphName = value[code]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if glyphName != ".notdef":
 | 
						
						
						
						
							 | 
							
								 | 
							
							                xmlWriter.simpletag("map", code=hex(code), name=glyphName)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.endtag(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if "name" in attrs:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return attrs["name"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        encoding = [".notdef"] * 256
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for element in content:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if isinstance(element, str):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            name, attrs, content = element
 | 
						
						
						
						
							 | 
							
								 | 
							
							            code = safeEval(attrs["code"])
 | 
						
						
						
						
							 | 
							
								 | 
							
							            glyphName = attrs["name"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            encoding[code] = glyphName
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return encoding
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def readSID(file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """Read a String ID (SID) — 2-byte unsigned integer."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data = file.read(2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if len(data) != 2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        raise EOFError("Unexpected end of file while reading SID")
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return struct.unpack(">H", data)[0]  # big-endian uint16
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def parseEncodingSupplement(file, encoding, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							    Parse the CFF Encoding supplement data:
 | 
						
						
						
						
							 | 
							
								 | 
							
							      - nSups: number of supplementary mappings
 | 
						
						
						
						
							 | 
							
								 | 
							
							      - each mapping: (code, SID) pair
 | 
						
						
						
						
							 | 
							
								 | 
							
							    and apply them to the `encoding` list in place.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							    nSups = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for _ in range(nSups):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        code = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        sid = readSID(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        name = strings[sid]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        encoding[code] = name
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def parseEncoding0(charset, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							    Format 0: simple list of codes.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    After reading the base table, optionally parse the supplement.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							    nCodes = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    encoding = [".notdef"] * 256
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for glyphID in range(1, nCodes + 1):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        code = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if code != 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            encoding[code] = charset[glyphID]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return encoding
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def parseEncoding1(charset, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							    Format 1: range-based encoding.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    After reading the base ranges, optionally parse the supplement.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							    nRanges = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    encoding = [".notdef"] * 256
 | 
						
						
						
						
							 | 
							
								 | 
							
							    glyphID = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for _ in range(nRanges):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        code = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        nLeft = readCard8(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for _ in range(nLeft + 1):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            encoding[code] = charset[glyphID]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            code += 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							            glyphID += 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return encoding
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def packEncoding0(charset, encoding, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    fmt = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							    m = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for code in range(len(encoding)):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        name = encoding[code]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if name != ".notdef":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            m[name] = code
 | 
						
						
						
						
							 | 
							
								 | 
							
							    codes = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for name in charset[1:]:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        code = m.get(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        codes.append(code)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    while codes and codes[-1] is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        codes.pop()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data = [packCard8(fmt), packCard8(len(codes))]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for code in codes:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if code is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            code = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data.append(packCard8(code))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def packEncoding1(charset, encoding, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    fmt = 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							    m = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for code in range(len(encoding)):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        name = encoding[code]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if name != ".notdef":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            m[name] = code
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ranges = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							    first = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							    end = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for name in charset[1:]:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        code = m.get(name, -1)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if first is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            first = code
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif end + 1 != code:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            nLeft = end - first
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ranges.append((first, nLeft))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            first = code
 | 
						
						
						
						
							 | 
							
								 | 
							
							        end = code
 | 
						
						
						
						
							 | 
							
								 | 
							
							    nLeft = end - first
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ranges.append((first, nLeft))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # remove unencoded glyphs at the end.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    while ranges and ranges[-1][0] == -1:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ranges.pop()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data = [packCard8(fmt), packCard8(len(ranges))]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for first, nLeft in ranges:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if first == -1:  # unencoded
 | 
						
						
						
						
							 | 
							
								 | 
							
							            first = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data.append(packCard8(first) + packCard8(nLeft))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class FDArrayConverter(TableConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        try:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            vstore = parent.VarStore
 | 
						
						
						
						
							 | 
							
								 | 
							
							        except AttributeError:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            vstore = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file = parent.file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCFF2 = parent._isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.seek(value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdArray = FDArrayIndex(file, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdArray.vstore = vstore
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdArray.strings = parent.strings
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdArray.GlobalSubrs = parent.GlobalSubrs
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return fdArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return 0  # dummy value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdArray = FDArrayIndex()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for element in content:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if isinstance(element, str):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            name, attrs, content = element
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdArray.fromXML(name, attrs, content)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return fdArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class FDSelectConverter(SimpleConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file = parent.file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.seek(value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdSelect = FDSelect(file, parent.numGlyphs)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return fdSelect
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return 0  # dummy value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # The FDSelect glyph data is written out to XML in the charstring keys,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # so we write out only the format selector
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.simpletag(name, [("format", value.format)])
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fmt = safeEval(attrs["format"])
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        numGlyphs = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdSelect = FDSelect(file, numGlyphs, fmt)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return fdSelect
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class VarStoreConverter(SimpleConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def _read(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file = parent.file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.seek(value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        varStore = VarStoreData(file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        varStore.decompile()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return varStore
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def write(self, parent, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return 0  # dummy value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value.writeXML(xmlWriter, name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        varStore = VarStoreData()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        varStore.xmlRead(name, attrs, content, parent)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return varStore
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def packFDSelect0(fdSelectArray):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    fmt = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data = [packCard8(fmt)]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for index in fdSelectArray:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data.append(packCard8(index))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def packFDSelect3(fdSelectArray):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    fmt = 3
 | 
						
						
						
						
							 | 
							
								 | 
							
							    fdRanges = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							    lenArray = len(fdSelectArray)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    lastFDIndex = -1
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for i in range(lenArray):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdIndex = fdSelectArray[i]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if lastFDIndex != fdIndex:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdRanges.append([i, fdIndex])
 | 
						
						
						
						
							 | 
							
								 | 
							
							            lastFDIndex = fdIndex
 | 
						
						
						
						
							 | 
							
								 | 
							
							    sentinelGID = i + 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data = [packCard8(fmt)]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data.append(packCard16(len(fdRanges)))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for fdRange in fdRanges:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data.append(packCard16(fdRange[0]))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data.append(packCard8(fdRange[1]))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data.append(packCard16(sentinelGID))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def packFDSelect4(fdSelectArray):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    fmt = 4
 | 
						
						
						
						
							 | 
							
								 | 
							
							    fdRanges = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							    lenArray = len(fdSelectArray)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    lastFDIndex = -1
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for i in range(lenArray):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdIndex = fdSelectArray[i]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if lastFDIndex != fdIndex:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdRanges.append([i, fdIndex])
 | 
						
						
						
						
							 | 
							
								 | 
							
							            lastFDIndex = fdIndex
 | 
						
						
						
						
							 | 
							
								 | 
							
							    sentinelGID = i + 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data = [packCard8(fmt)]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data.append(packCard32(len(fdRanges)))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for fdRange in fdRanges:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data.append(packCard32(fdRange[0]))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data.append(packCard16(fdRange[1]))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    data.append(packCard32(sentinelGID))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class FDSelectCompiler(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, fdSelect, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fmt = fdSelect.format
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fdSelectArray = fdSelect.gidArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if fmt == 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.data = packFDSelect0(fdSelectArray)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif fmt == 3:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.data = packFDSelect3(fdSelectArray)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif fmt == 4:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.data = packFDSelect4(fdSelectArray)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # choose smaller of the two formats
 | 
						
						
						
						
							 | 
							
								 | 
							
							            data0 = packFDSelect0(fdSelectArray)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            data3 = packFDSelect3(fdSelectArray)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if len(data0) < len(data3):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.data = data0
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fdSelect.format = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.data = data3
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fdSelect.format = 3
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent = parent
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def setPos(self, pos, endPos):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent.rawDict["FDSelect"] = pos
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getDataLength(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toFile(self, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.write(self.data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class VarStoreCompiler(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, varStoreData, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent = parent
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not varStoreData.data:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            varStoreData.compile()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        varStoreDataLen = min(0xFFFF, len(varStoreData.data))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data = [packCard16(varStoreDataLen), varStoreData.data]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.data = bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def setPos(self, pos, endPos):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent.rawDict["VarStore"] = pos
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getDataLength(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toFile(self, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.write(self.data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class ROSConverter(SimpleConverter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlWrite(self, xmlWriter, name, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        registry, order, supplement = value
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.simpletag(
 | 
						
						
						
						
							 | 
							
								 | 
							
							            name,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ("Registry", tostr(registry)),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ("Order", tostr(order)),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ("Supplement", supplement),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ],
 | 
						
						
						
						
							 | 
							
								 | 
							
							        )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def xmlRead(self, name, attrs, content, parent):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return (attrs["Registry"], attrs["Order"], safeEval(attrs["Supplement"]))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							topDictOperators = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # 	opcode		name			argument type	default	converter
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (25, "maxstack", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 30), "ROS", ("SID", "SID", "number"), None, ROSConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 20), "SyntheticBase", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (0, "version", "SID", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (1, "Notice", "SID", None, Latin1Converter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 0), "Copyright", "SID", None, Latin1Converter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (2, "FullName", "SID", None, Latin1Converter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 38), "FontName", "SID", None, Latin1Converter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (3, "FamilyName", "SID", None, Latin1Converter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (4, "Weight", "SID", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 1), "isFixedPitch", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 2), "ItalicAngle", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 3), "UnderlinePosition", "number", -100, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 4), "UnderlineThickness", "number", 50, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 5), "PaintType", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 6), "CharstringType", "number", 2, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 7), "FontMatrix", "array", [0.001, 0, 0, 0.001, 0, 0], None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (13, "UniqueID", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (5, "FontBBox", "array", [0, 0, 0, 0], None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 8), "StrokeWidth", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (14, "XUID", "array", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 21), "PostScript", "SID", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 22), "BaseFontName", "SID", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 23), "BaseFontBlend", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 31), "CIDFontVersion", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 32), "CIDFontRevision", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 33), "CIDFontType", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 34), "CIDCount", "number", 8720, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (15, "charset", "number", None, CharsetConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 35), "UIDBase", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (16, "Encoding", "number", 0, EncodingConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (18, "Private", ("number", "number"), None, PrivateDictConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 37), "FDSelect", "number", None, FDSelectConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 36), "FDArray", "number", None, FDArrayConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (17, "CharStrings", "number", None, CharStringsConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (24, "VarStore", "number", None, VarStoreConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							topDictOperators2 = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # 	opcode		name			argument type	default	converter
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (25, "maxstack", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 7), "FontMatrix", "array", [0.001, 0, 0, 0.001, 0, 0], None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 37), "FDSelect", "number", None, FDSelectConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 36), "FDArray", "number", None, FDArrayConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (17, "CharStrings", "number", None, CharStringsConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (24, "VarStore", "number", None, VarStoreConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							# Note! FDSelect and FDArray must both preceed CharStrings in the output XML build order,
 | 
						
						
						
						
							 | 
							
								 | 
							
							# in order for the font to compile back from xml.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							kBlendDictOpName = "blend"
 | 
						
						
						
						
							 | 
							
								 | 
							
							blendOp = 23
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							privateDictOperators = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # 	opcode		name			argument type	default	converter
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (22, "vsindex", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        blendOp,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        kBlendDictOpName,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        "blendList",
 | 
						
						
						
						
							 | 
							
								 | 
							
							        None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ),  # This is for reading to/from XML: it not written to CFF.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (6, "BlueValues", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (7, "OtherBlues", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (8, "FamilyBlues", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (9, "FamilyOtherBlues", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 9), "BlueScale", "number", 0.039625, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 10), "BlueShift", "number", 7, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 11), "BlueFuzz", "number", 1, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (10, "StdHW", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (11, "StdVW", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 12), "StemSnapH", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 13), "StemSnapV", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 14), "ForceBold", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 15), "ForceBoldThreshold", "number", None, None),  # deprecated
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 16), "lenIV", "number", None, None),  # deprecated
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 17), "LanguageGroup", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 18), "ExpansionFactor", "number", 0.06, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 19), "initialRandomSeed", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (20, "defaultWidthX", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (21, "nominalWidthX", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (19, "Subrs", "number", None, SubrsConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							privateDictOperators2 = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # 	opcode		name			argument type	default	converter
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (22, "vsindex", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        blendOp,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        kBlendDictOpName,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        "blendList",
 | 
						
						
						
						
							 | 
							
								 | 
							
							        None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ),  # This is for reading to/from XML: it not written to CFF.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (6, "BlueValues", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (7, "OtherBlues", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (8, "FamilyBlues", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (9, "FamilyOtherBlues", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 9), "BlueScale", "number", 0.039625, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 10), "BlueShift", "number", 7, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 11), "BlueFuzz", "number", 1, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (10, "StdHW", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (11, "StdVW", "number", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 12), "StemSnapH", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 13), "StemSnapV", "delta", None, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 17), "LanguageGroup", "number", 0, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ((12, 18), "ExpansionFactor", "number", 0.06, None),
 | 
						
						
						
						
							 | 
							
								 | 
							
							    (19, "Subrs", "number", None, SubrsConverter()),
 | 
						
						
						
						
							 | 
							
								 | 
							
							]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def addConverters(table):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for i in range(len(table)):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        op, name, arg, default, conv = table[i]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if conv is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if arg in ("delta", "array"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            conv = ArrayConverter()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif arg == "number":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            conv = NumberConverter()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif arg == "SID":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            conv = ASCIIConverter()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif arg == "blendList":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            conv = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            assert False
 | 
						
						
						
						
							 | 
							
								 | 
							
							        table[i] = op, name, arg, default, conv
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							addConverters(privateDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							addConverters(topDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class TopDictDecompiler(psCharStrings.DictDecompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    operators = buildOperatorDict(topDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class PrivateDictDecompiler(psCharStrings.DictDecompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    operators = buildOperatorDict(privateDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class DictCompiler(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    maxBlendStack = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, dictObj, strings, parent, isCFF2=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if strings:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            assert isinstance(strings, IndexedStrings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isCFF2 is None and hasattr(parent, "isCFF2"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            isCFF2 = parent.isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            assert isCFF2 is not None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.isCFF2 = isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.dictObj = dictObj
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.strings = strings
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent = parent
 | 
						
						
						
						
							 | 
							
								 | 
							
							        rawDict = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for name in dictObj.order:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value = getattr(dictObj, name, None)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if value is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            conv = dictObj.converters[name]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value = conv.write(dictObj, value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if value == dictObj.defaults.get(name):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            rawDict[name] = value
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.rawDict = rawDict
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def setPos(self, pos, endPos):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        pass
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getDataLength(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.compile("getDataLength"))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def compile(self, reason):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        log.log(DEBUG, "-- compiling %s for %s", self.__class__.__name__, reason)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        rawDict = self.rawDict
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for name in self.dictObj.order:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value = rawDict.get(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if value is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            op, argType = self.opcodes[name]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if isinstance(argType, tuple):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                l = len(argType)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                assert len(value) == l, "value doesn't match arg type"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for i in range(l):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    arg = argType[i]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    v = value[i]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    arghandler = getattr(self, "arg_" + arg)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    data.append(arghandler(v))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                arghandler = getattr(self, "arg_" + argType)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                data.append(arghandler(value))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            data.append(op)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data = bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return data
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toFile(self, file):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data = self.compile("toFile")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file.write(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def arg_number(self, num):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isinstance(num, list):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            data = [encodeNumber(val) for val in num]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            data.append(encodeNumber(1))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            data.append(bytechr(blendOp))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            datum = bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            datum = encodeNumber(num)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return datum
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def arg_SID(self, s):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return psCharStrings.encodeIntCFF(self.strings.getSID(s))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def arg_array(self, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        data = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for num in value:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            data.append(self.arg_number(num))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def arg_delta(self, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not value:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return b""
 | 
						
						
						
						
							 | 
							
								 | 
							
							        val0 = value[0]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isinstance(val0, list):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            data = self.arg_delta_blend(value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            out = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							            last = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for v in value:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                out.append(v - last)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                last = v
 | 
						
						
						
						
							 | 
							
								 | 
							
							            data = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for num in out:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                data.append(encodeNumber(num))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return bytesjoin(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def arg_delta_blend(self, value):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """A delta list with blend lists has to be *all* blend lists.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        The value is a list is arranged as follows::
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        [V0, d0..dn]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        [V1, d0..dn]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        ...
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        [Vm, d0..dn]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ``V`` is the absolute coordinate value from the default font, and ``d0-dn``
 | 
						
						
						
						
							 | 
							
								 | 
							
							        are the delta values from the *n* regions. Each ``V`` is an absolute
 | 
						
						
						
						
							 | 
							
								 | 
							
							        coordinate from the default font.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        We want to return a list::
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        [v0, v1..vm]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        [d0..dn]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        ...
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        [d0..dn]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        numBlends
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        blendOp
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        where each ``v`` is relative to the previous default font value.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """
 | 
						
						
						
						
							 | 
							
								 | 
							
							        numMasters = len(value[0])
 | 
						
						
						
						
							 | 
							
								 | 
							
							        numBlends = len(value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        numStack = (numBlends * numMasters) + 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if numStack > self.maxBlendStack:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # Figure out the max number of value we can blend
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # and divide this list up into chunks of that size.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            numBlendValues = int((self.maxBlendStack - 1) / numMasters)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            out = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							            while True:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                numVal = min(len(value), numBlendValues)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if numVal == 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    break
 | 
						
						
						
						
							 | 
							
								 | 
							
							                valList = value[0:numVal]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                out1 = self.arg_delta_blend(valList)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                out.extend(out1)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value = value[numVal:]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            firstList = [0] * numBlends
 | 
						
						
						
						
							 | 
							
								 | 
							
							            deltaList = [None] * numBlends
 | 
						
						
						
						
							 | 
							
								 | 
							
							            i = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            prevVal = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            while i < numBlends:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # For PrivateDict BlueValues, the default font
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # values are absolute, not relative.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # Must convert these back to relative coordinates
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # before writing to CFF2.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                defaultValue = value[i][0]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                firstList[i] = defaultValue - prevVal
 | 
						
						
						
						
							 | 
							
								 | 
							
							                prevVal = defaultValue
 | 
						
						
						
						
							 | 
							
								 | 
							
							                deltaList[i] = value[i][1:]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                i += 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            relValueList = firstList
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for blendList in deltaList:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                relValueList.extend(blendList)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            out = [encodeNumber(val) for val in relValueList]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            out.append(encodeNumber(numBlends))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            out.append(bytechr(blendOp))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return out
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def encodeNumber(num):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if isinstance(num, float):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return psCharStrings.encodeFloat(num)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return psCharStrings.encodeIntCFF(num)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class TopDictCompiler(DictCompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    opcodes = buildOpcodeDict(topDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getChildren(self, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCFF2 = self.isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        children = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self.dictObj.cff2GetGlyphOrder is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(self.dictObj, "charset") and self.dictObj.charset:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if hasattr(self.dictObj, "ROS"):  # aka isCID
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    charsetCode = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							                else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    charsetCode = getStdCharSet(self.dictObj.charset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if charsetCode is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    children.append(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        CharsetCompiler(strings, self.dictObj.charset, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    )
 | 
						
						
						
						
							 | 
							
								 | 
							
							                else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.rawDict["charset"] = charsetCode
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(self.dictObj, "Encoding") and self.dictObj.Encoding:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                encoding = self.dictObj.Encoding
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if not isinstance(encoding, str):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    children.append(EncodingCompiler(strings, encoding, self))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(self.dictObj, "VarStore"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                varStoreData = self.dictObj.VarStore
 | 
						
						
						
						
							 | 
							
								 | 
							
							                varStoreComp = VarStoreCompiler(varStoreData, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                children.append(varStoreComp)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(self.dictObj, "FDSelect"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # I have not yet supported merging a ttx CFF-CID font, as there are
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # interesting issues about merging the FDArrays. Here I assume that
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # either the font was read from XML, and the FDSelect indices are all
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # in the charstring data, or the FDSelect array is already fully defined.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdSelect = self.dictObj.FDSelect
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # probably read in from XML; assume fdIndex in CharString data
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if len(fdSelect) == 0:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charStrings = self.dictObj.CharStrings
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for name in self.dictObj.charset:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    fdSelect.append(charStrings[name].fdSelectIndex)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdSelectComp = FDSelectCompiler(fdSelect, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.append(fdSelectComp)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(self.dictObj, "CharStrings"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            items = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charStrings = self.dictObj.CharStrings
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for name in self.dictObj.charset:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                items.append(charStrings[name])
 | 
						
						
						
						
							 | 
							
								 | 
							
							            charStringsComp = CharStringsCompiler(items, strings, self, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.append(charStringsComp)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(self.dictObj, "FDArray"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # I have not yet supported merging a ttx CFF-CID font, as there are
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # interesting issues about merging the FDArrays. Here I assume that the
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # FDArray info is correct and complete.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fdArrayIndexComp = self.dictObj.FDArray.getCompiler(strings, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.append(fdArrayIndexComp)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.extend(fdArrayIndexComp.getChildren(strings))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(self.dictObj, "Private"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            privComp = self.dictObj.Private.getCompiler(strings, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.append(privComp)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.extend(privComp.getChildren(strings))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return children
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class FontDictCompiler(DictCompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    opcodes = buildOpcodeDict(topDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, dictObj, strings, parent, isCFF2=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        super(FontDictCompiler, self).__init__(dictObj, strings, parent, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        #
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # We now take some effort to detect if there were any key/value pairs
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # supplied that were ignored in the FontDict context, and issue a warning
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # for those cases.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        #
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ignoredNames = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        dictObj = self.dictObj
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for name in sorted(set(dictObj.converters) - set(dictObj.order)):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if name in dictObj.rawDict:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # The font was directly read from binary. In this
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # case, we want to report *all* "useless" key/value
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # pairs that are in the font, not just the ones that
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # are different from the default.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ignoredNames.append(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # The font was probably read from a TTX file. We only
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # warn about keys whos value is not the default. The
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # ones that have the default value will not be written
 | 
						
						
						
						
							 | 
							
								 | 
							
							                # to binary anyway.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                default = dictObj.defaults.get(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if default is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    conv = dictObj.converters[name]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    default = conv.read(dictObj, default)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if getattr(dictObj, name, None) != default:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    ignoredNames.append(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if ignoredNames:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            log.warning(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                "Some CFF FDArray/FontDict keys were ignored upon compile: "
 | 
						
						
						
						
							 | 
							
								 | 
							
							                + " ".join(sorted(ignoredNames))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            )
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getChildren(self, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        children = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(self.dictObj, "Private"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            privComp = self.dictObj.Private.getCompiler(strings, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.append(privComp)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.extend(privComp.getChildren(strings))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return children
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class PrivateDictCompiler(DictCompiler):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    maxBlendStack = maxStackLimit
 | 
						
						
						
						
							 | 
							
								 | 
							
							    opcodes = buildOpcodeDict(privateDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def setPos(self, pos, endPos):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        size = endPos - pos
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.parent.rawDict["Private"] = size, pos
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.pos = pos
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getChildren(self, strings):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        children = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(self.dictObj, "Subrs"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            children.append(self.dictObj.Subrs.getCompiler(strings, self))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return children
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class BaseDict(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, strings=None, file=None, offset=None, isCFF2=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        assert (isCFF2 is None) == (file is None)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.rawDict = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.skipNames = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.strings = strings
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if file is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self._isCFF2 = isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.file = file
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if offset is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            log.log(DEBUG, "loading %s at %s", self.__class__.__name__, offset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.offset = offset
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def decompile(self, data):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        log.log(DEBUG, "    length %s is %d", self.__class__.__name__, len(data))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        dec = self.decompilerClass(self.strings, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        dec.decompile(data)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.rawDict = dec.getDict()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.postDecompile()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def postDecompile(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        pass
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getCompiler(self, strings, parent, isCFF2=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.compilerClass(self, strings, parent, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __getattr__(self, name):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if name[:2] == name[-2:] == "__":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # to make deepcopy() and pickle.load() work, we need to signal with
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # AttributeError that dunder methods like '__deepcopy__' or '__getstate__'
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # aren't implemented. For more details, see:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # https://github.com/fonttools/fonttools/pull/1488
 | 
						
						
						
						
							 | 
							
								 | 
							
							            raise AttributeError(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value = self.rawDict.get(name, None)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if value is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value = self.defaults.get(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if value is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            raise AttributeError(name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        conv = self.converters[name]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value = conv.read(self, value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        setattr(self, name, value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return value
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toXML(self, xmlWriter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for name in self.order:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if name in self.skipNames:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value = getattr(self, name, None)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # XXX For "charset" we never skip calling xmlWrite even if the
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # value is None, so we always write the following XML comment:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            #
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # <!-- charset is dumped separately as the 'GlyphOrder' element -->
 | 
						
						
						
						
							 | 
							
								 | 
							
							            #
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # Charset is None when 'CFF ' table is imported from XML into an
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # empty TTFont(). By writing this comment all the time, we obtain
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # the same XML output whether roundtripping XML-to-XML or
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # dumping binary-to-XML
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if value is None and name != "charset":
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue
 | 
						
						
						
						
							 | 
							
								 | 
							
							            conv = self.converters[name]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            conv.xmlWrite(xmlWriter, name, value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ignoredNames = set(self.rawDict) - set(self.order)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if ignoredNames:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.comment(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                "some keys were ignored: %s" % " ".join(sorted(ignoredNames))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            )
 | 
						
						
						
						
							 | 
							
								 | 
							
							            xmlWriter.newline()
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def fromXML(self, name, attrs, content):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        conv = self.converters[name]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value = conv.xmlRead(name, attrs, content, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        setattr(self, name, value)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class TopDict(BaseDict):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """The ``TopDict`` represents the top-level dictionary holding font
 | 
						
						
						
						
							 | 
							
								 | 
							
							    information. CFF2 tables contain a restricted set of top-level entries
 | 
						
						
						
						
							 | 
							
								 | 
							
							    as described `here <https://docs.microsoft.com/en-us/typography/opentype/spec/cff2#7-top-dict-data>`_,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    but CFF tables may contain a wider range of information. This information
 | 
						
						
						
						
							 | 
							
								 | 
							
							    can be accessed through attributes or through the dictionary returned
 | 
						
						
						
						
							 | 
							
								 | 
							
							    through the ``rawDict`` property:
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    .. code:: python
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            font = tt["CFF "].cff[0]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            font.FamilyName
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # 'Linux Libertine O'
 | 
						
						
						
						
							 | 
							
								 | 
							
							            font.rawDict["FamilyName"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # 'Linux Libertine O'
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    More information is available in the CFF file's private dictionary, accessed
 | 
						
						
						
						
							 | 
							
								 | 
							
							    via the ``Private`` property:
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    .. code:: python
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            tt["CFF "].cff[0].Private.BlueValues
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # [-15, 0, 515, 515, 666, 666]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    defaults = buildDefaults(topDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    converters = buildConverters(topDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    compilerClass = TopDictCompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							    order = buildOrder(topDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    decompilerClass = TopDictDecompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        strings=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offset=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        GlobalSubrs=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        cff2GetGlyphOrder=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCFF2=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        super(TopDict, self).__init__(strings, file, offset, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.cff2GetGlyphOrder = cff2GetGlyphOrder
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.GlobalSubrs = GlobalSubrs
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.defaults = buildDefaults(topDictOperators2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.charset = cff2GetGlyphOrder()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.order = buildOrder(topDictOperators2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.defaults = buildDefaults(topDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.order = buildOrder(topDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getGlyphOrder(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        """Returns a list of glyph names in the CFF font."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.charset
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def postDecompile(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offset = self.rawDict.get("CharStrings")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if offset is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # get the number of glyphs beforehand.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.file.seek(offset)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if self._isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.numGlyphs = readCard32(self.file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.numGlyphs = readCard16(self.file)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def toXML(self, xmlWriter):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(self, "CharStrings"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.decompileAllCharStrings()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if hasattr(self, "ROS"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.skipNames = ["Encoding"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not hasattr(self, "ROS") or not hasattr(self, "CharStrings"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # these values have default values, but I only want them to show up
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # in CID fonts.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.skipNames = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                "CIDFontVersion",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                "CIDFontRevision",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                "CIDFontType",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                "CIDCount",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        BaseDict.toXML(self, xmlWriter)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def decompileAllCharStrings(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # Make sure that all the Private Dicts have been instantiated.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for i, charString in enumerate(self.CharStrings.values()):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            try:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                charString.decompile()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            except:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                log.error("Error in charstring %s", i)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                raise
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def recalcFontBBox(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        fontBBox = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for charString in self.CharStrings.values():
 | 
						
						
						
						
							 | 
							
								 | 
							
							            bounds = charString.calcBounds(self.CharStrings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if bounds is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if fontBBox is not None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    fontBBox = unionRect(fontBBox, bounds)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    fontBBox = bounds
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if fontBBox is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.FontBBox = self.defaults["FontBBox"][:]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.FontBBox = list(intRect(fontBBox))
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class FontDict(BaseDict):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    #
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # Since fonttools used to pass a lot of fields that are not relevant in the FDArray
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # FontDict, there are 'ttx' files in the wild that contain all these. These got in
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # the ttx files because fonttools writes explicit values for all the TopDict default
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # values. These are not actually illegal in the context of an FDArray FontDict - you
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # can legally, per spec, put any arbitrary key/value pair in a FontDict - but are
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # useless since current major company CFF interpreters ignore anything but the set
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # listed in this file. So, we just silently skip them. An exception is Weight: this
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # is not used by any interpreter, but some foundries have asked that this be
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # supported in FDArray FontDicts just to preserve information about the design when
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # the font is being inspected.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    #
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # On top of that, there are fonts out there that contain such useless FontDict values.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    #
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # By subclassing TopDict, we *allow* all key/values from TopDict, both when reading
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # from binary or when reading from XML, but by overriding `order` with a limited
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # list of names, we ensure that only the useful names ever get exported to XML and
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # ever get compiled into the binary font.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    #
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # We override compilerClass so we can warn about "useless" key/value pairs, either
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # from the original binary font or from TTX input.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    #
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # See:
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # - https://github.com/fonttools/fonttools/issues/740
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # - https://github.com/fonttools/fonttools/issues/601
 | 
						
						
						
						
							 | 
							
								 | 
							
							    # - https://github.com/adobe-type-tools/afdko/issues/137
 | 
						
						
						
						
							 | 
							
								 | 
							
							    #
 | 
						
						
						
						
							 | 
							
								 | 
							
							    defaults = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    converters = buildConverters(topDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    compilerClass = FontDictCompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							    orderCFF = ["FontName", "FontMatrix", "Weight", "Private"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    orderCFF2 = ["Private"]
 | 
						
						
						
						
							 | 
							
								 | 
							
							    decompilerClass = TopDictDecompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        strings=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        file=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        offset=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        GlobalSubrs=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        isCFF2=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        vstore=None,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        super(FontDict, self).__init__(strings, file, offset, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.vstore = vstore
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.setCFF2(isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def setCFF2(self, isCFF2):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # isCFF2 may be None.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.order = self.orderCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self._isCFF2 = True
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.order = self.orderCFF
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self._isCFF2 = False
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class PrivateDict(BaseDict):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    defaults = buildDefaults(privateDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    converters = buildConverters(privateDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    order = buildOrder(privateDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    decompilerClass = PrivateDictDecompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							    compilerClass = PrivateDictCompiler
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, strings=None, file=None, offset=None, isCFF2=None, vstore=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        super(PrivateDict, self).__init__(strings, file, offset, isCFF2=isCFF2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.vstore = vstore
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if isCFF2:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.defaults = buildDefaults(privateDictOperators2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.order = buildOrder(privateDictOperators2)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # Provide dummy values. This avoids needing to provide
 | 
						
						
						
						
							 | 
							
								 | 
							
							            # an isCFF2 state in a lot of places.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.nominalWidthX = self.defaultWidthX = None
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self._isCFF2 = True
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.defaults = buildDefaults(privateDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.order = buildOrder(privateDictOperators)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self._isCFF2 = False
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    @property
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def in_cff2(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self._isCFF2
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getNumRegions(self, vi=None):  # called from misc/psCharStrings.py
 | 
						
						
						
						
							 | 
							
								 | 
							
							        # if getNumRegions is being called, we can assume that VarStore exists.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if vi is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if hasattr(self, "vsindex"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							                vi = self.vsindex
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							                vi = 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							        numRegions = self.vstore.getNumRegions(vi)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return numRegions
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class IndexedStrings(object):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    """SID -> string mapping."""
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __init__(self, file=None):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if file is None:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            strings = []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            strings = [tostr(s, encoding="latin1") for s in Index(file, isCFF2=False)]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.strings = strings
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getCompiler(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return IndexedStringsCompiler(self, None, self, isCFF2=False)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __len__(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return len(self.strings)
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def __getitem__(self, SID):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if SID < cffStandardStringCount:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return cffStandardStrings[SID]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self.strings[SID - cffStandardStringCount]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getSID(self, s):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if not hasattr(self, "stringMapping"):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.buildStringMapping()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        s = tostr(s, encoding="latin1")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if s in cffStandardStringMapping:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            SID = cffStandardStringMapping[s]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        elif s in self.stringMapping:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            SID = self.stringMapping[s]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        else:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            SID = len(self.strings) + cffStandardStringCount
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.strings.append(s)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.stringMapping[s] = SID
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return SID
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def getStrings(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.strings
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    def buildStringMapping(self):
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.stringMapping = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for index in range(len(self.strings)):
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.stringMapping[self.strings[index]] = index + cffStandardStringCount
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							# The 391 Standard Strings as used in the CFF format.
 | 
						
						
						
						
							 | 
							
								 | 
							
							# from Adobe Technical None #5176, version 1.0, 18 March 1998
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							cffStandardStrings = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ".notdef",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "space",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "exclam",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotedbl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "numbersign",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollar",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "percent",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ampersand",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quoteright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "asterisk",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "plus",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "comma",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hyphen",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "period",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "slash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zero",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "one",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "two",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "three",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "four",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "five",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "six",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "seven",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eight",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nine",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "colon",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "semicolon",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "less",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "equal",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "greater",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "question",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "at",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "A",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "B",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "C",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "D",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "E",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "F",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "G",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "H",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "I",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "J",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "K",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "L",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "M",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "N",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "O",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "P",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Q",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "R",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "S",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "T",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "U",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "V",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "W",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "X",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Y",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Z",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bracketleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "backslash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bracketright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "asciicircum",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "underscore",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quoteleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "a",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "b",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "c",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "d",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "e",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "f",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "g",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "h",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "i",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "j",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "k",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "l",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "m",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "n",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "o",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "p",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "q",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "r",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "s",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "t",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "u",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "v",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "w",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "x",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "y",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "z",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "braceleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bar",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "braceright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "asciitilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "exclamdown",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "cent",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sterling",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fraction",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "yen",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "florin",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "section",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "currency",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotesingle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotedblleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "guillemotleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "guilsinglleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "guilsinglright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fi",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "endash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dagger",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "daggerdbl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "periodcentered",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "paragraph",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bullet",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotesinglbase",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotedblbase",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotedblright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "guillemotright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ellipsis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "perthousand",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "questiondown",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "grave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "acute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "circumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "tilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "macron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "breve",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dotaccent",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ring",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "cedilla",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hungarumlaut",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ogonek",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "caron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "emdash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "AE",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ordfeminine",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Lslash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Oslash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "OE",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ordmasculine",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ae",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dotlessi",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "lslash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oslash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oe",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "germandbls",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "logicalnot",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "mu",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "trademark",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Eth",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onehalf",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "plusminus",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Thorn",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onequarter",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "divide",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "brokenbar",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "degree",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "thorn",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threequarters",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twosuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "registered",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "minus",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eth",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "multiply",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "copyright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Aacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Acircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Adieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Agrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Aring",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Atilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ccedilla",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Eacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ecircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Edieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Egrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Iacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Icircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Idieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Igrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ntilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Oacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ocircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Odieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ograve",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Otilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Scaron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Uacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ucircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Udieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ugrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Yacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ydieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Zcaron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "aacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "acircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "adieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "agrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "aring",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "atilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ccedilla",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ecircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "edieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "egrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "iacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "icircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "idieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "igrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ntilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ocircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "odieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ograve",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "otilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "scaron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "uacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ucircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "udieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ugrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "yacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ydieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zcaron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "exclamsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Hungarumlautsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollaroldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollarsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ampersandsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Acutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenleftsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenrightsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twodotenleader",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onedotenleader",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zerooldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oneoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twooldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threeoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fouroldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fiveoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sixoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sevenoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eightoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nineoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "commasuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threequartersemdash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "periodsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "questionsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "asuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "centsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "esuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "isuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "lsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "msuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "osuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "rsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ssuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "tsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ff",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ffi",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ffl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenleftinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenrightinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Circumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hyphensuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Gravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Asmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Bsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Csmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Dsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Esmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Fsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Gsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Hsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ismall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Jsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ksmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Lsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Msmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Nsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Osmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Psmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Qsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Rsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ssmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Tsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Usmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Vsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Wsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Xsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ysmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Zsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "colonmonetary",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onefitted",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "rupiah",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Tildesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "exclamdownsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "centoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Lslashsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Scaronsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Zcaronsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Dieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Brevesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Caronsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Dotaccentsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Macronsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "figuredash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hypheninferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ogoneksmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ringsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Cedillasmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "questiondownsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oneeighth",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threeeighths",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fiveeighths",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "seveneighths",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onethird",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twothirds",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zerosuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "foursuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fivesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sixsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sevensuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eightsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ninesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zeroinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oneinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twoinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threeinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fourinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fiveinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sixinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "seveninferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eightinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nineinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "centinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollarinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "periodinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "commainferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Agravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Aacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Acircumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Atildesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Adieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Aringsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "AEsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ccedillasmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Egravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Eacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ecircumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Edieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Igravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Iacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Icircumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Idieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ethsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ntildesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ogravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Oacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ocircumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Otildesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Odieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "OEsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Oslashsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ugravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Uacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ucircumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Udieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Yacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Thornsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ydieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "001.000",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "001.001",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "001.002",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "001.003",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Black",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Bold",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Book",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Light",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Medium",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Regular",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Roman",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Semibold",
 | 
						
						
						
						
							 | 
							
								 | 
							
							]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							cffStandardStringCount = 391
 | 
						
						
						
						
							 | 
							
								 | 
							
							assert len(cffStandardStrings) == cffStandardStringCount
 | 
						
						
						
						
							 | 
							
								 | 
							
							# build reverse mapping
 | 
						
						
						
						
							 | 
							
								 | 
							
							cffStandardStringMapping = {}
 | 
						
						
						
						
							 | 
							
								 | 
							
							for _i in range(cffStandardStringCount):
 | 
						
						
						
						
							 | 
							
								 | 
							
							    cffStandardStringMapping[cffStandardStrings[_i]] = _i
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							cffISOAdobeStrings = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ".notdef",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "space",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "exclam",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotedbl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "numbersign",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollar",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "percent",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ampersand",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quoteright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "asterisk",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "plus",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "comma",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hyphen",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "period",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "slash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zero",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "one",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "two",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "three",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "four",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "five",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "six",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "seven",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eight",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nine",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "colon",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "semicolon",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "less",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "equal",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "greater",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "question",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "at",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "A",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "B",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "C",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "D",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "E",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "F",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "G",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "H",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "I",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "J",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "K",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "L",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "M",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "N",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "O",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "P",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Q",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "R",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "S",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "T",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "U",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "V",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "W",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "X",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Y",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Z",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bracketleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "backslash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bracketright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "asciicircum",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "underscore",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quoteleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "a",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "b",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "c",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "d",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "e",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "f",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "g",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "h",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "i",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "j",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "k",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "l",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "m",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "n",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "o",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "p",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "q",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "r",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "s",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "t",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "u",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "v",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "w",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "x",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "y",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "z",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "braceleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bar",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "braceright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "asciitilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "exclamdown",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "cent",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sterling",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fraction",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "yen",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "florin",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "section",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "currency",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotesingle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotedblleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "guillemotleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "guilsinglleft",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "guilsinglright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fi",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "endash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dagger",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "daggerdbl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "periodcentered",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "paragraph",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bullet",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotesinglbase",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotedblbase",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "quotedblright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "guillemotright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ellipsis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "perthousand",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "questiondown",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "grave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "acute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "circumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "tilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "macron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "breve",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dotaccent",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ring",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "cedilla",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hungarumlaut",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ogonek",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "caron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "emdash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "AE",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ordfeminine",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Lslash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Oslash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "OE",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ordmasculine",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ae",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dotlessi",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "lslash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oslash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oe",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "germandbls",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "logicalnot",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "mu",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "trademark",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Eth",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onehalf",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "plusminus",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Thorn",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onequarter",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "divide",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "brokenbar",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "degree",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "thorn",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threequarters",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twosuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "registered",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "minus",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eth",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "multiply",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "copyright",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Aacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Acircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Adieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Agrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Aring",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Atilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ccedilla",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Eacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ecircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Edieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Egrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Iacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Icircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Idieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Igrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ntilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Oacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ocircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Odieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ograve",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Otilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Scaron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Uacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ucircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Udieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ugrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Yacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ydieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Zcaron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "aacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "acircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "adieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "agrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "aring",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "atilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ccedilla",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ecircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "edieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "egrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "iacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "icircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "idieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "igrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ntilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ocircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "odieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ograve",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "otilde",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "scaron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "uacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ucircumflex",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "udieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ugrave",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "yacute",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ydieresis",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zcaron",
 | 
						
						
						
						
							 | 
							
								 | 
							
							]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							cffISOAdobeStringCount = 229
 | 
						
						
						
						
							 | 
							
								 | 
							
							assert len(cffISOAdobeStrings) == cffISOAdobeStringCount
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							cffIExpertStrings = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ".notdef",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "space",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "exclamsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Hungarumlautsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollaroldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollarsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ampersandsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Acutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenleftsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenrightsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twodotenleader",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onedotenleader",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "comma",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hyphen",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "period",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fraction",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zerooldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oneoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twooldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threeoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fouroldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fiveoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sixoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sevenoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eightoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nineoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "colon",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "semicolon",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "commasuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threequartersemdash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "periodsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "questionsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "asuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "centsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "esuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "isuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "lsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "msuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "osuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "rsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ssuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "tsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ff",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fi",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ffi",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ffl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenleftinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenrightinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Circumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hyphensuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Gravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Asmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Bsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Csmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Dsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Esmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Fsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Gsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Hsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ismall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Jsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ksmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Lsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Msmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Nsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Osmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Psmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Qsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Rsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ssmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Tsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Usmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Vsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Wsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Xsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ysmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Zsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "colonmonetary",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onefitted",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "rupiah",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Tildesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "exclamdownsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "centoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Lslashsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Scaronsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Zcaronsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Dieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Brevesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Caronsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Dotaccentsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Macronsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "figuredash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hypheninferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ogoneksmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ringsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Cedillasmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onequarter",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onehalf",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threequarters",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "questiondownsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oneeighth",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threeeighths",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fiveeighths",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "seveneighths",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onethird",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twothirds",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zerosuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twosuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "foursuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fivesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sixsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sevensuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eightsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ninesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zeroinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oneinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twoinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threeinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fourinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fiveinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sixinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "seveninferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eightinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nineinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "centinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollarinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "periodinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "commainferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Agravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Aacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Acircumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Atildesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Adieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Aringsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "AEsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ccedillasmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Egravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Eacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ecircumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Edieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Igravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Iacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Icircumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Idieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ethsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ntildesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ogravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Oacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ocircumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Otildesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Odieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "OEsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Oslashsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ugravesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Uacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ucircumflexsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Udieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Yacutesmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Thornsmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "Ydieresissmall",
 | 
						
						
						
						
							 | 
							
								 | 
							
							]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							cffExpertStringCount = 166
 | 
						
						
						
						
							 | 
							
								 | 
							
							assert len(cffIExpertStrings) == cffExpertStringCount
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							cffExpertSubsetStrings = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ".notdef",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "space",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollaroldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollarsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenleftsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenrightsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twodotenleader",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onedotenleader",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "comma",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hyphen",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "period",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fraction",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zerooldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oneoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twooldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threeoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fouroldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fiveoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sixoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sevenoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eightoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nineoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "colon",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "semicolon",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "commasuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threequartersemdash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "periodsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "asuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "bsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "centsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "esuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "isuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "lsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "msuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "osuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "rsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ssuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "tsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ff",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fi",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ffi",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ffl",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenleftinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "parenrightinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hyphensuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "colonmonetary",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onefitted",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "rupiah",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "centoldstyle",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "figuredash",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "hypheninferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onequarter",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onehalf",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threequarters",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oneeighth",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threeeighths",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fiveeighths",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "seveneighths",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onethird",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twothirds",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zerosuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "onesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twosuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "foursuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fivesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sixsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sevensuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eightsuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "ninesuperior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "zeroinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "oneinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "twoinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "threeinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fourinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "fiveinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "sixinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "seveninferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "eightinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "nineinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "centinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "dollarinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "periodinferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							    "commainferior",
 | 
						
						
						
						
							 | 
							
								 | 
							
							]
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							cffExpertSubsetStringCount = 87
 | 
						
						
						
						
							 | 
							
								 | 
							
							assert len(cffExpertSubsetStrings) == cffExpertSubsetStringCount
 |