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 <ulf.fini.jastrow@desy.de>
This commit is contained in:
Fini Jastrow 2021-12-31 14:09:00 +01:00
parent 99c2608313
commit ebd381c86b

View file

@ -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)
# 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 = 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
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
# 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
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:
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
(scale_ratio_x, scale_ratio_y) = self.get_scale_factors(sym_dim, sym_attr['stretch'])
# non-monospace (double width glyphs)
# elif sym_dim['width'] and sym_dim['height']:
if not self.args.single:
# 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']
# 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