def processFonts(font_paths_list, hex_colors_list, outputFolderPath, options): glyphSetsList = [] allGlyphNamesList = [] # Load the fonts and collect their glyph sets for fontPath in font_paths_list: font = ttLib.TTFont(fontPath) gSet = font.getGlyphSet() glyphSetsList.append(gSet) allGlyphNamesList.append(gSet.keys()) font.close() if not glyphSetsList: raise AssertionError("No glyph sets.") # Define the list of glyph names to convert to SVG if options.gnames_to_generate: glyphNamesList = sorted(options.gnames_to_generate) else: if options.glyphsets_union: glyphNamesList = sorted( list(set.union(*map(set, allGlyphNamesList)))) else: glyphNamesList = sorted( list(set.intersection(*map(set, allGlyphNamesList)))) # Extend the list with additional glyph names if options.gnames_to_add: glyphNamesList.extend(options.gnames_to_add) # Remove any duplicates and sort glyphNamesList = sorted(list(set(glyphNamesList))) # 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) # Gather the fonts' UPM. For simplicity, it's assumed that all fonts have # the same UPM value. If fetching the UPM value fails, default to 1000. try: upm = ttLib.TTFont(font_paths_list[0])['head'].unitsPerEm except KeyError: upm = 1000 nestedFolderPath = None filesSaved = 0 # Generate the SVGs for gName in glyphNamesList: svgStr = (u"""<svg xmlns="http://www.w3.org/2000/svg" """ u"""viewBox="0 -{} {} {}">\n""".format(upm, upm, upm)) for index, gSet in enumerate(glyphSetsList): # Skip glyphs that don't exist in the current font, # or that were requested to be skipped if gName not in gSet.keys() or gName in glyphNamesToSkipList: continue pen = SVGPen(gSet) tpen = TransformPen(pen, (1.0, 0.0, 0.0, -1.0, 0.0, 0.0)) glyph = gSet[gName] glyph.draw(tpen) d = pen.d # Skip glyphs with no contours if not len(d): continue hex_str = hex_colors_list[index] opc = '' if len(hex_str) != 6: opcHex = hex_str[6:] hex_str = hex_str[:6] if opcHex.lower() != 'ff': opc = ' opacity="{:.2f}"'.format(int(opcHex, 16) / 255) svgStr += u'\t<path{} fill="#{}" d="{}"/>\n'.format( opc, hex_str, d) svgStr += u'</svg>' # Skip saving files that have no paths if '<path' not in svgStr: 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, svgStr) filesSaved += 1 font.close() final_message(filesSaved)
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)
def test_read_write_file(self): content = '1st line\n2nd line\n3rd line' with tempfile.NamedTemporaryFile(delete=False) as tmp: shared_utils.write_file(tmp.name, content) result = shared_utils.read_file(tmp.name) self.assertEqual(result.splitlines()[1], '2nd line')