-
Notifications
You must be signed in to change notification settings - Fork 3.8k
font-patcher: Correct mono scaling of thin glyphs #749
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
[why] Some glyphs that are tall and thin, are too big in the resulting patched font, i.e. are higher than our 'line'. At least for --mono fonts. The non-mono fonts do not rescale the inserted glyphs at all, so there is no definition of 'too tall/wide'. [how] We want all glyphs to fit into the box defined by *_dim['height'] and *_dim['widths'], as it also defines our powerline-glyph scaling and horizontal and vertical advance widths. So we need to take that value (instead of EM) for the scaling calculation. The history of the use of EM here is a bit obscure, more explanations in the PR. Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
|
The comment raised my curiosity, and I needed an answer for #748 where the scaling operations are modernized/refactured. # font_dim['height'] represents total line height, keep our symbols sized based upon font's em
# NOTE: is this comment correct? font_dim['height'] isn't used here
scale_ratio_y = self.sourceFont.em / sym_dim['height']So the questions were
|
HistoryOrigin of comment-questionThe question comment has been introduced with 0a480bb -def get_scale_factor(font_dim, sym_dim):
- scale_ratio = 1
- # We want to preserve x/y aspect ratio, so find biggest scale factor that allows symbol to fit
- scale_ratio_x = font_dim['width'] / sym_dim['width']
- # font_dim['height'] represents total line height, keep our symbols sized based upon font's em
- scale_ratio_y = sourceFont.em / sym_dim['height']
- if scale_ratio_x > scale_ratio_y:
- scale_ratio = scale_ratio_y
- else:
- scale_ratio = scale_ratio_x
- return scale_ratio
+ def get_scale_factor(self, sym_dim):
+ scale_ratio = 1
+
+ # 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']
+
+ # font_dim['height'] represents total line height, keep our symbols sized based upon font's em
+ # NOTE: is this comment correct? font_dim['height'] isn't used here
+ scale_ratio_y = self.sourceFont.em / sym_dim['height']
+ if scale_ratio_x > scale_ratio_y:
+ scale_ratio = scale_ratio_y
+ else:
+ scale_ratio = scale_ratio_x
+ return scale_ratioThere is no explanation (well, that would probably not have resulted in a question then), and Jimmy Haas just noticed that while refactoring and added the comment 👍 Origin of code that uses
|
Experimental findingsAdd code that compares the scaling based on $ fontforge --script font-patcher --mono --powerline src/unpatched-fonts/ProggyClean/Regular/ProggyClean.ttf 2>/dev/null | grep ISSUE
ISSUE Glyph u_E610 height wins True em wins False FACT 0.8362103426972418
ISSUE Glyph u_E763 height wins True em wins False FACT 0.8376270545973712
ISSUE Glyph u_E7A4 height wins True em wins False FACT 0.83379033307312
ISSUE Glyph u_E7C4 height wins True em wins False FACT 0.8283919641695001
ISSUE Glyph u_E0A2 height wins True em wins False FACT 0.940164080613519
$ fontforge --script font-patcher --mono --powerline src/unpatched-fonts/CascadiaCode/Regular/CascadiaCode-Regular.otf 2>/dev/null | grep ISSUE
ISSUE Glyph u_E60A height wins False em wins True FACT 1.0706268488052681
ISSUE Glyph u_E70D height wins False em wins True FACT 1.0764005533441507
ISSUE Glyph u_E737 height wins False em wins True FACT 1.0100679916317992
ISSUE Glyph u_E0A2 height wins False em wins True FACT 1.1574252466091246
$ fontforge --script font-patcher --mono --complete src/unpatched-fonts/ProggyClean/Regular/ProggyClean.ttf 2>/dev/null | grep ISSUE | wc -l
58
$ fontforge --script font-patcher --mono --complete src/unpatched-fonts/CascadiaCode/Regular/CascadiaCode-Regular.otf 2>/dev/null | grep ISSUE | wc -l
40So total affected are in the 50 glyphs range. VisualThis is ProggyClean Nerd Font Mono without this patch: The comparsion is somehow rough, but all outlines are at 20% and clearly are higher than the powerline Triangular Thing that defines our full line height. After this patch, the glyphs are correctly within the line..: For other fonts it is not so obviously wrong, as Caskaydia, because here it scales too small rather than too big. Caskaydia Cove Nerd Font Mono Regular without patch: and with patch: Note that most of the glyphs scale bigger, but are limited by the width now. |
|
Here is my code change, the one for debugging purposes, to show which glyphs are affected. For reproducing purposes. Apply to From 0353bc31f34959d3cd6eae0f4bfe90417fd8287e Mon Sep 17 00:00:00 2001
From: Fini Jastrow <ulf.fini.jastrow@desy.de>
Date: Sat, 1 Jan 2022 15:14:05 +0100
Subject: [PATCH] add debug stuff
Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
---
font-patcher | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/font-patcher b/font-patcher
index 9440b2a5..415f3a50 100755
--- a/font-patcher
+++ b/font-patcher
@@ -633,19 +633,37 @@ class font_patcher:
self.font_dim['height'] = abs(self.font_dim['ymin']) + self.font_dim['ymax']
- def get_scale_factor(self, sym_dim):
+ def get_scale_factor(self, sym_dim, code):
scale_ratio = 1
# 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']
+ w_he = False
+ w_em = False
+
# font_dim['height'] represents total line height, keep our symbols sized based upon font's em
# NOTE: is this comment correct? font_dim['height'] isn't used here
+ scale_ratio_y_he = self.font_dim['height'] / sym_dim['height']
+ if scale_ratio_x > scale_ratio_y_he:
+ scale_ratio_he = scale_ratio_y_he
+ w_he = True
+ else:
+ scale_ratio_he = scale_ratio_x
+
scale_ratio_y = self.sourceFont.em / sym_dim['height']
if scale_ratio_x > scale_ratio_y:
scale_ratio = scale_ratio_y
+ w_em = True
else:
scale_ratio = scale_ratio_x
+
+ if w_he != w_em:
+ print("\nISSUE Glyph u_{:X} height wins {} em wins {} FACT {}".format(code,w_he,w_em,scale_ratio_he/scale_ratio))
+ self.fini = True
+ else:
+ self.fini = False
+
return scale_ratio
@@ -665,7 +683,7 @@ class font_patcher:
scale_factor = 0
if scaleGlyph:
sym_dim = get_glyph_dimensions(symbolFont[scaleGlyph['ScaleGlyph']])
- scale_factor = self.get_scale_factor(sym_dim)
+ scale_factor = self.get_scale_factor(sym_dim,0)
# Create glyphs from symbol font
#
@@ -752,7 +770,7 @@ class font_patcher:
scale_ratio_y = scale_factor
else:
# In this case, each glyph is sized independently to each other
- scale_ratio_x = self.get_scale_factor(sym_dim)
+ scale_ratio_x = self.get_scale_factor(sym_dim,currentSourceFontGlyph)
scale_ratio_y = scale_ratio_x
else:
if 'x' in sym_attr['stretch']:
@@ -769,6 +787,8 @@ class font_patcher:
# Stretch the glyph vertically to total line height (good for powerline separators)
# Currently stretching vertically for both monospace and double-width
scale_ratio_y = self.font_dim['height'] / sym_dim['height']
+ if self.fini:
+ print("ISSUE Redo!")
if scale_ratio_x != 1 or scale_ratio_y != 1:
if 'overlap' in sym_attr['params']:
@@ -777,6 +797,7 @@ class font_patcher:
self.sourceFont[currentSourceFontGlyph].transform(psMat.scale(scale_ratio_x, scale_ratio_y))
# Use the dimensions from the newly pasted and stretched glyph
+ self.fini = False
sym_dim = get_glyph_dimensions(self.sourceFont[currentSourceFontGlyph])
y_align_distance = 0
if sym_attr['valign'] == 'c':
--
2.32.0
|
|
Of course Cascadia Code and ProggyClean are different, because they have these: |
[why]
Some glyphs that are tall and thin, are too big in the resulting patched
font, i.e. are higher than our 'line'.
At least for
--monofonts. The non-mono fonts do not rescale theinserted glyphs at all, so there is no definition of 'too tall/wide'.
[how]
We want all glyphs to fit into the box defined by
*_dim['height']and*_dim['widths'], as it also defines our powerline-glyph scaling andhorizontal and vertical advance widths.
So we need to take that value (instead of EM) for the scaling
calculation. The history of the use of EM here is a bit obscure.
Requirements / Checklist
What does this Pull Request (PR) do?
Base mono-patched font glyph size on
heightandwidthand notEMandwidth.How should this be manually tested?
Any background context you can provide?
What are the relevant tickets (if any)?
Screenshots (if appropriate or helpful)
More in the comments below.