mirror of
https://github.com/ryanoasis/nerd-fonts.git
synced 2024-12-19 20:12:52 +02:00
95 lines
3.6 KiB
Plaintext
95 lines
3.6 KiB
Plaintext
|
#!/usr/bin/env python3
|
||
|
# coding=utf8
|
||
|
|
||
|
import sys
|
||
|
import os.path
|
||
|
import fontforge
|
||
|
|
||
|
###### Some helpers (code from font-patcher)
|
||
|
|
||
|
def check_panose_monospaced(font):
|
||
|
""" Check if the font's Panose flags say it is monospaced """
|
||
|
# https://forum.high-logic.com/postedfiles/Panose.pdf
|
||
|
panose = list(font.os2_panose)
|
||
|
if panose[0] < 2 or panose[0] > 5:
|
||
|
return -1 # invalid Panose info
|
||
|
panose_mono = ((panose[0] == 2 and panose[3] == 9) or
|
||
|
(panose[0] == 3 and panose[3] == 3))
|
||
|
return 1 if panose_mono else 0
|
||
|
|
||
|
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', '.'
|
||
|
if not glyph in font:
|
||
|
# A 'strange' font, believe Panose
|
||
|
return check_panose_monospaced(font) == 1
|
||
|
# print(" -> {} {}".format(glyph, font[glyph].width))
|
||
|
if width < 0:
|
||
|
width = font[glyph].width
|
||
|
continue
|
||
|
if font[glyph].width != width:
|
||
|
# Exception for fonts like Code New Roman Regular or Hermit Light/Bold:
|
||
|
# Allow small 'i' and dot to be smaller than normal
|
||
|
# I believe the source fonts are buggy
|
||
|
if glyph in [ 0x69, 0x2E ]:
|
||
|
if width > font[glyph].width:
|
||
|
continue
|
||
|
(xmin, _, xmax, _) = font[glyph].boundingBox()
|
||
|
if width > xmax - xmin:
|
||
|
continue
|
||
|
width_mono = False
|
||
|
break
|
||
|
# We believe our own check more then Panose ;-D
|
||
|
return width_mono
|
||
|
|
||
|
def get_advance_width(font, extended, minimum):
|
||
|
""" Get the maximum/minimum advance width in the extended(?) range """
|
||
|
width = 0
|
||
|
if extended:
|
||
|
end = 0x17f
|
||
|
else:
|
||
|
end = 0x07e
|
||
|
for glyph in range(0x21, end):
|
||
|
if not glyph in font:
|
||
|
continue
|
||
|
if glyph in range(0x7F, 0xBF):
|
||
|
continue # ignore special characters like '1/4' etc
|
||
|
if width == 0:
|
||
|
width = font[glyph].width
|
||
|
continue
|
||
|
if not minimum and width < font[glyph].width:
|
||
|
width = font[glyph].width
|
||
|
elif minimum and width > font[glyph].width:
|
||
|
width = font[glyph].width
|
||
|
return width
|
||
|
|
||
|
|
||
|
###### Let's go!
|
||
|
|
||
|
if len(sys.argv) < 2:
|
||
|
print('Usage: {} font_name [font_name ...]\n'.format(sys.argv[0]))
|
||
|
sys.exit(1)
|
||
|
|
||
|
print('Examining {} font files'.format(len(sys.argv) - 1))
|
||
|
|
||
|
|
||
|
for filename in sys.argv[1:]:
|
||
|
fullfile = os.path.basename(filename)
|
||
|
fname = os.path.splitext(fullfile)[0]
|
||
|
|
||
|
font = fontforge.open(filename, 1)
|
||
|
width_mono = is_monospaced(font)
|
||
|
panose_mono = check_panose_monospaced(font)
|
||
|
if (width_mono and panose_mono == 0) or (not width_mono and panose_mono == 1):
|
||
|
print('[{:50.50}] Warning: Monospaced check: Panose assumed to be wrong; Glyph widths {} / {} - {} and Panose says "monospace {}" ({})'.format(fullfile, get_advance_width(font, False, True),
|
||
|
get_advance_width(font, False, False), get_advance_width(font, True, False), panose_mono, list(font.os2_panose)))
|
||
|
if not width_mono:
|
||
|
print('[{:50.50}] Warning: Sourcefont is not monospaced - forcing to monospace not advisable, results might be useless; Glyph widths {} / {} - {}'.format(fullfile, get_advance_width(font, False, True),
|
||
|
get_advance_width(font, False, False), get_advance_width(font, True, False), panose_mono, list(font.os2_panose)))
|
||
|
else:
|
||
|
print('[{:50.50}] OK'.format(fullfile))
|
||
|
font.close()
|