mirror of
https://github.com/ryanoasis/nerd-fonts.git
synced 2025-01-25 03:32:02 +02:00
font-patcher: Introduce weight check
[why] Windows seems to construct the font names including the PS weight. We have some sourcefonts that are broken (i.e. have in fact different weights but have the same PS weight and/or OS2 weight. That raises problems with the fonts on Windows. [how] Check and compare all weight metadata (except CID) and issue a warning if they differ too much. That might fail with unusual weight names, though. See Issue #1333 and PR #1358. Reported-by: LeoniePhiline Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
This commit is contained in:
parent
35259124bd
commit
99688c40c7
@ -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:
|
||||
#
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user