diff --git a/font-patcher b/font-patcher index d6ae5a1..21db777 100755 --- a/font-patcher +++ b/font-patcher @@ -6,7 +6,7 @@ from __future__ import absolute_import, print_function, unicode_literals # Change the script version when you edit this script: -script_version = "4.18.0" +script_version = "4.18.1" version = "3.3.0" projectName = "Nerd Fonts" @@ -38,7 +38,7 @@ except ImportError: ) ) -sys.path.insert(0, os.path.abspath(os.path.dirname(sys.argv[0])) + '/bin/scripts/name_parser/') +sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'bin', 'scripts', 'name_parser')) try: from FontnameParser import FontnameParser from FontnameTools import FontnameTools @@ -321,8 +321,8 @@ def create_filename(fonts): def fetch_glyphnames(): """ Read the glyphname database and put it into a dictionary """ try: - glyphnamefile = os.path.abspath(os.path.dirname(sys.argv[0])) + '/glyphnames.json' - with open(glyphnamefile, 'r') as f: + glyphnamefile = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), 'glyphnames.json')) + with open(glyphnamefile, 'rb') as f: namelist = json.load(f) return { int(v['code'], 16): k for k, v in namelist.items() if 'code' in v } except Exception as error: @@ -1007,7 +1007,7 @@ class font_patcher: # 0x0100, 0x0300, 0x0400, # The single glyphs 0x0100, 0x0300, and 0x0400 # (0x0200, 0x0210), # All glyphs 0x0200 to 0x0210 including both 0x0200 and 0x0210 # ]} - # If you want to not only scale but also shift as the refenerce glyph you give the + # If you want to not only scale but also shift as the reference glyph you give the # data as 'GlyphsToScale+'. Note that only one set is used and the plus version is preferred. # # For the ScaleGroup method you define any number groups of glyphs and each group is @@ -1206,7 +1206,7 @@ class font_patcher: def get_sourcefont_dimensions(self): """ This gets the font dimensions (cell width and height), and makes them equal on all platforms """ # Step 1 - # There are three ways to discribe the baseline to baseline distance + # There are three ways to describe the baseline to baseline distance # (a.k.a. line spacing) of a font. That is all a kuddelmuddel # and we try to sort this out here # See also https://glyphsapp.com/learn/vertical-metrics @@ -1298,7 +1298,7 @@ class font_patcher: self.font_dim['iconheight'] = self.font_dim['height'] if self.args.single and self.sourceFont.capHeight > 0 and not isinstance(self.args.cellopt, list): # Limit the icon height on monospaced fonts because very slender and tall icons render - # excessivly tall otherwise. We ignore that effect for the other variants because it + # excessively tall otherwise. We ignore that effect for the other variants because it # does not look so much out of place there. # Icons can be bigger than the letter capitals, but not the whole cell: self.font_dim['iconheight'] = (self.sourceFont.capHeight * 2 + self.font_dim['height']) / 3 @@ -1506,7 +1506,7 @@ class font_patcher: continue else: # If we overwrite an existing glyph all subtable entries regarding it will be wrong - # (Probably; at least if we add a symbol and do not substitude a ligature or such) + # (Probably; at least if we add a symbol and do not substitute a ligature or such) if currentSourceFontGlyph in self.sourceFont: self.sourceFont[currentSourceFontGlyph].removePosSub("*") @@ -1685,11 +1685,11 @@ class font_patcher: for glyph in self.sourceFont.glyphs(): if (glyph.width == self.font_dim['width']): # Don't touch the (negative) bearings if the width is ok - # Ligartures will have these. + # Ligatures will have these. continue if (glyph.width != 0): - # If the width is zero this glyph is intened to be printed on top of another one. + # If the width is zero this glyph is intended to be printed on top of another one. # In this case we need to keep the negative bearings to shift it 'left'. # Things like Ä have these: composed of U+0041 'A' and U+0308 'double dot above' # @@ -1767,9 +1767,9 @@ class font_patcher: if ('x' in mode) != (sym_dim['advance'] is not None): d = '0x{:X} - 0x{:X}'.format(group[0], group[-1]) if ('x' in mode) : - logger.critical("Scaling in group %s is expected to do horizonal shifts but can not", d) + logger.critical("Scaling in group %s is expected to do horizontal shifts but can not", d) else: - logger.critical("Scaling in group %s is expected to not do horizonal shifts but will", d) + logger.critical("Scaling in group %s is expected to not do horizontal shifts but will", d) sys.exit(1) if 'ScaleGlyph' in scaleRules: @@ -1797,7 +1797,7 @@ class font_patcher: def get_glyph_scale(self, symbol_unicode, scaleRules, stretch, symbolFont, dest_unicode): """ Determines whether or not to use scaled glyphs for glyph in passed symbol_unicode """ - # Potentially destorys the contents of self.sourceFont[dest_unicode] + # Potentially destroys the contents of self.sourceFont[dest_unicode] if not 'scales' in scaleRules: if not dest_unicode in self.sourceFont: self.sourceFont.createChar(dest_unicode) @@ -1842,9 +1842,10 @@ def make_sure_path_exists(path): raise def sanitize_filename(filename, allow_dirs = False): - """ Enforces to not use forbitten characters in a filename/path. """ + """ Enforces to not use forbidden characters in a filename/path. """ if filename == '.' and not allow_dirs: return '_' + restore_colon = sys.platform == 'win32' and re.match('[a-z]:', filename, re.I) trans = filename.maketrans('<>:"|?*', '_______') for i in range(0x00, 0x20): trans[i] = ord('_') @@ -1852,8 +1853,11 @@ def sanitize_filename(filename, allow_dirs = False): trans[ord('/')] = ord('_') trans[ord('\\')] = ord('_') else: - trans[ord('\\')] = ord('/') # We use posix paths - return filename.translate(trans) + trans[ord('\\')] = ord('/') # We use Posix paths + new_filename = filename.translate(trans) + if restore_colon: + new_filename = new_filename[ :1] + ':' + new_filename[2: ] + return new_filename def get_multiglyph_boundingBox(glyphs, destGlyph = None): """ Returns dict of the dimensions of multiple glyphs combined(, as if they are copied into destGlyph) """ @@ -1901,7 +1905,7 @@ def get_multiglyph_boundingBox(glyphs, destGlyph = None): } def get_glyph_dimensions(glyph): - """ Returns dict of the dimesions of the glyph passed to it. """ + """ Returns dict of the dimensions of the glyph passed to it. """ return get_multiglyph_boundingBox([ glyph ]) def scale_bounding_box(bbox, scale_x, scale_y): @@ -1988,22 +1992,24 @@ def setup_arguments(): '* Version: ' + version + '\n' '* Development Website: https://github.com/ryanoasis/nerd-fonts\n' '* Changelog: https://github.com/ryanoasis/nerd-fonts/blob/-/changelog.md'), - formatter_class=RawTextHelpFormatter + formatter_class=RawTextHelpFormatter, + add_help=False, ) - # optional arguments parser.add_argument('font', help='The path to the font to patch (e.g., Inconsolata.otf)') - parser.add_argument('-v', '--version', action='version', version=projectName + ": %(prog)s (" + version + ")") - parser.add_argument('-s', '--mono', dest='forcemono', default=False, action='count', help='Create monospaced font, existing and added glyphs are single-width (implies --single-width-glyphs)') - parser.add_argument('--use-single-width-glyphs', dest='forcemono', default=False, action='count', help=argparse.SUPPRESS) - parser.add_argument('--single-width-glyphs', dest='single', default=False, action='store_true', help='Whether to generate the glyphs as single-width not double-width (default is double-width) (Nerd Font Mono)') - parser.add_argument('--variable-width-glyphs', dest='nonmono', default=False, action='store_true', help='Do not adjust advance width (no "overhang") (Nerd Font Propo)') - parser.add_argument('--debug', dest='debugmode', default=0, type=int, nargs='?', help='Verbose mode (optional: 1=just to file; 2*=just to terminal; 3=display and file)', const=2, choices=range(0, 3 + 1)) - parser.add_argument('-q', '--quiet', dest='quiet', default=False, action='store_true', help='Do not generate verbose output') + # optional arguments parser.add_argument('--careful', dest='careful', default=False, action='store_true', help='Do not overwrite existing glyphs if detected') - parser.add_argument('-ext', '--extension', dest='extension', default="", type=str, help='Change font file type to create (e.g., ttf, otf)') - parser.add_argument('-out', '--outputdir', dest='outputdir', default=".", type=str, help='The directory to output the patched font file to') + parser.add_argument('--debug', dest='debugmode', default=0, type=int, nargs='?', help='Verbose mode (optional: 1=just to file; 2*=just to terminal; 3=display and file)', const=2, choices=range(0, 3 + 1)) + parser.add_argument('--extension', '-ext', dest='extension', default="", type=str, help='Change font file type to create (e.g., ttf, otf)') + parser.add_argument('--help', '-h', action='help', default=argparse.SUPPRESS, help='Show this help message and exit') parser.add_argument('--makegroups', dest='makegroups', default=1, type=int, nargs='?', help='Use alternative method to name patched fonts (default=1)', const=1, choices=range(-1, 6 + 1)) + parser.add_argument('--mono', '-s', dest='forcemono', default=False, action='count', help='Create monospaced font, existing and added glyphs are single-width (implies --single-width-glyphs)') + parser.add_argument('--outputdir', '-out', dest='outputdir', default=".", type=str, help='The directory to output the patched font file to') + parser.add_argument('--quiet', '-q', dest='quiet', default=False, action='store_true', help='Do not generate verbose output') + parser.add_argument('--single-width-glyphs', dest='single', default=False, action='store_true', help='Whether to generate the glyphs as single-width not double-width (default is double-width) (Nerd Font Mono)') + parser.add_argument('--use-single-width-glyphs', dest='forcemono', default=False, action='count', help=argparse.SUPPRESS) + parser.add_argument('--variable-width-glyphs', dest='nonmono', default=False, action='store_true', help='Do not adjust advance width (no "overhang") (Nerd Font Propo)') + parser.add_argument('--version', '-v', action='version', version=projectName + ': %(prog)s (' + version + ')', help='Show program\'s version number and exit') # --makegroup has an additional undocumented numeric specifier. '--makegroup' is in fact '--makegroup 1'. # Original font name: Hugo Sans Mono ExtraCondensed Light Italic # NF Fam agg. @@ -2017,40 +2023,39 @@ def setup_arguments(): # 6 HugoSansMono NF XCn Lt It [X] [X] [X] sym_font_group = parser.add_argument_group('Symbol Fonts') - sym_font_group.add_argument('-c', '--complete', dest='complete', default=False, action='store_true', help='Add all available Glyphs') + sym_font_group.add_argument('--complete', '-c', dest='complete', default=False, action='store_true', help='Add all available Glyphs') sym_font_group.add_argument('--codicons', dest='codicons', default=False, action='store_true', help='Add Codicons Glyphs (https://github.com/microsoft/vscode-codicons)') sym_font_group.add_argument('--fontawesome', dest='fontawesome', default=False, action='store_true', help='Add Font Awesome Glyphs (http://fontawesome.io/)') sym_font_group.add_argument('--fontawesomeext', dest='fontawesomeextension', default=False, action='store_true', help='Add Font Awesome Extension Glyphs (https://andrelzgava.github.io/font-awesome-extension/)') sym_font_group.add_argument('--fontlogos', dest='fontlogos', default=False, action='store_true', help='Add Font Logos Glyphs (https://github.com/Lukas-W/font-logos)') sym_font_group.add_argument('--material', '--mdi', dest='material', default=False, action='store_true', help='Add Material Design Icons (https://github.com/templarian/MaterialDesign)') sym_font_group.add_argument('--octicons', dest='octicons', default=False, action='store_true', help='Add Octicons Glyphs (https://octicons.github.com)') - sym_font_group.add_argument('--powersymbols', dest='powersymbols', default=False, action='store_true', help='Add IEC Power Symbols (https://unicodepowersymbol.com/)') sym_font_group.add_argument('--pomicons', dest='pomicons', default=False, action='store_true', help='Add Pomicon Glyphs (https://github.com/gabrielelana/pomicons)') sym_font_group.add_argument('--powerline', dest='powerline', default=False, action='store_true', help='Add Powerline Glyphs') sym_font_group.add_argument('--powerlineextra', dest='powerlineextra', default=False, action='store_true', help='Add Powerline Extra Glyphs (https://github.com/ryanoasis/powerline-extra-symbols)') + sym_font_group.add_argument('--powersymbols', dest='powersymbols', default=False, action='store_true', help='Add IEC Power Symbols (https://unicodepowersymbol.com/)') sym_font_group.add_argument('--weather', dest='weather', default=False, action='store_true', help='Add Weather Icons (https://github.com/erikflowers/weather-icons)') expert_group = parser.add_argument_group('Expert Options') + expert_group.add_argument('--adjust-line-height', '-l', dest='adjustLineHeight', default=False, action='store_true', help='Whether to adjust line heights (attempt to center powerline separators more evenly)') expert_group.add_argument('--boxdrawing', dest='forcebox', default=False, action='store_true', help='Force patching in (over existing) box drawing glyphs') + expert_group.add_argument('--cell', dest='cellopt', default=None, type=str, help='Adjust or query the call size, e.g. use "0:1000:-200:800" resp "?"') expert_group.add_argument('--configfile', dest='configfile', default=False, type=str, help='Specify a file path for configuration file (see sample: src/config.sample.cfg)') expert_group.add_argument('--custom', dest='custom', default=False, type=str, help='Specify a custom symbol font, all glyphs will be copied; absolute path suggested') - expert_group.add_argument('--dry', dest='dry_run', default=False, action='store_true', help='Do neither patch nor store the font, to check naming') expert_group.add_argument('--glyphdir', dest='glyphdir', default=__dir__ + "/src/glyphs/", type=str, help='Path to glyphs to be used for patching') expert_group.add_argument('--has-no-italic', dest='noitalic', default=False, action='store_true', help='Font family does not have Italic (but Oblique), to help create correct RIBBI set') - expert_group.add_argument('-l', '--adjust-line-height', dest='adjustLineHeight', default=False, action='store_true', help='Whether to adjust line heights (attempt to center powerline separators more evenly)') expert_group.add_argument('--metrics', dest='metrics', default=None, choices=get_metrics_names(), help='Select vertical metrics source (for problematic cases)') expert_group.add_argument('--name', dest='force_name', default=None, type=str, help='Specify naming source (\'full\', \'postscript\', \'filename\', or concrete free name-string)') expert_group.add_argument('--postprocess', dest='postprocess', default=False, type=str, help='Specify a Script for Post Processing') progressbars_group_parser = expert_group.add_mutually_exclusive_group(required=False) - expert_group.add_argument('--removeligs', '--removeligatures', dest='removeligatures', default=False, action='store_true', help='Removes ligatures specificed in configuration file (needs --configfile)') + expert_group.add_argument('--removeligs', '--removeligatures', dest='removeligatures', default=False, action='store_true', help='Removes ligatures specified in configuration file (needs --configfile)') expert_group.add_argument('--xavgcharwidth', dest='xavgwidth', default=None, type=int, nargs='?', help='Adjust xAvgCharWidth (optional: concrete value)', const=True) # --xavgcharwidth for compatibility with old applications like notepad and non-latin fonts # Possible values with examples: # - copy from sourcefont (default) # 0 - calculate from font according to OS/2-version-2 # 500 - set to 500 - expert_group.add_argument('--cell', dest='cellopt', default=None, type=str, help='Adjust or quiery the call size, e.g. use "0:1000:-200:800" resp "?"') # progress bar arguments - https://stackoverflow.com/questions/15008758/parsing-boolean-values-with-argparse progressbars_group_parser.add_argument('--progressbars', dest='progressbars', action='store_true', help='Show percentage completion progress bars per Glyph Set (default)') @@ -2124,7 +2129,7 @@ def setup_arguments(): if len(parts) != 4: raise except: - logger.critical("Parameter for --cell is not 4 colon seprated integer numbers: '%s'", args.cellopt) + logger.critical("Parameter for --cell is not 4 colon separated integer numbers: '%s'", args.cellopt) sys.exit(2) if parts[0] >= parts[1] or parts[2] >= parts[3]: logger.critical("Parameter for --cell do not result in positive cell size: %d x %d",