diff --git a/bin/scripts/name_parser/FontnameParser.py b/bin/scripts/name_parser/FontnameParser.py index 2c5aff4b1..fbfc7ef3d 100644 --- a/bin/scripts/name_parser/FontnameParser.py +++ b/bin/scripts/name_parser/FontnameParser.py @@ -271,12 +271,34 @@ class FontnameParser: self.logger.error('====-< {:18} too long ({:2} > {:2}): {}'.format(entry_id, len(name), max_len, name)) return name + def check_weights(self, font): + """ Check weight metadata for consistency """ + # Some weights are hidden in styles + ignore_token = list(FontnameTools.known_widths) + list(FontnameTools.known_slopes) + ignore_token += [ m + s + for s in list(FontnameTools.known_widths) + for m in list(FontnameTools.known_modifiers) ] + restored_weight_token = [ w for w in self.style_token + self.weight_token if w not in ignore_token ] + weight = ''.join(restored_weight_token) + os2_weight = font.os2_weight + ps_weight = FontnameTools.weight_string_to_number(font.weight) + name_weight = FontnameTools.weight_string_to_number(weight) + if name_weight is None: + self.logger.error('Can not parse name for weight: {}'.format(restored_weight_token)) + return + if abs(os2_weight - ps_weight) > 50 or abs(os2_weight - name_weight) > 50: + self.logger.warning('Possible problem with the weight metadata detected, check with --debug') + self.logger.debug('Weight approximations: OS2/PS/Name: {}/{}/{} (from {}/\'{}\'/\'{}\')'.format( + os2_weight, ps_weight, name_weight, + font.os2_weight, font.weight, weight)) + def rename_font(self, font): """Rename the font to include all information we found (font is fontforge font object)""" font.fondname = None font.fontname = self.psname() font.fullname = self.fullname() font.familyname = self.ps_familyname() + self.check_weights(font) # We have to work around several issues in fontforge: # diff --git a/bin/scripts/name_parser/FontnameTools.py b/bin/scripts/name_parser/FontnameTools.py index 0e664f6d2..fe22fef21 100644 --- a/bin/scripts/name_parser/FontnameTools.py +++ b/bin/scripts/name_parser/FontnameTools.py @@ -247,6 +247,9 @@ class FontnameTools: 'Light': ('Lt', 'Light'), ' ': (), # Just for CodeClimate :-/ } + known_styles = [ # Keywords that end up as style (i.e. a RIBBI set) + 'Bold', 'Italic', 'Regular', 'Normal' + ] known_widths = { # can take modifiers 'Compressed': ('Cm', 'Comp'), 'Extended': ('Ex', 'Extd'), @@ -268,6 +271,51 @@ class FontnameTools: 'Semi': ('Sm', 'Sem'), 'Extra': ('X', 'Ext'), } + equivalent_weights = { + 100: ('thin', 'hairline'), + 200: ('extralight', 'ultralight'), + 300: ('light', ), + 350: ('semilight', ), + 400: ('regular', 'normal', 'book', 'text', 'nord', 'retina'), + 500: ('medium', ), + 600: ('semibold', 'demibold', 'demi'), + 700: ('bold', ), + 800: ('extrabold', 'ultrabold'), + 900: ('black', 'heavy', 'poster', 'extrablack', 'ultrablack'), + } + + @staticmethod + def weight_string_to_number(w): + """ Convert a common string approximation to a PS/2 weight value """ + if not len(w): + return 400 + for num, strs in FontnameTools.equivalent_weights.items(): + if w.lower() in strs: + return num + return None + + @staticmethod + def weight_to_string(w): + """ Convert a PS/2 weight value to the common string approximation """ + if w < 150: + str = 'Thin' + elif w < 250: + str = 'Extra-Light' + elif w < 350: + str = 'Light' + elif w < 450: + str = 'Regular' + elif w < 550: + str = 'Medium' + elif w < 650: + str = 'Semi-Bold' + elif w < 750: + str = 'Bold' + elif w < 850: + str = 'Extra-Bold' + else: + str = 'Black' + return str @staticmethod def is_keep_regular(basename): @@ -342,8 +390,7 @@ class FontnameTools: for s in list(FontnameTools.known_weights2) + list(FontnameTools.known_widths) for m in list(FontnameTools.known_modifiers) + [''] if m != s ] + list(FontnameTools.known_weights1) + list(FontnameTools.known_slopes) - styles = [ 'Bold', 'Italic', 'Regular', 'Normal', ] - weights = [ w for w in weights if w not in styles ] + weights = [ w for w in weights if w not in FontnameTools.known_styles ] # Some font specialities: other = [ '-', 'Book', 'For', 'Powerline', @@ -355,7 +402,7 @@ class FontnameTools: ] ( style, weight_token ) = FontnameTools.get_name_token(style, weights) - ( style, style_token ) = FontnameTools.get_name_token(style, styles) + ( style, style_token ) = FontnameTools.get_name_token(style, FontnameTools.known_styles) ( style, other_token ) = FontnameTools.get_name_token(style, other) while 'Regular' in style_token and len(style_token) > 1: # Correct situation where "Regular" and something else is given diff --git a/font-patcher b/font-patcher index 1d0f4a3e7..5efec62c2 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.5.1" +script_version = "4.5.2" version = "3.0.2" projectName = "Nerd Fonts"