Example #1
0
def packSFNT(header,
             directory,
             tableData,
             flavor="cff",
             calcCheckSum=True,
             applyPadding=True,
             sortDirectory=True,
             searchRange=None,
             entrySelector=None,
             rangeShift=None):
    # update the checkSum
    if calcCheckSum:
        if flavor == "cff":
            f = "OTTO"
        else:
            f = "\000\001\000\000"
        calcHeadCheckSumAdjustmentSFNT(directory, tableData, flavor=f)
    # update the header
    cSearchRange, cEntrySelector, cRangeShift = getSearchRange(
        len(directory), 16)
    if searchRange is None:
        searchRange = cSearchRange
    if entrySelector is None:
        entrySelector = cEntrySelector
    if rangeShift is None:
        rangeShift = cRangeShift
    if flavor == "cff":
        header["sfntVersion"] = "OTTO"
    else:
        header["sfntVersion"] = "\000\001\000\000"
    header["searchRange"] = searchRange
    header["entrySelector"] = entrySelector
    header["rangeShift"] = rangeShift
    # version and num tables should already be set
    sfntData = sstruct.pack(sfntDirectoryFormat, header)
    # compile the directory
    sfntDirectoryEntries = {}
    entryOrder = []
    for entry in directory:
        sfntEntry = SFNTDirectoryEntry()
        sfntEntry.tag = entry["tag"]
        sfntEntry.checkSum = entry["checksum"]
        sfntEntry.offset = entry["offset"]
        sfntEntry.length = entry["length"]
        sfntDirectoryEntries[entry["tag"]] = sfntEntry
        entryOrder.append(entry["tag"])
    if sortDirectory:
        entryOrder = sorted(entryOrder)
    for tag in entryOrder:
        entry = sfntDirectoryEntries[tag]
        sfntData += entry.toString()
    # compile the data
    directory = [(entry["offset"], entry["tag"]) for entry in directory]
    for o, tag in sorted(directory):
        data = tableData[tag]
        if applyPadding:
            data = padData(data)
        sfntData += data
    # done
    return sfntData
Example #2
0
File: woff.py Project: w3c/woff
def packTestTableData(directory, tableData, calcCheckSum=True):
    if calcCheckSum:
        calcHeadCheckSumAdjustment(directory, tableData)
    orderedData = []
    for entry in directory:
        tag = entry["tag"]
        origData, compData = tableData[tag]
        compData = padData(compData)
        orderedData.append(compData)
    return "".join(orderedData)
Example #3
0
def packSFNT(header, directory, tableData, flavor="cff",
    calcCheckSum=True, applyPadding=True, sortDirectory=True,
    searchRange=None, entrySelector=None, rangeShift=None):
    # update the checkSum
    if calcCheckSum:
        if flavor == "cff":
            f = "OTTO"
        else:
            f = "\000\001\000\000"
        calcHeadCheckSumAdjustmentSFNT(directory, tableData, flavor=f)
    # update the header
    cSearchRange, cEntrySelector, cRangeShift = getSearchRange(len(directory), 16)
    if searchRange is None:
        searchRange = cSearchRange
    if entrySelector is None:
        entrySelector = cEntrySelector
    if rangeShift is None:
        rangeShift = cRangeShift
    if flavor == "cff":
        header["sfntVersion"] = "OTTO"
    else:
        header["sfntVersion"] = "\000\001\000\000"
    header["searchRange"] = searchRange
    header["entrySelector"] = entrySelector
    header["rangeShift"] = rangeShift
    # version and num tables should already be set
    sfntData = sstruct.pack(sfntDirectoryFormat, header)
    # compile the directory
    sfntDirectoryEntries = {}
    entryOrder = []
    for entry in directory:
        sfntEntry = SFNTDirectoryEntry()
        sfntEntry.tag = entry["tag"]
        sfntEntry.checkSum = entry["checksum"]
        sfntEntry.offset = entry["offset"]
        sfntEntry.length = entry["length"]
        sfntDirectoryEntries[entry["tag"]] = sfntEntry
        entryOrder.append(entry["tag"])
    if sortDirectory:
        entryOrder = sorted(entryOrder)
    for tag in entryOrder:
        entry = sfntDirectoryEntries[tag]
        sfntData += entry.toString()
    # compile the data
    directory = [(entry["offset"], entry["tag"]) for entry in directory]
    for o, tag in sorted(directory):
        data = tableData[tag]
        if applyPadding:
            data = padData(data)
        sfntData += data
    # done
    return sfntData
Example #4
0
        if tag in transformedTables:
            transformed = True
            if transformFlag == 3:
                transformed = False
        else:
            transformed = transformFlag != 0

        if transformed and not skipTransformLength:
            data += packBase128(table["transformLength"], bug=Base128Bug)
    return data

def packTestCollectionHeader(header):
    return struct.pack(">L", header["version"]) + pack255UInt16(header["numFonts"])

def packTestCollectionDirectory(directory):
    data = ""
    for entry in directory:
        data += pack255UInt16(entry["numTables"])
        data += struct.pack(">4s", entry["flavor"])
        for i in entry["index"]:
            data += pack255UInt16(entry["index"][i])
    return data

def packTestMetadata((origMetadata, compMetadata), havePrivateData=False):
    if havePrivateData:
        compMetadata = padData(compMetadata)
    return compMetadata

def packTestPrivateData(privateData):
    return privateData
Example #5
0
def getSFNTCollectionData(pathOrFiles, modifyNames=True, reverseNames=False, DSIG=False, duplicates=[], shared=[]):
    tables = []
    offsets = {}

    fonts = [TTFont(pathOrFile) for pathOrFile in pathOrFiles]
    numFonts = len(fonts)

    header = dict(
        TTCTag="ttcf",
        Version=0x00010000,
        numFonts=numFonts,
    )

    if DSIG:
        header["version"] = 0x00020000

    fontData = sstruct.pack(ttcHeaderFormat, header)
    offset = ttcHeaderSize + (numFonts * struct.calcsize(">L"))
    if DSIG:
        offset += 3 * struct.calcsize(">L")

    for font in fonts:
        fontData += struct.pack(">L", offset)
        tags = [i for i in sorted(font.keys()) if len(i) == 4]
        offset += sfntDirectorySize + (len(tags) * sfntDirectoryEntrySize)

    if DSIG:
        data = "\0" * 4
        tables.append(data)
        offset += len(data)
        fontData += struct.pack(">4s", "DSIG")
        fontData += struct.pack(">L", len(data))
        fontData += struct.pack(">L", offset)

    for i, font in enumerate(fonts):
        # Make the name table unique
        if modifyNames:
            index = i
            if reverseNames:
                index = len(fonts) - i - 1
            name = font["name"]
            for namerecord in name.names:
                nameID = namerecord.nameID
                string = namerecord.toUnicode()
                if nameID == 1:
                    namerecord.string = "%s %d" % (string, index)
                elif nameID == 4:
                    namerecord.string = string.replace("Regular", "%d Regular" % index)
                elif nameID == 6:
                    namerecord.string = string.replace("-", "%d-" % index)

        tags = [i for i in sorted(font.keys()) if len(i) == 4]

        searchRange, entrySelector, rangeShift = getSearchRange(len(tags), 16)
        offsetTable = dict(
            sfntVersion=font.sfntVersion,
            numTables=len(tags),
            searchRange=searchRange,
            entrySelector=entrySelector,
            rangeShift=rangeShift,
        )

        fontData += sstruct.pack(sfntDirectoryFormat, offsetTable)

        for tag in tags:
            data = font.getTableData(tag)
            checksum = calcTableChecksum(tag, data)
            entry = dict(
                tag=tag,
                offset=offset,
                length=len(data),
                checkSum=checksum,
            )

            if (shared and tag not in shared) or tag in duplicates or data not in tables:
                tables.append(data)
                offsets[checksum] = offset
                offset += len(data) + calcPaddingLength(len(data))
            else:
                entry["offset"] = offsets[checksum]

            fontData += sstruct.pack(sfntDirectoryEntryFormat, entry)

    for table in tables:
        fontData += padData(table)

    for font in fonts:
        font.close()

    return fontData
Example #6
0
def getWOFFCollectionData(pathOrFiles, MismatchGlyfLoca=False, reverseNames=False):
    from defaultData import defaultTestData

    tableChecksums = []
    tableData = []
    tableOrder = []
    collectionDirectory = []
    locaIndices = []

    fonts = [TTFont(pathOrFile) for pathOrFile in pathOrFiles]
    for i, font in enumerate(fonts):
        index = i
        if reverseNames:
            index = len(fonts) - i - 1

        # Make the name table unique
        name = font["name"]
        for namerecord in name.names:
            nameID = namerecord.nameID
            string = namerecord.toUnicode()
            if nameID == 1:
                namerecord.string = "%s %d" % (string, index)
            elif nameID == 4:
                namerecord.string = string.replace("Regular", "%d Regular" % index)
            elif nameID == 6:
                namerecord.string = string.replace("-", "%d-" % index)

        tags = [i for i in sorted(font.keys()) if len(i) == 4]
        if "glyf" in tags:
            glyf = tags.index("glyf")
            loca = tags.index("loca")
            tags.insert(glyf + 1, tags.pop(loca))
        tableIndices = OrderedDict()
        for tag in tags:
            data = transformTable(font, tag)
            if MismatchGlyfLoca and tag in ("glyf", "loca"):
                tableData.append([tag, data])
                tableChecksums.append([tag, font.reader.tables[tag].checkSum])
                tableOrder.append(tag)
                tableIndex = len(tableData) - 1
                tableIndices[tag] = tableIndex
                if tag == "loca":
                    locaIndices.append(tableIndex)
            else:
                if [tag, data] not in tableData:
                    tableData.append([tag, data])
                    tableChecksums.append([tag, font.reader.tables[tag].checkSum])
                    tableOrder.append(tag)
                tableIndices[tag] = tableData.index([tag, data])
        collectionDirectory.append(dict(numTables=len(tableIndices), flavor=font.sfntVersion, index=tableIndices))
        font.close()
        del font

    if MismatchGlyfLoca:
        locaIndices.reverse()
        for i, entry in enumerate(collectionDirectory):
            entry["index"]["loca"] = locaIndices[i]
    totalData = "".join([data[1][1] for data in tableData])
    compData = brotli.compress(totalData, brotli.MODE_FONT)
    if len(compData) >= len(totalData):
        compData = totalData

    directory = [dict(tag=tag, origLength=0, transformLength=0, transformFlag=0) for tag in tableOrder]

    header, directory, collectionHeader, collectionDirectory, tableData = defaultTestData(directory=directory,
            tableData=tableData, compressedData=compData, collectionDirectory=collectionDirectory)

    data = packTestHeader(header)
    data += packTestDirectory(directory, isCollection=True)
    data += packTestCollectionHeader(collectionHeader)
    data += packTestCollectionDirectory(collectionDirectory)
    data += tableData

    data = padData(data)

    return data
Example #7
0
def getSFNTCollectionData(pathOrFiles,
                          modifyNames=True,
                          reverseNames=False,
                          duplicates=[]):
    tables = []
    offsets = {}

    fonts = [TTFont(pathOrFile) for pathOrFile in pathOrFiles]
    numFonts = len(fonts)

    header = dict(
        TTCTag="ttcf",
        Version=0x00010000,
        numFonts=numFonts,
    )

    fontData = sstruct.pack(ttcHeaderFormat, header)
    offset = ttcHeaderSize + (numFonts * struct.calcsize(">L"))
    for font in fonts:
        fontData += struct.pack(">L", offset)
        tags = [i for i in sorted(font.keys()) if len(i) == 4]
        offset += sfntDirectorySize + (len(tags) * sfntDirectoryEntrySize)

    for i, font in enumerate(fonts):
        # Make the name table unique
        if modifyNames:
            index = i
            if reverseNames:
                index = len(fonts) - i - 1
            name = font["name"]
            for namerecord in name.names:
                nameID = namerecord.nameID
                string = namerecord.toUnicode()
                if nameID == 1:
                    namerecord.string = "%s %d" % (string, index)
                elif nameID == 4:
                    namerecord.string = string.replace("Regular",
                                                       "%d Regular" % index)
                elif nameID == 6:
                    namerecord.string = string.replace("-", "%d-" % index)

        tags = [i for i in sorted(font.keys()) if len(i) == 4]

        searchRange, entrySelector, rangeShift = getSearchRange(len(tags), 16)
        offsetTable = dict(
            sfntVersion=font.sfntVersion,
            numTables=len(tags),
            searchRange=searchRange,
            entrySelector=entrySelector,
            rangeShift=rangeShift,
        )

        fontData += sstruct.pack(sfntDirectoryFormat, offsetTable)

        for tag in tags:
            data = font.getTableData(tag)
            checksum = font.reader.tables[tag].checkSum
            entry = dict(
                tag=tag,
                offset=offset,
                length=len(data),
                checkSum=checksum,
            )

            if tag in duplicates or data not in tables:
                tables.append(data)
                offsets[checksum] = offset
                offset += len(data) + calcPaddingLength(len(data))
            else:
                entry["offset"] = offsets[checksum]

            fontData += sstruct.pack(sfntDirectoryEntryFormat, entry)

    for table in tables:
        fontData += padData(table)

    for font in fonts:
        font.close()

    return fontData
Example #8
0
def getWOFFCollectionData(pathOrFiles, MismatchGlyfLoca=False):
    from defaultData import defaultTestData

    tableChecksums = []
    tableData = []
    tableOrder = []
    collectionDirectory = []
    locaIndices = []

    for i, pathOrFile in enumerate(pathOrFiles):
        font = TTFont(pathOrFile)

        # Make the name table unique
        name = font["name"]
        for namerecord in name.names:
            nameID = namerecord.nameID
            string = namerecord.toUnicode()
            if nameID == 1:
                namerecord.string = "%s %d" % (string, i)
            elif nameID == 4:
                namerecord.string = string.replace("Regular", "%d Regular" % i)
            elif nameID == 6:
                namerecord.string = string.replace("-", "%d-" % i)

        tags = [i for i in sorted(font.keys()) if len(i) == 4]
        if "glyf" in tags:
            glyf = tags.index("glyf")
            loca = tags.index("loca")
            tags.insert(glyf + 1, tags.pop(loca))
        tableIndices = OrderedDict()
        for tag in tags:
            data = transformTable(font, tag)
            if MismatchGlyfLoca and tag in ("glyf", "loca"):
                tableData.append([tag, data])
                tableChecksums.append([tag, font.reader.tables[tag].checkSum])
                tableOrder.append(tag)
                tableIndex = len(tableData) - 1
                tableIndices[tag] = tableIndex
                if tag == "loca":
                    locaIndices.append(tableIndex)
            else:
                if [tag, data] not in tableData:
                    tableData.append([tag, data])
                    tableChecksums.append(
                        [tag, font.reader.tables[tag].checkSum])
                    tableOrder.append(tag)
                tableIndices[tag] = tableData.index([tag, data])
        collectionDirectory.append(
            dict(numTables=len(tableIndices),
                 flavor=font.sfntVersion,
                 index=tableIndices))
        font.close()
        del font

    if MismatchGlyfLoca:
        locaIndices.reverse()
        for i, entry in enumerate(collectionDirectory):
            entry["index"]["loca"] = locaIndices[i]
    totalData = "".join([data[1][1] for data in tableData])
    compData = brotli.compress(totalData, brotli.MODE_FONT)
    if len(compData) >= len(totalData):
        compData = totalData

    directory = [
        dict(tag=tag, origLength=0, transformLength=0) for tag in tableOrder
    ]

    header, directory, collectionHeader, collectionDirectory, tableData = defaultTestData(
        directory=directory,
        tableData=tableData,
        compressedData=compData,
        collectionDirectory=collectionDirectory)

    data = packTestHeader(header)
    data += packTestDirectory(directory, isCollection=True)
    data += packTestCollectionHeader(collectionHeader)
    data += packTestCollectionDirectory(collectionDirectory)
    data += tableData

    data = padData(data)

    return data
Example #9
0
    for tag, table in directory:
        if tag in knownTableTags:
            data += struct.pack(">B", knownTableTags.index(tag))
        else:
            data += struct.pack(">B", unknownTableTagFlag)
            data += struct.pack(">4s", tag)
        data += packBase128(table["origLength"], bug=Base128Bug)
        if tag in transformedTables:
            data += packBase128(table["transformLength"], bug=Base128Bug)
    return data

def packTestCollectionHeader(header):
    return struct.pack(">L", header["version"]) + pack255UInt16(header["numFonts"])

def packTestCollectionDirectory(directory):
    data = ""
    for entry in directory:
        data += pack255UInt16(entry["numTables"])
        data += struct.pack(">4s", entry["flavor"])
        for i in entry["index"]:
            data += pack255UInt16(entry["index"][i])
    return data

def packTestMetadata((origMetadata, compMetadata), havePrivateData=False):
    if havePrivateData:
        compMetadata = padData(compMetadata)
    return compMetadata

def packTestPrivateData(privateData):
    return privateData