mirror of
https://github.com/daylinmorgan/monolisa-nerdfont-patch.git
synced 2024-12-23 07:20:44 -06:00
chore: change batteries
This commit is contained in:
parent
a148894512
commit
e577167bdc
3 changed files with 128 additions and 52 deletions
180
bin/font-patcher
180
bin/font-patcher
|
@ -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.
Loading…
Reference in a new issue