Esempio n. 1
0
def main():
    options = parser.parse_args()
    fonts = options.ttf_font
    if options.ascents or \
       options.descents or \
       options.linegaps or \
       options.linegaps  == 0 or \
       options.ascents_hhea or \
       options.ascents_typo or \
       options.ascents_win or \
       options.descents_hhea or \
       options.descents_typo or \
       options.descents_win or \
       options.linegaps_hhea or \
       options.linegaps_hhea == 0 or \
       options.linegaps_typo or \
       options.linegaps_typo == 0:
        for f in fonts:
            try:
                ttfont = ttLib.TTFont(f)
            except TTLibError as ex:
                print('Error: {0}: {1}'.format(f, ex))
                continue

            if options.ascents:
                ttfont['hhea'].ascent = options.ascents
                ttfont['OS/2'].sTypoAscender = options.ascents
                ttfont['OS/2'].usWinAscent = options.ascents

            if options.descents:
                ttfont['hhea'].descent = options.descents
                ttfont['OS/2'].sTypoDescender = options.descents
                ttfont['OS/2'].usWinDescent = abs(options.descents)

            if options.linegaps or options.linegaps == 0:
                ttfont['hhea'].lineGap = options.linegaps
                ttfont['OS/2'].sTypoLineGap = options.linegaps

            if options.ascents_hhea:
                ttfont['hhea'].ascent = options.ascents_hhea
            if options.ascents_typo:
                ttfont['OS/2'].sTypoAscender = options.ascents_typo
            if options.ascents_win:
                ttfont['OS/2'].usWinAscent = options.ascents_win

            if options.descents_hhea:
                ttfont['hhea'].descent = options.descents_hhea
            if options.descents_typo:
                ttfont['OS/2'].sTypoDescender = options.descents_typo
            if options.descents_win:
                ttfont['OS/2'].usWinDescent = abs(options.descents_win)

            if options.linegaps_hhea or options.linegaps_hhea == 0:
                ttfont['hhea'].lineGap = options.linegaps_hhea
            if options.linegaps_typo or options.linegaps_typo == 0:
                ttfont['OS/2'].sTypoLineGap = options.linegaps_typo

            ttfont.save(f[:-4] + '.fix.ttf')

    elif options.autofix:
        ttFonts = []
        for f in fonts:
            try:
                ttFonts.append(ttLib.TTFont(f))
            except TTLibError as ex:
                print('Error: {0}: {1}'.format(f, ex))
                continue

        v_metrics = vmetrics(ttFonts)
        for ttfont in ttFonts:
            ttfont['hhea'].ascent = v_metrics["ymax"]
            ttfont['OS/2'].sTypoAscender = v_metrics["ymax"]
            ttfont['OS/2'].usWinAscent = v_metrics["ymax"]

            ttfont['hhea'].descent = v_metrics["ymin"]
            ttfont['OS/2'].sTypoDescender = v_metrics["ymin"]
            ttfont['OS/2'].usWinDescent = abs(v_metrics["ymin"])

            ttfont.save(ttfont.reader.file.name[:-4] + '.fix.ttf')

    else:
        entries = [('hhea', 'ascent'), ('OS/2', 'sTypoAscender'),
                   ('OS/2', 'usWinAscent'), ('hhea', 'descent'),
                   ('OS/2', 'sTypoDescender'), ('OS/2', 'usWinDescent'),
                   ('hhea', 'lineGap'), ('OS/2', 'sTypoLineGap')]

        for f in fonts:
            ttfont = ttLib.TTFont(f)
            print("## {}".format(f))
            for table, field in entries:
                print("{} {}: {}".format(table, field,
                                         getattr(ttfont[table], field)))
            print()
Esempio n. 2
0
 def setUp(self):
     self.font = font = ttLib.TTFont(recalcBBoxes=False,
                                     recalcTimestamp=False)
     font['head'] = ttLib.newTable('head')
     font['loca'] = WOFF2LocaTable()
     font['glyf'] = WOFF2GlyfTable()
Esempio n. 3
0
 def __init__(self, path):
     self.font = ttLib.TTFont(path)
     self.path = path
     self.saveit = False
Esempio n. 4
0
 def __init__(self, font_file):
     MAPPING_FILE = './character'
     self.font = ttLib.TTFont(font_file)
     self.table = pickle.load(open(MAPPING_FILE, 'rb'))
Esempio n. 5
0
 def test_required_tables(self):
     font = ttLib.TTFont(flavor="woff2")
     with self.assertRaisesRegex(ttLib.TTLibError,
                                 "missing required table"):
         font.save(BytesIO())
Esempio n. 6
0
 def upm(self, ftpath):
     ft = ttLib.TTFont(ftpath)
     upm = ft["head"].unitsPerEm
     return ft, upm
Esempio n. 7
0
 def fromfontcmap(fontname):
     font = ttLib.TTFont(fontname)
     return CodeList.fromset(font_data.get_cmap(font))
Esempio n. 8
0
def main():

    global maxInstructions, quietcount

    # First read the command-line arguments. At minimum we need the inputfile.

    argparser = argparse.ArgumentParser(
        prog='xgridfit',
        description=
        'Compile XML into TrueType instructions and add them to a font.')
    argparser.add_argument('-v',
                           '--version',
                           action='version',
                           version='Xgridfit ' + __version__)
    argparser.add_argument(
        '-e',
        '--expand',
        action="store_true",
        help="Convert file to expanded syntax, save, and exit")
    argparser.add_argument(
        '-c',
        '--compact',
        action="store_true",
        help="Convert file to compact syntax, save, and exit")
    argparser.add_argument('-n',
                           '--novalidation',
                           action="store_true",
                           help="Skip validation of the Xgridfit program")
    argparser.add_argument('--nocompilation',
                           action="store_true",
                           help="Skip compilation of the Xgridfit program")
    argparser.add_argument(
        '--nocompact',
        action="store_true",
        help="Do not compact glyph programs (can help with debugging)")
    argparser.add_argument('-m',
                           '--merge',
                           action="store_true",
                           help="Merge Xgridfit with existing instructions")
    argparser.add_argument(
        '-r',
        '--replaceprep',
        action="store_true",
        help=
        "Whether to replace the existing prep table or append the new one (use with --merge)"
    )
    argparser.add_argument(
        '--initgraphics',
        choices=['yes', 'no'],
        help=
        "Whether to initialize graphics-tracking variables at the beginning of glyph program"
    )
    argparser.add_argument(
        '-a',
        '--assume_y',
        choices=['yes', 'no'],
        help="Whether compiler should assume that your hints are all vertical")
    argparser.add_argument(
        '-q',
        '--quiet',
        action="count",
        default=0,
        help="No progress messages (-qq to suppress warnings too)")
    argparser.add_argument('-g',
                           '--glyphlist',
                           help="List of glyphs to compile")
    argparser.add_argument('-i',
                           '--inputfont',
                           action='store',
                           type=str,
                           help="The font file to add instructions to")
    argparser.add_argument('-o',
                           '--outputfont',
                           action='store',
                           type=str,
                           help="The font file to write")
    argparser.add_argument('-s',
                           '--saveprograms',
                           action="store_true",
                           help="Save generated instructions to text files")
    argparser.add_argument(
        '-f',
        '--coordinatefuzz',
        type=int,
        default=1,
        help=
        "Error tolerance for points identified by coordinates (default is 1)")
    argparser.add_argument("inputfile", help='Xgridfit (XML) file to process.')
    argparser.add_argument(
        "outputfile",
        nargs='?',
        help="Filename for options (e.g. --expand) that produce text output")
    args = argparser.parse_args()

    inputfile = args.inputfile
    outputfile = args.outputfile
    inputfont = args.inputfont
    outputfont = args.outputfont
    skipval = args.novalidation
    skipcomp = args.nocompilation
    expandonly = args.expand
    compactonly = args.compact
    mergemode = args.merge
    quietcount = args.quiet
    initgraphics = args.initgraphics
    assume_y = args.assume_y
    glyphlist = args.glyphlist
    replaceprep = args.replaceprep
    saveprograms = args.saveprograms
    nocompact = args.nocompact
    cfuzz = args.coordinatefuzz

    if quietcount < 1:
        print("Opening the Xgridfit file ...")

    if cfuzz > 1:
        coordinateFuzz = cfuzz

    xgffile = etree.parse(inputfile)

    # We'll need namespaces

    ns = {
        "xgf": "http://xgridfit.sourceforge.net/Xgridfit2",
        "xi": "http://www.w3.org/2001/XInclude",
        "xsl": "http://www.w3.org/1999/XSL/Transform"
    }

    # Do xinclude if this is a multipart file

    if len(xgffile.xpath("/xgf:xgridfit/xi:include", namespaces=ns)):
        xgffile.xinclude()

    # Next determine whether we are using long tagnames or short. Best way
    # is to find out which tag is used for the required <pre-program> (<prep>)
    # element. If we don't find it, print an error message and exit. Here's
    # where we validate too; and if we're only expanding or compacting a file,
    # do that and exit before we go to the trouble of opening the font.
    if quietcount < 1:
        print("Validating ...")

    if len(xgffile.xpath("/xgf:xgridfit/xgf:prep", namespaces=ns)):
        # first validate
        validate(xgffile, "compact", skipval)
        # as we can't use the compact syntax, always expand
        if quietcount < 1:
            print("Expanding compact to normal syntax ...")
        xslfile = get_file_path("XSL/expand.xsl")
        etransform = etree.XSLT(etree.parse(xslfile))
        xgffile = etransform(xgffile)
        if expandonly:
            tstr = str(xgffile)
            tstr = tstr.replace('xgf:', '')
            tstr = tstr.replace(
                'xmlns:xgf="http://xgridfit.sourceforge.net/Xgridfit2"', '')
            if outputfile:
                of = open(outputfile, "w")
                of.write(tstr)
                of.close()
            else:
                print(tstr)
            sys.exit(0)
    elif len(xgffile.xpath("/xgf:xgridfit/xgf:pre-program", namespaces=ns)):
        validate(xgffile, "normal", skipval)
        if compactonly:
            xslfile = get_file_path("XSL/compact.xsl")
            etransform = etree.XSLT(etree.parse(xslfile))
            xgffile = etransform(xgffile)
            tstr = str(xgffile)
            tstr = tstr.replace('xgf:', '')
            tstr = tstr.replace(
                'xmlns:xgf="http://xgridfit.sourceforge.net/Xgridfit2"', '')
            tstr = tstr.replace(' >', '>')
            if outputfile:
                of = open(outputfile, "w")
                of.write(tstr)
                of.close()
            else:
                print(tstr)
            sys.exit(0)
    else:
        print(
            "The xgridfit program must contain a pre-program (prep) element,")
        print("even if it's empty.")
        sys.exit(1)

    if skipcomp and quietcount < 1:
        print("Skipping compilation")
        sys.exit(0)

    # Now open the font. If we're in merge-mode, we need to know some things
    # about the current state of it; otherwise we just wipe it.

    if quietcount < 1:
        print("Opening and evaluating the font ...")
    if not inputfont:
        inputfont = xgffile.xpath("/xgf:xgridfit/xgf:inputfont/text()",
                                  namespaces=ns)[0]
    if not inputfont:
        print("Need the filename of a font to read. Use the --inputfont")
        print("command-line argument or the <inputfont> element in your")
        print("Xgridfit file.")
        sys.exit(1)
    thisFont = ttLib.TTFont(inputfont)
    functionBase = 0  # Offset to account for functions in existing font
    cvtBase = 0  # Offset to account for CVs in existing font
    storageBase = 0  # Offset to account for storage in existing font
    maxStack = 256  # Our (generous) default stack size
    twilightBase = 0  # Offset to account for twilight space in existing font
    if mergemode:
        maxInstructions = max(maxInstructions,
                              thisFont['maxp'].maxSizeOfInstructions)
        storageBase = thisFont['maxp'].maxStorage
        maxStack = max(maxStack, thisFont['maxp'].maxStackElements)
        functionBase = thisFont['maxp'].maxFunctionDefs
        twilightBase = thisFont['maxp'].maxTwilightPoints
        try:
            cvtBase = len(getattr(thisFont['cvt '], 'values'))
        except:
            cvtBase = 0
    else:
        wipe_font(thisFont)

    # Get the xsl file, change some defaults (only relevant in merge-mode),
    # and get a transform object

    xslfile = etree.parse(get_file_path("XSL/xgridfit-ft.xsl"))
    if mergemode:
        xslfile.xpath("/xsl:stylesheet/xsl:param[@name='function-base']",
                      namespaces=ns)[0].attrib['select'] = str(functionBase)
        xslfile.xpath("/xsl:stylesheet/xsl:param[@name='cvt-base']",
                      namespaces=ns)[0].attrib['select'] = str(cvtBase)
        xslfile.xpath("/xsl:stylesheet/xsl:param[@name='storage-base']",
                      namespaces=ns)[0].attrib['select'] = str(storageBase)
    etransform = etree.XSLT(xslfile)

    # Get a list of the glyphs to compile

    if quietcount < 1:
        print("Getting glyph list ...")

    if glyphlist:
        # a list passed in as a command-line argument
        glyph_list = glyphlist
    else:
        # all the glyph programs in the file
        glyph_list = str(etransform(xgffile, **{"get-glyph-list": "'yes'"}))
    glyph_list = list(glyph_list.split(" "))
    no_compact_list = str(
        etransform(xgffile, **{"get-no-compact-list": "'yes'"}))
    if no_compact_list == None:
        no_compact_list = []
    else:
        no_compact_list = list(no_compact_list.split(" "))

    # Now that we have a glyph list, we can make the coordinate index
    # and substitute point numbers for coordinates.

    coordinateIndex = make_coordinate_index(glyph_list, thisFont)
    coordinates_to_points(glyph_list, xgffile, coordinateIndex, ns)

    # Back to the xgf file. We're also going to need a list of stack-safe
    # functions in this font.

    if quietcount < 1:
        print("Getting list of safe function calls ...")

    safe_calls = etransform(xgffile, **{"stack-safe-list": "'yes'"})
    safe_calls = literal_eval(str(safe_calls))

    # Get cvt

    if quietcount < 1:
        print("Building control-value table ...")

    cvt_list = str(etransform(xgffile, **{"get-cvt-list": "'yes'"}))
    cvt_list = literal_eval("[" + cvt_list + "]")
    install_cvt(thisFont, cvt_list, cvtBase)

    # Test whether we have a cvar element (i.e. this is a variable font)

    cvar_count = len(xgffile.xpath("/xgf:xgridfit/xgf:cvar", namespaces=ns))
    if cvar_count > 0:
        if quietcount < 1:
            print("Building cvar table ...")
        tuple_store = literal_eval(
            str(etransform(xgffile, **{"get-cvar": "'yes'"})))
        install_cvar(thisFont, tuple_store, mergemode, cvtBase)

    if quietcount < 1:
        print("Building fpgm table ...")

    predef_functions = int(
        xslfile.xpath(
            "/xsl:stylesheet/xsl:variable[@name='predefined-functions']",
            namespaces=ns)[0].attrib['select'])
    maxFunction = etransform(xgffile, **{"function-count": "'yes'"})
    maxFunction = int(maxFunction) + predef_functions + functionBase

    fpgm_code = etransform(xgffile, **{"fpgm-only": "'yes'"})
    install_functions(thisFont, fpgm_code, functionBase)
    if saveprograms:
        instf = open("fpgm.instructions", "w")
        instf.write(str(fpgm_code))
        instf.close

    if quietcount < 1:
        print("Building prep table ...")

    prep_code = etransform(xgffile, **{"prep-only": "'yes'"})
    install_prep(thisFont, prep_code, mergemode, replaceprep)
    if saveprograms:
        instf = open("prep.instructions", "w")
        instf.write(str(prep_code))
        instf.close

    # Now loop through the glyphs for which there is code.

    cycler = 0
    for g in glyph_list:
        if quietcount < 1:
            print("Processing glyph " + g)
        elif quietcount < 2 and cycler == 4:
            print(".", end=" ", flush=True)
        cycler += 1
        if cycler == 5:
            cycler = 0
        try:
            gt = "'" + g + "'"
            glyph_args = {'singleGlyphId': gt}
            if initgraphics:
                glyph_args['init_graphics'] = "'" + initgraphics + "'"
            if assume_y:
                glyph_args['assume-always-y'] = "'" + assume_y + "'"
            g_inst = etransform(xgffile, **glyph_args)
        except Exception as e:
            print(e)
            for entry in etransform.error_log:
                print('message from line %s, col %s: %s' %
                      (entry.line, entry.column, entry.message))
            sys.exit(1)
        if nocompact or g in no_compact_list:
            g_inst_final = str(g_inst)
        else:
            g_inst_final = compact_instructions(str(g_inst), safe_calls)
        install_glyph_program(g, thisFont, g_inst_final)
        if saveprograms:
            gfn = userNameToFileName(g) + ".instructions"
            gfnfile = open(gfn, "w")
            if nocompact or g in no_compact_list:
                gfnfile.write(g_inst_final)
            else:
                gfnfile.write("Uncompacted:\n\n")
                gfnfile.write(str(g_inst))
                gfnfile.write("\n\nCompacted:\n\n")
                gfnfile.write(g_inst_final)
            gfnfile.close
    print("")

    if quietcount < 1:
        print("Hinted " + str(len(glyph_list)) + " glyphs.")
        print("Cleaning up and writing the new font")
    thisFont['maxp'].maxSizeOfInstructions = maxInstructions + 50
    thisFont['maxp'].maxTwilightPoints = twilightBase + 25
    thisFont['maxp'].maxStorage = storageBase + 64
    thisFont['maxp'].maxStackElements = maxStack
    thisFont['maxp'].maxFunctionDefs = maxFunction
    thisFont['head'].flags |= 0b0000000000001000
    if skipcomp:
        if quietcount < 1:
            print(
                "As --nocompilation flag is set, exiting without writing font file."
            )
        sys.exit(0)
    if not outputfont:
        outputfont = str(
            xgffile.xpath("/xgf:xgridfit/xgf:outputfont/text()",
                          namespaces=ns)[0])
    if not outputfont:
        print("Need the filename of a font to write. Use the --outputfont")
        print("command-line argument or the <outputfont> element in your")
        print("Xgridfit file.")
        sys.exit(1)
    thisFont.save(outputfont, 1)
Esempio n. 9
0
def copy_ttx_files(project, build, log):
    from .app import app
    config = project.config

    param = {
        'login': project.login,
        'id': project.id,
        'revision': build.revision,
        'build': build.id
    }

    _in = os.path.join(app.config['DATA_ROOT'], '%(login)s/%(id)s.in/' % param)
    _out = os.path.join(app.config['DATA_ROOT'],
                        '%(login)s/%(id)s.out/%(build)s.%(revision)s/' % param)
    _out_src = os.path.join(
        app.config['DATA_ROOT'],
        '%(login)s/%(id)s.out/%(build)s.%(revision)s/sources/' % param)

    ttx_files = []
    for x in config['state'].get('process_files', []):
        if x.endswith('.ttx'):
            ttx_files.append(x)

    for ttx_file in ttx_files:
        _ttx_path = os.path.join(_in, ttx_file)
        if not os.path.exists(_ttx_path):
            run("echo file '{}' not found".format(_ttx_path),
                cwd=_out,
                log=log)
            continue

        font = ttLib.TTFont(None,
                            lazy=False,
                            recalcBBoxes=True,
                            verbose=False,
                            allowVID=False)
        font.importXML(_ttx_path, quiet=True)
        _ttx_name = os.path.splitext(os.path.basename(_ttx_path))[0]

        def nameTableRead(font, NameID, fallbackNameID=False):
            for record in font['name'].names:
                if record.nameID == NameID:
                    if b'\000' in record.string:
                        return record.string.decode('utf-16-be').encode(
                            'utf-8')
                    else:
                        return record.string

            if fallbackNameID:
                return nameTableRead(font, fallbackNameID)

        styleName = nameTableRead(font, 17, 2)
        # Always have a regular style
        if styleName == 'Normal':
            styleName = 'Regular'

        # NameID=1 is required
        familyName = nameTableRead(font, 16, 1)
        # Remove whitespace from names
        styleNameNoWhitespace = re.sub(r'\s', '', styleName)
        familyNameNoWhitespace = re.sub(r'\s', '', familyName)

        _out_ttx_name = "{familyname}-{stylename}".format(
            familyname=familyNameNoWhitespace, stylename=styleNameNoWhitespace)

        if font.sfntVersion == '\x00\x01\x00\x00':  # TTF
            _out_name = '{}.ttf.ttx'.format(_out_ttx_name)
        elif font.sfntVersion == 'OTTO':  # OTF
            _out_name = '{}.otf.ttx'.format(_out_ttx_name)

        run("cp '{}' '{}'".format(_ttx_path, _out_src), cwd=_out, log=log)
        run("mv '{ttx_name}.ttx' '{out_name}'".format(ttx_name=_ttx_name,
                                                      out_name=_out_name),
            cwd=_out_src,
            log=log)
        run("ttx -i -q {}".format(_out_name), cwd=_out_src, log=log)
        run("mv {0}.ttf.ttf {0}.ttf".format(_out_ttx_name),
            cwd=_out_src,
            log=log)
        if font.sfntVersion == 'OTTO':  # OTF
            scripts_folder = os.path.join(app.config['ROOT'], 'scripts')
            cmd = "python autoconvert.py '{out_src}{ttx_name}.otf' '{out}{ttx_name}.ttf'".format(
                out_src=_out_src, ttx_name=_out_ttx_name, out=_out)
            run(cmd, cwd=scripts_folder, log=log)
        else:
            run("mv '{0}.ttf' '../{0}.ttf'".format(_out_ttx_name),
                _out_src,
                log=log)
Esempio n. 10
0
 def _remove_from_cmap(infile, outfile, exclude=[]):
   font = ttLib.TTFont(infile)
   font_data.delete_from_cmap(font, exclude)
   font.save(outfile)
def splitFont(
    fontPath,
    outputDirectory="fonts/rec_mono-for-code",
    newName="Rec Mono",
    ttc=False,
    zip=False,
):

    # access font as TTFont object
    varfont = ttLib.TTFont(fontPath)

    fontFileName = os.path.basename(fontPath)

    for package in instanceValues:
        outputSubDir = f"{outputDirectory}/{package}"

        for instance in instanceValues[package]:

            print(instance)

            instanceFont = instancer.instantiateVariableFont(
                varfont,
                {
                    "wght": instanceValues[package][instance]["wght"],
                    "CASL": instanceValues[package][instance]["CASL"],
                    "MONO": instanceValues[package][instance]["MONO"],
                    "slnt": instanceValues[package][instance]["slnt"],
                    "CRSV": instanceValues[package][instance]["CRSV"],
                },
            )

            # UPDATE NAME ID 6, postscript name
            currentPsName = getFontNameID(instanceFont, 6)
            newPsName = (currentPsName.replace("Sans", "").replace(
                oldName,
                newName.replace(" ", "")).replace("LinearLight",
                                                  instance.replace(" ", "")))
            setFontNameID(instanceFont, 6, newPsName)

            # UPDATE NAME ID 4, full font name
            currentFullName = getFontNameID(instanceFont, 4)
            newFullName = (currentFullName.replace("Sans", "").replace(
                oldName, newName).replace(" Linear Light", instance))
            setFontNameID(instanceFont, 4, newFullName)

            # UPDATE NAME ID 3, unique font ID
            currentUniqueName = getFontNameID(instanceFont, 3)
            newUniqueName = (currentUniqueName.replace("Sans", "").replace(
                oldName,
                newName.replace(" ", "")).replace("LinearLight",
                                                  instance.replace(" ", "")))
            setFontNameID(instanceFont, 3, newUniqueName)

            # ADD name 2, style linking name
            newStyleLinkingName = instanceValues[package][instance]["style"]
            setFontNameID(instanceFont, 2, newStyleLinkingName)
            setFontNameID(instanceFont, 17, newStyleLinkingName)

            # UPDATE NAME ID 1, unique font ID
            currentFamName = getFontNameID(instanceFont, 1)
            newFamName = (currentFamName.replace(" Sans", "").replace(
                oldName, newName).replace(
                    "Linear Light",
                    instance.replace(
                        " " + instanceValues[package][instance]["style"], ""),
                ))
            setFontNameID(instanceFont, 1, newFamName)
            setFontNameID(instanceFont, 16, newFamName)

            newFileName = fontFileName.replace(oldName, newName.replace(
                " ", "")).replace("_VF_",
                                  "-" + instance.replace(" ", "") + "-")

            # make dir for new fonts
            pathlib.Path(outputSubDir).mkdir(parents=True, exist_ok=True)

            # drop STAT table to allow RIBBI style naming & linking on Windows
            del instanceFont["STAT"]

            outputPath = f"{outputSubDir}/{newFileName}"

            # save font
            instanceFont.save(outputPath)

            # freeze in rvrn features with pyftfeatfreeze
            pyftfeatfreeze.main(["--features=rvrn", outputPath, outputPath])

            # swap dlig2calt to make code ligatures work in old code editor apps
            dlig2calt(outputPath, inplace=True)

        # -----------------------------------------------------------
        # make TTC (truetype collection) of fonts – doesn't current work on Mac very well :(

        if ttc:
            # make list of fonts in subdir
            fontPaths = [
                os.path.abspath(outputSubDir + "/" + x)
                for x in os.listdir(outputSubDir)
            ]

            # form command
            command = f"otf2otc {' '.join(fontPaths)} -o {outputDirectory}/RecMono-{package}.ttc"
            print("▶", command, "\n")

            # run command in shell
            subprocess.run(command.split(), check=True, text=True)

            # remove dir with individual fontpaths
            shutil.rmtree(os.path.abspath(outputSubDir))

    # Make zip of output, then put inside output directory
    if zip:
        shutil.make_archive(f"{outputDirectory}", "zip", outputDirectory)
        shutil.move(
            f"{outputDirectory}.zip",
            f"{outputDirectory}/{outputDirectory.split('/')[-1]}.zip",
        )
Esempio n. 12
0
def processFont(fontPath, outputFolderPath, options):
    font = ttLib.TTFont(fontPath)
    glyphOrder = font.getGlyphOrder()
    svgTag = 'SVG '

    if svgTag not in font:
        print("ERROR: The font does not have the {} table.".format(
            svgTag.strip()),
              file=sys.stderr)
        sys.exit(1)

    svgTable = font[svgTag]

    if not len(svgTable.docList):
        print("ERROR: The {} table has no data that can be output.".format(
            svgTag.strip()),
              file=sys.stderr)
        sys.exit(1)

    # Define the list of glyph names to convert to SVG
    if options.gnames_to_generate:
        glyphNamesList = sorted(options.gnames_to_generate)
    else:
        glyphNamesList = sorted(glyphOrder)

    # Confirm that there's something to process
    if not glyphNamesList:
        print("The fonts and options provided can't produce any SVG files.",
              file=sys.stdout)
        return

    # Define the list of glyph names to skip
    glyphNamesToSkipList = [".notdef"]
    if options.gnames_to_exclude:
        glyphNamesToSkipList.extend(options.gnames_to_exclude)

    # Determine which glyph names need to be saved in a nested folder
    glyphNamesToSaveInNestedFolder = get_gnames_to_save_in_nested_folder(
        glyphNamesList)

    nestedFolderPath = None
    filesSaved = 0
    unnamedNum = 1

    # Write the SVG files by iterating over the entries in the SVG table.
    # The process assumes that each SVG document contains only one 'id' value,
    # i.e. the artwork for two or more glyphs is not included in a single SVG.
    for svgItemsList in svgTable.docList:
        svgItemData, startGID, endGID = svgItemsList

        if options.reset_viewbox:
            svgItemData = resetViewBox(svgItemData)

        while (startGID != endGID + 1):
            try:
                gName = glyphOrder[startGID]
            except IndexError:
                gName = "_unnamed{}".format(unnamedNum)
                glyphNamesList.append(gName)
                unnamedNum += 1
                print("WARNING: The SVG table references a glyph ID (#{}) "
                      "which the font does not contain.\n"
                      "         The artwork will be saved as '{}.svg'.".format(
                          startGID, gName),
                      file=sys.stderr)

            if gName not in glyphNamesList or gName in glyphNamesToSkipList:
                startGID += 1
                continue

            # Create the output folder.
            # This may be necessary if the folder was not provided.
            # The folder is made this late in the process because
            # only now it's clear that's needed.
            create_folder(outputFolderPath)

            # Create the nested folder, if there are conflicting glyph names.
            if gName in glyphNamesToSaveInNestedFolder:
                folderPath = create_nested_folder(nestedFolderPath,
                                                  outputFolderPath)
            else:
                folderPath = outputFolderPath

            svgFilePath = os.path.join(folderPath, gName + '.svg')
            write_file(svgFilePath, svgItemData)
            filesSaved += 1
            startGID += 1

    font.close()
    final_message(filesSaved)
Esempio n. 13
0
def _ttFont(font_file):
    return ttLib.TTFont(font_file)
Esempio n. 14
0
def font():
    font = ttLib.TTFont()
    font.setGlyphOrder(["glyph%05d" % i for i in range(30)])
    return font
Esempio n. 15
0
 def opener(path):
     font = ttLib.TTFont()
     font.importXML(path)
     return font
Esempio n. 16
0
 def __init__(self, font_file):
     """传入woff文件实例化, 调用 convert 方法转换加密字体"""
     MAPPING_FILE = './character'
     self.font = ttLib.TTFont(font_file)
     self.table = pickle.load(open(MAPPING_FILE, 'rb'))
Esempio n. 17
0
 def glyphOrders(self, fontpathlist):
     ftpath2glyphorder = dict()
     for fpath in fontpathlist:
         ftpath2glyphorder[fpath] = ttLib.TTFont(fpath).getGlyphOrder()
     return ftpath2glyphorder
Esempio n. 18
0
def main():
    TTF_FILES = []

    parser = argparse.ArgumentParser()
    parser.add_argument('-l',
                        '--license',
                        help='show license terms',
                        action='store_true')
    parser.add_argument('-f',
                        '--ttf_folder',
                        default='C:\\Windows\\Fonts\\',
                        help='Folder where ttf files are stored')
    parser.add_argument(
        '-o',
        '--output_folder',
        default='..\\bmh_fonts',
        help=
        'Folder where bitmapheader output files will be stored. A subfolder for each Font will be created under the directory.'
    )
    parser.add_argument('-c',
                        '--character_filename',
                        default='..//characters_digits.txt',
                        help='filename for characters to be processed')
    parser.add_argument(
        '--font',
        default='',
        help=
        'Define Font Name to be processed. Name should include modifier like Bold or Italic. If none is given, all fonts in folder will be processed.'
    )
    parser.add_argument('-s',
                        '--fontsize',
                        default='32',
                        choices=['24', '32', '40', '48', '56', '64', 'all'],
                        help='Fontsize (Fontheight) in pixels. Default: 32')
    parser.add_argument('--variable_width',
                        default=False,
                        action='store_true',
                        help='Variable width of characters.')
    parser.add_argument(
        '--progmem',
        dest='progmem',
        default=False,
        action='store_true',
        help=
        'C Variable declaration adds PROGMEM to character arrays. Useful to store the characters in porgram memory for AVR Microcontrollers with limited Flash or EEprom'
    )
    parser.add_argument(
        '-p',
        '--print_ascii',
        dest='print_ascii',
        default=False,
        action='store_true',
        help='Print each character as ASCII Art on commandline, for debugging')

    args = parser.parse_args()
    print_program_header()

    if len(sys.argv) == 1:
        parser.print_help()
        return (1)
    elif (args.license):
        print_license()
        return (0)

    else:
        progmem = args.progmem
        print_ascii = args.print_ascii
        # Folder to iterate on
        ttf_searchfolder = args.ttf_folder
        output_folder = args.output_folder

        if not (os.path.exists(output_folder)):
            os.mkdir(output_folder)

        if not (os.path.exists(ttf_searchfolder)):
            print('TTF Folder does not exist')
            return (-1)

        variable_width = args.variable_width

        Target_Font = args.font
        if not (Target_Font == ''):
            ttf_filename = get_ttf_filename(Target_Font, ttf_searchfolder)
            if (ttf_filename == -1):
                print('No font with name: ' + Target_Font + ' found')
                return (-1)
            else:
                ttf_file = {'dir': ttf_searchfolder, 'filename': ttf_filename}
            TTF_FILES.append(ttf_file)
        else:
            TTF_FILES = search_ttf_folder(ttf_searchfolder)

        # Definition of Font Heights and offsets
        font_heights = [24, 32, 40, 48, 56, 64]
        font_yoffsets = [3, 5, 7, 8, 9, 10]

        if (args.fontsize == 'all'):
            height_indices = range(len(font_heights))
        else:
            height_indices = [font_heights.index(int(args.fontsize))]

        # Read characters from file
        [character_line, chars] = read_character_file(args.character_filename)

        # Start logging
        logfile = logfile_open(output_folder)

        # Main Loop
        for ttf_file in TTF_FILES:
            # Generate and check file paths and
            ttf_filename = ttf_file['filename']
            ttf_filepath = os.path.abspath(ttf_file['dir'])
            ttf_absolute_filename = ttf_filepath + '\\' + ttf_filename
            tt = ttLib.TTFont(ttf_absolute_filename)
            fm = tt['name'].names[4].string
            Font = fm.decode('utf-8')
            Font = re.sub('\x00', '', Font)

            output_bmh_folder = output_folder + '\\' + Font
            if not (os.path.exists(output_bmh_folder)):
                os.mkdir(output_bmh_folder)

            for height_idx in height_indices:
                width_array = []

                # initialize PIL Image
                height = font_heights[height_idx]
                width = int(height * 0.75)
                yoffset = font_yoffsets[height_idx]

                # Filename Definitions
                filename = Font + '_' + str(height)  # General Filename
                h_filename = output_bmh_folder + '\\' + filename + '.h'  # Outputfile for font
                png_filename = output_bmh_folder + '\\' + filename + '.png'  # Outputfile for font

                # define PILfont
                size = [width, height]
                PILfont = ImageFont.truetype(ttf_absolute_filename,
                                             int(height * 1.25))

                # Open BMH file and start writing
                outfile = write_bmh_head(h_filename, Font, height)

                for char in chars:
                    # Create pixel image with PIL
                    image = Image.new('1', size, color=255)
                    draw = ImageDraw.Draw(image)
                    draw.text((0, -yoffset), char, font=PILfont)

                    # Calculate byte arrays and write to file

                    if (variable_width):
                        [zero_col_cnt_left, zero_col_cnt_right
                         ] = calculate_char_width(image, width, height)
                        char_width = width - zero_col_cnt_right - zero_col_cnt_left
                        x_offset = zero_col_cnt_left
                    else:
                        char_width = width
                        x_offset = 0

                    width_array.append(str(char_width))
                    dot_array = get_pixel_byte(image, height, char_width,
                                               x_offset)

                    write_bmh_char(outfile, char, dot_array, progmem)
                    if (print_ascii):
                        print_char(image, height, char_width, x_offset)

                # write tail and close bmh file
                write_bmh_tail(outfile, width_array, character_line)
                # write Image picture with all characters
                write_pic_file(character_line, PILfont, width, height,
                               png_filename)
                if (len(TTF_FILES) < 20):
                    print(filename + '.h written')
                logfile_append(logfile, filename)

        print(
            '-------------------------------------------------------------------------'
        )
        print("TTF2BMH Finished")
        logfile_close(logfile)
Esempio n. 19
0
    def swaper(self):
        ftpathList, swaped, unicodesInt = [], [], []
        propLF = [
            "zero.lf",
            "one.lf",
            "two.lf",
            "three.lf",
            "four.lf",
            "five.lf",
            "six.lf",
            "seven.lf",
            "eight.lf",
            "nine.lf",
        ]
        propOSF = [
            "zero.osf",
            "one.osf",
            "two.osf",
            "three.osf",
            "four.osf",
            "five.osf",
            "six.osf",
            "seven.osf",
            "eight.osf",
            "nine.osf",
        ]
        tabOSF = [
            "zero.tosf",
            "one.tosf",
            "two.tosf",
            "three.tosf",
            "four.tosf",
            "five.tosf",
            "six.tosf",
            "seven.tosf",
            "eight.tosf",
            "nine.tosf",
        ]
        salt = [
            'I.salt', 'IJ.salt', 'Iacute.salt', 'Ibreve.salt', 'uni01CF.salt',
            'Icircumflex.salt', 'uni0208.salt', 'Idieresis.salt',
            'uni1E2E.salt', 'Idotaccent.salt', 'uni1ECA.salt', 'Igrave.salt',
            'uni1EC8.salt', 'uni020A.salt', 'Imacron.salt', 'Iogonek.salt',
            'Itilde.salt', 'uni1E2C.salt', 'J.salt', 'Jcircumflex.salt',
            'uni01C7.salt', 'uni01CA.salt', 'uniA7F7.salt', 'uni0406.salt',
            'uni0407.salt', 'uni0408.salt', 'uni04C0.salt', 'uni04CF.salt',
            'uni037F.salt', 'Iota.salt', 'Iotatonos.salt', 'Iotadieresis.salt',
            'uni1F38.salt', 'uni1F39.salt', 'uni1F3A.salt', 'uni1F3B.salt',
            'uni1F3C.salt', 'uni1F3D.salt', 'uni1F3E.salt', 'uni1F3F.salt',
            'uni1FDA.salt', 'uni1FDB.salt', 'uni1FD8.salt', 'uni1FD9.salt',
            'uni1D35.salt', 'uni1D36.salt'
        ]
        unicodeIJ = [
            73, 306, 205, 300, 463, 206, 520, 207, 7726, 304, 7882, 204, 7880,
            522, 298, 302, 296, 7724, 74, 308, 455, 458, 42999, 1030, 1031,
            1032, 1216, 1231, 895, 921, 906, 938, 7992, 7993, 7994, 7995, 7996,
            7997, 7998, 7999, 8154, 8155, 8152, 8153, 7477, 7478
        ]
        unicodesFig = [i for i in range(48, 58)]

        for path in self.fonts2merge_list:
            if os.path.basename(path).split("-")[0] in self.lgcfonts:
                ftpathList.append(path)

        tosfOsfLinningFonts = [
            "NotoSans", "NotoSans-Italic", "NotoSerif", "NotoSerif-Italic",
            "NotoSansDisplay-Italic", "NotoSansDisplay", "NotoSerifDisplay",
            "NotoSerifDisplay-Italic"
        ]
        altIJFonts = [
            "NotoSans", "NotoSans-Italic", "NotoSansDisplay",
            "NotoSansDisplay-Italic"
        ]

        if self.repoNames[0] in tosfOsfLinningFonts:
            if "tosf" in self.swapedstyles:
                swaped = tabOSF
            elif "osf" in self.swapedstyles:
                swaped = propOSF
            elif "plf" in self.swapedstyles:
                swaped = propLF

        if len(swaped) > 0:
            unicodesInt = unicodesFig

        if "Sans" in self.contrast:
            lgc = set(altIJFonts) & set(self.repoNames)
            if "altIJ" in self.swapedstyles and len(lgc) > 0:
                swaped = swaped + salt
                unicodesInt = unicodesInt + unicodeIJ

        for path in ftpathList:
            ft = ttLib.TTFont(path)
            cmap = ft['cmap']
            go = ft.getGlyphOrder()
            outtables = []

            for table in cmap.tables:
                modif = table.cmap
                for uni in unicodesInt:
                    if uni in modif:
                        if swaped[unicodesInt.index(uni)] in go:
                            modif[uni] = swaped[unicodesInt.index(uni)]
                newtable = CmapSubtable.newSubtable(table.format)
                newtable.platformID = table.platformID
                newtable.platEncID = table.platEncID
                newtable.language = table.language
                newtable.cmap = modif
                outtables.append(newtable)

                cmap.tables = []
                cmap.tables = outtables
                newpath = path.replace(".ttf", "_edited.ttf")

                ft.save(newpath)
                self.fonts2merge_list = self.listReplacer(
                    path, newpath, self.fonts2merge_list)
Esempio n. 20
0
def openFont(filename):
    font = ttLib.TTFont(filename)
    if font.sfntVersion == 'OTTO':
        sys.exit("Error: Need TTF font, got CFF")
    return font
Esempio n. 21
0
def _get_font(fontname):
    font = _FONT_CACHE.get(fontname)
    if not font:
        font = ttLib.TTFont(fontname)
        _FONT_CACHE[fontname] = font
    return font
Esempio n. 22
0
def generate(in_file, format='.ttf', out_file=None):
    font = ttLib.TTFont(in_file)
    if out_file is None:
        out_file = in_file + format
    font.save(out_file)
Esempio n. 23
0
#!/usr/bin/env python
import sys
from fontTools import ttLib

font = ttLib.TTFont(sys.argv[1])

MS_Platform_ID = 3
MS_Enc_ID = 1
MS_Lang_US_ID = 0x409

FullName_ID = 4

name = font["name"]
cff = font["CFF "]

psname = cff.cff.fontNames[0]

# set MS full name to psname
# per name table spec
fullname = name.getName(FullName_ID, MS_Platform_ID, MS_Enc_ID, MS_Lang_US_ID)
fullname.string = psname.encode("utf_16_be")

font.save(sys.argv[1] + ".post")
Esempio n. 24
0
def dir_font_info(
    fonts_dir: str = "",
    info_file_dir: str = "font_info",
    info_filename: str = "font_info.json",
):

    available_font_extension_set: set = [
        ".ttf",
        ".ttc",
        ".otf",
        ".woff",
        ".woff2",
    ]

    if not fonts_dir:
        if os.name != "nt":
            raise OSError("only available in Windows")
        windows_fonts_dir: str = os.path.join(os.environ["SystemRoot"],
                                              "Fonts")
        fonts_dir = windows_fonts_dir

    FONTTOOLS_NAME_ID_FAMILY = 1
    FONTTOOLS_NAME_ID_NAME = 4
    FONTTOOLS_PLATFORM_ID_WINDOWS = 3
    LCID_EN = 1033

    update_font_info_bool: bool = True

    info_file_dir = os.path.abspath(info_file_dir)

    if not os.path.isdir(info_file_dir):
        os.makedirs(info_file_dir)

    info_filepath: str = os.path.join(info_file_dir, info_filename)

    font_info_dict: dict = dict(font_info_list=[])
    if os.path.isfile(info_filepath):
        font_info_dict = load_config(info_filepath)

    all_font_filename_list: list = [
        filename for filename in os.listdir(fonts_dir)
        if any(filename.lower().endswith(ext)
               for ext in available_font_extension_set)
    ]
    all_font_filepath_list: list = [
        os.path.join(fonts_dir, filename)
        for filename in all_font_filename_list
    ]

    info_existed_font_filepath_set: set = set(
        single_font_info_dict["filepath"]
        for single_font_info_dict in font_info_dict["font_info_list"])

    if set(all_font_filepath_list) == info_existed_font_filepath_set:
        update_font_info_bool = False

    if update_font_info_bool:
        font_info_dict = dict(font_info_list=[])
        for font_path in all_font_filepath_list:
            font_num: int = 1

            with open(font_path, "rb") as file:
                font_sfnt_version: str = ""

                file.seek(0)
                font_sfnt_version = file.read(4)
                file.seek(0)

                if font_sfnt_version == b"ttcf":
                    header = readTTCHeader(file)
                    font_num = header.numFonts

                    file.seek(header.offsetTable[0])
                    data = file.read(sfntDirectorySize)
                    if len(data) != sfntDirectorySize:
                        font_error_warning_str: str = (
                            f"{font_path} is Not a Font Collection "
                            "(not enough data), skip.")
                        g_logger.log(logging.WARNING, font_error_warning_str)
                        warnings.warn(font_error_warning_str, RuntimeWarning)
                        continue
                    data_dict: dict = sstruct.unpack(sfntDirectoryFormat, data)
                    font_sfnt_version = data_dict["sfntVersion"]
                elif font_sfnt_version == b"wOFF":
                    font_num = 1

                    data = file.read(woffDirectorySize)
                    if len(data) != woffDirectorySize:
                        font_error_warning_str: str = (
                            f"{font_path} is Not a WOFF font "
                            "(not enough data), skip.")
                        g_logger.log(logging.WARNING, font_error_warning_str)
                        warnings.warn(font_error_warning_str, RuntimeWarning)
                        continue
                    data_dict: dict = sstruct.unpack(woffDirectoryFormat, data)
                    font_sfnt_version = data_dict["sfntVersion"]
                else:
                    font_num = 1

                    data = file.read(sfntDirectorySize)
                    if len(data) != sfntDirectorySize:
                        font_error_warning_str: str = (
                            f"{font_path} is Not a TrueType or OpenType font "
                            "(not enough data), skip.")
                        g_logger.log(logging.WARNING, font_error_warning_str)
                        warnings.warn(font_error_warning_str, RuntimeWarning)
                        continue
                    data_dict: dict = sstruct.unpack(sfntDirectoryFormat, data)
                    font_sfnt_version = data_dict["sfntVersion"]

                font_sfnt_version_tag = Tag(font_sfnt_version)

                if font_sfnt_version_tag not in (
                        "\x00\x01\x00\x00",
                        "OTTO",
                        "true",
                ):
                    print(font_sfnt_version)
                    print(font_sfnt_version_tag)
                    font_error_warning_str: str = (
                        f"{font_path} is Not a TrueType or OpenType font "
                        "(bad sfntVersion), skip.")
                    g_logger.log(logging.WARNING, font_error_warning_str)
                    warnings.warn(font_error_warning_str, RuntimeWarning)
                    continue

            for font_num_index in range(font_num):
                tt_font = ttLib.TTFont(font_path, fontNumber=font_num_index)
                family_list: list = []
                for name_record in tt_font["name"].names:
                    if (name_record.nameID == FONTTOOLS_NAME_ID_FAMILY
                            and name_record.platformID
                            == FONTTOOLS_PLATFORM_ID_WINDOWS):
                        record_str: str = ""
                        try:
                            record_str = name_record.toStr()
                        except UnicodeDecodeError:
                            encoding: str = chardet.detect(
                                name_record.string)["encoding"]
                            if encoding:
                                record_str = name_record.string.decode(
                                    encoding)
                            else:
                                continue
                        family_list.append(record_str)

                family_list = list(set(family_list))

                single_font_info_dict: dict = dict(
                    filepath=font_path,
                    family_list=family_list,
                    index=font_num_index,
                    file_font_num=font_num,
                )
                font_info_dict["font_info_list"].append(single_font_info_dict)

        save_config(info_filepath, font_info_dict)
    return font_info_dict["font_info_list"]
Esempio n. 25
0
 def test_tables_sorted_alphabetically(self):
     expected = sorted([t for t in self.tags if t != 'DSIG'])
     woff2font = ttLib.TTFont(self.file)
     self.assertEqual(expected, list(woff2font.reader.keys()))
Esempio n. 26
0
def check_spreadsheet(src_file):
    filenames = set()
    prev_script_name = None
    fontdata = {}
    filedata = {}
    with open(src_file) as csvfile:
        reader = csv.DictReader(csvfile)
        for index, row in enumerate(reader):
            font = row['Fonts'].replace('\xc2\xa0', ' ').strip()
            hinting = row['Hinting'].strip()
            status = row['Status'].strip()
            accepted_version = row['Accepted Version'].strip()
            note = row['Note'].strip()

            # family script style (variant UI) weight, mostly
            m = re.match(
                r'Noto (Kufi|Naskh|Color Emoji|Emoji|Sans|Serif|Nastaliq)'
                r'(?: (.*?))?'
                r'(?: (UI))?'
                r' (Thin|Light|DemiLight|Regular|Medium|Bold Italic'
                r'|Bold|Black|Italic)(?: \(merged\))?$', font)
            if not m:
                m = re.match(r'Noto (Sans) (Myanmar) (UI)(.*)', font)
                if not m:
                    print('could not parse Myanmar exception: "%s"' % font)
                    continue

            style, script, ui, weight = m.groups()

            weight = weight or 'Regular'
            weight = weight.replace(' ', '')
            ui = ui or ''
            script = script or ''
            script = re.sub('-| ', '', script)
            style = style.replace(' ', '')
            ext = 'ttf'
            if script == 'CJK':
                ext = 'ttc'
            elif script.startswith('TTC'):
                ext = 'ttc'
                script = ''
            elif script == '(LGC)':
                script = ''
            elif script == 'UI':
                ui = 'UI'
                script = ''
            elif script == 'Phagspa':
                script = 'PhagsPa'
            elif script == 'SumeroAkkadianCuneiform':
                script = 'Cuneiform'

            fontname = ''.join(
                ['Noto', style, script, ui, '-', weight, '.', ext])
            # print('%s:\n--> %s\n--> %s' % (
            #    font, str((style, script, ui, weight)), fontname))

            if not hinting in ['hinted', 'hinted (CFF)', 'unhinted']:
                print('unrecognized hinting value \'%s\' on line %d (%s)' %
                      (hinting, index, fontname))
                continue
            hinted = 'hinted' if hinting in ['hinted', 'hinted (CFF)'
                                             ] else 'unhinted'

            if not status in [
                    'In finishing', 'Released w. lint errors',
                    'Approved & Released', 'Approved & Not Released',
                    'In design', 'Design approved', 'Design re-approved',
                    'Released'
            ]:
                print('unrecognized status value \'%s\' on line %d (%s)' %
                      (status, index, fontname))
                continue

            expect_font = status in [
                'Released w. lint errors', 'Approved & Released',
                'Approved & Not Released', 'Released'
            ]

            data = (fontname, (index, font, style, script, ui, weight), hinted,
                    status, accepted_version, note, expect_font)
            filedata[hinted + '/' + fontname] = data

        # ok, now let's see if we can find these files
        all_noto = noto_fonts.get_noto_fonts()
        notodata = {('hinted' if f.is_hinted else 'unhinted') + '/' +
                    path.basename(f.filepath): f
                    for f in all_noto}
        noto_filenames = frozenset(notodata.keys())
        spreadsheet_filenames = frozenset(k for k in filedata
                                          if filedata[k][6])
        spreadsheet_extra = spreadsheet_filenames - noto_filenames
        spreadsheet_missing = noto_filenames - spreadsheet_filenames
        if spreadsheet_extra:
            print('spreadsheet extra:\n  ' +
                  '\n  '.join(sorted(spreadsheet_extra)))
        if spreadsheet_missing:
            print('spreadsheet missing:\n  ' +
                  '\n  '.join(sorted(spreadsheet_missing)))

        spreadsheet_match = spreadsheet_filenames & noto_filenames
        for filename in sorted(spreadsheet_match):
            data = filedata[filename]
            filepath = notodata[filename].filepath
            ttfont = ttLib.TTFont(filepath, fontNumber=0)
            font_version = font_data.printable_font_revision(ttfont)
            approved_version = data[4]
            if approved_version:
                warn = '!!!' if approved_version != font_version else ''
                print('%s%s version: %s approved: %s' %
                      (warn, filename, font_version, approved_version))
            else:
                print('%s version: %s' % (filename, font_version))
Esempio n. 27
0
 def setUpClass(cls):
     cls.file = BytesIO(CFF_WOFF2.getvalue())
     cls.font = ttLib.TTFont(recalcBBoxes=False, recalcTimestamp=False)
     cls.font.importXML(OTX)
Esempio n. 28
0
            else:
                family = record.string
        if name and family:
            break
    return name, family


if __name__ == '__main__':
    if (len(sys.argv[1:]) < 1):
        print "Usage: ", sys.argv[0], "Target(Font File)"
        sys.exit()

    else:
        fileFont = sys.argv[1]
        try:
            tt = ttLib.TTFont(fileFont)

        except:
            print "Font File Corrupted"

        else:
            fontName = shortName(tt)[1]
            lf = win32gui.LOGFONT()
            htr = windll.gdi32.AddFontResourceExA(fileFont, FR_PRIVATE, None)
            w = mainWindow()
            hwnd = w.CreateWindow()
            hdc = windll.user32.GetDC(hwnd)
            for fontsize in range(0, 1000, 100):
                lf.lfHeight = fontsize
                lf.lfFaceName = fontName
                #lf.lfFaceName=fontPath
import tabulate

from fontTools import ttLib

args = argparse.ArgumentParser(
    description='Print out italicAngle of the fonts')
args.add_argument('font', nargs="+")
args.add_argument('--csv', default=False, action='store_true')


if __name__ == '__main__':
    arg = args.parse_args()

    headers = ['filename', 'italicAngle']
    rows = []
    for font in arg.font:
        ttfont = ttLib.TTFont(font)
        rows.append([os.path.basename(font), ttfont['post'].italicAngle])

    def as_csv(rows):
        import csv
        import sys
        writer = csv.writer(sys.stdout)
        writer.writerows([headers])
        writer.writerows(rows)
        sys.exit(0)

    if arg.csv:
        as_csv(rows)

    print(tabulate.tabulate(rows, headers, tablefmt="pipe"))
Esempio n. 30
0

def getFuzzerInstance(folder, queue):
    return NativeFuzzer(os.path.join('fonts_extracted', folder), queue)


if __name__ == '__main__':

    if (len(sys.argv[1:]) < 1):
        print 'Usage: {} font_directory'.format(sys.argv[0])

    elif (len(sys.argv[1:]) == 2 and sys.argv[1] == 'd'):
        try:
            abspath = os.path.abspath(sys.argv[2])
            print 'Testing font {}'.format(abspath)
            deploy(abspath, ttLib.TTFont(abspath))

        except Exception as e:
            print '[E] Issues parsing font {}: {}'.format(sys.argv[2], e)

    # fuzz
    else:
        for i in range(0, 1):
            #break

            # 2] generate test cases
            numberOfTestCases = generateTestCases(sys.argv[1])

            print '[*] Generated {} test cases'.format(numberOfTestCases)

            for i in os.listdir('testcases'):