From ebd381c86bbc2a9c7d1df0fd06e3aa5e597eb2db Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Fri, 31 Dec 2021 14:09:00 +0100 Subject: [PATCH 01/16] font-patcher: Centralize scaling code [why] The glyph rescaling is scattered about two functions and several branches. It becomes hard to follow what is done when and why. [how] Use one function that determines any glyph scaling, that includes all handling except ScaleGlyph related stuff. This simplifies the code in copy_glyphs() a lot, and keeps all the scaling in get_scale_factors(). [note] No behavioral change introduced with this. [note] Well, it fixes the possible problem (it will never happen, but lurks) that a glyph is in the ScaleGlyph range AND has Y scaling set. The old code first uses the ScaleGlyph scaling and afterwards violates it by mindlessly doing the Y stretch. This would not happen anymore with the new code. If a ScaleGlyph is specified for a certain glyph, that ScaleGlyph is followed and nothing else. Signed-off-by: Fini Jastrow --- font-patcher | 98 ++++++++++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 53 deletions(-) diff --git a/font-patcher b/font-patcher index 5e7b8e3ce..9187858d0 100755 --- a/font-patcher +++ b/font-patcher @@ -969,17 +969,33 @@ class font_patcher: # print("FINAL", self.font_dim) - def get_scale_factor(self, sym_dim): - scale_ratio = 1 + def get_scale_factors(self, sym_dim, stretch): + """ Get scale in x and y as tuple """ + # It is possible to have empty glyphs, so we need to skip those. + if not sym_dim['width'] or not sym_dim['height']: + return (1.0, 1.0) - # We want to preserve x/y aspect ratio, so find biggest scale factor that allows symbol to fit - scale_ratio_x = self.font_dim['width'] / sym_dim['width'] - scale_ratio_y = self.font_dim['height'] / sym_dim['height'] - if scale_ratio_x > scale_ratio_y: - scale_ratio = scale_ratio_y + # For monospaced fonts all chars need to be maximum 'one' space wide + target_width = self.font_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 + # Use the font_dim['height'] only for explicit 'y' scaling (not 'pa') + target_height = self.font_dim['height'] + scale_ratio_y = target_height / sym_dim['height'] + + if stretch == 'pa': + # 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_y = scale_ratio_x else: - scale_ratio = scale_ratio_x - return scale_ratio + # Keep the not-stretched direction + if not 'x' in stretch: + scale_ratio_x = 1.0 + if not 'y' in stretch: + scale_ratio_y = 1.0 + + return (scale_ratio_x, scale_ratio_y) def copy_glyphs(self, sourceFontStart, symbolFont, symbolFontStart, symbolFontEnd, exactEncoding, scaleRules, setName, attributes): @@ -1039,6 +1055,10 @@ class font_patcher: currentSourceFontGlyph = sourceFontStart + sourceFontCounter sourceFontCounter += 1 + # For debugging process only limited glyphs + # if currentSourceFontGlyph != 0xe7bd: + # continue + if not self.args.quiet: if self.args.progressbars: update_progress(round(float(index + 1) / glyphSetLength, 2)) @@ -1077,48 +1097,20 @@ class font_patcher: # Prepare symbol glyph dimensions sym_dim = get_glyph_dimensions(self.sourceFont[currentSourceFontGlyph]) - scale_ratio_x = 1 - scale_ratio_y = 1 + if glyph_scale_data is not None: + # 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: + (scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, sym_attr['stretch']) - # Now that we have copy/pasted the glyph, if we are creating a monospace - # font we need to scale and move the glyphs. It is possible to have - # empty glyphs, so we need to skip those. - if self.args.single and sym_dim['width'] and sym_dim['height']: - # If we want to preserve that aspect ratio of the glyphs we need to - # find the largest possible scaling factor that will allow the glyph - # to fit in both the x and y directions - if sym_attr['stretch'] == 'pa': - scale_ratio_x = None - if glyph_scale_data: - # We want to preserve the relative size of each glyph in a glyph group - scale_ratio_x = glyph_scale_data[0] - if scale_ratio_x is None: - # In the remaining cases, each glyph is sized independently to each other - scale_ratio_x = self.get_scale_factor(sym_dim) - scale_ratio_y = scale_ratio_x - else: - if 'x' in sym_attr['stretch']: - # Stretch the glyph horizontally to fit the entire available width - scale_ratio_x = None - if glyph_scale_data is not None and glyph_scale_data[1] is not None: - scale_ratio_x = self.font_dim['width'] / glyph_scale_data[1]['width'] - if scale_ratio_x is None: - scale_ratio_x = self.font_dim['width'] / sym_dim['width'] - # end if single width - - # non-monospace (double width glyphs) - # elif sym_dim['width'] and sym_dim['height']: - # any special logic we want to apply for double-width variation - # would go here - - if 'y' in sym_attr['stretch']: - # Stretch the glyph vertically to total line height (good for powerline separators) - # Currently stretching vertically for both monospace and double-width - scale_ratio_y = None - if glyph_scale_data is not None and glyph_scale_data[1] is not None: - scale_ratio_y = self.font_dim['height'] / glyph_scale_data[1]['height'] - if scale_ratio_y is None: - scale_ratio_y = self.font_dim['height'] / sym_dim['height'] + if not self.args.single: + # any special logic we want to apply for double-width variation + # would go here: + # non monospaced fonts just scale y, on 'y' scale request (not 'pa') + scale_ratio_x = 1.0 + if not 'y' in sym_attr['stretch']: + scale_ratio_y = 1.0 overlap = sym_attr['params'].get('overlap') @@ -1286,7 +1278,7 @@ class font_patcher: # 'bbdims': [ dim_dict1, dim_dict2, ] } # # Each item in 'ScaleGroups' (a range or an explicit list) forms a group of glyphs that shall be - # as rescaled all with the same and maximum possible (for the included glyphs) factor. + # as rescaled all with the same and maximum possible (for the included glyphs) 'pa' factor. # If the 'bbdims' is present they all shall be shifted in the same way. # # Previously this structure has been used: @@ -1307,7 +1299,7 @@ class font_patcher: scaleRules['ScaleGroups'] = [] for group in scaleRules['ScaleGroups']: sym_dim = get_multiglyph_boundingBox([ symbolFont[g] if g in symbolFont else None for g in group ], destGlyph) - scale = self.get_scale_factor(sym_dim) + scale = self.get_scale_factors(sym_dim, 'pa')[0] scaleRules['scales'].append(scale) scaleRules['bbdims'].append(sym_dim) @@ -1320,7 +1312,7 @@ class font_patcher: else: group_list.append(i) sym_dim = get_glyph_dimensions(symbolFont[scaleRules['ScaleGlyph']]) - scale = self.get_scale_factor(sym_dim) + scale = self.get_scale_factors(sym_dim, 'pa')[0] scaleRules['ScaleGroups'].append(group_list) scaleRules['scales'].append(scale) scaleRules['bbdims'].append(None) # The 'old' style keeps just the scale, not the positioning From 22684bc4bc1bd4b75b0925c7a8ce3bc530abfeff Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Fri, 31 Dec 2021 14:46:14 +0100 Subject: [PATCH 02/16] font-patcher: Allow glyph down-scaling for non-mono fonts [why] On very small source fonts the patched-in symbol-glyphs can become very big and create overlay problems. It might be desirable to scale them down to 'two advance widths'. [how] It could be that the glyphs in question are in a ScaleGlyph range. So we need to activate that code also for non-single fonts. Further we allow two slots wide symbols in get_scale_factors() for those fonts. Now we take the computed scale factors for non-single fonts - only if we scale down and not up. It will confuse/upset people if the known symbols in their fonts suddenly become bigger - and it also does not look right. Fixes: #718 Fixes: #747 Reported-by: Rui Ming (Max) Xiong Signed-off-by: Fini Jastrow --- font-patcher | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/font-patcher b/font-patcher index 9187858d0..6df3375b8 100755 --- a/font-patcher +++ b/font-patcher @@ -6,7 +6,7 @@ from __future__ import absolute_import, print_function, unicode_literals # Change the script version when you edit this script: -script_version = "3.3.3" +script_version = "3.4.0" version = "2.3.0-RC" projectName = "Nerd Fonts" @@ -976,7 +976,8 @@ class font_patcher: return (1.0, 1.0) # For monospaced fonts all chars need to be maximum 'one' space wide - target_width = self.font_dim['width'] + # other fonts allows double width glyphs (for 'pa', 'x' scale target is still one space) + target_width = self.font_dim['width'] * (1.0 if self.args.single or stretch != 'pa' else 2.0) scale_ratio_x = target_width / sym_dim['width'] # font_dim['height'] represents total line height, keep our symbols sized based upon font's em @@ -1107,10 +1108,17 @@ class font_patcher: if not self.args.single: # any special logic we want to apply for double-width variation # would go here: - # non monospaced fonts just scale y, on 'y' scale request (not 'pa') - scale_ratio_x = 1.0 - if not 'y' in sym_attr['stretch']: - scale_ratio_y = 1.0 + # non monospaced fonts scale y, on 'y' scale request + # non monospaced fonts just scale down on 'pa', not up + if sym_attr['stretch'] == 'pa': + # both scale factors are the same, thus we can limit them + # individually, which is still the same + scale_ratio_x = min(scale_ratio_x, 1.0) + scale_ratio_y = min(scale_ratio_y, 1.0) + else: + scale_ratio_x = 1.0 + if not 'y' in sym_attr['stretch']: + scale_ratio_y = 1.0 overlap = sym_attr['params'].get('overlap') From b571415e6baf95b363be8a31a3cbd3cd108a95b7 Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Wed, 11 Jan 2023 18:00:35 +0100 Subject: [PATCH 03/16] font-patcher: Fix right-waveform scaling [why] While the left-side-waveform gets 'xy' scaled the right-side gets 'pa' scaled. This has been obviously forgotten. [how] Add specific scale rule for right-side-waveform. Signed-off-by: Fini Jastrow --- font-patcher | 1 + 1 file changed, 1 insertion(+) diff --git a/font-patcher b/font-patcher index 6df3375b8..37dbb0945 100755 --- a/font-patcher +++ b/font-patcher @@ -720,6 +720,7 @@ class font_patcher: # Waveform 0xe0c8: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01}}, + 0xe0ca: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01}}, # Hexagons 0xe0cc: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, From 5f852405192ee13129c5238bc0c155b9feac3fb3 Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Wed, 11 Jan 2023 18:37:14 +0100 Subject: [PATCH 04/16] font-patcher: Centralize more scaling code [why] Obviously we can drop more code and shuffle scaling logic into the scaling function. Signed-off-by: Fini Jastrow --- font-patcher | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/font-patcher b/font-patcher index 37dbb0945..1783ed1e0 100755 --- a/font-patcher +++ b/font-patcher @@ -989,10 +989,14 @@ class font_patcher: if stretch == 'pa': # 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) + if not self.args.single: + # non monospaced fonts just scale down on 'pa', not up + scale_ratio_x = min(scale_ratio_x, 1.0) scale_ratio_y = scale_ratio_x else: # Keep the not-stretched direction - if not 'x' in stretch: + if not self.args.single or not 'x' in stretch: + # non monospaced fonts scale y, on 'y' scale request (not x) scale_ratio_x = 1.0 if not 'y' in stretch: scale_ratio_y = 1.0 @@ -1106,21 +1110,6 @@ class font_patcher: else: (scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, sym_attr['stretch']) - if not self.args.single: - # any special logic we want to apply for double-width variation - # would go here: - # non monospaced fonts scale y, on 'y' scale request - # non monospaced fonts just scale down on 'pa', not up - if sym_attr['stretch'] == 'pa': - # both scale factors are the same, thus we can limit them - # individually, which is still the same - scale_ratio_x = min(scale_ratio_x, 1.0) - scale_ratio_y = min(scale_ratio_y, 1.0) - else: - scale_ratio_x = 1.0 - if not 'y' in sym_attr['stretch']: - scale_ratio_y = 1.0 - overlap = sym_attr['params'].get('overlap') if scale_ratio_x != 1 or scale_ratio_y != 1: From 95f29260b06fa359dc2a1c1925336a6a974b557f Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Wed, 11 Jan 2023 18:55:14 +0100 Subject: [PATCH 05/16] font-patcher: Prepare for code change No functional change. Signed-off-by: Fini Jastrow --- font-patcher | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/font-patcher b/font-patcher index 1783ed1e0..953a794fe 100755 --- a/font-patcher +++ b/font-patcher @@ -978,7 +978,11 @@ class font_patcher: # For monospaced fonts all chars need to be maximum 'one' space wide # other fonts allows double width glyphs (for 'pa', 'x' scale target is still one space) - target_width = self.font_dim['width'] * (1.0 if self.args.single or stretch != 'pa' else 2.0) + if self.args.single or stretch != 'pa': + 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'] # font_dim['height'] represents total line height, keep our symbols sized based upon font's em From b3c079d6d3179e0824d68e6db478a480eb9711f2 Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 12 Jan 2023 10:44:42 +0100 Subject: [PATCH 06/16] font-patcher: Correct overlap [why] The overlap formula seems to be off sometimes. Although the shift is correct (and thus the number of 'pixels' that overlap), but the non overlapping part of the glyph is often not as wide as expected, off by up to some percent. [how] The formula is too simple. It just calculates an additional scale factor on top of the already existing factor. To get it 'pixel perfect' we need to calculate first how much the glyph fills the cell - because we want the overlap to be in 'cell percent' and not 'glyph percent'. That might be sometimes the same (if the cell is filled completely), but usually it is not completely full, and that means the overlap will be smaller than intended. [note] To get the current glyph bounding box we pull some lines up in the code that get the 'dim' variable. Also use float constants to calculate with float variables. Signed-off-by: Fini Jastrow --- font-patcher | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/font-patcher b/font-patcher index 953a794fe..fe3daeffb 100755 --- a/font-patcher +++ b/font-patcher @@ -1116,17 +1116,18 @@ class font_patcher: overlap = sym_attr['params'].get('overlap') - if scale_ratio_x != 1 or scale_ratio_y != 1: + if scale_ratio_x != 1.0 or scale_ratio_y != 1.0: + if glyph_scale_data is not None and glyph_scale_data[1] is not None: + dim = glyph_scale_data[1] + else: + dim = sym_dim if overlap: - scale_ratio_x *= 1 + overlap - scale_ratio_y *= 1 + overlap + scale_ratio_x *= 1.0 + (self.font_dim['width'] / (dim['width'] * scale_ratio_x)) * overlap + scale_ratio_y *= 1.0 + (self.font_dim['width'] / (dim['width'] * scale_ratio_y)) * overlap + # Size in x to size in y ratio limit (to prevent over-wide glyphs) xy_ratio_max = sym_attr['params'].get('xy-ratio') if (xy_ratio_max): - if glyph_scale_data is not None and glyph_scale_data[1] is not None: - dim = glyph_scale_data[1] - else: - dim = sym_dim xy_ratio = dim['width'] * scale_ratio_x / (dim['height'] * scale_ratio_y) if xy_ratio > xy_ratio_max: scale_ratio_x = scale_ratio_x * xy_ratio_max / xy_ratio From a6a5a38af563a9ce5713dbabde940bf70b3f245a Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 12 Jan 2023 10:59:55 +0100 Subject: [PATCH 07/16] font-patcher: Do x-scale powerline glyphs [why] For the non-Mono variants ('Nerd Font' and 'Nerd Font Propo') the Powerline symbols are scaled in Y but the width is just kept from the symbol font, whatever that might be (and if it makes any sense). If you have for example the triangular thing (`E0B0`) it is bigger than 'one cell' and extrudes into the following cell (on 'Nerd Font'). For the other side (`E0B2`) it is even worse; it is right aligned in the current cell and so (because it is wider than one cell) it protrudes into the previous cell. [how] Just allow not only Y scaling but also X scaling for non-Mono fonts. [note] This is of relevance just for 'xy' scaling, and only the Powerline symbols do that. Signed-off-by: Fini Jastrow --- font-patcher | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/font-patcher b/font-patcher index fe3daeffb..d301e740a 100755 --- a/font-patcher +++ b/font-patcher @@ -999,8 +999,7 @@ class font_patcher: scale_ratio_y = scale_ratio_x else: # Keep the not-stretched direction - if not self.args.single or not 'x' in stretch: - # non monospaced fonts scale y, on 'y' scale request (not x) + if not 'x' in stretch: scale_ratio_x = 1.0 if not 'y' in stretch: scale_ratio_y = 1.0 From eb396e617dcbd23f9baa3a48017da9c85540002f Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 12 Jan 2023 11:26:35 +0100 Subject: [PATCH 08/16] font-patcher: Remove overlap from line-ish glyphs [why] Most Powerline glyphs have a little bit over overlap to the previous or next glyph to prevent a 'break' in a colored prompt. It does not make sense to have overlap with glyphs that can never produce any of that issues, i.e. glyphs that are not filled to the border. Like all the line-ish glyphs. Signed-off-by: Fini Jastrow --- font-patcher | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/font-patcher b/font-patcher index d301e740a..e93c4e3fc 100755 --- a/font-patcher +++ b/font-patcher @@ -682,33 +682,33 @@ class font_patcher: # Arrow tips 0xe0b0: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02, 'xy-ratio': 0.7}}, - 0xe0b1: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02, 'xy-ratio': 0.7}}, + 0xe0b1: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'xy-ratio': 0.7}}, 0xe0b2: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02, 'xy-ratio': 0.7}}, - 0xe0b3: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02, 'xy-ratio': 0.7}}, + 0xe0b3: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'xy-ratio': 0.7}}, # Rounded arcs 0xe0b4: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01, 'xy-ratio': 0.59}}, - 0xe0b5: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01, 'xy-ratio': 0.5}}, + 0xe0b5: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'xy-ratio': 0.5}}, 0xe0b6: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01, 'xy-ratio': 0.59}}, - 0xe0b7: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01, 'xy-ratio': 0.5}}, + 0xe0b7: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'xy-ratio': 0.5}}, # Bottom Triangles 0xe0b8: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, - 0xe0b9: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, + 0xe0b9: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, 0xe0ba: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, - 0xe0bb: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, + 0xe0bb: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {}}, # Top Triangles 0xe0bc: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, - 0xe0bd: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, + 0xe0bd: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, 0xe0be: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, - 0xe0bf: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, + 0xe0bf: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {}}, # Flames 0xe0c0: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01}}, - 0xe0c1: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01}}, + 0xe0c1: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, 0xe0c2: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01}}, - 0xe0c3: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01}}, + 0xe0c3: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {}}, # Small squares 0xe0c4: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, From c303a1ee18179ab8094c1655f39c00c7894eef94 Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 12 Jan 2023 11:31:27 +0100 Subject: [PATCH 09/16] font-patcher: Default some Powerline glyphs to '2 cells wide' [why] When we scale all Powerline glyphs also horizontally (in X direction) to 'one cell' some might look a bit too small; especially because they were very big previoulsy (before commit 'font-patcher: Do x-scale powerline glyphs'). [how] To get them to a reasonable and always equal width a new scale code is introduced: '2'. It is evaluated in 'x' or 'y' scaling contexts and doubles the target cell width (unless a "Nerd Font Mono" is generated where all glyphs must be one cell wide). Signed-off-by: Fini Jastrow --- font-patcher | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/font-patcher b/font-patcher index e93c4e3fc..d33ae5f1f 100755 --- a/font-patcher +++ b/font-patcher @@ -693,22 +693,22 @@ class font_patcher: 0xe0b7: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'xy-ratio': 0.5}}, # Bottom Triangles - 0xe0b8: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, - 0xe0b9: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, - 0xe0ba: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, - 0xe0bb: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {}}, + 0xe0b8: {'align': 'l', 'valign': 'c', 'stretch': 'xy2', 'params': {'overlap': 0.02}}, + 0xe0b9: {'align': 'l', 'valign': 'c', 'stretch': 'xy2', 'params': {}}, + 0xe0ba: {'align': 'r', 'valign': 'c', 'stretch': 'xy2', 'params': {'overlap': 0.02}}, + 0xe0bb: {'align': 'r', 'valign': 'c', 'stretch': 'xy2', 'params': {}}, # Top Triangles - 0xe0bc: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, - 0xe0bd: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, - 0xe0be: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, - 0xe0bf: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {}}, + 0xe0bc: {'align': 'l', 'valign': 'c', 'stretch': 'xy2', 'params': {'overlap': 0.02}}, + 0xe0bd: {'align': 'l', 'valign': 'c', 'stretch': 'xy2', 'params': {}}, + 0xe0be: {'align': 'r', 'valign': 'c', 'stretch': 'xy2', 'params': {'overlap': 0.02}}, + 0xe0bf: {'align': 'r', 'valign': 'c', 'stretch': 'xy2', 'params': {}}, # Flames - 0xe0c0: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01}}, - 0xe0c1: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, - 0xe0c2: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01}}, - 0xe0c3: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {}}, + 0xe0c0: {'align': 'l', 'valign': 'c', 'stretch': 'xy2', 'params': {'overlap': 0.01}}, + 0xe0c1: {'align': 'l', 'valign': 'c', 'stretch': 'xy2', 'params': {}}, + 0xe0c2: {'align': 'r', 'valign': 'c', 'stretch': 'xy2', 'params': {'overlap': 0.01}}, + 0xe0c3: {'align': 'r', 'valign': 'c', 'stretch': 'xy2', 'params': {}}, # Small squares 0xe0c4: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, @@ -719,8 +719,8 @@ class font_patcher: 0xe0c7: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {}}, # Waveform - 0xe0c8: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01}}, - 0xe0ca: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.01}}, + 0xe0c8: {'align': 'l', 'valign': 'c', 'stretch': 'xy2', 'params': {'overlap': 0.01}}, + 0xe0ca: {'align': 'r', 'valign': 'c', 'stretch': 'xy2', 'params': {'overlap': 0.01}}, # Hexagons 0xe0cc: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, @@ -977,8 +977,8 @@ class font_patcher: return (1.0, 1.0) # For monospaced fonts all chars need to be maximum 'one' space wide - # other fonts allows double width glyphs (for 'pa', 'x' scale target is still one space) - if self.args.single or stretch != 'pa': + # other fonts allows double width glyphs for 'pa' or if requested with '2' + if self.args.single or (stretch != 'pa' and '2' not in stretch): relative_width = 1.0 else: relative_width = 2.0 @@ -1168,6 +1168,8 @@ class font_patcher: elif sym_attr['align'] == 'r': # Right align x_align_distance += self.font_dim['width'] - sym_dim['width'] + if not self.args.single and '2' in sym_attr['stretch']: + x_align_distance += self.font_dim['width'] if overlap: overlap_width = self.font_dim['width'] * overlap From 1637ef7ff2909bc508d07b2a7e9ba0de8a41586b Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 12 Jan 2023 11:53:40 +0100 Subject: [PATCH 10/16] font-patcher: Unwrap complicated looking code [why] We have two variables that hold the same data (sym_dim and dim), which is confusing ('why do we have it?'). There is also the big 'if' on 'do we want to scale', which contains too much. In the unlikely event that we have a glyph that needs to be scaled by 1.0 AND have an overlap the code produces the wrong results. [how] Shuffle lines but no functional change (except that now we obey 'overlap' always (not that it has been a problem)). Signed-off-by: Fini Jastrow --- font-patcher | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/font-patcher b/font-patcher index d33ae5f1f..ab3ae588e 100755 --- a/font-patcher +++ b/font-patcher @@ -1107,6 +1107,8 @@ class font_patcher: # Prepare symbol glyph dimensions sym_dim = get_glyph_dimensions(self.sourceFont[currentSourceFontGlyph]) if glyph_scale_data is not None: + if glyph_scale_data[1] is not None: + sym_dim = glyph_scale_data[1] # Use combined bounding box # 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]) @@ -1114,23 +1116,18 @@ class font_patcher: (scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, sym_attr['stretch']) overlap = sym_attr['params'].get('overlap') + if overlap: + scale_ratio_x *= 1.0 + (self.font_dim['width'] / (sym_dim['width'] * scale_ratio_x)) * overlap + scale_ratio_y *= 1.0 + (self.font_dim['width'] / (sym_dim['width'] * scale_ratio_y)) * overlap + + # Size in x to size in y ratio limit (to prevent over-wide glyphs) + xy_ratio_max = sym_attr['params'].get('xy-ratio') + if (xy_ratio_max): + xy_ratio = sym_dim['width'] * scale_ratio_x / (sym_dim['height'] * scale_ratio_y) + if xy_ratio > xy_ratio_max: + scale_ratio_x = scale_ratio_x * xy_ratio_max / xy_ratio if scale_ratio_x != 1.0 or scale_ratio_y != 1.0: - if glyph_scale_data is not None and glyph_scale_data[1] is not None: - dim = glyph_scale_data[1] - else: - dim = sym_dim - if overlap: - scale_ratio_x *= 1.0 + (self.font_dim['width'] / (dim['width'] * scale_ratio_x)) * overlap - scale_ratio_y *= 1.0 + (self.font_dim['width'] / (dim['width'] * scale_ratio_y)) * overlap - - # Size in x to size in y ratio limit (to prevent over-wide glyphs) - xy_ratio_max = sym_attr['params'].get('xy-ratio') - if (xy_ratio_max): - xy_ratio = dim['width'] * scale_ratio_x / (dim['height'] * scale_ratio_y) - if xy_ratio > xy_ratio_max: - scale_ratio_x = scale_ratio_x * xy_ratio_max / xy_ratio - self.sourceFont[currentSourceFontGlyph].transform(psMat.scale(scale_ratio_x, scale_ratio_y)) # We pasted and scaled now we want to align/move From 95bdc420dadb6a2f89daa6cc7a8222461daa1bd2 Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Fri, 14 Oct 2022 17:00:16 +0200 Subject: [PATCH 11/16] font-patcher: Limit vertical overlap [why] The vertical overlap has never been a problem (as far as I know). It is maybe good to have some overlap for the terminal emulators that support vertical overlap. On terminals that truncate at the nominal cell border too much overlap looks bad, i.e. the glyphs 'distorted'. If we ever increase the overlap it is most likely be meant to be the left-right overlap. Note that the glyphs are usually valign='c' and the overlap is distributed half top and half bottom. There are no other valign values implemented (just 'not align' which is ... most likely bad). [note] Originally this has been part of commit fecda6a of #780. [note2] Originally this has been part of PR #967. Although that had a bug :grimacing: It used max() instead of min() (T_T) Signed-off-by: Fini Jastrow f --- font-patcher | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/font-patcher b/font-patcher index ab3ae588e..be23e0b42 100755 --- a/font-patcher +++ b/font-patcher @@ -676,6 +676,7 @@ class font_patcher: def setup_patch_set(self): """ Creates list of dicts to with instructions on copying glyphs from each symbol font into self.sourceFont """ # Supported params: overlap | careful + # Overlap value is used horizontally but vertically limited to 0.01 # Powerline dividers SYM_ATTR_POWERLINE = { 'default': {'align': 'c', 'valign': 'c', 'stretch': 'pa', 'params': {}}, @@ -1118,7 +1119,8 @@ class font_patcher: overlap = sym_attr['params'].get('overlap') if overlap: scale_ratio_x *= 1.0 + (self.font_dim['width'] / (sym_dim['width'] * scale_ratio_x)) * overlap - scale_ratio_y *= 1.0 + (self.font_dim['width'] / (sym_dim['width'] * scale_ratio_y)) * overlap + y_overlap = min(0.01, overlap) # never aggressive vertical overlap + scale_ratio_y *= 1.0 + (self.font_dim['width'] / (sym_dim['width'] * scale_ratio_y)) * y_overlap # Size in x to size in y ratio limit (to prevent over-wide glyphs) xy_ratio_max = sym_attr['params'].get('xy-ratio') From 8d78b63764488d6328a77ffb4d85deaa87f0974c Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 12 Jan 2023 14:11:40 +0100 Subject: [PATCH 12/16] gotta-patch-em-all: Fix --help option [why] Somehow the option is mentioned but not implemented. Signed-off-by: Fini Jastrow --- bin/scripts/gotta-patch-em-all-font-patcher!.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/scripts/gotta-patch-em-all-font-patcher!.sh b/bin/scripts/gotta-patch-em-all-font-patcher!.sh index cb656c4b5..f02c55d70 100755 --- a/bin/scripts/gotta-patch-em-all-font-patcher!.sh +++ b/bin/scripts/gotta-patch-em-all-font-patcher!.sh @@ -102,6 +102,9 @@ while getopts ":chijtv-:" option; do checkfont) activate_checkfont ;; + help) + show_help + exit 0;; info) activate_info ;; From f311401e329dd429760446147a02d06221a4fd33 Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 12 Jan 2023 16:35:08 +0100 Subject: [PATCH 13/16] font-patcher: Add overlap to left-hexagons E0CC [why] The hexagons touch the left edge with a full body, so most likely people do not want to have any visible gap there. Signed-off-by: Fini Jastrow --- font-patcher | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/font-patcher b/font-patcher index be23e0b42..5f7bd88e2 100755 --- a/font-patcher +++ b/font-patcher @@ -724,7 +724,7 @@ class font_patcher: 0xe0ca: {'align': 'r', 'valign': 'c', 'stretch': 'xy2', 'params': {'overlap': 0.01}}, # Hexagons - 0xe0cc: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, + 0xe0cc: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, 0xe0cd: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {}}, # Legos From ed929aa7f44def6a3250901a27d4473f417cec64 Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 12 Jan 2023 16:37:09 +0100 Subject: [PATCH 14/16] font-patcher: Wide fonts get only 1 cell Powerline glyphs [why] The change introduced with commit Default some Powerline glyphs to '2 cells wide' scales some Powerline glyphs to fit exactly into a 2 cell width. That looks good on 'normal' fonts, but when the font becomes wider and less tall at some point that is just too wide. This is especially the case with the SymbolsOnly font which has a 1:1 aspect ratio. Two cell Powerline glyphs would have an aspect ratio of 2:1 which is unusable. [how] Check the destination font cell aspect ratio. When a two-cell glyph would be wider than 1.6 times its height the two-cell-mode is forbitten and all Powerline glyphs are scaled into one cell width. Signed-off-by: Fini Jastrow --- font-patcher | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/font-patcher b/font-patcher index 5f7bd88e2..68d8210dc 100755 --- a/font-patcher +++ b/font-patcher @@ -245,6 +245,7 @@ class font_patcher: self.sourceFont = None # class 'fontforge.font' self.patch_set = None # class 'list' self.font_dim = None # class 'dict' + self.font_extrawide = False self.onlybitmaps = 0 self.essential = set() self.config = configparser.ConfigParser(empty_lines_in_values=False, allow_no_value=True) @@ -275,6 +276,11 @@ class font_patcher: panose[3] = 9 # 3 (4th value) = propotion; 9 = monospaced self.sourceFont.os2_panose = tuple(panose) + # For very wide (almost square or wider) fonts we do not want to generate 2 cell wide Powerline glyphs + if self.font_dim['height'] * 1.8 < self.font_dim['width'] * 2: + print("Very wide and short font, disabling 2 cell Powerline glyphs") + self.font_extrawide = True + # Prevent opening and closing the fontforge font. Makes things faster when patching # multiple ranges using the same symbol font. PreviousSymbolFilename = "" @@ -1036,15 +1042,19 @@ class font_patcher: sys.stdout.write("Adding " + str(max(1, glyphSetLength)) + " Glyphs from " + setName + " Set \n") currentSourceFontGlyph = -1 # initialize for the exactEncoding case + width_warning = False for index, sym_glyph in enumerate(symbolFontSelection): index = max(1, index) - try: - sym_attr = attributes[sym_glyph.unicode] - except KeyError: + sym_attr = attributes.get(sym_glyph.unicode) + if sym_attr is None: sym_attr = attributes['default'] + if self.font_extrawide: + # Do not allow 'xy2' scaling + sym_attr['stretch'] = sym_attr['stretch'].replace('2', '') + if exactEncoding: # Use the exact same hex values for the source font as for the symbol font. # Problem is we do not know the codepoint of the sym_glyph and because it From 0db79a0b97bd9f9dbf4e7a1edd9813ee632458c3 Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 12 Jan 2023 16:55:38 +0100 Subject: [PATCH 15/16] font-patcher: Fix vertical overlap [why] The vertical overlap is still not 'pixel perfect', it is off by a small amount that differs by font. [how] The reason is the wrong formula. We take the relative widths of the glyph to calculate the factor needed to add an overlap in height. Of course we need to take the relative heights *duh*. Sometimes I think how dumb can a single person be? :-} I would say this is copy-and-paste laziness. Signed-off-by: Fini Jastrow --- font-patcher | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/font-patcher b/font-patcher index 68d8210dc..e5ca0a13e 100755 --- a/font-patcher +++ b/font-patcher @@ -1130,7 +1130,7 @@ class font_patcher: if overlap: scale_ratio_x *= 1.0 + (self.font_dim['width'] / (sym_dim['width'] * scale_ratio_x)) * overlap y_overlap = min(0.01, overlap) # never aggressive vertical overlap - scale_ratio_y *= 1.0 + (self.font_dim['width'] / (sym_dim['width'] * scale_ratio_y)) * y_overlap + scale_ratio_y *= 1.0 + (self.font_dim['height'] / (sym_dim['height'] * scale_ratio_y)) * y_overlap # Size in x to size in y ratio limit (to prevent over-wide glyphs) xy_ratio_max = sym_attr['params'].get('xy-ratio') From 6115c0be11a89df472470d3d38e2ce803d5a34a8 Mon Sep 17 00:00:00 2001 From: Fini Jastrow Date: Thu, 12 Jan 2023 17:09:43 +0100 Subject: [PATCH 16/16] font-patcher: Make trapezoids more slim [why] The trapezoids look very clumsy if scaled too wide. No user request, just aesthetics. Signed-off-by: Fini Jastrow --- font-patcher | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/font-patcher b/font-patcher index e5ca0a13e..934f49edc 100755 --- a/font-patcher +++ b/font-patcher @@ -739,8 +739,8 @@ class font_patcher: 0xe0d1: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, # Top and bottom trapezoid - 0xe0d2: {'align': 'l', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}}, - 0xe0d4: {'align': 'r', 'valign': 'c', 'stretch': 'xy', 'params': {'overlap': 0.02}} + 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}} } SYM_ATTR_DEFAULT = {