font-patcher: Fix alignment with overlap

[why]
Some few glyphs get a wrong left side bearing in `Nerd Font`:
    E0C2: -1230
    E0C5: -857
    E0C7: -667
    E0CA: -1230

These are the powerline glyphs which are right aligned and have overlap
and a target width of 2 cells wide.

[how]
To simplify the code add a new function that decides if a symbol shall
be one or two cells wide.
That function is then used where we had explicit tests already.

Use the function also in the overlap correction code, such that the
overlap is corrected for the right cell occupancy of the concrete glyph.

[note]
I guess that the overlap correction for 'c' alignment for 2 cell wide
glyphs is also broken. But we do not have such glyphs, so we ignore it
for now :-}

This fixes the previous commit 'font-patcher: Fix overlap for align c and r'.

Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
This commit is contained in:
Fini Jastrow 2023-03-07 19:49:41 +01:00
parent acd49cc33c
commit 964a0c8eb3

View file

@ -1144,19 +1144,21 @@ class font_patcher:
# 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
@ -1351,9 +1353,7 @@ 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(self.font_dim['xmin'] - sym_dim['xmin'], x_align_distance) x_align_distance = max(self.font_dim['xmin'] - sym_dim['xmin'], x_align_distance)
@ -1366,8 +1366,10 @@ class font_patcher:
x_align_distance -= overlap_width / 2 x_align_distance -= overlap_width / 2
elif sym_attr['align'] == 'r': elif sym_attr['align'] == 'r':
# Check and correct overlap; it can go wrong if we have a xy-ratio limit # Check and correct overlap; it can go wrong if we have a xy-ratio limit
correction = ((self.font_dim['xmin'] + self.font_dim['width'] + overlap_width) - target_xmax = (self.font_dim['xmin'] + self.font_dim['width']) * self.get_target_width(sym_attr['stretch'])
(sym_dim['xmax'] + x_align_distance)) target_xmax += overlap_width
glyph_xmax = sym_dim['xmax'] + x_align_distance
correction = target_xmax - glyph_xmax
x_align_distance += correction x_align_distance += correction
align_matrix = psMat.translate(x_align_distance, y_align_distance) align_matrix = psMat.translate(x_align_distance, y_align_distance)