Пример #1
1
    def run(self, destDir, progress):
        paths = self.controller.get(["ufo"])

        report = Report()

        tempDir = os.path.join(destDir, "temp")
        if not os.path.exists(tempDir):
            os.makedirs(tempDir)
        tempExportPaths = self._generateCallback(tempDir, progress, report)

        progress.update("Merging Tables...")
        report.writeTitle("Merged Fonts:")
        report.newLine()

        tableNames = [item["tableName"] for item in self.tableList if item["add"]]

        for fontIndex, path in enumerate(paths):
            font = RFont(path, document=False, showInterface=False)
            binarySourcepath = font.lib.get("com.typemytype.robofont.binarySource")
            tempExportPath = tempExportPaths[fontIndex]
            if binarySourcepath:
                binaryIs
                Type = os.path.splitext(binarySourcepath)[1].lower() in [".ttf", ".otf"]
                tempIsOpenType = os.path.splitext(tempExportPath)[1].lower() in [".ttf", ".otf"]
                if binaryIsOpenType and tempIsOpenType:
                    if os.path.exists(binarySourcepath) and os.path.exists(tempExportPath):
                        binarySource = TTFont(binarySourcepath)
                        tempFont = TTFont(tempExportPath)
                        fileName = os.path.basename(tempExportPath)
                        if not self.controller.keepFileNames():
                            fileName = "%s-%s%s" % (font.info.familyName, font.info.styleName, os.path.splitext(tempExportPath)[1])
                        path = os.path.join(destDir, fileName)
                        report.writeTitle(os.path.basename(path), "'")
                        report.write("source: %s" % tempExportPath)
                        report.write("binary source: %s" % binarySourcepath)
                        report.newLine()
                        report.indent()
                        for table in tableNames:
                            if table in binarySource:
                                report.write("merge %s table" % table)
                                tempFont[table] = binarySource[table]
                        report.write("save to %s" % path)
                        tempFont.save(path)
                        report.dedent()
                        report.newLine()
                        tempFont.close()
                        binarySource.close()
            if not font.hasInterface():
                font.close()

        reportPath = os.path.join(destDir, "Binary Merge Report.txt")
        report.save(reportPath)

        if not getDefault("Batch.Debug", False):
            if os.path.exists(tempDir):
                shutil.rmtree(tempDir)
Пример #2
0
def update_tables(font_path, revision):
    font = TTFont(font_path)
    font['head'].fontRevision = float(revision)
    if 'CFF ' in font:
        cff = font['CFF '].cff
        cff_font = cff[cff.fontNames[0]]
        top_dict = cff_font.rawDict
        top_dict['version'] = revision
        top_dict['FullName'] = FULL_NAME
        top_dict['FamilyName'] = FAMILY_NAME
        cff.fontNames = [PS_NAME]
    VERSION_STRING = 'Version {};{}'.format(revision, VENDOR)
    UNIQUE_ID = '{};{};{}'.format(revision, VENDOR, PS_NAME)
    name_strings = {
        1: FAMILY_NAME,
        3: UNIQUE_ID,
        4: FULL_NAME,
        5: VERSION_STRING,
        6: PS_NAME,
    }
    name_table = font['name']
    for nameID, string in name_strings.items():
        name_table.setName(string, nameID, 3, 1, 0x409)  # Windows only
    font.save(font_path)
    font.close()
    log.info('Updated font tables.')
Пример #3
0
def main():
    infile = sys.argv[1]
    outfile = sys.argv[2]
    jsonSources = sys.argv[3:]

    font = TTFont(infile)

    i = 0
    while i + 1 < len(jsonSources):
        sourcetype = jsonSources[i]
        sourcedata = jsonSources[i + 1]
        if sourcetype == '-r':
            # raw, the sourcedata is the json
            data = json.loads(sourcedata)
        elif sourcetype == '-f':
            # file, the sourcedata is a json file name
            with open(sourcedata) as f:
                data = json.load(f)
        else:
            raise ValueError(
                'unknown json source type "{0}"'.format(sourcetype))

        writeData(font, data)
        i += 2

    clean(font)
    font.save(outfile)
    font.close()
Пример #4
0
def fix_naming(font_path):
    font = TTFont(font_path)
    italic = True
    if not "ITALIC" in font_path.upper():
        italic = False

    family_name = "Fraunces"
    if not italic:
        style_name = "Roman"
    else:
        style_name = "Italic"

    name_dict = {
        1: family_name,
        4: family_name,
        6: f"{family_name}-{style_name}",
        16: family_name,
        17: style_name
    }

    if italic:
        name_dict[2] = style_name
        name_dict[4] = f"{family_name} {style_name}"

    for name_id, name_string in name_dict.items():
        font["name"].setName(name_string, name_id, 3, 1, 0x409)

    #get current ID3, rsplit on ; add id6
    old_name = font["name"].getName(3, 3, 1, 0x409).toUnicode()
    new_name = f'{old_name.rsplit(";",1)[0]};{name_dict[6]}'
    font["name"].setName(new_name, 3, 3, 1, 0x409)
    font.save(font_path)
    font.close()
    print("Fixed NameIDs")
    def installFont(self, path):
        """
        Install a font with a given path.
        """
        success, error = self._dummyContext.installFont(path)
        self._installedFontPaths.add(path)
        self._addInstruction("installFont", path)

        from fontTools.ttLib import TTFont, TTLibError
        try:
            font = TTFont(path)
            psName = font["name"].getName(6, 1, 0)
            if psName is None:
                psName = font["name"].getName(6, 3, 1)
            font.close()
        except IOError:
            raise DrawBotError("Font '%s' does not exist." % path)
        except TTLibError:
            raise DrawBotError("Font '%s' is not a valid font." % path)
        if psName is not None:
            psName = psName.toUnicode()

        if not success:
            warnings.warn("install font: %s" % error)
        return psName
def _optimizeForEOT(sourcePath, destPath):
    source = TTFont(sourcePath)
    # fix naming
    nameTable = source["name"]
    familyName = nameTable.getName(1, 3, 1)
    styleName = nameTable.getName(2, 3, 1)
    if familyName:
        familyName = familyName.string
    else:
        familyName = "Untitled"
    if styleName:
        styleName = styleName.string
    else:
        styleName = "Regular"

    records = []
    for record in nameTable.names:
        # ignore preferred naming
        if record.nameID not in [16, 17]:
            if record.nameID == 4:
                s = "%s %s" % (familyName, styleName)
                if record.platformID == 3 and record.platEncID in (0, 1):
                    record.string = _winStr(s)
                else:
                    record.string = _macStr(s)
        records.append(record)

    nameTable.names = records

    # set embedding bit
    os2 = source["OS/2"]
    os2.fsType = 4
    source.save(destPath)
    source.close()
Пример #7
0
def cleanTTF(ttfFile, outfile):
    # now open in fontTools
    ftfont = TTFont(ttfFile)

    # the ttf contains NAME table IDs with platformID="1", these should be removed
    name = ftfont['name']
    names = []
    for record in name.names:
        if record.platformID == 1:
            continue
        names.append(record)
    name.names = names

    # remove non-standard 'FFTM' the FontForge time stamp table
    del ftfont['FFTM']

    # issue #40 let Adobe InDesign show the font in the Arabic section of the font menu.
    # This essentially says the only codepage that "is considered functional" is Arabic.
    # https://www.microsoft.com/typography/otspec/os2.htm#cpr
    ftfont['OS/2'].ulCodePageRange1 = 64
    ftfont['OS/2'].ulCodePageRange2 = 0

    # force compiling tables by fontTools, saves few tens of KBs
    for tag in ftfont.keys():
        if hasattr(ftfont[tag], "compile"):
            ftfont[tag].compile(ftfont)

    ftfont.save(outfile)
    ftfont.close()
Пример #8
0
def extractFontFromOpenType(
    pathOrFile,
    destination,
    doGlyphOrder=True,
    doGlyphs=True,
    doInfo=True,
    doKerning=True,
    customFunctions=[],
    doInstructions=True,
):
    source = TTFont(pathOrFile)
    if doInfo:
        extractOpenTypeInfo(source, destination)
    if doGlyphs:
        extractOpenTypeGlyphs(source, destination)
    if doGlyphOrder:
        extractGlyphOrder(source, destination)
    if doKerning:
        kerning, groups = extractOpenTypeKerning(source, destination)
        destination.groups.update(groups)
        destination.kerning.clear()
        destination.kerning.update(kerning)
    for function in customFunctions:
        function(source, destination)
    if doInstructions:
        extractInstructions(source, destination)
    source.close()
Пример #9
0
def font_import(filename, font_id=-1, lang="en"):
    #language localization
    if lang == "zhs":  #simplified chinese
        message_title = "进度"
        message_text = "已加载字体文件:"
    elif lang == "zht":  #traditional chinese
        message_title = "進度"
        message_text = "已加載字型文件:"
    else:
        message_title = "Progress"
        message_text = "Loaded font file: "

    messagebox.showinfo(message_title, message_text + filename)
    #open font with given number
    ttf = TTFont(filename,
                 0,
                 allowVID=0,
                 ignoreDecompileErrors=True,
                 fontNumber=font_id)
    #get chars from cmap
    chars = chain.from_iterable(
        [y + (Unicode[y[0]], ) for y in x.cmap.items()]
        for x in ttf["cmap"].tables)

    return chars
    #close font
    ttf.close()
Пример #10
0
def webfonts(infont, type):
    font = TTFont(infont, recalcBBoxes=0)
    woffFileName = makeOutputFileName(
        infont, outputDir=None, extension='.' + type)
    font.flavor = type
    font.save(woffFileName, reorderTables=False)
    font.close()
Пример #11
0
 def import_from_otf(self, otfpath):
     """Import color data (CPAL/COLR) from a font file.
         otfpath: Path of the font file"""
     font = TTFont(otfpath)
     if not (font.has_key("COLR") and font.has_key("CPAL")):
         print("ERROR: No COLR and CPAL table present in %s" % otfpath)
     else:
         print("Reading palette data ...")
         cpal = table_C_P_A_L_("CPAL")
         cpal.decompile(font["CPAL"].data, font)
         for j in range(len(cpal.palettes)):
             palette = cpal.palettes[j]
             _palette = {}
             for i in range(len(palette)):
                 color = palette[i]
                 _palette[str(i)] = "#%02x%02x%02x%02x" % (
                     color.red, color.green, color.blue, color.alpha)
             self.palettes.append(_palette)
         colr = table_C_O_L_R_("COLR")
         colr.decompile(font["COLR"].data, font)
         print("Reading layer data ...")
         for glyphname in colr.ColorLayers:
             layers = colr[glyphname]
             _glyph = ColorGlyph(self)
             _glyph.basename = glyphname
             for layer in layers:
                 _glyph.layers.append(layer.name)
                 _glyph.colors.append(layer.colorID)
             self[glyphname] = _glyph
         print("Done.")
     font.close()
Пример #12
0
    def installFont(self, path):
        """
        Install a font with a given path and the postscript font name will be returned.
        The postscript font name can be used to set the font as the active font.

        Fonts are installed only for the current process.
        Fonts will not be accesible outside the scope of drawBot.

        All installed fonts will automatically be uninstalled when the script is done.

        .. showcode:: /../examples/installFont.py
        """
        success, error = self._dummyContext.installFont(path)
        self._installedFontPaths.add(path)
        self._addInstruction("installFont", path)

        from fontTools.ttLib import TTFont, TTLibError
        try:
            font = TTFont(path)
            psName = font["name"].getName(6, 1, 0)
            if psName is None:
                psName = font["name"].getName(6, 3, 1)
            font.close()
        except IOError:
            raise DrawBotError("Font '%s' does not exist." % path)
        except TTLibError:
            raise DrawBotError("Font '%s' is not a valid font." % path)
        if psName is not None:
            psName = psName.toUnicode()

        if not success:
            warnings.warn("install font: %s" % error)
        return psName
Пример #13
0
def generate(font, extension):
    """ Clean GSUB lookups and merge them from the feature files """
    for lookup in font.gsub_lookups:
        font.removeLookup(lookup)
    
    font.mergeFeature('%s/%s_features.fea' %(feafiles, style))

    font.selection.all()
    font.autoHint()

    if extension == 'ttf':
#        font.em = 2048
        font.round()
        font.autoInstr()

    path = '%s/%s.%s' %(build, font.fontname, extension)
    tmp_path = '%s.tmp.%s' %(font.fontname, extension)

    font.generate(tmp_path)

    tmp_font = TTFont(tmp_path)
#    tmp_font['OS/2'].sxHeight, tmp_font['OS/2'].sCapHeight = getHeights(font)
    tmp_font.save(path)
    tmp_font.close()
    os.remove(tmp_path)
Пример #14
0
def ttCount(input, options):
    ttf = TTFont(input, fontNumber=options.fontNumber, lazy=True)
    reader = ttf.reader
    hasPrep = 'prep' in reader.tables
    hasFpgm = 'fpgm' in reader.tables
    glyf_program_counts = 0
    glyf_names = ttf.getGlyphSet().keys()
    for glyf_name in glyf_names:
        glyf = ttf['glyf'].glyphs[glyf_name]
        glyf.expand(ttf['glyf'])
        if hasattr(ttf['glyf'].glyphs[glyf_name], "program"):
            prog = ttf['glyf'].glyphs[glyf_name].program
            if (hasattr(prog, "bytecode") and len(prog.bytecode) > 0) or (hasattr(prog, "assembly") and len(prog.assembly) > 0):
                glyf_program_counts += 1
        #print ("%s %s" % (glyf, hasattr(ttf['glyf'].glyphs[glyf_name], "program")))
    hasSomeGlyfCode = glyf_program_counts > 0
    globalAnswer = hasPrep or hasFpgm or hasSomeGlyfCode
    print ("%s: %s, prep = %s, fpgm = %s, glyf = %s [%d/%d]" %
           (input,
            yes_or_no(globalAnswer),
            yes_or_no(hasPrep),
            yes_or_no(hasFpgm),
            yes_or_no(hasSomeGlyfCode),
            glyf_program_counts,
            len(glyf_names)))
    ttf.close()
Пример #15
0
def makeWeb(args):
    font = TTFont(args.file)

    base, ext = os.path.splitext(args.file)
    font.flavor = "woff"
    font.save(os.path.join(args.dir, base + ".woff"))
    font.close()
Пример #16
0
def getSFNTData(pathOrFile,
                unsortGlyfLoca=False,
                glyphBBox="",
                alt255UInt16=False):
    font = TTFont(pathOrFile)
    tableChecksums = {}
    tableData = {}
    tableOrder = [i for i in sorted(font.keys()) if len(i) == 4]
    if unsortGlyfLoca:
        assert "loca" in tableOrder
        loca = tableOrder.index("loca")
        glyf = tableOrder.index("glyf")
        tableOrder.insert(glyf, tableOrder.pop(loca))
    for tag in tableOrder:
        tableChecksums[tag] = font.reader.tables[tag].checkSum
        tableData[tag] = transformTable(font,
                                        tag,
                                        glyphBBox=glyphBBox,
                                        alt255UInt16=alt255UInt16)
    totalData = "".join([tableData[tag][1] for tag in tableOrder])
    compData = brotli.compress(totalData, brotli.MODE_FONT)
    if len(compData) >= len(totalData):
        compData = totalData
    font.close()
    del font
    return tableData, compData, tableOrder, tableChecksums
Пример #17
0
    def _autohint(self, otf, fmt):
        logger.info(f"Autohinting {self.name}.{fmt.value}")
        if fmt == Format.TTF:
            from io import BytesIO

            from ttfautohint import ttfautohint

            buf = BytesIO()
            otf.save(buf)
            otf.close()
            data = ttfautohint(in_buffer=buf.getvalue(), no_info=True)
            otf = TTFont(BytesIO(data))

            # Set bit 3 on head.flags
            # https://font-bakery.readthedocs.io/en/latest/fontbakery/profiles/googlefonts.html#com.google.fonts/check/integer_ppem_if_hinted
            head = otf["head"]
            head.flags |= 1 << 3
        elif fmt == Format.OTF:
            from tempfile import TemporaryDirectory

            from psautohint.__main__ import main as psautohint

            with TemporaryDirectory() as d:
                path = Path(d) / "tmp.otf"
                otf.save(path)
                with TemporaryLogLevel(logging.ERROR):
                    psautohint([str(path)])
                otf.close()
                otf = TTFont(path)
        return otf
Пример #18
0
  def cmap_dump(self):
    font = TTFont(self.fontfile)
    #TODO(ahmetcelik) cmap in format 12 should be used if it exists
    cmapTable = font['cmap'].getcmap(3, 10)
    if not cmapTable:
      cmapTable = font['cmap'].getcmap(3, 1)
    assert cmapTable,'Unicode cmap table required'
    cmap = cmapTable.cmap  # unicode table


    codepoints = []
    glyphs = []

    for code, name in cmap.iteritems():
      id = font.getGlyphID(name)
      glyphs.append(id)
      codepoints.append(code)
      if self.debug:
        print id,name,code
    font.close()

    cp_dumper = Dumper(self.folder + '/codepoints')
    cp_dumper.dump_array(codepoints, 'I', '>')
    cp_dumper.close()

    gid_dumper = Dumper(self.folder + '/gids')
    gid_dumper.dump_array(glyphs, 'H', '>')
    gid_dumper.close()
Пример #19
0
def _optimizeForEOT(sourcePath, destPath):
    source = TTFont(sourcePath)
    # fix naming
    nameTable = source["name"]
    familyName = nameTable.getName(1, 3, 1)
    styleName = nameTable.getName(2, 3, 1)
    if familyName:
        familyName = familyName.string
    else:
        familyName = "Untitled"
    if styleName:
        styleName = styleName.string
    else:
        styleName = "Regular"

    records = []
    for record in nameTable.names:
        # ignore preferred naming
        if record.nameID not in [16, 17]:
            if record.nameID == 4:
                s = "%s %s" % (familyName, styleName)
                if record.platformID == 3 and record.platEncID in (0, 1):
                    record.string = _winStr(s)
                else:
                    record.string = _macStr(s)
        records.append(record)

    nameTable.names = records

    # set embedding bit
    os2 = source["OS/2"]
    os2.fsType = 4
    source.save(destPath)
    source.close()
Пример #20
0
 def __zero_charset_fmt(self,output):
   font = TTFont(output)
   cffTableOffset = font.reader.tables['CFF '].offset
   cffTable = font['CFF '].cff
   assert len(cffTable.fontNames) == 1 #only one font should be present
   charsetOffset = cffTable[cffTable.fontNames[0]].rawDict['charset']
   numGlyphs = font['maxp'].numGlyphs
   inner_file = font.reader.file
   inner_file.seek(cffTableOffset+charsetOffset)
   format = readCard8(inner_file);
   if format != 2 and format != 1:
     return None
   record_len = 4 if format == 2 else 3
   seenGlyphCount = 0
   size = 0
   while seenGlyphCount < numGlyphs:
     inner_file.seek(2,io.SEEK_CUR)
     if format == 2:
       nLeft = readCard16(inner_file)
     else: #format 1
       nLeft = readCard8(inner_file)
     seenGlyphCount += nLeft + 1
     size += 1
   font.close()
   filler = Filler(output)
   filler.fill(cffTableOffset+charsetOffset+1, record_len*size, '\x00')
   filler.close()
Пример #21
0
def makeWeb(args):
    """If we are building a web version then try to minimise file size"""

    font = TTFont(args.file)

    # removed compatibility glyphs that of little use on the web
    ranges = (
            (0xfb50, 0xfbb1),
            (0xfbd3, 0xfd3d),
            (0xfd50, 0xfdf9),
            (0xfdfc, 0xfdfc),
            (0xfe70, 0xfefc),
            )

    cmap = font['cmap'].buildReversed()
    unicodes = set([min(cmap[c]) for c in cmap])
    for r in ranges:
        unicodes -= set(range(r[0], r[1] + 1))

    options = subset.Options()
    options.set(layout_features='*', name_IDs='*', drop_tables=['DSIG'])
    subsetter = subset.Subsetter(options=options)
    subsetter.populate(unicodes=unicodes)
    subsetter.subset(font)

    base, ext = os.path.splitext(args.file)
    for flavor in ("ttf", "woff", "woff2"):
        if flavor is not "ttf":
            font.flavor = flavor
        font.save(args.dir + "/" + base + "." + flavor)
    font.close()
Пример #22
0
def decompileBinaryToObject(pathOrFile, compress=True, excludeFeatures=None):
    from fontTools.ttLib import TTFont
    from feaTools2.objects import Tables
    from feaTools2.parsers.binaryParser import parseTable
    # load font
    closeFont = True
    if isinstance(pathOrFile, TTFont):
        font = pathOrFile
        closeFont = False
    else:
        font = TTFont(pathOrFile)
    # decompile
    tables = Tables()
    if "GSUB" in font:
        table = tables["GSUB"]
        parseTable(table,
                   font["GSUB"].table,
                   "GSUB",
                   excludeFeatures=excludeFeatures)
        if compress:
            table.compress()
    # close
    if closeFont:
        font.close()
    # done
    return tables
Пример #23
0
def parse_font(url, word_list):
    # 破解自定义字典,换回真实数据
    # {100416: 'zero', 100418: 'period', 100419: 'two', 100420: 'eight', 100421: 'six', 100422: 'three',
    #  100423: 'seven', 100424: 'nine', 100425: 'five', 100426: 'one', 100427: 'four'}
    word_map = {
        'period': '.',
        'zero': '0',
        'one': '1',
        'two': '2',
        'three': '3',
        'four': '4',
        'five': '5',
        'six': '6',
        'seven': '7',
        'eight': '8',
        'nine': '9'
    }
    resp = requests.get(url)
    font = TTFont(BytesIO(resp.content))
    cmap = font.getBestCmap()
    font.close()
    res = ""
    for word in word_list:
        En = cmap[int(word[2:])]
        res += word_map[En]
    return res
Пример #24
0
    def _autohint(self, otf, fmt):
        logger.info(f"Autohinting {self.name}.{fmt.value}")
        if fmt == Format.TTF:
            from io import BytesIO

            from ttfautohint import ttfautohint

            buf = BytesIO()
            otf.save(buf)
            otf.close()
            data = ttfautohint(in_buffer=buf.getvalue(), no_info=True)
            otf = TTFont(BytesIO(data))
        elif fmt == Format.OTF:
            from tempfile import TemporaryDirectory

            from psautohint.__main__ import main as psautohint

            with TemporaryDirectory() as d:
                path = Path(d) / "tmp.otf"
                otf.save(path)
                with TemporaryLogLevel(logging.ERROR):
                    psautohint([str(path)])
                otf.close()
                otf = TTFont(path)
        return otf
Пример #25
0
    def cmap_dump(self):
        font = TTFont(self.fontfile)
        #TODO(ahmetcelik) cmap in format 12 should be used if it exists
        cmapTable = font['cmap'].getcmap(3, 10)
        if not cmapTable:
            cmapTable = font['cmap'].getcmap(3, 1)
        assert cmapTable, 'Unicode cmap table required'
        cmap = cmapTable.cmap  # unicode table

        codepoints = []
        glyphs = []

        for code, name in cmap.iteritems():
            id = font.getGlyphID(name)
            glyphs.append(id)
            codepoints.append(code)
            if self.debug:
                print id, name, code
        font.close()

        cp_dumper = Dumper(self.folder + '/codepoints')
        cp_dumper.dump_array(codepoints, 'I', '>')
        cp_dumper.close()

        gid_dumper = Dumper(self.folder + '/gids')
        gid_dumper.dump_array(glyphs, 'H', '>')
        gid_dumper.close()
Пример #26
0
def get_font_code(url, encry_text):
    #字典,同伙FontCreator 软件打开字体文件得到解密字典
    WORS_MAP = {
        'period': '.',
        'zero': '0',
        'one': '1',
        'two': '2',
        'three': '3',
        'four': '4',
        'five': '5',
        'six': '6',
        'seven': '7',
        'eight': '8',
        'nine': '9'
    }
    #通过TTFont解密字体文件
    res = requests.get(url, headers=headers)
    font = TTFont(BytesIO(res.content))
    cmap = font.getBestCmap()
    font.close()

    #解密字体
    word_count = ''
    for flag in encry_text.split(";"):
        #去掉多余字符
        ch = cmap.get(int(flag[2:]))
        word_count += WORS_MAP.get(ch, '')
    return word_count
Пример #27
0
def makeWeb(args):
    """If we are building a web version then try to minimise file size"""

    font = TTFont(args.file, recalcTimestamp=False)

    # removed compatibility glyphs that of little use on the web
    ranges = (
        (0xfb50, 0xfbb1),
        (0xfbd3, 0xfd3d),
        (0xfd50, 0xfdf9),
        (0xfdfc, 0xfdfc),
        (0xfe70, 0xfefc),
    )

    cmap = font['cmap'].buildReversed()
    unicodes = set([min(cmap[c]) for c in cmap])
    for r in ranges:
        unicodes -= set(range(r[0], r[1] + 1))

    options = subset.Options()
    options.set(layout_features='*', name_IDs='*', drop_tables=['DSIG'])
    subsetter = subset.Subsetter(options=options)
    subsetter.populate(unicodes=unicodes)
    subsetter.subset(font)

    base, ext = os.path.splitext(args.file)
    for flavor in ("woff", "woff2"):
        font.flavor = flavor
        font.save(args.dir + "/" + base + "." + flavor)
    font.close()
def generateFont(font, outfile):
    flags  = ("opentype", "dummy-dsig", "round", "omit-instructions")

    font.selection.all()
    font.correctReferences()
    font.selection.none()

    # fix some common font issues
    validateGlyphs(font)

    tmpfile = mkstemp(suffix=os.path.basename(outfile))[1]
    font.generate(tmpfile, flags=flags)
    font.close()

    # now open in fontTools
    from fontTools.ttLib import TTFont
    ftfont = TTFont(tmpfile)

    # force compiling tables by fontTools, saves few tens of KBs
    for tag in ftfont.keys():
        if hasattr(ftfont[tag], "compile"):
            ftfont[tag].compile(ftfont)

    ftfont.save(outfile)
    ftfont.close()
    os.remove(tmpfile)
Пример #29
0
class TestClosureTaker(unittest.TestCase):

  def setUp(self):
    """Loads font and initializes ClosureTaker
    """
    self.font = TTFont('test_data/NotoSans-Regular_subset.ttf')
    self.closureTaker = ClosureTaker(self.font)

  def test_c(self):
    """Takes closure of character 'c' Expected result is array: [3]
    """
    self.closureTaker.clear()
    self.closureTaker.add_glyph_names(['c'])
    gids = self.closureTaker.closure()
    self.assertTrue(gids == [3], 'Closure of c is [c]')

  def test_clear(self):
    """Takes closure of cleared input lists Expected result is array: []
    """
    self.closureTaker.clear()
    gids = self.closureTaker.closure()
    self.assertTrue(gids == [], 'Closure of empty is []')

  def tearDown(self):
    """Closes font
    """
    self.font.close()
Пример #30
0
def get_font(url):
    """ 字数反爬 解析字体 """
    response = requests.get(url)
    font = TTFont(BytesIO(response.content))
    cmap = font.getBestCmap()
    font.close()
    return cmap
def read_metadata(font):
    ttf = TTFont(font, lazy=True)
    try:
        ttf.getGlyphNames()
    except Exception:
        logging.error('Not a vaild font: ' + request['url'])
        return None
    reader = ttf.reader

    metadata = {
        'table_sizes':
        {tag: reader.tables[tag].length
         for tag in sorted(reader.keys())},
        'names':
        _read_names(ttf, (_NAME_ID_VERSION, _NAME_ID_POSTSCRIPT_NAME,
                          _NAME_ID_LICENSE_URL)),
        'OS2':
        _read_os2(ttf),
        'post':
        _read_post(ttf),
        'fvar':
        _read_fvar(ttf),
        'counts':
        _read_codepoint_glyph_counts(ttf),
    }
    ttf.close()

    return {k: v for k, v in metadata.items() if v is not None}
Пример #32
0
 def generateWoff2(self, verbosity=0):
     woff2_list = []
     os.makedirs(self.assetdir, exist_ok=True)
     for subname, (subrange, unicodes) in self.urdict.items():
         if verbosity == 2: print("Processing", subname)
         subs = Subsetter()
         font = TTFont(self.fontfile)
         subs.populate(unicodes=unicodes)
         subs.subset(font)
         cmap = font.getBestCmap()
         glyphcount = len(font.getGlyphOrder()) - 1
         if cmap:
             outfile = os.path.join(self.assetdir,
                                    self.basename + "." + subname + ".woff2")
             font.flavor = 'woff2'
             font.save(outfile)
             woff2_list.append((outfile, subrange))
             if verbosity == 1:
                 print("Generated", outfile)
             elif verbosity == 2:
                 print("  Generated", outfile)
                 print("  Found", glyphcount, "glyphs for",
                       len(cmap), "out of", len(unicodes), "unicodes")
         else:
             if verbosity == 2:
                 print("  Found no glyphs for any of", len(unicodes), "unicodes")
         font.close()
     return woff2_list
Пример #33
0
 def check_fonts(self):
     """Check each request to extract metadata about fonts"""
     start = monotonic.monotonic()
     try:
         from fontTools.ttLib import TTFont
         for request_id in self.requests:
             try:
                 request = self.requests[request_id]
                 if 'body' in request:
                     sniff_type = self.sniff_file_content(request['body'])
                     if sniff_type is not None and sniff_type in [
                             'OTF', 'TTF', 'WOFF', 'WOFF2'
                     ]:
                         tables = None
                         ttf = TTFont(request['body'], lazy=True)
                         reader = ttf.reader
                         tags = sorted(reader.keys())
                         for tag in tags:
                             entry = reader.tables[tag]
                             if tables is None:
                                 tables = {}
                             tables[tag] = entry.length
                         ttf.close()
                         if tables is not None:
                             self.font_results[request_id] = {
                                 'table_sizes': tables
                             }
             except Exception:
                 pass
     except Exception:
         pass
     self.font_time = monotonic.monotonic() - start
Пример #34
0
 def import_from_otf(self, otfpath):
     """Import color data (CPAL/COLR) from a font file.
         otfpath: Path of the font file"""
     font = TTFont(otfpath)
     if not (font.has_key("COLR") and font.has_key("CPAL")):
         print("ERROR: No COLR and CPAL table present in %s" % otfpath)
     else:
         print("Reading palette data ...")
         cpal = table_C_P_A_L_("CPAL")
         cpal.decompile(font["CPAL"].data, font)
         for j in range(len(cpal.palettes)):
             palette = cpal.palettes[j]
             _palette = {}
             for i in range(len(palette)):
                 color = palette[i]
                 _palette[str(i)] = "#%02x%02x%02x%02x" % (
                     color.red,
                     color.green,
                     color.blue,
                     color.alpha
                 )
             self.palettes.append(_palette)
         colr = table_C_O_L_R_("COLR")
         colr.decompile(font["COLR"].data, font)
         print("Reading layer data ...")
         for glyphname in colr.ColorLayers:
             layers = colr[glyphname]
             _glyph = ColorGlyph(self)
             _glyph.basename = glyphname
             for layer in layers:
                 _glyph.layers.append(layer.name)
                 _glyph.colors.append(layer.colorID)
             self[glyphname] = _glyph
         print("Done.")
     font.close()
Пример #35
0
def generateFont(font, outfile):
    flags = ("opentype", "dummy-dsig", "round", "omit-instructions")

    font.selection.all()
    font.correctReferences()
    font.selection.none()

    # fix some common font issues
    validateGlyphs(font)

    tmpfile = mkstemp(suffix=os.path.basename(outfile))[1]
    font.generate(tmpfile, flags=flags)
    font.close()

    # now open in fontTools
    from fontTools.ttLib import TTFont
    ftfont = TTFont(tmpfile)

    # force compiling tables by fontTools, saves few tens of KBs
    for tag in ftfont.keys():
        if hasattr(ftfont[tag], "compile"):
            ftfont[tag].compile(ftfont)

    ftfont.save(outfile)
    ftfont.close()
    os.remove(tmpfile)
Пример #36
0
  def __zero_cmaps(self,output):
    font = TTFont(output)
    old_cmap_method = change_method(_c_m_a_p.table__c_m_a_p, _decompile_in_table_cmap,'decompile')
    old_12_method = change_method(_c_m_a_p.cmap_format_12_or_13,_decompile_in_cmap_format_12_13, 'decompile')
    old_4_method = change_method(_c_m_a_p.cmap_format_4,_decompile_in_cmap_format_4, 'decompile')

    cmap_offset = font.reader.tables['cmap'].offset
    cmapTables = font['cmap']
    cmap12 = cmapTables.getcmap(3, 10) #format 12
    cmap4 = cmapTables.getcmap(3, 1) #format 4

    ranges_to_zero = []
    if cmap12:
      ranges_to_zero.append((cmap_offset+cmap12.offset+16,cmap12.length-16))
    #if cmap4:
    #  ranges_to_zero.append((cmap_offset+cmap4.offset+14,cmap4.length-14))

    change_method(_c_m_a_p.cmap_format_12_or_13,old_12_method,'decompile')
    change_method(_c_m_a_p.cmap_format_4,old_4_method,'decompile')
    change_method(_c_m_a_p.table__c_m_a_p,old_cmap_method,'decompile')

    font.close()

    #if len(ranges_to_zero)<2: #return if both doesn't exist
    #  return

    for block in ranges_to_zero:
      filler = Filler(output)
      filler.fill(block[0], block[1], '\x00')
      filler.close()
    def parse_detial(self, response):
        font = TTFont(BytesIO(response.body))
        cmap = font.getBestCmap()
        font.close()
        self.font_dic[response.url] = cmap

        return self.processing_data(cmap, response.meta)
Пример #38
0
class TestClosureTaker(unittest.TestCase):
    def setUp(self):
        """Loads font and initializes ClosureTaker
    """
        self.font = TTFont('test_data/NotoSans-Regular_subset.ttf')
        self.closureTaker = ClosureTaker(self.font)

    def test_c(self):
        """Takes closure of character 'c' Expected result is array: [3]
    """
        self.closureTaker.clear()
        self.closureTaker.add_glyph_names(['c'])
        gids = self.closureTaker.closure()
        self.assertTrue(gids == [3], 'Closure of c is [c]')

    def test_clear(self):
        """Takes closure of cleared input lists Expected result is array: []
    """
        self.closureTaker.clear()
        gids = self.closureTaker.closure()
        self.assertTrue(gids == [], 'Closure of empty is []')

    def tearDown(self):
        """Closes font
    """
        self.font.close()
Пример #39
0
def patch(filepath):
    print "Patching '%s' ..." % filepath,
    base, ext = filepath.rsplit(".", 1)
    font = TTFont(filepath)
    patch_cmap(font)
    font.save("%s_patch.%s" % (base, ext))
    font.close()
    print "OK"
Пример #40
0
def get_font(url):

    time.sleep(1)
    response = requests.get(url)
    font = TTFont(BytesIO(response.content))
    web_font_relation = font.getBestCmap()
    font.close()
    return web_font_relation
Пример #41
0
def patch(filepath):
    print "Patching '%s' ..." % filepath,
    base, ext = filepath.rsplit(".", 1)
    font = TTFont(filepath)
    patch_cmap(font)
    font.save("%s_patch.%s" % (base, ext))
    font.close()
    print "OK"
Пример #42
0
def webfonts(infont, type):
    font = TTFont(infont, recalcBBoxes=0)
    # Generate WOFF2
    woffFileName = makeOutputFileName(infont, outputDir=None, extension='.' + type)
    print("Processing %s => %s" % (infont, woffFileName))
    font.flavor = type
    font.save(woffFileName, reorderTables=False)
    font.close()
Пример #43
0
def main(file_name):
    excluded_chars = ["????", "SPACE", "NO-BREAK SPACE"]
    font = TTFont(file_name)
    for cmap in font["cmap"].tables: 
        char_list = sorted(cmap.cmap.items())
        for item in char_list:
            item_description = Unicode[item[0]]
            if item_description not in excluded_chars:
                print hex(item[0]), item_description
    font.close()
Пример #44
0
def makeWeb(args):
    """If we are building a web version then try to minimise file size"""

    font = TTFont(args.file)

    base, ext = os.path.splitext(args.file)
    for flavor in ("woff", "woff2"):
        font.flavor = flavor
        font.save(args.dir + "/" + base + "." + flavor)
    font.close()
Пример #45
0
    def _export_colr(self, otfpath):
        font = TTFont(otfpath)
        if (font.has_key("COLR") and font.has_key("CPAL")):
            print("    WARNING: Replacing existing COLR and CPAL tables in %s" % otfpath)

        print("    Writing palette data ...")
        cpal = table_C_P_A_L_("CPAL")
        cpal.version = 0
        cpal.numPaletteEntries = len(self.palettes[0])
        cpal.palettes = []

        for j in range(len(self.palettes)):
            palette = self.palettes[j]
            _palette = []
            # keep a map of old to new indices (palette indices are
            # not saved in font)
            if j == 0:
                reindex = {0xffff: 0xffff}
                count = 0
            for i in sorted(palette.keys(), key=lambda k: int(k)):
                _color = Color()
                _color.red   = int(palette[i][1:3], 16)
                _color.green = int(palette[i][3:5], 16)
                _color.blue  = int(palette[i][5:7], 16)
                if len(palette[i]) >= 9:
                    _color.alpha  = int(palette[i][7:9], 16)
                else:
                    _color.alpha = 0xff
                if j == 0:
                    reindex[int(i)] = count
                    count += 1
                _palette.append(_color)
            print("        Appending palette", _palette)
            #print("ReIndex:", reindex)
            cpal.palettes.append(_palette)

        print("    Writing layer data ...")
        colr = table_C_O_L_R_("COLR")
        colr.version = 0
        colr.ColorLayers = {}

        for glyphname in self.keys():
            _layer_records = []
            for i in range(len(self[glyphname].layers)):
                glyph = self[glyphname]
                _layer_records.append(
                    LayerRecord(glyph.layers[i], reindex[glyph.colors[i]])
                )
            colr[glyphname] = _layer_records

        # save
        font["CPAL"] = cpal
        font["COLR"] = colr
        font.save(otfpath[:-4] + "_colr" + otfpath[-4:])
        font.close()
Пример #46
0
 def getInformation(fontfile, tags):
   # TODO(bstell) check if font already opened
   font = TTFont(fontfile)
   dict_of_data = {}
   for tag in tags:
     assert tag in FontInfo.TAGS
     result = FontInfo.TAGS[tag]['fn'](font)
     if result:
       dict_of_data[tag] = result
   font.close()
   return dict_of_data
Пример #47
0
def ttDump(input, output, options):
	print('Dumping "%s" to "%s"...' % (input, output))
	ttf = TTFont(input, 0, verbose=options.verbose, allowVID=options.allowVID,
			ignoreDecompileErrors=options.ignoreDecompileErrors,
			fontNumber=options.fontNumber)
	ttf.saveXML(output,
			tables=options.onlyTables,
			skipTables=options.skipTables, 
			splitTables=options.splitTables,
			disassembleInstructions=options.disassembleInstructions)
	ttf.close()
Пример #48
0
def can_display_text_using_font(text, font_path):
    ttf = TTFont(font_path, 0, verbose=0, allowVID=0, ignoreDecompileErrors=True, fontNumber=-1)
    chars = chain.from_iterable([y + (Unicode[y[0]],) for y in x.cmap.items()] for x in ttf["cmap"].tables)
    chars = {unichr(x[0]) for x in chars}
    for char in text:
        if unicode(char) not in chars:
            ttf.close()
            return False

    ttf.close()
    return True
Пример #49
0
def ttDump(input):
    output = tempfile.TemporaryFile(suffix=".ttx")
    ttf = TTFont(input, 0, allowVID=False,
            quiet=None, ignoreDecompileErrors=True,
            fontNumber=-1)
    ttf.saveXML(output, tables= [],
                skipTables= [], splitTables=False,
                disassembleInstructions=True,
                bitmapGlyphDataFormat='raw')
    ttf.close()
    return output
Пример #50
0
 def getInformation(fontfile, tags):
   # TODO(bstell) check if font already opened
   font = TTFont(fontfile)
   dict_of_data = collections.OrderedDict()
   for tag, fn in FontInfo.TAGS.iteritems():
     if tag in tags:
       if tag == 'SHA1':
         result = FontInfo.TAGS[tag]['fn'](fontfile)
       else:
         result = FontInfo.TAGS[tag]['fn'](font)
       if result:
         dict_of_data[tag] = result
   font.close()
   return dict_of_data
Пример #51
0
def ttDump(input, output, options):
	log.info('Dumping "%s" to "%s"...', input, output)
	if options.unicodedata:
		setUnicodeData(options.unicodedata)
	ttf = TTFont(input, 0, allowVID=options.allowVID,
			ignoreDecompileErrors=options.ignoreDecompileErrors,
			fontNumber=options.fontNumber)
	ttf.saveXML(output,
			tables=options.onlyTables,
			skipTables=options.skipTables,
			splitTables=options.splitTables,
			disassembleInstructions=options.disassembleInstructions,
			bitmapGlyphDataFormat=options.bitmapGlyphDataFormat)
	ttf.close()
Пример #52
0
def makeCss(infiles, outfile):
    """Builds a CSS file for the entire font family."""

    css = ""

    for f in infiles.split():
        base = os.path.splitext(os.path.basename(f))[0]
        font = TTFont(f)
        css += genCSS(font, base)
        font.close()

    out = open(outfile, "w")
    out.write(css)
    out.close()
Пример #53
0
def extractFontFromOpenType(pathOrFile, destination, doGlyphs=True, doInfo=True, doKerning=True, customFunctions=[]):
    source = TTFont(pathOrFile)
    if doInfo:
        extractOpenTypeInfo(source, destination)
    if doGlyphs:
        extractOpenTypeGlyphs(source, destination)
    if doKerning:
        kerning, groups = extractOpenTypeKerning(source, destination)
        destination.groups.update(groups)
        destination.kerning.clear()
        destination.kerning.update(kerning)
    for function in customFunctions:
        function(source, destination)
    source.close()
Пример #54
0
def save_font(bytecode, fontfile):
    
    font_roundtrip = TTFont(fontfile)
    bytecodeContainer = BytecodeContainer(font_roundtrip)
    for key in bytecode.keys():
        # we don't want GS initialize instructions
        if key == 'prep':
            del bytecode[key][:17]
        program_tag = key
        instruction = bytecodeContainer.constructInstructions(program_tag, bytecode[key])
        bytecodeContainer.tag_to_programs[program_tag] = Program(instruction)
    bytecodeContainer.updateTTFont(font_roundtrip)
    roundtrip_filename = "{0}_roundtrip.ttf".format(fontfile.split(".ttf")[0])
    font_roundtrip.save(roundtrip_filename)
    font_roundtrip.close()
Пример #55
0
def ttDump(input, output, options):
	if not options.quiet:
		print('Dumping "%s" to "%s"...' % (input, output))
	ttf = TTFont(input, 0, verbose=options.verbose, allowVID=options.allowVID,
			quiet=options.quiet,
			ignoreDecompileErrors=options.ignoreDecompileErrors,
			fontNumber=options.fontNumber)
	ttf.saveXML(output,
			quiet=options.quiet,
			tables=options.onlyTables,
			skipTables=options.skipTables,
			splitTables=options.splitTables,
			disassembleInstructions=options.disassembleInstructions,
			bitmapGlyphDataFormat=options.bitmapGlyphDataFormat)
	ttf.close()
Пример #56
0
def namelist_from_font(file_name, out=None):
    if out is None:
        out = sys.stdout
    excluded_chars = ["????", "SPACE", "NO-BREAK SPACE"]
    font = TTFont(file_name)
    charcodes = set()
    for cmap in font["cmap"].tables:
        if not cmap.isUnicode():
            continue
        charcodes.update(cp for cp,name in cmap.cmap.items())
    charcodes = sorted(charcodes)
    for charcode in charcodes:
        hexchar, char, item_description = _format_codepoint(charcode)
        if item_description not in excluded_chars:
            print(hexchar, char, item_description, file=out)
    font.close()
Пример #57
0
def extractFontFromTTX(pathOrFile, destination, doGlyphs=True, doInfo=True, doKerning=True, customFunctions=[]):
    from fontTools.ttLib import TTFont, TTLibError
    source = TTFont()
    source.importXML(pathOrFile)
    if doInfo:
        extractOpenTypeInfo(source, destination)
    if doGlyphs:
        extractOpenTypeGlyphs(source, destination)
    if doKerning:
        kerning, groups = extractOpenTypeKerning(source, destination)
        destination.groups.update(groups)
        destination.kerning.clear()
        destination.kerning.update(kerning)
    for function in customFunctions:
        function(source, destination)
    source.close()