chore: change batteries

This commit is contained in:
github-actions 2023-03-15 01:26:02 +00:00 committed by Daylin Morgan
parent 04081cc370
commit 32a93386bd
Signed by: daylin
GPG key ID: C1E52E7DD81DF79F
3 changed files with 128 additions and 52 deletions

View file

@ -6,7 +6,7 @@
from __future__ import absolute_import, print_function, unicode_literals from __future__ import absolute_import, print_function, unicode_literals
# Change the script version when you edit this script: # Change the script version when you edit this script:
script_version = "3.5.11" script_version = "3.6.1"
version = "2.3.3" version = "2.3.3"
projectName = "Nerd Fonts" projectName = "Nerd Fonts"
@ -292,6 +292,7 @@ class font_patcher:
self.patch_set = None # class 'list' self.patch_set = None # class 'list'
self.font_dim = None # class 'dict' self.font_dim = None # class 'dict'
self.font_extrawide = False self.font_extrawide = False
self.source_monospaced = None # Later True or False
self.onlybitmaps = 0 self.onlybitmaps = 0
self.essential = set() self.essential = set()
self.config = configparser.ConfigParser(empty_lines_in_values=False, allow_no_value=True) self.config = configparser.ConfigParser(empty_lines_in_values=False, allow_no_value=True)
@ -301,8 +302,7 @@ class font_patcher:
self.setup_version() self.setup_version()
self.get_essential_references() self.get_essential_references()
self.setup_name_backup(font) self.setup_name_backup(font)
if not self.args.nonmono: self.assert_monospace()
self.assert_monospace()
self.remove_ligatures() self.remove_ligatures()
self.setup_patch_set() self.setup_patch_set()
self.get_sourcefont_dimensions() self.get_sourcefont_dimensions()
@ -343,6 +343,7 @@ class font_patcher:
sys.exit("{}: Can not open symbol source for '{}'\n{:>{}} (i.e. {})".format( sys.exit("{}: Can not open symbol source for '{}'\n{:>{}} (i.e. {})".format(
projectName, patch['Name'], '', len(projectName), self.args.glyphdir + patch['Filename'])) projectName, patch['Name'], '', len(projectName), self.args.glyphdir + patch['Filename']))
symfont = fontforge.open(os.path.join(self.args.glyphdir, patch['Filename'])) symfont = fontforge.open(os.path.join(self.args.glyphdir, patch['Filename']))
symfont.encoding = 'UnicodeFull'
# Match the symbol font size to the source font size # Match the symbol font size to the source font size
symfont.em = self.sourceFont.em symfont.em = self.sourceFont.em
@ -448,7 +449,6 @@ class font_patcher:
def setup_font_names(self, font): def setup_font_names(self, font):
print(font.persistent)
font.fontname = font.persistent["fontname"] font.fontname = font.persistent["fontname"]
if isinstance(font.persistent["fullname"], str): if isinstance(font.persistent["fullname"], str):
font.fullname = font.persistent["fullname"] font.fullname = font.persistent["fullname"]
@ -716,6 +716,9 @@ class font_patcher:
def assert_monospace(self): def assert_monospace(self):
# Check if the sourcefont is monospaced # Check if the sourcefont is monospaced
width_mono, offending_char = is_monospaced(self.sourceFont) width_mono, offending_char = is_monospaced(self.sourceFont)
self.source_monospaced = width_mono
if self.args.nonmono:
return
panose_mono = check_panose_monospaced(self.sourceFont) panose_mono = check_panose_monospaced(self.sourceFont)
# The following is in fact "width_mono != panose_mono", but only if panose_mono is not 'unknown' # The following is in fact "width_mono != panose_mono", but only if panose_mono is not 'unknown'
if (width_mono and panose_mono == 0) or (not width_mono and panose_mono == 1): if (width_mono and panose_mono == 0) or (not width_mono and panose_mono == 1):
@ -735,12 +738,36 @@ class font_patcher:
def setup_patch_set(self): def setup_patch_set(self):
""" Creates list of dicts to with instructions on copying glyphs from each symbol font into self.sourceFont """ """ Creates list of dicts to with instructions on copying glyphs from each symbol font into self.sourceFont """
# Supported params: overlap | careful
box_enabled = self.source_monospaced # Box glyph only for monospaced
if box_enabled:
self.sourceFont.selection.select(("ranges",), 0x2500, 0x259f)
box_glyphs_target = len(list(self.sourceFont.selection))
box_glyphs_current = len(list(self.sourceFont.selection.byGlyphs))
if box_glyphs_target > box_glyphs_current:
# Sourcefont does not have all of these glyphs, do not mix sets
if not self.args.quiet and box_glyphs_current > 0:
print("INFO: {}/{} box drawing glyphs will be replaced".format(
box_glyphs_current, box_glyphs_target))
box_keep = False
box_enabled = True
else:
box_keep = True # just scale do not copy
box_enabled = False # Cowardly not scaling existing glyphs, although the code would allow this
# Stretch 'xz' or 'pa' (preserve aspect ratio)
# Supported params: overlap | careful | xy-ratio | dont_copy
# Overlap value is used horizontally but vertically limited to 0.01 # Overlap value is used horizontally but vertically limited to 0.01
# Careful does not overwrite/modify existing glyphs
# The xy-ratio limits the x-scale for a given y-scale to make the ratio <= this value (to prevent over-wide glyphs) # The xy-ratio limits the x-scale for a given y-scale to make the ratio <= this value (to prevent over-wide glyphs)
# '1' means occupu 1 cell (default for 'xy') # '1' means occupu 1 cell (default for 'xy')
# '2' means occupy 2 cells (default for 'pa') # '2' means occupy 2 cells (default for 'pa')
# Powerline dividers # '!' means do the 'pa' scaling even with non mono fonts (else it just scales down, never up)
# Dont_copy does not overwrite existing glyphs but rescales the preexisting ones
SYM_ATTR_DEFAULT = {
'default': {'align': 'c', 'valign': 'c', 'stretch': 'pa', 'params': {}}
}
SYM_ATTR_POWERLINE = { SYM_ATTR_POWERLINE = {
'default': {'align': 'c', 'valign': 'c', 'stretch': 'pa', 'params': {}}, 'default': {'align': 'c', 'valign': 'c', 'stretch': 'pa', 'params': {}},
@ -800,12 +827,9 @@ class font_patcher:
0xe0d2: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02, 'xy-ratio': 0.7}}, 0xe0d2: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02, 'xy-ratio': 0.7}},
0xe0d4: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02, 'xy-ratio': 0.7}} 0xe0d4: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02, 'xy-ratio': 0.7}}
} }
SYM_ATTR_TRIGRAPH = {
SYM_ATTR_DEFAULT = { 'default': {'align': 'c', 'valign': 'c', 'stretch': 'pa1!', 'params': {'overlap': -0.10, 'careful': True}}
# 'pa' == preserve aspect ratio
'default': {'align': 'c', 'valign': 'c', 'stretch': 'pa', 'params': {}}
} }
SYM_ATTR_FONTA = { SYM_ATTR_FONTA = {
# 'pa' == preserve aspect ratio # 'pa' == preserve aspect ratio
'default': {'align': 'c', 'valign': 'c', 'stretch': 'pa', 'params': {}}, 'default': {'align': 'c', 'valign': 'c', 'stretch': 'pa', 'params': {}},
@ -818,7 +842,13 @@ class font_patcher:
SYM_ATTR_HEAVYBRACKETS = { SYM_ATTR_HEAVYBRACKETS = {
'default': {'align': 'c', 'valign': 'c', 'stretch': 'pa', 'params': {'careful': True}} 'default': {'align': 'c', 'valign': 'c', 'stretch': 'pa', 'params': {'careful': True}}
} }
SYM_ATTR_BOX = {
'default': {'align': 'c', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02, 'dont_copy': box_keep}},
# No overlap with checkered greys (commented out because that raises problems on rescaling clients)
# 0x2591: {'align': 'c', 'valign': 'c', 'stretch': 'xy', 'params': {'dont_copy': box_keep}},
# 0x2592: {'align': 'c', 'valign': 'c', 'stretch': 'xy', 'params': {'dont_copy': box_keep}},
# 0x2593: {'align': 'c', 'valign': 'c', 'stretch': 'xy', 'params': {'dont_copy': box_keep}},
}
CUSTOM_ATTR = { CUSTOM_ATTR = {
# 'pa' == preserve aspect ratio # 'pa' == preserve aspect ratio
'default': {'align': 'c', 'valign': '', 'stretch': '', 'params': {}} 'default': {'align': 'c', 'valign': '', 'stretch': '', 'params': {}}
@ -867,10 +897,24 @@ class font_patcher:
# For historic reasons ScaleGroups is sometimes called 'new method' and ScaleGlyph 'old'. # For historic reasons ScaleGroups is sometimes called 'new method' and ScaleGlyph 'old'.
# The codepoints mentioned here are symbol-font-codepoints. # The codepoints mentioned here are symbol-font-codepoints.
DEVI_SCALE_LIST = {'ScaleGlyph': 0xE60E, # Android logo BOX_SCALE_LIST = {'ScaleGroups': [
[*range(0x2500, 0x2570 + 1), *range(0x2574, 0x257f + 1)], # box drawing
range(0x2571, 0x2573 + 1), # diagonals
[*range(0x2580, 0x2590 + 1), 0x2594, 0x2595], # blocks
range(0x2591, 0x2593 + 1), # greys
range(0x2594, 0x259f + 1), # quards (Note: quard 2597 in Hack is wrong, scales like block!)
]}
CODI_SCALE_LIST = {'ScaleGroups': [
range(0xea99, 0xeaa1 + 1), # arrows
range(0xeb6e, 0xeb71 + 1), # triangles
range(0xeab4, 0xeab7 + 1), # chevrons
[0xea71, *range(0xeaa6, 0xeaab + 1), 0xeabc, 0xeb18, 0xeb87, 0xeb88, 0xeb8a, 0xeb8c, 0xebb4], # cicles
[0xeacc, 0xeaba], # dash
]}
DEVI_SCALE_LIST = {'ScaleGlyph': 0xE60E, # Android logo
'GlyphsToScale': [ 'GlyphsToScale': [
(0xe6bd, 0xe6c3) # very small things (0xe6bd, 0xe6c3) # very small things
]} ]}
FONTA_SCALE_LIST = {'ScaleGroups': [ FONTA_SCALE_LIST = {'ScaleGroups': [
[0xf005, 0xf006, 0xf089], # star, star empty, half star [0xf005, 0xf006, 0xf089], # star, star empty, half star
range(0xf026, 0xf028 + 1), # volume off, down, up range(0xf026, 0xf028 + 1), # volume off, down, up
@ -892,7 +936,7 @@ class font_patcher:
range(0xf221, 0xf22d + 1), # gender or so range(0xf221, 0xf22d + 1), # gender or so
range(0xf255, 0xf25b + 1), # hand symbols range(0xf255, 0xf25b + 1), # hand symbols
]} ]}
OCTI_SCALE_LIST = {'ScaleGlyph': 0xF02E, # looking glass (probably biggest glyph?) OCTI_SCALE_LIST = {'ScaleGlyph': 0xF02E, # looking glass (probably biggest glyph?)
'GlyphsToScale': [ 'GlyphsToScale': [
(0xf03d, 0xf040), # arrows (0xf03d, 0xf040), # arrows
0xf044, 0xf05a, 0xf05b, 0xf0aa, # triangles 0xf044, 0xf05a, 0xf05b, 0xf0aa, # triangles
@ -900,7 +944,7 @@ class font_patcher:
0xf071, 0xf09f, 0xf0a0, 0xf0a1, # small arrows 0xf071, 0xf09f, 0xf0a0, 0xf0a1, # small arrows
0xf078, 0xf0a2, 0xf0a3, 0xf0a4, # chevrons 0xf078, 0xf0a2, 0xf0a3, 0xf0a4, # chevrons
0xf0ca, # dash 0xf0ca, # dash
]} ]}
WEATH_SCALE_LIST = {'ScaleGroups': [ WEATH_SCALE_LIST = {'ScaleGroups': [
[0xf03c, 0xf042, 0xf045 ], # degree signs [0xf03c, 0xf042, 0xf045 ], # degree signs
[0xf043, 0xf044, 0xf048, 0xf04b, 0xf04c, 0xf04d, 0xf057, 0xf058, 0xf087, 0xf088], # arrows [0xf043, 0xf044, 0xf048, 0xf04b, 0xf04c, 0xf04d, 0xf057, 0xf058, 0xf087, 0xf088], # arrows
@ -921,11 +965,13 @@ class font_patcher:
]} ]}
MDI_SCALE_LIST = None # Maybe later add some selected ScaleGroups MDI_SCALE_LIST = None # Maybe later add some selected ScaleGroups
# Define the character ranges # Define the character ranges
# Symbol font ranges # Symbol font ranges
self.patch_set = [ self.patch_set = [
{'Enabled': True, 'Name': "Seti-UI + Custom", 'Filename': "original-source.otf", 'Exact': False, 'SymStart': 0xE4FA, 'SymEnd': 0xE5FF, 'SrcStart': 0xE5FA, 'ScaleRules': None, 'Attributes': SYM_ATTR_DEFAULT}, {'Enabled': True, 'Name': "Seti-UI + Custom", 'Filename': "original-source.otf", 'Exact': False, 'SymStart': 0xE4FA, 'SymEnd': 0xE5FF, 'SrcStart': 0xE5FA, 'ScaleRules': None, 'Attributes': SYM_ATTR_DEFAULT},
{'Enabled': True, 'Name': "Heavy Angle Brackets", 'Filename': "extraglyphs.sfd", 'Exact': True, 'SymStart': 0x0000, 'SymEnd': 0x0000, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_HEAVYBRACKETS}, {'Enabled': True, 'Name': "Heavy Angle Brackets", 'Filename': "extraglyphs.sfd", 'Exact': True, 'SymStart': 0x276C, 'SymEnd': 0x2771, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_HEAVYBRACKETS},
{'Enabled': box_enabled, 'Name': "Box Drawing", 'Filename': "extraglyphs.sfd", 'Exact': True, 'SymStart': 0x2500, 'SymEnd': 0x259F, 'SrcStart': None, 'ScaleRules': BOX_SCALE_LIST, 'Attributes': SYM_ATTR_BOX},
{'Enabled': True, 'Name': "Devicons", 'Filename': "devicons.ttf", 'Exact': False, 'SymStart': 0xE600, 'SymEnd': 0xE6C5, 'SrcStart': 0xE700, 'ScaleRules': DEVI_SCALE_LIST, 'Attributes': SYM_ATTR_DEFAULT}, {'Enabled': True, 'Name': "Devicons", 'Filename': "devicons.ttf", 'Exact': False, 'SymStart': 0xE600, 'SymEnd': 0xE6C5, 'SrcStart': 0xE700, 'ScaleRules': DEVI_SCALE_LIST, 'Attributes': SYM_ATTR_DEFAULT},
{'Enabled': self.args.powerline, 'Name': "Powerline Symbols", 'Filename': "powerline-symbols/PowerlineSymbols.otf", 'Exact': True, 'SymStart': 0xE0A0, 'SymEnd': 0xE0A2, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_POWERLINE}, {'Enabled': self.args.powerline, 'Name': "Powerline Symbols", 'Filename': "powerline-symbols/PowerlineSymbols.otf", 'Exact': True, 'SymStart': 0xE0A0, 'SymEnd': 0xE0A2, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_POWERLINE},
{'Enabled': self.args.powerline, 'Name': "Powerline Symbols", 'Filename': "powerline-symbols/PowerlineSymbols.otf", 'Exact': True, 'SymStart': 0xE0B0, 'SymEnd': 0xE0B3, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_POWERLINE}, {'Enabled': self.args.powerline, 'Name': "Powerline Symbols", 'Filename': "powerline-symbols/PowerlineSymbols.otf", 'Exact': True, 'SymStart': 0xE0B0, 'SymEnd': 0xE0B3, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_POWERLINE},
@ -933,6 +979,7 @@ class font_patcher:
{'Enabled': self.args.powerlineextra, 'Name': "Powerline Extra Symbols", 'Filename': "PowerlineExtraSymbols.otf", 'Exact': True, 'SymStart': 0xE0B4, 'SymEnd': 0xE0C8, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_POWERLINE}, {'Enabled': self.args.powerlineextra, 'Name': "Powerline Extra Symbols", 'Filename': "PowerlineExtraSymbols.otf", 'Exact': True, 'SymStart': 0xE0B4, 'SymEnd': 0xE0C8, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_POWERLINE},
{'Enabled': self.args.powerlineextra, 'Name': "Powerline Extra Symbols", 'Filename': "PowerlineExtraSymbols.otf", 'Exact': True, 'SymStart': 0xE0CA, 'SymEnd': 0xE0CA, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_POWERLINE}, {'Enabled': self.args.powerlineextra, 'Name': "Powerline Extra Symbols", 'Filename': "PowerlineExtraSymbols.otf", 'Exact': True, 'SymStart': 0xE0CA, 'SymEnd': 0xE0CA, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_POWERLINE},
{'Enabled': self.args.powerlineextra, 'Name': "Powerline Extra Symbols", 'Filename': "PowerlineExtraSymbols.otf", 'Exact': True, 'SymStart': 0xE0CC, 'SymEnd': 0xE0D4, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_POWERLINE}, {'Enabled': self.args.powerlineextra, 'Name': "Powerline Extra Symbols", 'Filename': "PowerlineExtraSymbols.otf", 'Exact': True, 'SymStart': 0xE0CC, 'SymEnd': 0xE0D4, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_POWERLINE},
{'Enabled': self.args.powerlineextra, 'Name': "Powerline Extra Symbols", 'Filename': "PowerlineExtraSymbols.otf", 'Exact': True, 'SymStart': 0x2630, 'SymEnd': 0x2630, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_TRIGRAPH},
{'Enabled': self.args.pomicons, 'Name': "Pomicons", 'Filename': "Pomicons.otf", 'Exact': True, 'SymStart': 0xE000, 'SymEnd': 0xE00A, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_DEFAULT}, {'Enabled': self.args.pomicons, 'Name': "Pomicons", 'Filename': "Pomicons.otf", 'Exact': True, 'SymStart': 0xE000, 'SymEnd': 0xE00A, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_DEFAULT},
{'Enabled': self.args.fontawesome, 'Name': "Font Awesome", 'Filename': "font-awesome/FontAwesome.otf", 'Exact': True, 'SymStart': 0xF000, 'SymEnd': 0xF2E0, 'SrcStart': None, 'ScaleRules': FONTA_SCALE_LIST, 'Attributes': SYM_ATTR_FONTA}, {'Enabled': self.args.fontawesome, 'Name': "Font Awesome", 'Filename': "font-awesome/FontAwesome.otf", 'Exact': True, 'SymStart': 0xF000, 'SymEnd': 0xF2E0, 'SrcStart': None, 'ScaleRules': FONTA_SCALE_LIST, 'Attributes': SYM_ATTR_FONTA},
{'Enabled': self.args.fontawesomeextension, 'Name': "Font Awesome Extension", 'Filename': "font-awesome-extension.ttf", 'Exact': False, 'SymStart': 0xE000, 'SymEnd': 0xE0A9, 'SrcStart': 0xE200, 'ScaleRules': None, 'Attributes': SYM_ATTR_DEFAULT}, # Maximize {'Enabled': self.args.fontawesomeextension, 'Name': "Font Awesome Extension", 'Filename': "font-awesome-extension.ttf", 'Exact': False, 'SymStart': 0xE000, 'SymEnd': 0xE0A9, 'SrcStart': 0xE200, 'ScaleRules': None, 'Attributes': SYM_ATTR_DEFAULT}, # Maximize
@ -946,7 +993,7 @@ class font_patcher:
{'Enabled': self.args.octicons, 'Name': "Octicons", 'Filename': "octicons.ttf", 'Exact': True, 'SymStart': 0x2665, 'SymEnd': 0x2665, 'SrcStart': None, 'ScaleRules': OCTI_SCALE_LIST, 'Attributes': SYM_ATTR_DEFAULT}, # Heart {'Enabled': self.args.octicons, 'Name': "Octicons", 'Filename': "octicons.ttf", 'Exact': True, 'SymStart': 0x2665, 'SymEnd': 0x2665, 'SrcStart': None, 'ScaleRules': OCTI_SCALE_LIST, 'Attributes': SYM_ATTR_DEFAULT}, # Heart
{'Enabled': self.args.octicons, 'Name': "Octicons", 'Filename': "octicons.ttf", 'Exact': True, 'SymStart': 0X26A1, 'SymEnd': 0X26A1, 'SrcStart': None, 'ScaleRules': OCTI_SCALE_LIST, 'Attributes': SYM_ATTR_DEFAULT}, # Zap {'Enabled': self.args.octicons, 'Name': "Octicons", 'Filename': "octicons.ttf", 'Exact': True, 'SymStart': 0X26A1, 'SymEnd': 0X26A1, 'SrcStart': None, 'ScaleRules': OCTI_SCALE_LIST, 'Attributes': SYM_ATTR_DEFAULT}, # Zap
{'Enabled': self.args.octicons, 'Name': "Octicons", 'Filename': "octicons.ttf", 'Exact': False, 'SymStart': 0xF27C, 'SymEnd': 0xF27C, 'SrcStart': 0xF4A9, 'ScaleRules': OCTI_SCALE_LIST, 'Attributes': SYM_ATTR_DEFAULT}, # Desktop {'Enabled': self.args.octicons, 'Name': "Octicons", 'Filename': "octicons.ttf", 'Exact': False, 'SymStart': 0xF27C, 'SymEnd': 0xF27C, 'SrcStart': 0xF4A9, 'ScaleRules': OCTI_SCALE_LIST, 'Attributes': SYM_ATTR_DEFAULT}, # Desktop
{'Enabled': self.args.codicons, 'Name': "Codicons", 'Filename': "codicons/codicon.ttf", 'Exact': True, 'SymStart': 0xEA60, 'SymEnd': 0xEBEB, 'SrcStart': None, 'ScaleRules': None, 'Attributes': SYM_ATTR_DEFAULT}, {'Enabled': self.args.codicons, 'Name': "Codicons", 'Filename': "codicons/codicon.ttf", 'Exact': True, 'SymStart': 0xEA60, 'SymEnd': 0xEBEB, 'SrcStart': None, 'ScaleRules': CODI_SCALE_LIST, 'Attributes': SYM_ATTR_DEFAULT},
{'Enabled': self.args.custom, 'Name': "Custom", 'Filename': self.args.custom, 'Exact': True, 'SymStart': 0x0000, 'SymEnd': 0x0000, 'SrcStart': None, 'ScaleRules': None, 'Attributes': CUSTOM_ATTR} {'Enabled': self.args.custom, 'Name': "Custom", 'Filename': self.args.custom, 'Exact': True, 'SymStart': 0x0000, 'SymEnd': 0x0000, 'SrcStart': None, 'ScaleRules': None, 'Attributes': CUSTOM_ATTR}
] ]
@ -976,9 +1023,10 @@ class font_patcher:
self.add_glyphrefs_to_essential(altcode) self.add_glyphrefs_to_essential(altcode)
# From fontforge documentation: # From fontforge documentation:
# glyph.references return a tuple of tuples containing, for each reference in foreground, # glyph.references return a tuple of tuples containing, for each reference in foreground,
# a glyph name, a transformation matrix, and whether the reference is currently selected. # a glyph name, a transformation matrix, and (depending on ff version) whether the
# reference is currently selected.
references = self.sourceFont[unicode].references references = self.sourceFont[unicode].references
for refcode in [ self.sourceFont[n].unicode for n, m, s in references ]: for refcode in [ self.sourceFont[n].unicode for n, *_ in references ]: # tuple of 2 or 3 depending on ff version
if refcode not in self.essential and refcode >= 0: if refcode not in self.essential and refcode >= 0:
self.add_glyphrefs_to_essential(refcode) self.add_glyphrefs_to_essential(refcode)
@ -1075,7 +1123,8 @@ class font_patcher:
# Step 2 # Step 2
# Find the biggest char width and advance width # Find the biggest char width and advance width
# 0x00-0x17f is the Latin Extended-A range # 0x00-0x17f is the Latin Extended-A range
warned = self.args.quiet or self.args.nonmono # Do not warn if quiet or proportional target warned1 = self.args.quiet or self.args.nonmono # Do not warn if quiet or proportional target
warned2 = warned1
for glyph in range(0x21, 0x17f): for glyph in range(0x21, 0x17f):
if glyph in range(0x7F, 0xBF) or glyph in [ if glyph in range(0x7F, 0xBF) or glyph in [
0x132, 0x133, # IJ, ij (in Overpass Mono) 0x132, 0x133, # IJ, ij (in Overpass Mono)
@ -1091,30 +1140,39 @@ class font_patcher:
# print("WIDTH {:X} {} ({} {})".format(glyph, self.sourceFont[glyph].width, self.font_dim['width'], xmax)) # print("WIDTH {:X} {} ({} {})".format(glyph, self.sourceFont[glyph].width, self.font_dim['width'], xmax))
if self.font_dim['width'] < self.sourceFont[glyph].width: if self.font_dim['width'] < self.sourceFont[glyph].width:
self.font_dim['width'] = self.sourceFont[glyph].width self.font_dim['width'] = self.sourceFont[glyph].width
if not warned and glyph > 0x7a: # NOT 'basic' glyph, which includes a-zA-Z if not warned1 and glyph > 0x7a: # NOT 'basic' glyph, which includes a-zA-Z
print("Warning: Extended glyphs wider than basic glyphs, results might be useless\n {}".format( print("Warning: Extended glyphs wider than basic glyphs, results might be useless\n {}".format(
report_advance_widths(self.sourceFont))) report_advance_widths(self.sourceFont)))
warned = True warned1 = True
# print("New MAXWIDTH-A {:X} {} -> {} {}".format(glyph, self.sourceFont[glyph].width, self.font_dim['width'], xmax)) # print("New MAXWIDTH-A {:X} {} -> {} {}".format(glyph, self.sourceFont[glyph].width, self.font_dim['width'], xmax))
if xmax > self.font_dim['xmax']: if xmax > self.font_dim['xmax']:
self.font_dim['xmax'] = xmax self.font_dim['xmax'] = xmax
if not warned2 and glyph > 0x7a: # NOT 'basic' glyph, which includes a-zA-Z
print("Info: Extended glyphs wider bounding box than basic glyphs")
warned2 = True
# print("New MAXWIDTH-B {:X} {} -> {} {}".format(glyph, self.sourceFont[glyph].width, self.font_dim['width'], xmax)) # print("New MAXWIDTH-B {:X} {} -> {} {}".format(glyph, self.sourceFont[glyph].width, self.font_dim['width'], xmax))
if self.font_dim['width'] < self.font_dim['xmax']:
if not self.args.quiet:
print("Warning: Font has negative right side bearing in extended glyphs")
self.font_dim['xmax'] = self.font_dim['width'] # In fact 'xmax' is never used
# print("FINAL", self.font_dim) # print("FINAL", self.font_dim)
def get_target_width(self, stretch):
""" Get the target width (1 or 2 'cell') for a given stretch parameter """
# For monospaced fonts all chars need to be maximum 'one' space wide
# other fonts allows double width glyphs for 'pa' or if requested with '2'
if self.args.single or ('pa' not in stretch and '2' not in stretch) or '1' in stretch:
return 1
return 2
def get_scale_factors(self, sym_dim, stretch): def get_scale_factors(self, sym_dim, stretch):
""" Get scale in x and y as tuple """ """ Get scale in x and y as tuple """
# It is possible to have empty glyphs, so we need to skip those. # It is possible to have empty glyphs, so we need to skip those.
if not sym_dim['width'] or not sym_dim['height']: if not sym_dim['width'] or not sym_dim['height']:
return (1.0, 1.0) return (1.0, 1.0)
# For monospaced fonts all chars need to be maximum 'one' space wide target_width = self.font_dim['width'] * self.get_target_width(stretch)
# other fonts allows double width glyphs for 'pa' or if requested with '2'
if self.args.single or ('pa' not in stretch and '2' not in stretch) or '1' in stretch:
relative_width = 1.0
else:
relative_width = 2.0
target_width = self.font_dim['width'] * relative_width
scale_ratio_x = target_width / sym_dim['width'] scale_ratio_x = target_width / sym_dim['width']
# font_dim['height'] represents total line height, keep our symbols sized based upon font's em # font_dim['height'] represents total line height, keep our symbols sized based upon font's em
@ -1125,7 +1183,7 @@ class font_patcher:
if 'pa' in stretch: if 'pa' in stretch:
# We want to preserve x/y aspect ratio, so find biggest scale factor that allows symbol to fit # We want to preserve x/y aspect ratio, so find biggest scale factor that allows symbol to fit
scale_ratio_x = min(scale_ratio_x, scale_ratio_y) scale_ratio_x = min(scale_ratio_x, scale_ratio_y)
if not self.args.single: if not self.args.single and not '!' in stretch:
# non monospaced fonts just scale down on 'pa', not up # non monospaced fonts just scale down on 'pa', not up
scale_ratio_x = min(scale_ratio_x, 1.0) scale_ratio_x = min(scale_ratio_x, 1.0)
scale_ratio_y = scale_ratio_x scale_ratio_y = scale_ratio_x
@ -1163,7 +1221,9 @@ class font_patcher:
glyphSetLength = len(symbolFontSelection) glyphSetLength = len(symbolFontSelection)
if not self.args.quiet: if not self.args.quiet:
sys.stdout.write("Adding {} Glyphs from {} Set\n".format(glyphSetLength, setName)) modify = attributes['default']['params'].get('dont_copy')
sys.stdout.write("{} {} Glyphs from {} Set\n".format(
"Adding" if not modify else "Rescaling", glyphSetLength, setName))
currentSourceFontGlyph = -1 # initialize for the exactEncoding case currentSourceFontGlyph = -1 # initialize for the exactEncoding case
width_warning = False width_warning = False
@ -1223,29 +1283,37 @@ class font_patcher:
if currentSourceFontGlyph in self.sourceFont: if currentSourceFontGlyph in self.sourceFont:
self.sourceFont[currentSourceFontGlyph].removePosSub("*") self.sourceFont[currentSourceFontGlyph].removePosSub("*")
# This will destroy any content currently in currentSourceFontGlyph, so do it first dont_copy = sym_attr['params'].get('dont_copy')
glyph_scale_data = self.get_glyph_scale(sym_glyph.encoding, scaleRules, symbolFont, currentSourceFontGlyph) if scaleRules is not None else None
# Select and copy symbol from its encoding point if dont_copy:
# We need to do this select after the careful check, this way we don't # Just prepare scaling of existing glyphs
# reset our selection before starting the next loop glyph_scale_data = self.get_glyph_scale(sym_glyph.encoding, scaleRules, self.sourceFont, currentSourceFontGlyph) if scaleRules is not None else None
symbolFont.selection.select(sym_glyph.encoding) else:
symbolFont.copy() # This will destroy any content currently in currentSourceFontGlyph, so do it first
glyph_scale_data = self.get_glyph_scale(sym_glyph.encoding, scaleRules, symbolFont, currentSourceFontGlyph) if scaleRules is not None else None
# Paste it # Select and copy symbol from its encoding point
self.sourceFont.selection.select(currentSourceFontGlyph) # We need to do this select after the careful check, this way we don't
self.sourceFont.paste() # reset our selection before starting the next loop
self.sourceFont[currentSourceFontGlyph].glyphname = sym_glyph.glyphname symbolFont.selection.select(sym_glyph.encoding)
self.sourceFont[currentSourceFontGlyph].manualHints = True # No autohints for symbols symbolFont.copy()
# Paste it
self.sourceFont.selection.select(currentSourceFontGlyph)
self.sourceFont.paste()
self.sourceFont[currentSourceFontGlyph].glyphname = sym_glyph.glyphname
self.sourceFont[currentSourceFontGlyph].manualHints = True # No autohints for symbols
# Prepare symbol glyph dimensions # Prepare symbol glyph dimensions
sym_dim = get_glyph_dimensions(self.sourceFont[currentSourceFontGlyph]) sym_dim = get_glyph_dimensions(self.sourceFont[currentSourceFontGlyph])
if glyph_scale_data is not None: if glyph_scale_data is not None:
if glyph_scale_data[1] is not None: if glyph_scale_data[1] is not None:
sym_dim = glyph_scale_data[1] # Use combined bounding box sym_dim = glyph_scale_data[1] # Use combined bounding box
# This is roughly alike get_scale_factors(glyph_scale_data[1], 'pa') (scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, sym_attr['stretch'])
# Except we do not have glyph_scale_data[1] always... else:
(scale_ratio_x, scale_ratio_y) = (glyph_scale_data[0], glyph_scale_data[0]) # This is roughly alike get_scale_factors(glyph_scale_data[1], 'pa')
# Except we do not have glyph_scale_data[1] always...
(scale_ratio_x, scale_ratio_y) = (glyph_scale_data[0], glyph_scale_data[0])
else: else:
(scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, sym_attr['stretch']) (scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, sym_attr['stretch'])
@ -1299,16 +1367,24 @@ class font_patcher:
x_align_distance += (self.font_dim['width'] / 2) - (sym_dim['width'] / 2) x_align_distance += (self.font_dim['width'] / 2) - (sym_dim['width'] / 2)
elif sym_attr['align'] == 'r': elif sym_attr['align'] == 'r':
# Right align # Right align
x_align_distance += self.font_dim['width'] - sym_dim['width'] x_align_distance += self.font_dim['width'] * self.get_target_width(sym_attr['stretch']) - sym_dim['width']
if not self.args.single and '2' in sym_attr['stretch']:
x_align_distance += self.font_dim['width']
# If symbol glyph is wider than target font cell, just left-align # If symbol glyph is wider than target font cell, just left-align
x_align_distance = max(-sym_dim['xmin'], x_align_distance) x_align_distance = max(self.font_dim['xmin'] - sym_dim['xmin'], x_align_distance)
if overlap: if overlap:
overlap_width = self.font_dim['width'] * overlap overlap_width = self.font_dim['width'] * overlap
if sym_attr['align'] == 'l': if sym_attr['align'] == 'l':
x_align_distance -= overlap_width x_align_distance -= overlap_width
elif sym_attr['align'] == 'c':
if overlap_width > 0:
x_align_distance -= overlap_width / 2
elif sym_attr['align'] == 'r':
# Check and correct overlap; it can go wrong if we have a xy-ratio limit
target_xmax = (self.font_dim['xmin'] + self.font_dim['width']) * self.get_target_width(sym_attr['stretch'])
target_xmax += overlap_width
glyph_xmax = sym_dim['xmax'] + x_align_distance
correction = target_xmax - glyph_xmax
x_align_distance += correction
align_matrix = psMat.translate(x_align_distance, y_align_distance) align_matrix = psMat.translate(x_align_distance, y_align_distance)
self.sourceFont[currentSourceFontGlyph].transform(align_matrix) self.sourceFont[currentSourceFontGlyph].transform(align_matrix)
@ -1531,7 +1607,7 @@ def get_multiglyph_boundingBox(glyphs, destGlyph = None):
if glyph is None: if glyph is None:
# Glyph has been in defining range but is not in the actual font # Glyph has been in defining range but is not in the actual font
continue continue
if destGlyph: if destGlyph and glyph.font != destGlyph.font:
glyph.font.selection.select(glyph) glyph.font.selection.select(glyph)
glyph.font.copy() glyph.font.copy()
destGlyph.font.selection.select(destGlyph) destGlyph.font.selection.select(destGlyph)

Binary file not shown.

Binary file not shown.