Skip to content

Commit d5d0f2d

Browse files
authored
Merge pull request #1733 from ryanoasis/feature/progress-indicators
font-patcher: Add progress indicators
2 parents d43e4a2 + 33d4af7 commit d5d0f2d

File tree

2 files changed

+69
-31
lines changed

2 files changed

+69
-31
lines changed

font-patcher

+69-31
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from __future__ import absolute_import, print_function, unicode_literals
77

88
# Change the script version when you edit this script:
9-
script_version = "4.15.0"
9+
script_version = "4.16.0"
1010

1111
version = "3.2.1"
1212
projectName = "Nerd Fonts"
@@ -964,6 +964,16 @@ class font_patcher:
964964
# 0x2592: {'align': 'c', 'valign': 'c', 'stretch': 'xy', 'params': {'dont_copy': box_keep}},
965965
# 0x2593: {'align': 'c', 'valign': 'c', 'stretch': 'xy', 'params': {'dont_copy': box_keep}},
966966
}
967+
SYM_ATTR_PROGRESS = {
968+
'default': {'align': 'c', 'valign': 'c', 'stretch': '^pa1!', 'params': {'overlap': -0.03, 'careful': True}}, # Cirles
969+
# All the squares:
970+
0xee00: {'align': 'r', 'valign': 'c', 'stretch': '^xy', 'params': {'overlap': 0.05, 'careful': True}},
971+
0xee01: {'align': 'c', 'valign': 'c', 'stretch': '^xy', 'params': {'overlap': 0.10, 'careful': True}},
972+
0xee02: {'align': 'l', 'valign': 'c', 'stretch': '^xy', 'params': {'overlap': 0.05, 'careful': True}},
973+
0xee03: {'align': 'r', 'valign': 'c', 'stretch': '^xy', 'params': {'overlap': 0.05, 'careful': True}},
974+
0xee04: {'align': 'c', 'valign': 'c', 'stretch': '^xy', 'params': {'overlap': 0.10, 'careful': True}},
975+
0xee05: {'align': 'l', 'valign': 'c', 'stretch': '^xy', 'params': {'overlap': 0.05, 'careful': True}},
976+
}
967977
CUSTOM_ATTR = {
968978
# previous custom scaling => do not touch the icons
969979
# 'default': {'align': 'c', 'valign': '', 'stretch': '', 'params': {}}
@@ -983,9 +993,9 @@ class font_patcher:
983993
# Shifting in addition to scaling can be selected too (see below).
984994
# - ScaleGroups:
985995
# Here you specify a group of glyphs that should be handled together
986-
# with the same scaling and shifting. The basis for it is a 'combined
987-
# bounding box' of all glyphs in that group. All glyphs are handled as
988-
# if they fill that combined bounding box.
996+
# with the same scaling and shifting (see bottom). The basis for it is
997+
# a 'combined bounding box' of all glyphs in that group. All glyphs are
998+
# handled as if they fill that combined bounding box.
989999
# (- ScaleGroupsVert: Removed with this commit)
9901000
#
9911001
# The ScaleGlyph method: You set 'ScaleGlyph' to the unicode of the reference glyph.
@@ -1002,7 +1012,7 @@ class font_patcher:
10021012
#
10031013
# For the ScaleGroup method you define any number groups of glyphs and each group is
10041014
# handled separately. The combined bounding box of all glyphs in the group is determined
1005-
# and based on that the scale and shift for all the glyphs in the group.
1015+
# and based on that the scale and shift (see bottom) for all the glyphs in the group.
10061016
# You define the groups as value of 'ScaleGroups'.
10071017
# It is a List of: ((lists of glyph codes) or (ranges of glyph codes))
10081018
# 'ScaleGroups': [
@@ -1013,15 +1023,21 @@ class font_patcher:
10131023
# See prepareScaleRules() for some more details.
10141024
# For historic reasons ScaleGroups is sometimes called 'new method' and ScaleGlyph 'old'.
10151025
# The codepoints mentioned here are symbol-font-codepoints.
1016-
1017-
BOX_SCALE_LIST = {'ScaleGroups': [
1026+
#
1027+
# Shifting:
1028+
# If we have a combined bounding box stored in a range, that
1029+
# box is used to align all symbols in the range identically.
1030+
# - If the symbol font is proportinal only the v alignment is synced.
1031+
# - If the symbol font is monospaced v and h alignemnts are synced.
1032+
# To make sure the behavior is as expected you are required to set a ShiftMode property
1033+
# accordingly. It just checks, you can not (!) select what is done with that property.
1034+
1035+
BOX_SCALE_LIST = {'ShiftMode': 'xy', 'ScaleGroups': [
10181036
[*range(0x2500, 0x2570 + 1), *range(0x2574, 0x257f + 1)], # box drawing
10191037
range(0x2571, 0x2573 + 1), # diagonals
1020-
[*range(0x2580, 0x2590 + 1), 0x2594, 0x2595], # blocks
1021-
range(0x2591, 0x2593 + 1), # greys
1022-
range(0x2594, 0x259f + 1), # quards (Note: quard 2597 in Hack is wrong, scales like block!)
1038+
range(0x2580, 0x259f + 1), # blocks and greys (greys are less tall originally, so overlap will be less)
10231039
]}
1024-
CODI_SCALE_LIST = {'ScaleGroups': [
1040+
CODI_SCALE_LIST = {'ShiftMode': 'xy', 'ScaleGroups': [
10251041
[0xea61, 0xeb13], # lightbulb
10261042
range(0xeab4, 0xeab7 + 1), # chevrons
10271043
[0xea7d, *range(0xea99, 0xeaa1 + 1), 0xebcb], # arrows
@@ -1033,7 +1049,7 @@ class font_patcher:
10331049
range(0xebd5, 0xebd7 + 1), # compasses
10341050
]}
10351051
DEVI_SCALE_LIST = None
1036-
FONTA_SCALE_LIST = {'ScaleGroups': [
1052+
FONTA_SCALE_LIST = {'ShiftMode': '', 'ScaleGroups': [
10371053
[0xf005, 0xf006, 0xf089], # star, star empty, half star
10381054
range(0xf026, 0xf028 + 1), # volume off, down, up
10391055
range(0xf02b, 0xf02c + 1), # tag, tags
@@ -1054,11 +1070,11 @@ class font_patcher:
10541070
range(0xf221, 0xf22d + 1), # gender or so
10551071
range(0xf255, 0xf25b + 1), # hand symbols
10561072
]}
1057-
HEAVY_SCALE_LIST = {'ScaleGlyph': 0x2771, # widest bracket, horizontally
1073+
HEAVY_SCALE_LIST = {'ShiftMode': 'y', 'ScaleGlyph': 0x2771, # widest bracket, horizontally
10581074
'GlyphsToScale': [
10591075
(0x276c, 0x2771) # all
10601076
]}
1061-
OCTI_SCALE_LIST = {'ScaleGroups': [
1077+
OCTI_SCALE_LIST = {'ShiftMode': '', 'ScaleGroups': [
10621078
[*range(0xf03d, 0xf040 + 1), 0xf019, 0xf030, 0xf04a, 0xf051, 0xf071, 0xf08c ], # arrows
10631079
[0xF0E7, # Smily and ...
10641080
0xf044, 0xf05a, 0xf05b, 0xf0aa, # triangles
@@ -1070,7 +1086,11 @@ class font_patcher:
10701086
range(0xf2c2, 0xf2c5 + 1), # move to
10711087
[0xf07b, 0xf0a1, 0xf0d6, 0xf306], # bookmarks
10721088
]}
1073-
WEATH_SCALE_LIST = {'ScaleGroups': [
1089+
PROGR_SCALE_LIST = {'ShiftMode': 'xy', 'ScaleGroups': [
1090+
range(0xedff, 0xee05 + 1), # boxes... with helper glyph for Y padding
1091+
range(0xee06, 0xee0b + 1), # circles
1092+
]}
1093+
WEATH_SCALE_LIST = {'ShiftMode': '', 'ScaleGroups': [
10741094
[0xf03c, 0xf042, 0xf045 ], # degree signs
10751095
[0xf043, 0xf044, 0xf048, 0xf04b, 0xf04c, 0xf04d, 0xf057, 0xf058, 0xf087, 0xf088], # arrows
10761096
range(0xf053, 0xf055 + 1), # thermometers
@@ -1104,6 +1124,7 @@ class font_patcher:
11041124
{'Enabled': True, 'Name': "Seti-UI + Custom", 'Filename': "original-source.otf", 'Exact': False, 'SymStart': 0xE4FA, 'SymEnd': 0xE5FF, 'SrcStart': 0xE5FA, 'ScaleRules': None, 'Attributes': SYM_ATTR_DEFAULT},
11051125
{'Enabled': True, 'Name': "Heavy Angle Brackets", 'Filename': "extraglyphs.sfd", 'Exact': True, 'SymStart': 0x276C, 'SymEnd': 0x2771, 'SrcStart': None, 'ScaleRules': HEAVY_SCALE_LIST, 'Attributes': SYM_ATTR_HEAVYBRACKETS},
11061126
{'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},
1127+
{'Enabled': True, 'Name': "Progress Indicators", 'Filename': "extraglyphs.sfd", 'Exact': True, 'SymStart': 0xEE00, 'SymEnd': 0xEE0B, 'SrcStart': None, 'ScaleRules': PROGR_SCALE_LIST, 'Attributes': SYM_ATTR_PROGRESS},
11071128
{'Enabled': True, 'Name': "Devicons", 'Filename': "devicons/devicons.ttf", 'Exact': False, 'SymStart': 0xE600, 'SymEnd': 0xE7E3, 'SrcStart': 0xE700, 'ScaleRules': DEVI_SCALE_LIST, 'Attributes': SYM_ATTR_DEFAULT},
11081129
{'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},
11091130
{'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},
@@ -1344,25 +1365,29 @@ class font_patcher:
13441365
return 1
13451366
return 2
13461367

1347-
def get_scale_factors(self, sym_dim, stretch):
1368+
def get_scale_factors(self, sym_dim, stretch, overlap=None):
13481369
""" Get scale in x and y as tuple """
13491370
# It is possible to have empty glyphs, so we need to skip those.
13501371
if not sym_dim['width'] or not sym_dim['height']:
13511372
return (1.0, 1.0)
13521373

13531374
target_width = self.font_dim['width'] * self.get_target_width(stretch)
1375+
if overlap:
1376+
target_width += self.font_dim['width'] * overlap
13541377
scale_ratio_x = target_width / sym_dim['width']
13551378

13561379
# font_dim['height'] represents total line height, keep our symbols sized based upon font's em
13571380
# Use the font_dim['height'] only for explicit 'y' scaling (not 'pa')
13581381
target_height = self.font_dim['height'] if '^' in stretch else self.font_dim['iconheight']
13591382
target_height *= 1.0 - self.font_dim['ypadding']
1383+
if overlap:
1384+
target_height *= 1.0 + min(0.01, overlap) # never aggressive vertical overlap
13601385
scale_ratio_y = target_height / sym_dim['height']
13611386

13621387
if 'pa' in stretch:
13631388
# We want to preserve x/y aspect ratio, so find biggest scale factor that allows symbol to fit
13641389
scale_ratio_x = min(scale_ratio_x, scale_ratio_y)
1365-
if not self.args.single and not '!' in stretch:
1390+
if not self.args.single and not '!' in stretch and not overlap:
13661391
# non monospaced fonts just scale down on 'pa', not up
13671392
scale_ratio_x = min(scale_ratio_x, 1.0)
13681393
scale_ratio_y = scale_ratio_x
@@ -1502,25 +1527,26 @@ class font_patcher:
15021527

15031528
# Prepare symbol glyph dimensions
15041529
sym_dim = get_glyph_dimensions(self.sourceFont[currentSourceFontGlyph])
1530+
overlap = sym_attr['params'].get('overlap')
1531+
if overlap and ypadding:
1532+
logger.critical("Conflicting params: overlap and ypadding")
1533+
sys.exit(1)
1534+
15051535
if glyph_scale_data is not None:
15061536
if glyph_scale_data[1] is not None:
15071537
sym_dim = glyph_scale_data[1] # Use combined bounding box
1508-
(scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, stretch)
1538+
(scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, stretch, overlap)
15091539
else:
15101540
# This is roughly alike get_scale_factors(glyph_scale_data[1], 'pa')
15111541
# Except we do not have glyph_scale_data[1] always...
15121542
(scale_ratio_x, scale_ratio_y) = (glyph_scale_data[0], glyph_scale_data[0])
1543+
if overlap:
1544+
scale_ratio_x *= 1.0 + (self.font_dim['width'] / (sym_dim['width'] * scale_ratio_x)) * overlap
1545+
y_overlap = min(0.01, overlap) # never aggressive vertical overlap
1546+
scale_ratio_y *= 1.0 + (self.font_dim['height'] / (sym_dim['height'] * scale_ratio_y)) * y_overlap
15131547
else:
1514-
(scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, stretch)
1548+
(scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, stretch, overlap)
15151549

1516-
overlap = sym_attr['params'].get('overlap')
1517-
if overlap and ypadding:
1518-
logger.critical("Conflicting params: overlap and ypadding")
1519-
sys.exit(1)
1520-
if overlap:
1521-
scale_ratio_x *= 1.0 + (self.font_dim['width'] / (sym_dim['width'] * scale_ratio_x)) * overlap
1522-
y_overlap = min(0.01, overlap) # never aggressive vertical overlap
1523-
scale_ratio_y *= 1.0 + (self.font_dim['height'] / (sym_dim['height'] * scale_ratio_y)) * y_overlap
15241550

15251551
# Size in x to size in y ratio limit (to prevent over-wide glyphs)
15261552
xy_ratio_max = sym_attr['params'].get('xy-ratio')
@@ -1567,15 +1593,17 @@ class font_patcher:
15671593
elif sym_attr['align'] == 'r':
15681594
# Right align
15691595
x_align_distance += self.font_dim['width'] * self.get_target_width(stretch) - sym_dim['width']
1570-
# If symbol glyph is wider than target font cell, just left-align
1571-
x_align_distance = max(self.font_dim['xmin'] - sym_dim['xmin'], x_align_distance)
1596+
if not overlap:
1597+
# If symbol glyph is wider than target font cell, just left-align
1598+
x_align_distance = max(self.font_dim['xmin'] - sym_dim['xmin'], x_align_distance)
15721599

15731600
if overlap:
15741601
overlap_width = self.font_dim['width'] * overlap
15751602
if sym_attr['align'] == 'l':
15761603
x_align_distance -= overlap_width
15771604
elif sym_attr['align'] == 'c':
1578-
if overlap_width > 0:
1605+
# center aligned keeps being center aligned even with overlap
1606+
if overlap_width < 0 and self.args.nonmono and sym_dim['advance'] is None: # Keep positive bearing due to negative overlap (propo)
15791607
x_align_distance -= overlap_width / 2
15801608
elif sym_attr['align'] == 'r' and not self.args.nonmono:
15811609
# Check and correct overlap; it can go wrong if we have a xy-ratio limit
@@ -1609,7 +1637,7 @@ class font_patcher:
16091637
else:
16101638
width = sym_dim['width']
16111639
# If we have overlap we need to subtract that to keep/get negative bearings
1612-
if overlap and (sym_attr['align'] == 'l' or sym_attr['align'] == 'r'):
1640+
if overlap:
16131641
width -= overlap_width
16141642
# Fontforge handles the width change like this:
16151643
# - Keep existing left_side_bearing
@@ -1707,11 +1735,21 @@ class font_patcher:
17071735
scaleRules['bbdims'] = []
17081736
if 'ScaleGroups' not in scaleRules:
17091737
scaleRules['ScaleGroups'] = []
1738+
1739+
mode = scaleRules['ShiftMode'] # Mode is only documentary
17101740
for group in scaleRules['ScaleGroups']:
17111741
sym_dim = get_multiglyph_boundingBox([ symbolFont[g] if g in symbolFont else None for g in group ], destGlyph)
17121742
scale = self.get_scale_factors(sym_dim, stretch)[0]
17131743
scaleRules['scales'].append(scale)
17141744
scaleRules['bbdims'].append(sym_dim)
1745+
if (mode):
1746+
if ('x' in mode) != (sym_dim['advance'] is not None):
1747+
d = '0x{:X} - 0x{:X}'.format(group[0], group[-1])
1748+
if ('x' in mode) :
1749+
logger.critical("Scaling in group %s is expected to do horizonal shifts but can not", d)
1750+
else:
1751+
logger.critical("Scaling in group %s is expected to not do horizonal shifts but will", d)
1752+
sys.exit(1)
17151753

17161754
if 'ScaleGlyph' in scaleRules:
17171755
# Rewrite to equivalent ScaleGroup

src/glyphs/extraglyphs.sfd

46.2 KB
Binary file not shown.

0 commit comments

Comments
 (0)