mirror of
https://github.com/ryanoasis/nerd-fonts.git
synced 2024-12-25 20:18:01 +02:00
font-patcher: Introduce less severe family name shortening
[why] We want to keep "Nerd Font" in the font name if possible and instead shorten the weight part with accepted abbreviations. But these abbrevs are hard to read and sometimes a more mild abbreviating might be sufficient to get the desired name length. [how] Introduce a new shortening method for the weight parts of a family name. It takes a longer word (often un-shortened) when a weight stands on its own, but when a modifier is used together with the weight the more aggressive two-letter abbreviations are used. That new shortening method becomes the default and all the functions get a new parameter to enforce completely aggressive shortening, i.e. always use the shortest possible form. The new way to shorten is exposed all the way out to the font-patcher user who can select the shortening method as parameter to the --makegroups option. That option is undocumented because I expect some changes later on, still. Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
This commit is contained in:
parent
ff2be6af81
commit
9be4835c29
@ -10,7 +10,7 @@ class FontnameParser:
|
||||
def __init__(self, filename, logger):
|
||||
"""Parse a font filename and store the results"""
|
||||
self.parse_ok = False
|
||||
self.use_short_families = (False, False) # ( camelcase name, short styles )
|
||||
self.use_short_families = (False, False, False) # ( camelcase name, short styles, aggressive )
|
||||
self.keep_regular_in_family = None # None = auto, True, False
|
||||
self.suppress_preferred_if_identical = True
|
||||
self.family_suff = ''
|
||||
@ -65,13 +65,13 @@ class FontnameParser:
|
||||
self.short_family_suff = short_family.strip()
|
||||
return self
|
||||
|
||||
def enable_short_families(self, camelcase_name, prefix):
|
||||
def enable_short_families(self, camelcase_name, prefix, aggressive):
|
||||
"""Enable short styles in Family when (original) font name starts with prefix; enable CamelCase basename in (Typog.) Family"""
|
||||
# camelcase_name is boolean
|
||||
# prefix is either a string or False/True
|
||||
if isinstance(prefix, str):
|
||||
prefix = self._basename.startswith(prefix)
|
||||
self.use_short_families = ( camelcase_name, prefix )
|
||||
self.use_short_families = ( camelcase_name, prefix, aggressive )
|
||||
return self
|
||||
|
||||
def add_name_substitution_table(self, table):
|
||||
@ -145,15 +145,15 @@ class FontnameParser:
|
||||
(weights, styles) = FontnameTools.make_oblique_style(weights, styles)
|
||||
(name, rest) = self._shortened_name()
|
||||
if self.use_short_families[1]:
|
||||
[ weights, styles ] = FontnameTools.short_styles([ weights, styles ])
|
||||
[ weights, styles ] = FontnameTools.short_styles([ weights, styles ], self.use_short_families[2])
|
||||
return FontnameTools.concat(name, rest, self.other_token, self.short_family_suff, weights, styles)
|
||||
|
||||
def psname(self):
|
||||
"""Get the SFNT PostScriptName (ID 6)"""
|
||||
# This is almost self.family() + '-' + self.subfamily()
|
||||
(name, rest) = self._shortened_name()
|
||||
styles = FontnameTools.short_styles(self.style_token)
|
||||
weights = FontnameTools.short_styles(self.weight_token)
|
||||
styles = FontnameTools.short_styles(self.style_token, self.use_short_families[2])
|
||||
weights = FontnameTools.short_styles(self.weight_token, self.use_short_families[2])
|
||||
fam = FontnameTools.camel_casify(FontnameTools.concat(name, rest, self.other_token, self.ps_fontname_suff))
|
||||
sub = FontnameTools.camel_casify(FontnameTools.concat(weights, styles))
|
||||
if len(sub) > 0:
|
||||
@ -190,7 +190,7 @@ class FontnameParser:
|
||||
other = self.other_token
|
||||
weight = self.weight_token
|
||||
if self.use_short_families[1]:
|
||||
[ other, weight ] = FontnameTools.short_styles([ other, weight ])
|
||||
[ other, weight ] = FontnameTools.short_styles([ other, weight ], self.use_short_families[2])
|
||||
return FontnameTools.concat(name, rest, other, self.short_family_suff, weight)
|
||||
|
||||
def subfamily(self):
|
||||
|
@ -93,31 +93,38 @@ class FontnameTools:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def shorten_style_name(name):
|
||||
def shorten_style_name(name, aggressive):
|
||||
"""Substitude some known styles to short form"""
|
||||
# If aggressive is False create the mild short form
|
||||
# aggressive == True: Always use first form of everything
|
||||
# aggressive == False:
|
||||
# - has no modifier: use the second form
|
||||
# - has modifier: use second form of mod plus first form of main
|
||||
name_rest = name
|
||||
name_pre = ''
|
||||
form = 0 if aggressive else 1
|
||||
for mod in FontnameTools.known_modifiers:
|
||||
if name.startswith(mod) and len(name) > len(mod): # Second condition specifically for 'Demi'
|
||||
name_pre = FontnameTools.known_modifiers[mod]
|
||||
name_pre = FontnameTools.known_modifiers[mod][form]
|
||||
name_rest = name[len(mod):]
|
||||
break
|
||||
form = 0 if aggressive or len(name_pre) else 1
|
||||
subst = FontnameTools.find_in_dicts(name_rest, [ FontnameTools.known_weights2, FontnameTools.known_widths ])
|
||||
if isinstance(subst, str):
|
||||
return name_pre + subst
|
||||
if isinstance(subst, tuple):
|
||||
return name_pre + subst[form]
|
||||
if not len(name_pre):
|
||||
# The following sets do not allow modifiers
|
||||
subst = FontnameTools.find_in_dicts(name_rest, [ FontnameTools.known_weights1, FontnameTools.known_slopes ])
|
||||
if isinstance(subst, str):
|
||||
return subst
|
||||
if isinstance(subst, tuple):
|
||||
return subst[form]
|
||||
return name
|
||||
|
||||
@staticmethod
|
||||
def short_styles(lists):
|
||||
def short_styles(lists, aggressive):
|
||||
"""Shorten all style names in a list or a list of lists"""
|
||||
if not len(lists) or not isinstance(lists[0], list):
|
||||
return list(map(FontnameTools.shorten_style_name, lists))
|
||||
return [ list(map(FontnameTools.shorten_style_name, styles)) for styles in lists ]
|
||||
return list(map(lambda x: FontnameTools.shorten_style_name(x, aggressive), lists))
|
||||
return [ list(map(lambda x: FontnameTools.shorten_style_name(x, aggressive), styles)) for styles in lists ]
|
||||
|
||||
@staticmethod
|
||||
def make_oblique_style(weights, styles):
|
||||
@ -198,44 +205,52 @@ class FontnameTools:
|
||||
]
|
||||
|
||||
# From https://adobe-type-tools.github.io/font-tech-notes/pdfs/5088.FontNames.pdf
|
||||
# The first short variant is from the linked table.
|
||||
# The second (longer) short variant is from diverse fonts like Noto.
|
||||
# We can
|
||||
# - use the long form
|
||||
# - use the very short form (first)
|
||||
# - use mild short form:
|
||||
# - has no modifier: use the second form
|
||||
# - has modifier: use second form of mod plus first form of main
|
||||
known_weights1 = { # can not take modifiers
|
||||
'Medium': 'Md',
|
||||
'Nord': 'Nd',
|
||||
'Book': 'Bk',
|
||||
'Poster': 'Po',
|
||||
'Demi': 'Dm', # Demi is sometimes used as a weight, sometimes as a modifier
|
||||
'Regular': 'Rg',
|
||||
'Display': 'DS',
|
||||
'Super': 'Su',
|
||||
'Retina': 'Rt',
|
||||
'Medium': ('Md', 'Med'),
|
||||
'Nord': ('Nd', 'Nord'),
|
||||
'Book': ('Bk', 'Book'),
|
||||
'Poster': ('Po', 'Poster'),
|
||||
'Demi': ('Dm', 'Demi'), # Demi is sometimes used as a weight, sometimes as a modifier
|
||||
'Regular': ('Rg', 'Reg'),
|
||||
'Display': ('DS', 'Disp'),
|
||||
'Super': ('Su', 'Sup'),
|
||||
'Retina': ('Rt', 'Ret'),
|
||||
}
|
||||
known_weights2 = { # can take modifiers
|
||||
'Black': 'Blk',
|
||||
'Bold': 'Bd',
|
||||
'Heavy': 'Hv',
|
||||
'Thin': 'Th',
|
||||
'Light': 'Lt',
|
||||
'Black': ('Blk', 'Black'),
|
||||
'Bold': ('Bd', 'Bold'),
|
||||
'Heavy': ('Hv', 'Heavy'),
|
||||
'Thin': ('Th', 'Thin'),
|
||||
'Light': ('Lt', 'Light'),
|
||||
}
|
||||
known_widths = { # can take modifiers
|
||||
'Compressed': 'Cm',
|
||||
'Extended': 'Ex',
|
||||
'Condensed': 'Cn',
|
||||
'Narrow': 'Nr',
|
||||
'Compact': 'Ct',
|
||||
'Compressed': ('Cm', 'Comp'),
|
||||
'Extended': ('Ex', 'Extd'),
|
||||
'Condensed': ('Cn', 'Cond'),
|
||||
'Narrow': ('Nr', 'Narrow'),
|
||||
'Compact': ('Ct', 'Compact'),
|
||||
}
|
||||
known_slopes = {
|
||||
'Inclined': 'Ic',
|
||||
'Oblique': 'Obl',
|
||||
'Italic': 'It',
|
||||
'Upright': 'Up',
|
||||
'Kursiv': 'Ks',
|
||||
'Sloped': 'Sl',
|
||||
'Inclined': ('Ic', 'Incl'),
|
||||
'Oblique': ('Obl', 'Obl'),
|
||||
'Italic': ('It', 'Italic'),
|
||||
'Upright': ('Up', 'Uprght'),
|
||||
'Kursiv': ('Ks', 'Kurs'),
|
||||
'Sloped': ('Sl', 'Slop'),
|
||||
}
|
||||
known_modifiers = {
|
||||
'Demi': 'Dm',
|
||||
'Ultra': 'Ult',
|
||||
'Semi': 'Sm',
|
||||
'Extra': 'X',
|
||||
'Demi': ('Dm', 'Dem'),
|
||||
'Ultra': ('Ult', 'Ult'),
|
||||
'Semi': ('Sm', 'Sem'),
|
||||
'Extra': ('X', 'Ext'),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
24
font-patcher
24
font-patcher
@ -569,7 +569,7 @@ class font_patcher:
|
||||
if not n.parse_ok:
|
||||
logger.warning("Have only minimal naming information, check resulting name. Maybe omit --makegroups option")
|
||||
n.drop_for_powerline()
|
||||
n.enable_short_families(True, self.args.makegroups in [ 1, 3])
|
||||
n.enable_short_families(True, self.args.makegroups in [ 2, 3, 5, 6, ], self.args.makegroups in [ 3, 6, ])
|
||||
|
||||
# All the following stuff is ignored in makegroups-mode
|
||||
|
||||
@ -723,7 +723,7 @@ class font_patcher:
|
||||
font.appendSFNTName(str('English (US)'), str('Compatible Full'), font.fullname)
|
||||
font.appendSFNTName(str('English (US)'), str('SubFamily'), subFamily)
|
||||
else:
|
||||
short_family = projectNameAbbreviation + variant_abbrev if self.args.makegroups in [ 2, 3] else projectNameSingular + variant_full
|
||||
short_family = projectNameAbbreviation + variant_abbrev if self.args.makegroups >= 4 else projectNameSingular + variant_full
|
||||
# inject_suffix(family, ps_fontname, short_family)
|
||||
n.inject_suffix(verboseAdditionalFontNameSuffix, ps_suffix, short_family)
|
||||
n.rename_font(font)
|
||||
@ -1805,14 +1805,18 @@ def setup_arguments():
|
||||
parser.add_argument('-ext', '--extension', dest='extension', default="", type=str, nargs='?', help='Change font file type to create (e.g., ttf, otf)')
|
||||
parser.add_argument('-out', '--outputdir', dest='outputdir', default=".", type=str, nargs='?', help='The directory to output the patched font file to')
|
||||
parser.add_argument('--glyphdir', dest='glyphdir', default=__dir__ + "/src/glyphs/", type=str, nargs='?', help='Path to glyphs to be used for patching')
|
||||
parser.add_argument('--makegroups', dest='makegroups', default=0, type=int, nargs='?', help='Use alternative method to name patched fonts (recommended)', const=3, choices=range(0, 4 + 1))
|
||||
# --makegroup has an additional undocumented numeric specifier. '--makegroup' is in fact '--makegroup 3'.
|
||||
# Possible values with examples:
|
||||
# 0 - turned off, use old naming scheme
|
||||
# 1 - turned on, shortening 'Bold' to 'Bd'
|
||||
# 2 - turned on, shortening 'Nerd Font' to 'NF'
|
||||
# 3 - turned on, shortening 'Nerd Font' to 'NF' and 'Bold' to 'Bd'
|
||||
# 4 - turned on, no shortening
|
||||
parser.add_argument('--makegroups', dest='makegroups', default=0, type=int, nargs='?', help='Use alternative method to name patched fonts (recommended)', const=1, choices=range(0, 6 + 1))
|
||||
# --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.
|
||||
# 0 turned off, use old naming scheme [-] [-] [-]
|
||||
# 1 HugoSansMono Nerd Font ExtraCondensed Light Italic [ ] [ ] [ ]
|
||||
# 2 HugoSansMono Nerd Font ExtCn Light Italic [ ] [X] [ ]
|
||||
# 3 HugoSansMono Nerd Font XCn Lt It [ ] [X] [X]
|
||||
# 4 HugoSansMono NF ExtraCondensed Light Italic [X] [ ] [ ]
|
||||
# 5 HugoSansMono NF ExtCn Light Italic [X] [X] [ ]
|
||||
# 6 HugoSansMono NF XCn Lt It [X] [X] [X]
|
||||
|
||||
parser.add_argument('--variable-width-glyphs', dest='nonmono', default=False, action='store_true', help='Do not adjust advance width (no "overhang")')
|
||||
|
||||
# progress bar arguments - https://stackoverflow.com/questions/15008758/parsing-boolean-values-with-argparse
|
||||
|
Loading…
Reference in New Issue
Block a user