Skip to content
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

font-patcher: Fix: Fix more 'Nerd Font Mono' too wide #1062

Merged
merged 5 commits into from
Jan 22, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 30 additions & 15 deletions font-patcher
Original file line number Diff line number Diff line change
Expand Up @@ -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.4.4"
script_version = "3.4.5"

version = "2.3.0"
projectName = "Nerd Fonts"
Expand Down Expand Up @@ -36,7 +36,6 @@ except ImportError:
)
)

# This is for experimenting
sys.path.insert(0, os.path.abspath(os.path.dirname(sys.argv[0])) + '/bin/scripts/name_parser/')
try:
from FontnameParser import FontnameParser
Expand Down Expand Up @@ -187,15 +186,23 @@ def check_panose_monospaced(font):
(panose[0] == 3 and panose[3] == 3))
return 1 if panose_mono else 0

def panose_check_to_text(value, panose = False):
""" Convert value from check_panose_monospaced() to human readable string """
if value == 0:
return "Panose says \"not monospaced\""
if value == 1:
return "Panose says \"monospaced\""
return "Panose is invalid" + (" ({})".format(list(panose)) if panose else "")

def is_monospaced(font):
""" Check if a font is probably monospaced """
# Some fonts lie (or have not any Panose flag set), spot check monospaced:
width = -1
width_mono = True
for glyph in [ 0x49, 0x4D, 0x57, 0x61, 0x69, 0x2E ]: # wide and slim glyphs 'I', 'M', 'W', 'a', 'i', '.'
for glyph in [ 0x49, 0x4D, 0x57, 0x61, 0x69, 0x6d, 0x2E ]: # wide and slim glyphs 'I', 'M', 'W', 'a', 'i', 'm', '.'
if not glyph in font:
# A 'strange' font, believe Panose
return check_panose_monospaced(font) == 1
return (check_panose_monospaced(font) == 1, None)
# print(" -> {} {}".format(glyph, font[glyph].width))
if width < 0:
width = font[glyph].width
Expand All @@ -213,7 +220,7 @@ def is_monospaced(font):
width_mono = False
break
# We believe our own check more then Panose ;-D
return width_mono
return (width_mono, None if width_mono else glyph)

def get_advance_width(font, extended, minimum):
""" Get the maximum/minimum advance width in the extended(?) range """
Expand All @@ -236,6 +243,11 @@ def get_advance_width(font, extended, minimum):
width = font[glyph].width
return width

def report_advance_widths(font):
return "Advance widths (base/extended): {} - {} / {} - {}".format(
get_advance_width(font, True, True), get_advance_width(font, False, True),
get_advance_width(font, False, False), get_advance_width(font, True, False))


class font_patcher:
def __init__(self, args):
Expand Down Expand Up @@ -673,15 +685,18 @@ class font_patcher:

def assert_monospace(self):
# Check if the sourcefont is monospaced
width_mono = is_monospaced(self.sourceFont)
width_mono, offending_char = is_monospaced(self.sourceFont)
panose_mono = check_panose_monospaced(self.sourceFont)
# The following is in fact "width_mono != panose_mono", but only if panose_mono is not 'unknown'
if (width_mono and panose_mono == 0) or (not width_mono and panose_mono == 1):
print(" Warning: Monospaced check: Panose assumed to be wrong")
print(" Glyph widths {} / {} - {} and Panose says \"monospace {}\" ({})".format(get_advance_width(self.sourceFont, False, True),
get_advance_width(self.sourceFont, False, False), get_advance_width(self.sourceFont, True, False), panose_mono, list(self.sourceFont.os2_panose)))
print(" {} and {}".format(
report_advance_widths(self.sourceFont),
panose_check_to_text(panose_mono, self.sourceFont.os2_panose)))
if not width_mono:
print(" Warning: Sourcefont is not monospaced - forcing to monospace not advisable, results might be useless")
if offending_char is not None:
print(" Offending char: 0x{:X}".format(offending_char))
if self.args.single <= 1:
sys.exit(projectName + ": Font will not be patched! Give --mono (or -s, or --use-single-width-glyphs) twice to force patching")

Expand Down Expand Up @@ -963,16 +978,15 @@ class font_patcher:
self.sourceFont.os2_typodescent = self.sourceFont.os2_typodescent - gap_bottom
# TODO Check what to do with win and hhea values

# Find the biggest char width
# Ignore the y-values, os2_winXXXXX values set above are used for line height
#
# Find the biggest char width and advance width
# 0x00-0x17f is the Latin Extended-A range
warned = self.args.quiet or self.args.nonmono # Do not warn if quiet or proportional target
for glyph in range(0x21, 0x17f):
if glyph in range(0x7F, 0xBF) or glyph in [
0x132, 0x134, # IJ, ij (in Overpass Mono)
0x132, 0x133, # IJ, ij (in Overpass Mono)
0x022, 0x027, 0x060, # Single and double quotes in Inconsolata LGC
0x0D0, 0x10F, 0x110, 0x111, 0x127, 0x13E, 0x140, 0x165, # Eth and others with stroke or caron in RobotoMono
0x02D, # hyphen for Monofur
]:
continue # ignore special characters like '1/4' etc and some specifics
try:
Expand All @@ -983,12 +997,13 @@ class font_patcher:
if self.font_dim['width'] < self.sourceFont[glyph].width:
self.font_dim['width'] = self.sourceFont[glyph].width
if not warned and glyph > 0x7a: # NOT 'basic' glyph, which includes a-zA-Z
print("Extended glyphs wider than basic glyphs")
print("Warning: Extended glyphs wider than basic glyphs, results might be useless\n {}".format(
report_advance_widths(self.sourceFont)))
warned = True
# print("New MAXWIDTH-A {} {} -> {} {}".format(glyph, self.sourceFont[glyph].width, self.font_dim['width'], xmax))
# print("New MAXWIDTH-A {:X} {} -> {} {}".format(glyph, self.sourceFont[glyph].width, self.font_dim['width'], xmax))
if xmax > self.font_dim['xmax']:
self.font_dim['xmax'] = xmax
# print("New MAXWIDTH-B {} {} -> {} {}".format(glyph, self.sourceFont[glyph].width, self.font_dim['width'], xmax))
# print("New MAXWIDTH-B {:X} {} -> {} {}".format(glyph, self.sourceFont[glyph].width, self.font_dim['width'], xmax))
# print("FINAL", self.font_dim)


Expand Down